How money flows: net sales, costs & P&L
proWhere each peso lands: net sales vs tips, discounts, payroll cost, and what your reports actually count.
Every report, dashboard and profit-and-loss (P&L) figure in Apolaris AI is built from the same handful of records. If you understand which number each record stores — and which ones the reports actually read — your analytics will always make sense, and you will avoid the one mistake that silently breaks your payroll totals.
This page is the manager's mental model for the money. It explains what a sale stores, how discounts and tips behave, where payroll cost comes from, and how loyalty and material costs show up. It is conceptual; for the click-by-click steps see the linked guides.
Throughout this page "organization" means your whole business (one tenant) and "site (location)" means a single location/branch. See Organizations & sites.
Who can do this
| Action | Who |
|---|---|
| Take a sale / apply a discount at checkout | Any employee working the POS/Caja with the sales privilege |
| Process payroll | Domain manager (is_manager), or a non-manager with the payroll privilege |
| Read P&L, profitability and analytics | Domain manager, or a non-manager with can_explore_data / analytics access |
| Create discount codes / manage loyalty | can_manage_discounts / can_manage_loyalty (a manager always passes) |
Access is granular per-privilege, not by fixed role names: a manager always passes, while a non-manager needs the specific privilege. Whatever a user can see is scoped to their sites. See Employees, users & permissions.
The sale is the centre of gravity
A sale (the Sale record) is the single source of truth for revenue. The key
idea is that the sale stores the net amount — the money actually collected
for services and products, after any discount.
| Field on a sale | What it holds | Counts as revenue? |
|---|---|---|
amount |
The net total — what was charged after the discount | Yes — this is the revenue figure every report reads |
discount_amount |
How much a promo/discount code took off | No (it is money not collected) |
gross_amount |
A computed value = amount + discount_amount (the pre-discount subtotal) |
No (informational; shown on the receipt) |
tip |
Gratuity for staff | No — tips are never revenue |
So if a customer's services add up to $1,000, a discount code takes $150 off, and they leave a $200 tip:
gross_amount= $1,000 (pre-discount subtotal)discount_amount= $150amount(net) = $850 ← this is what revenue and profit reports counttip= $200 (tracked separately, paid out to staff)- What the customer actually pays at the counter = net + tip = $1,050 (the sale's "collectible total")
When a manager asks "why doesn't my revenue match the cash drawer?", it is almost always tips. The drawer holds net plus tips; revenue is net only.
Only realized sales count
Reports count realized sales — money that was actually collected or is pending collection. A sale whose payment status is refunded or failed is excluded from every revenue, profit, commission and tip total, so a returned or declined sale stops counting as income. A pending gateway sale (card / OXXO / SPEI awaiting the provider's confirmation) still counts until it is confirmed or fails.
Discounts lower the net — and that is what reports see
When a discount code is applied at checkout, the sale's net amount is reduced
by the discount and a redemption row is written for attribution. Crucially:
- The discount lowers
amount(the net). That lower net is exactly what analytics, P&L and profitability all count. - A redemption ledger row records the campaign impact: the pre-discount
gross_amount, thediscount_amount, and the resultingnet_amount.
A discount is real revenue you chose not to collect. Because the sale stores the net, your reported revenue and profit drop by the discount amount. This is correct — but it means a generous promo will visibly pull down the revenue line. Use the discount-code reporting to weigh revenue driven against discount cost.
See Discount codes for creating and tracking codes, and Run a promo for the end-to-end campaign flow.
Tips are a pass-through, not income
Tips are deliberately kept off the revenue line. A tip:
- is stored on the sale separately from
amount, - is excluded from revenue, profit and the receipt total,
- is attributed to a tip recipient (defaults to the employee on the sale), and
- is paid out to staff in full and untaxed through payroll.
In payroll, the tip total is added to an employee's net pay after deductions, so it is never folded into the taxable gross. This keeps the tip a clean pass-through from customer to staff.
Where payroll cost comes from (and the trap to avoid)
Payroll is the most important place to understand the data flow, because it is stored in two places that must stay in sync.
The payroll entry is authoritative
When you process a pay period, Apolaris AI creates one payroll entry per employee. Each entry stores the salary components (base, overtime, commission, bonus, tips) and the deductions (tax, social security, statutory/legal deductions, unpaid-leave deduction), and computes:
- gross pay = base + overtime + commission + bonus
- net pay = gross − deductions + tips
All P&L and analytics read the payroll entry. Profit/P&L and the business summary cost payroll from the sum of every entry's gross pay; the payroll trend and components charts aggregate the entries directly. The payroll entry is the authoritative record of payroll cost.
A mirror expense keeps the expenses ledger in sync
So that payroll also appears in the expenses ledger, processing a period also creates one mirror expense row per entry — a matching expense record. The system tracks whether it was created, so payroll and expenses stay in sync. Background sync keeps the mirror's amount in step with the entry's net pay on every write.
To avoid counting payroll twice, P&L and operating-expense reports exclude these mirror rows. Payroll cost enters P&L once, through the authoritative entry's gross — never through the mirror.
Never hand-delete a payroll expense to "fix" double-counted payroll. Reports read the authoritative payroll entry, not the mirror expense. Deleting the mirror expense row changes nothing in P&L, profitability or dashboards — and it leaves a dangling pointer behind. If you ran payroll twice over overlapping dates, the duplicate entries are still there and still double-counted. To genuinely correct it, contact Apolaris support; cleanup is an operator-only maintenance task, not something you fix by editing the expenses list.
Two safe rules of thumb: (1) treat the payroll month-sheet as the source of truth for staff cost; (2) if a payroll number looks wrong in analytics, the fix is in payroll (re-process or cancel the period), never in the expenses list.
See Payroll and the Monthly close workflow.
How discounts, tips and pay flow into P&L
| Money item | Stored on | Counted in P&L as | Notes |
|---|---|---|---|
| Net service/product revenue | Sale amount |
Revenue (+) | Realized sales only |
| Discount given | Sale discount_amount |
Reduces revenue (already netted out of amount) |
Tracked for campaign reporting |
| Tip | Sale tip |
Not in P&L | Pass-through to staff via payroll |
| Payroll cost | PayrollEntry.gross_pay |
Payroll cost (−) | Authoritative; mirror expense excluded |
| Operating expenses | Approved Expense rows (non-payroll) |
Operating cost (−) | Only approved expenses count |
| Material / inventory cost | Expenses + inventory valuation | Operating cost (−) | See below |
Only approved expenses count anywhere. A pending (awaiting approval) or rejected expense appears in no report, dashboard, chart, budget or analytic. An expense influences P&L only once it is approved.
How loyalty appears
Loyalty does not change the revenue your reports count.
- Earning happens when a sale is paid. Points are calculated from the sale's
net
amount(and, only if the program is set to "earn on tips", from the tip as well). The customer's balance is the authoritative cached figure, backed by an immutable points ledger. - Redeeming a reward typically takes the form of a discount on the next
sale. When that happens, it flows through the discount path above: it lowers
that sale's net
amount, and your revenue counts the lower net.
So loyalty is a marketing cost expressed as lower net sales, not a separate line that inflates or deflates revenue on its own. See Loyalty program.
How material and inventory costs appear
Two distinct money flows touch stock:
- Buying stock is recorded as an expense (and, for franchises buying from a central warehouse / HQ, on the order). That expense — once approved — is an operating cost in P&L.
- Consuming or valuing stock shows up in inventory analytics and valuation, not as a second deduction from the sale.
A sale itself does not automatically subtract a cost of goods from its amount
— the amount is the net revenue. Profitability is the net revenue minus your
recorded costs (payroll + approved operating/material expenses), so keeping
material purchases recorded and approved is what makes margin reporting accurate.
See Inventory,
Expenses and
Material ordering (franchise).
Keeping your data aligned (manager edition)
You do not need to know the internals to keep your numbers trustworthy. Follow these data-alignment rules:
- Net is the truth. Revenue, profit, commissions and loyalty earning are all
built from the sale's net
amount. Tips and pre-discount gross are separate. - A discount is real lost revenue. Expect the revenue line to drop by the discount; that is the system working correctly.
- Fix payroll in payroll. The payroll entry — not the expenses list — drives reports. Re-process or cancel a period to correct payroll; never hand-delete the mirror payroll expense.
- Only approved expenses count. If a cost is missing from P&L, check whether the expense is still pending approval.
- Refunded/failed sales drop out. Marking a sale refunded or failed removes it from every income total automatically — you do not also need to "subtract" it elsewhere.
Deleting historical financial records by hand (payroll expenses, individual mirror rows) is the most common way to desync analytics from reality. If something looks double-counted or wrong at the data level, contact Apolaris support rather than editing rows directly.