fix: shift closing total reflects money collected, not invoiced - #312
fix: shift closing total reflects money collected, not invoiced#312NotAbdelrahmanelsayed wants to merge 2 commits into
Conversation
Credit (Pay-on-Account) sales inflated the POS shift closing total.
`_process_invoice()` added the full `base_grand_total` of every invoice to
the sales summary (`grand_total`/`net_total`/`sales_total`) and the per-row
amount, regardless of how much was actually paid. The cash Payment
Reconciliation, however, is built only from real payment rows — so a pure
credit sale pushed Net Sales up by the full amount while contributing 0 to
the drawer, leaving the two figures inconsistent within a single shift.
For non-return invoices the money summaries and the per-row `grand_total`
now use the amount actually collected (`base_paid_amount`): a pure credit
sale contributes 0, a partial sale contributes only its down-payment, and
`net_total` is scaled by the paid ratio. The full invoice value is preserved
in `transaction_amount`; display-only `invoice_total` and
`outstanding_amount` are added for the dialog badge and stripped before the
child-table set. Returns, quantities and tax accrual are unchanged.
The Close Shift dialog now shows an "On Account" / "Partially Paid" badge and
an "Unpaid: {amount}" sub-line on rows collected for less than their invoice
value. Adds unit tests for the collected-money totals and an Arabic string.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…closing-total # Conflicts: # POS/src/components/ShiftClosingDialog.vue # pos_next/pos_next/doctype/pos_closing_shift/pos_closing_shift.py # pos_next/pos_next/doctype/pos_closing_shift/test_pos_closing_shift.py # pos_next/translations/ar.csv
|
This pull request has been automatically marked as stale because it has not had recent activity for 21 days. To keep this PR open, please:
If no further activity occurs within the next 14 days, this PR will be automatically closed. |
|
This pull request has been automatically marked as stale because it has not had recent activity for 21 days. To keep this PR open, please:
If no further activity occurs within the next 14 days, this PR will be automatically closed. |
|
Nice fix @NotAbdelrahmanelsayed!, this closes a real gap between Net Sales and what's actually in the drawer. Two things I found while testing that are worth patching before merge:
Fix: subtract change before it's used anywhere:
net_total/grand_total now scale by paid_ratio for partial/credit sales, but the tax loop still aggregates the full tax_amount regardless of what was collected. That breaks grand_total ≈ net_total + taxes for any shift with a partial/credit sale that has tax on it. Worth a deliberate call. I'd scale it too, for consistency: One unrelated nit: test_pos_closing_shift.py is 4-space indented. repo convention is tabs (ruff format will flag it). |
Problem
When closing a POS shift, the closing total counts the full grand total of every invoice linked to the shift — even pure Pay-on-Account credit sales where no money was received. The cash Payment Reconciliation is built only from real payment rows, so it is already correct — but
Net Sales(grand_total) disagrees with it within a single shift:grand_total)Root cause:
pos_closing_shift.py › _process_invoice()addedbase_grand_total(the full invoice value) intogrand_total/net_total/sales_totaland the per-row amount, ignoring how much was actually paid.Fix
For non-return invoices, the money summaries and the per-row
grand_totalnow use the amount actually collected (base_paid_amount):net_totalscaled bypaid_ratio = base_paid / base_grand_totalThe full invoice value is preserved in
transaction_amount; display-onlyinvoice_totalandoutstanding_amountare added for the dialog and stripped before the child-table set (Sales Invoice Referencehas no such columns). Quantities, tax accrual and the returns branch are unchanged. With this change Net Sales == sum of per-invoice collected == reconciliation cash delta.The Close Shift dialog shows an
On Account/Partially Paidbadge and anUnpaid: {amount}sub-line on rows collected for less than their invoice value (desktop + mobile).Tests
Adds unit tests for
_process_invoicecovering fully-paid, pure-credit, partial and credit-return cases, asserting the summary equals only the collected portions and per-row amounts sum to the header total. Adds the Arabic translation for the newUnpaid: {0}string.🤖 Generated with Claude Code