Retail and e-commerce · Sales by store

Daily sales by store and salesperson from the ERP

Net revenue, average ticket, cancellations and returns by store, day and salesperson, on the right business day and matching the ERP close.

UsageWidely used
EffortMedium
ForRetail chains with several stores or branches that sell through an ERP or POS.
Source

Receipts and invoices from the ERP or POS

Rule

Business day, store + invoice key and operation type

Outcome

Net sales and ticket by store, day and salesperson

Activation

Dashboard, daily report and AI agent

What it solves

  • Each store's revenue lands on the right business day, with no day zeroed out or shifted by time zone.
  • Gross sales, net sales, returns and future-delivery sales follow a single rule and match the ERP.
  • Each sale stays with the store and salesperson from when it happened.

Business questions it answers

Ask your agent these questions once the case is live.

How much did each store sell yesterday, net?
What is the average ticket per store this week, and how does it compare with last week?
How much were returns and cancellations this month, by store?
What is revenue by store and salesperson over the last 14 months?
Which store is at risk of missing this month's target, and how much does it need to sell per day?

What you need

  • The ERP or POS connected to Nekt (Oracle or SAP database, or a cloud ERP)
  • The ERP operation codes: sale, future-delivery sale, return, shipment
  • Targets by store or product, if you want target vs. actual

What you get

  • A table by store and day with gross, net, tickets and cancellations
  • A table by invoice line item with salesperson and product
  • Chain dashboard with target, actual and projection by store
  • Daily report of yesterday by store, via WhatsApp or email

Where to activate

Chain dashboard

Net sales, ticket and target vs. actual by store, with month-end projection and traffic light.

Daily report

At 8 a.m., yesterday's sales by store and salesperson via management's WhatsApp or email.

Alerts

A selling store that dropped to zero, or an ERP load that has not arrived by the expected time.

Ready to build?

One source, but with date, invoice key and operation type rules that need to be confirmed with finance before the first dashboard. The detailed view has the business rules, the pitfalls and the acceptance test. Or send everything straight to your agent with the Nekt MCP.

The problem

The ERP stores the sale date as midnight UTC, and whoever converts the time zone pushes the sale to the previous day or zeroes out the day. Invoice numbers repeat across stores, and joining on the number alone mixes sales from different stores and salespeople. Sales, future-delivery sales, negative returns, cancellations and shipments all live in the same table, and every report adds them up differently.

How it is usually done, and the rule

Each row is a mistake that already happened in practice.

The common wayThe rule
01
Applying AT TIME ZONE 'America/Sao_Paulo' to the sale date field.
The ERP date is the business day

In many ERPs and POS systems the sale date field is stored as midnight UTC representing the business date, and the real time sits in another field. Compute today and yesterday in the America/Sao_Paulo time zone and compare directly with that date, without converting the field. Converting to BRT moves midnight UTC to 9 p.m. on the previous day.

02
Sending the ERP TIMESTAMP to the BI Postgres and trusting the server time zone.
Write DATE, not TIMESTAMP, to the destination

Destination databases and BI tools reinterpret a midnight UTC TIMESTAMP in the local time zone and show the previous day. Convert to DATE before sending. Check source by source: some bring a plain date, others bring the real time in UTC (e-commerce usually has the real time, and then you do convert to BRT).

03
JOIN on invoice number only.
An invoice is store + number

Invoice numbers are reused across locations: the same number in two stores is two different documents. Every join of invoices with line items, carts, returns or commissions uses the composite key (store, invoice number). Count invoices with a distinct count of the pair, not with a count of line item rows.

04
A "sales" column that does not say whether it is gross or net.
Say whether it is gross or net

Gross sales is the value of receipts before discounts and cancellations. Net sales = gross minus discounts minus cancellations. The two can differ by six figures in a single day at one store. Every published number states which one it is, and the question "how much did we sell" is answered with net.

05
Filtering only direct sales and losing future-delivery sales, or excluding returns from net.
Each operation type has a sign

Direct sales add. Future-delivery sales (invoiced for later delivery) are valid revenue and add. Returns come in with a negative value and are added, reducing the total on the return date. Shipments, transfers and bonus goods stay out: filter by the sales CFOPs (fiscal operation codes). Confirm the list of operation codes with finance.

06
Dividing by the count of line item rows, or averaging each store's ticket.
Average ticket uses valid receipts

Average ticket = net sales / valid tickets. A valid ticket is a distinct receipt (store, POS, number) that was not cancelled. Average ticket is not additive: the chain's and the month's are recomputed from the sums, never as an average of daily tickets.

07
Joining salesperson to store through the current record and rewriting history.
Salesperson with the store at the time

