Receipts and invoices from the ERP or POS
Business day, store + invoice key and operation type
Net sales and ticket by store, day and salesperson
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.
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
Net sales, ticket and target vs. actual by store, with month-end projection and traffic light.
At 8 a.m., yesterday's sales by store and salesperson via management's WhatsApp or email.
A selling store that dropped to zero, or an ERP load that has not arrived by the expected time.
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 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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
Definitions
Pitfalls that already happened
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.
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.
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.
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.
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.
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.
- For three stores and one closed day, gross and net sales match the ERP cash close (zero difference).
- The sum of stores is the chain total for the day, and the sum of days for each store equals the value in the monthly table.
- The daily table has exactly one row per store and day.
- "Yesterday" queried at 10 p.m. and at 11:59 p.m. in São Paulo returns the same business day and the same value.
- The count of distinct invoices by (store, number) in the month equals the total sales invoices issued in the ERP.
Agent package
Paste into Claude, ChatGPT or any client with the Nekt MCP connected.
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.
Build the "Daily sales by store and salesperson from the ERP" case in my Nekt workspace following the rules at https://academy.nekt.com/en/industrias/varejo/vendas-diarias-loja-erp.md. 1) Find the source tables and confirm the columns the rules use. 2) Create a transformation at the stated grain applying every rule. 3) Run the acceptance test and show me the result of each item. 4) Create the case's context document in the workspace, leaving my clients' exceptions open for me to fill in.
Variations
Same rule in each instance, unified with a store column before aggregating.
Daily FX rate carrying the last value forward on weekends, and a time zone rule per country.
Keep versions of the daily table (SCD type 2) to know when a closed day was changed.