Sales Invoice — Chart of Accounts & Tax Routing ================================================ Accounts required at invoice creation -------------------------------------- The Sales Invoice flow creates a core ``InvoiceModel`` inside django-ledger, so the standard account requirements apply when creating a sales invoice: * **Cash account** (role: ``ASSET_CA_CASH``) — records cash receipts on payment * **Receivable account** (role: ``ASSET_CA_RECEIVABLES``) — records the amount owed by the customer * **Deferred revenue account** (role: ``LIABILITY_CL_DEFERRED_REVENUE``) — holds revenue until the invoice is approved Accounts required on sellable items ------------------------------------- For every product or service added as a line item, the underlying ``ItemModel`` must have the following accounts assigned before it can appear on an invoice: * **Earnings account** — where revenue is recognized (e.g., *Sales Revenue*) * **COGS account** (products only) — cost of goods sold * **Inventory account** (physical products only) — stock value These are set on the item record, not on the invoice itself. Choosing the right income account per line item ------------------------------------------------ When you add a line item to an invoice you select an **earnings account** — this is the account that gets **credited** in the general ledger when the invoice is approved. The choice determines which bucket revenue lands in on your Income Statement (Profit & Loss). .. list-table:: Income account roles :header-rows: 1 :widths: 30 25 45 * - Role (django-ledger) - What it means - Correct use * - ``INCOME_OPERATIONAL`` ✓ - Operational / trading revenue - Product sales, service fees, shipping charges to customers, e-commerce sales * - ``INCOME_PASSIVE`` - Passive / investing income - Rental income, royalties, licensing fees * - ``INCOME_INTEREST`` - Interest earned - Bank interest, loan interest received * - ``INCOME_CAPITAL_GAIN_LOSS`` - Asset disposal gain or loss - Selling a vehicle, equipment, or investment at a profit * - ``INCOME_OTHER`` - Miscellaneous income - One-off items that don't fit the categories above .. important:: Picking the wrong role does not break the books (debits still equal credits), but your P&L will misrepresent the business — for example, regular service revenue appearing under *Capital Gains*. .. rubric:: Project sales account presets The project now provisions dedicated sales accounts automatically for each entity default Chart of Accounts. This happens during migrations, when a default CoA is populated, and when the Sales Invoice flow is opened for an existing entity. ======== ============================ ========================================== Code Account Name Used for ======== ============================ ========================================== 4010 Sales Income Existing generic sales fallback 4011 Product Sales Physical goods sold to customers 4012 Service Revenue Labour, consulting, creative services 4013 Freight Revenue Shipping charges billed to customers 4014 E-commerce Sales Online channel revenue (Shopify, Amazon) ======== ============================ ========================================== The line-item **Account** dropdown defaults to Product Sales when available, then falls back to Sales Income. .. note:: *Freight Revenue* (4013) is the correct account for the **Shipping** line item. When a customer is charged for shipping, credit Freight Revenue. When you pay the carrier, that is a separate transaction debiting a **Freight Out** expense account (under ``COGS`` or ``EXPENSES``). Tax payable accounts (GST / PST / HST) ----------------------------------------- .. rubric:: Project tax payable presets The project provisions these current-liability accounts automatically under the ``LIABILITY_CL_TAXES_PAYABLE`` role: ================== ===================== ===================== Code Account Name Role ================== ===================== ===================== 2080 Sales Tax Payable Taxes Payable / LC 2081 GST Payable Taxes Payable / LC 2082 PST/QST Payable Taxes Payable / LC 2083 HST Payable Taxes Payable / LC 2084 US Sales Tax Payable Taxes Payable / LC ================== ===================== ===================== The provisioning step also creates or updates the entity's ``SalesTaxAccountMapping``: * ``default_tax_payable_account`` -> 2080 Sales Tax Payable * ``gst_account`` -> 2081 GST Payable * ``pst_account`` -> 2082 PST/QST Payable * ``hst_account`` -> 2083 HST Payable * ``us_sales_tax_account`` -> 2084 US Sales Tax Payable If a code is already used by a different account, the project picks the next available nearby code and still maps the tax code to the created account. .. rubric:: What the sales invoice stores ``SalesInvoiceProfile.recalculate_snapshot()`` writes: * ``SalesInvoiceTaxComponent`` rows — aggregate GST/PST amounts for the whole invoice * ``SalesInvoiceLineTaxComponent`` rows — per-line breakdown for each item * ``SalesInvoiceProfile.tax_total_amount`` — total tax collected * auto-generated invoice item transactions for tax payable accounts This data is used for reporting and display. The underlying ``InvoiceModel`` total (``amount_due``) includes the tax amount so the customer is billed correctly, and the tax portion uses the mapped Taxes Payable accounts instead of ordinary sales income accounts. .. rubric:: How tax flows through the journal (double-entry) When an invoice is **approved** and ``migrate_state()`` runs, django-ledger posts the following journal entries automatically: .. code-block:: text Dr Accounts Receivable $560.00 (full amount incl. tax) Cr Sales Revenue $500.00 (pre-tax line items) Cr GST Payable $25.00 (5% × $500 taxable) Cr PST Payable $35.00 (7% × $500 taxable) The mapping is implemented through auto-generated tax item transactions. Each tax item uses its mapped Taxes Payable account as the item earnings account, so django-ledger's normal invoice migration credits the correct liability account. Tax-exempt items ----------------- An item is treated as tax-exempt when its ``additional_info`` dict contains: .. code-block:: python {"sales_tax_exempt": True} Set this on the ``ItemModel`` record. The ``recalculate_snapshot`` method reads this flag per line item and skips tax calculation for exempt items. Exempt lines display an *Exempt* badge in the line items editor. Discount allocation -------------------- When a discount is applied, it is pro-rated across taxable line items before tax is calculated. A $50 discount on two taxable lines of $300 and $200 is split $30/$20 respectively, reducing the taxable base for each line and therefore reducing the GST/PST amounts proportionally. Summary flow ------------- .. code-block:: text Customer Order │ ▼ SalesInvoiceProfile (created with InvoiceModel) │ ship_to_* + tax_calculation_mode + tax_preset │ ▼ Add Line Items ──► ItemTransactionModel saved │ │ │ post_save signal │ │ ▼ ▼ recalculate_snapshot() ──► SalesInvoiceLineSummary SalesInvoiceLineTaxComponent (per-line GST/PST) SalesInvoiceTaxComponent (aggregate) SalesInvoiceProfile totals (subtotal/tax/total) │ ▼ (on approval) migrate_state() ──► Revenue entries posted to sales accounts Tax entries posted to mapped payable accounts