Salespeople move between stores or help out at other locations. The store of the sale is the one on the document, and the salesperson x store relationship has a validity period; the salesperson's current store is never applied retroactively. Normalize the name (the ERP may add a " - 123" suffix with the code) and keep a null salesperson as "no salesperson", without dropping the sale.

08
Merging by store and month in a table that receives daily rows.
The grain is in the name and in the upsert key

The daily table has one row per store per day, and its name says so. The upsert key is exactly the grain (store + day). Each run reprocesses today and yesterday to catch late adjustments. A monthly table does not receive daily data.

09
Reloading the whole spreadsheet and wiping out targets from previous months.
Target vs. actual with projection

Targets come from a spreadsheet by store or product and reference month. The load replaces only the items present in the spreadsheet for that month and keeps the rest. Actual is the month's net sales. Gap = target minus actual; required daily average = gap / remaining days; projection = actual / elapsed days x days in the month.

How each operation enters revenue

Confirm your ERP codes with finance.

Direct saleAddspositive value
Future-delivery sale (later delivery)Adds, it is valid revenuepositive value
ReturnAdds the negative valuenegative value, return date
DiscountSubtracts from grossgross - discounts
Cancelled receiptSubtracts from gross and leaves valid ticketsgross - cancellations
Shipment, transfer, bonus goodsOutside revenueCFOP not in the sales list
Head office or DC without direct salesNo sales is expecteddo not alert

Definitions

Gross sales
sum of the gross value of sales receipts and invoices, by store and business day
Net sales
gross sales minus discounts minus cancellations, with future-delivery sales added and returns negative, by store and business day
Valid tickets
distinct count of non-cancelled receipts (store, POS, number), by store and day
Average ticket
net sales / valid tickets in the requested cut; not additive, recomputed at every aggregation
Returns
sum of the value of return operations (negative), by return date, by store and month
Cancellation rate
cancelled receipts / total receipts, by store and period
Invoices issued
distinct count of the pair (store, invoice number) in the period
% attainment
month's net sales / month's target, by store or product
Required daily average
(target minus actual) / remaining days in the month

Pitfalls that already happened

High-sales day zeroed out

A query converted the date field stored as midnight UTC to BRT and answered zero sales for a day that had hundreds of thousands of reais.

Do not convert the business date field; compute only today in BRT.

Day shifted in BI

The midnight UTC TIMESTAMP sent to the BI Postgres was read in the São Paulo time zone, and every sale showed up on the previous day.

CAST to DATE before the destination.

Negative margin from a repeated invoice

Joining on invoice number alone matched a cart from one store with an invoice from another store, with a different salesperson and customer. The result was negative margins and margins above 100%.

Composite key (store, invoice number) in every JOIN.

Head office without sales triggers an alert

The head office or DC has no direct sales and showed up as a zeroed store, raising suspicion of a sync failure.

Flag stores without direct sales in the store dimension and exclude them from the zero alert.

Silent duplication

A table with a monthly grain in its name started receiving daily rows, and a merge key different from the grain duplicated records with no error.

Name, grain and merge key aligned; uniqueness test by store and day.

Month-to-date report

Some sources export the month-to-date total every day. Adding up the files multiplied sales.

Deduplicate by whole day and keep the latest file for each date.

Acceptance test

The case is done when every item passes.

Agent package

Paste into Claude, ChatGPT or any client with the Nekt MCP connected.

Full Markdown
Daily sales by store (ERP)
- Grain: one row per store, per business day. Detail by salesperson and product in the invoice line item table.
- The sale date is stored as midnight UTC and represents the business day. Do not apply a time zone conversion to this field. Compute today and yesterday in America/Sao_Paulo and compare directly.
- The invoice (nota fiscal) is identified by (store, invoice number). Never JOIN on the number alone.
- Net sales = gross minus discounts minus cancellations. When asked "how much did we sell", answer with net and say it is net.
- Direct sales and future-delivery sales add. Returns come in negative and add. Shipments and transfers stay out (sales CFOP, the fiscal operation code).
- Average ticket = net sales / valid (non-cancelled) receipts. Do not sum or average average tickets.
- The store of the sale is the one on the document. The salesperson's current store is not applied to history.
- The head office and the DC have no direct sales: no sales there is expected.
- Target: % attainment = month's net / target; required daily average = gap / remaining days.
Client exceptions:
- <client>: sales operation codes <list>; future-delivery sale = <code>; return = <code>.
- <client>: stores without direct sales <list>.
- <client>: source <country or channel> brings the real time in UTC and needs conversion to the local time zone.

Variations

One ERP instance per store

Same rule in each instance, unified with a store column before aggregating.

Chain in several countries

Daily FX rate carrying the last value forward on weekends, and a time zone rule per country.

Adjustment history

Keep versions of the daily table (SCD type 2) to know when a closed day was changed.