Finance-Accounts/ar-aging-app/backend/app/core/definitions.py

271 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
Plain-language definitions of every figure the dashboard shows — served to the UI as the
content of the (i) info buttons.
These live in the backend, next to the engine, ON PURPOSE: each entry describes what
`journal._contribute_components`, `movement.compute_movement`, `receivable.py` and
`settlements.py` actually do, and anyone changing that code is looking at the file that
documents it. If you change a rule, change its definition in the same commit.
Shape per entry:
formula : the arithmetic, in one line
source : which source-report columns / transaction types feed it
note : anything Finance should know when tying it out (optional)
Column names in `source` are the Amazon report's own headers (localized headers map to
these via column_map.py).
"""
from __future__ import annotations
REFUND_TYPES_LABEL = "Refund, Refund_Retrocharge, Chargeback Refund, A-to-z Guarantee Claim"
DEFINITIONS: dict[str, dict[str, str]] = {
# ------------------------------------------------- revenue components (journal.py)
"product_sales": {
"formula": "Σ `product sales`",
"source": f"the `product sales` column of every row except Transfers and "
f"refund-type rows ({REFUND_TYPES_LABEL})",
"note": "Refund-type rows' product sales are shown in the Refunds line instead, "
"so sales and refunds are visible separately.",
},
"shipping_credits": {
"formula": "Σ `shipping credits`",
"source": "the `shipping credits` column of non-refund, non-transfer rows",
},
"gift_wrap_credits": {
"formula": "Σ `gift wrap credits`",
"source": "the `gift wrap credits` column of non-refund, non-transfer rows",
},
"other_sales_credits": {
"formula": "Σ `regulatory fee`",
"source": "the `regulatory fee` column of every non-transfer row",
},
"refunds": {
"formula": "Σ (`product sales` + `shipping credits` + `gift wrap credits`) over refund rows",
"source": f"rows whose type is one of: {REFUND_TYPES_LABEL}",
"note": "Negative: money returned to buyers.",
},
"promotional_rebates": {
"formula": "Σ `promotional rebates`",
"source": "the `promotional rebates` column of every non-transfer row",
},
"tax_net": {
"formula": "Σ (`product sales tax` + `shipping credits tax` + `gift wrap credits tax` "
"+ `tax on regulatory fee` + `promotional rebates tax` "
"+ `marketplace withheld tax` + `sales tax collected`)",
"source": "every tax column, netted together",
"note": "Where Amazon collects and remits the tax itself, collected and withheld "
"cancel and this nets to ~0.",
},
"selling_fees": {
"formula": "Σ `selling fees`",
"source": "the `selling fees` column (referral commissions, variable closing fees)",
},
"fba_fees": {
"formula": "Σ `fba fees`",
"source": "the `fba fees` / `fulfilment by amazon fees` column (pick & pack, weight handling)",
},
"storage_fees": {
"formula": "Σ `other` over FBA Inventory Fee rows",
"source": "rows whose type is `FBA Inventory Fee` (monthly + long-term storage); "
"the amount sits in the `other` column",
},
"advertising": {
"formula": "Σ (`other` + `other transaction fees`) over advertising rows",
"source": "rows whose DESCRIPTION reads as advertising — \"Cost of advertising\", "
"\"Sponsored Products\", Werbekosten, publicité, pubblicità, … — regardless "
"of type (Amazon books these as plain `Service Fee`)",
"note": "The amount column differs by marketplace: `other` in the North-America "
"report, `other transaction fees` in the UK/EU report. Both are captured.",
},
"other_transaction_fees": {
"formula": "Σ `other transaction fees` (excluding advertising rows)",
"source": "the `other transaction fees` column — chargebacks, shipping holdbacks — "
"minus the rows identified as advertising, which move to the "
"Advertising line",
},
"adjustments": {
"formula": "Σ `other` over Adjustment rows",
"source": "rows of type `Adjustment` (FBA inventory reimbursements, buyer "
"recharges); the amount sits in the `other` column",
},
"freight": {
"formula": "Σ `other` over Shipping Services rows",
"source": "rows of type `Shipping Services` — outward freight billed by Amazon",
},
"other_service_charges": {
"formula": "Σ `other` over the remaining rows",
"source": "the `other` column of rows not classified as storage, freight, "
"advertising, or adjustment (e.g. subscription fees)",
"note": "If this is unexpectedly large, open Transaction Details and check the "
"descriptions — a new Amazon charge type may deserve its own line.",
},
"transfers": {
"formula": "Σ `total` over Transfer rows",
"source": "rows of type `Transfer` — Amazon's bank payouts (negative = paid out to us)",
},
"liquidations": {
"formula": "Σ `total` over Liquidations rows — memo only",
"source": "rows of type `Liquidations` / `Liquidations Adjustments`",
"note": "Already included in the lines above; shown separately for visibility, "
"never added twice.",
},
# ------------------------------------------------- aggregate lines
"gross_revenue": {
"formula": "Order/product sales + Shipping credits + Gift-wrap credits "
"+ Other sales credits + Refunds",
"source": "the revenue-group lines above",
},
"net_revenue": {
"formula": "Gross revenue + every fee line (rebates, tax, selling, FBA, storage, "
"advertising, other fees, adjustments, freight, other services)",
"source": "every line above except Transfers — i.e. all activity except bank payouts",
"note": "Equals the month's accrued receivable movement before payouts.",
},
"opening_balance": {
"formula": "prior month's closing receivable",
"source": "carried forward from the prior closing, or entered from last month's "
"workbook on the Opening Balances tab",
"note": "Zero on a first-ever closing. Until entered, the roll-forward measures "
"only this month's movement (see control C4).",
},
"disbursements": {
"formula": "Σ payouts RECEIVED by month-end",
"source": "a payout counts as received from its BANK-receipt date when Finance has "
"entered one (received ⇔ bank date ≤ month-end); otherwise the "
"clearing-lag heuristic on Amazon's transfer date (auto mode) or not at "
"all (manual mode)",
"note": "Amazon's Transfer date is when the payout was initiated — the bank credit "
"lands 3-5 working days later. Enter bank dates on the AR Ledger tab.",
},
"in_transit_payouts": {
"formula": "Σ payouts NOT received by month-end",
"source": "payouts Amazon initiated whose bank credit had not arrived by month-end; "
"their settlements stay in the receivable",
},
"bank_receipt": {
"formula": "received ⇔ bank date ≤ month-end",
"source": "the date (and amount) Finance records when a payout lands in the bank "
"account — overrides the clearing-lag heuristic for that payout",
"note": "auto mode: payouts without a receipt fall back to the clearing-lag "
"heuristic. manual mode: a payout without a receipt is NOT received. "
"Changes apply when the closing is re-processed. If the bank amount "
"differs from Amazon's payout, a variance warning is raised on the "
"Exceptions tab; the ledger keeps Amazon's amount.",
},
"closing_receivable": {
"formula": "Opening AR balance + Net revenue Payouts received",
"source": "the roll-forward method — cross-checked against the settlement method "
"(control C4)",
},
"settlement_closing": {
"formula": "ROUND(reserve + additional sales) per marketplace",
"source": "`additional sales` = Σ `total` over open (unpaid) settlements, for real "
"order account types, excluding Transfers — the workbook's SUMIFS method",
"note": "This is the method the Finance workbook uses (USA Jan-26 = 11,110,433) and "
"the benchmark figure. FX converts it to USD per marketplace.",
},
"reserve": {
"formula": "Opening + Sales Receipts Refunds Expenses over PAID settlements (≈ 0)",
"source": "a small Finance-maintained reconciliation carry entered per marketplace",
},
# ------------------------------------------------- overview / other tabs
"closing_receivable_usd": {
"formula": "Σ over marketplaces of ROUND(reserve + additional sales) × FX rate, "
"+ manual adjustments",
"source": "the settlement method per marketplace, converted at the session's "
"confirmed FX rates",
},
"receivable_orders": {
"formula": "Σ `total` over rows in RECEIVABLE settlements",
"source": "non-transfer rows of settlements not yet paid out by the cutoff",
},
"paid_orders": {
"formula": "Σ `total` over rows in PAID settlements",
"source": "non-transfer rows of settlements whose payout reached the bank by the cutoff",
},
"transfers_total": {
"formula": "Σ `total` over every Transfer row",
"source": "all bank payouts in the uploaded files, received or in transit",
},
"settlement_status": {
"formula": "receivable ⇔ settlement id ≥ the paid boundary",
"source": "a settlement stays receivable until the Transfer that pays it out is "
"dated on/before month-end clearing-lag; the boundary is the newest "
"settlement with a received payout",
},
"aging_basis": {
"formula": "days past DUE at month-end; due = last activity + 14-day settlement "
"cycle + clearing lag",
"source": "each receivable settlement's last activity date",
"note": "Amazon settles ~biweekly, so a healthy month is ~100% Current. A "
"settlement Amazon is holding ages into 1-30/31-60/61-90.",
},
# ------------------------------------------------- journal entry (GL lines)
"journal_entry": {
"formula": "Dr fees & refunds · Cr sales & tax · balancing Dr A/R = net revenue",
"source": "the month-end ACCRUAL entry. Positive line totals are credits, negative "
"are debits, so debits always equal credits",
"note": "Bank receipts (Transfer) are posted separately from bank statements and are "
"deliberately not part of this entry. Approval publishes the month to the "
"Accounts Summary; re-processing withdraws the sign-off.",
},
"Sales": {
"formula": "Σ (`product sales` + `shipping credits` + `gift wrap credits`) over non-refund rows",
"source": "gross sales value of every order-type row — Credit",
},
"Refunds": {
"formula": "Σ (`product sales` + `shipping credits` + `gift wrap credits`) over refund rows",
"source": f"rows of type {REFUND_TYPES_LABEL} — Debit",
},
"Tax": {
"formula": "Σ of every tax column, netted",
"source": "product/shipping/gift-wrap sales tax + regulatory + promotional-rebate tax "
"+ marketplace-withheld + collected — nets ≈ 0 where Amazon remits",
},
"FBA Selling Fee": {
"formula": "Σ `selling fees`",
"source": "referral commissions and variable closing fees — Debit",
},
"FBA Storage": {
"formula": "Σ `other` over FBA Inventory Fee rows",
"source": "monthly + long-term storage fees — Debit",
},
"FBA Fee": {
"formula": "Σ (`fba fees` + `promotional rebates` + non-advertising `other transaction "
"fees` + `regulatory fee` + unclassified `other`)",
"source": "the catch-all Amazon fee/adjustment bucket — Debit",
"note": "Advertising is broken out to its own line and is NOT in here.",
},
"Advertising Cost": {
"formula": "Σ (`other` + `other transaction fees`) over advertising rows",
"source": "rows whose description reads as advertising (\"Cost of advertising\", "
"Sponsored Products, localized variants) — Debit",
"note": "Amazon books these as plain `Service Fee`; the description is the only "
"signal, and the amount column differs by region.",
},
"Inventory Adjustment": {
"formula": "manual sheet line (0 unless classified)",
"source": "inventory adjustments booked to Sales:Inventory Adjustments",
},
"Outward Freight / Shipping": {
"formula": "Σ `other` over Shipping Services rows",
"source": "outward freight billed by Amazon — Debit",
},
"Receivable": {
"formula": "−Σ(all lines above) = net revenue",
"source": "the balancing figure of the accrual entry — Dr Accounts Receivable",
"note": "Equals the AR Ledger's net revenue for the month; bank receipts then "
"credit A/R as they arrive.",
},
"uploaded_total": {
"formula": "Σ `total` over every row of every uploaded file",
"source": "identical to receivable + paid + transfers by construction — a "
"self-consistency figure, NOT a control (see the Controls tab for the "
"checks that can actually fail)",
},
}