Repository navigation
feat(billing): correct the payment method on a paid bill while its shift is open #1337
Copy link
Copy link
Open
Labels
area:backendBackend (Express/SQLite)Backend (Express/SQLite)area:frontendFrontend (React/Next.js)Frontend (React/Next.js)enhancementNew feature or requestNew feature or requeststate:readyScoped and ready for implementationScoped and ready for implementationtype:featureNew capability or enhancement requestNew capability or enhancement request
Description
Parent: #830 (S2). Verified against main @ 8e39053.
Problem
A cashier picks the wrong tender (cash instead of card, or the reverse) and cannot fix it after checkout (+63, 11 Sep). The shift count is then off by that amount.
Current behavior (verified)
- Payment lines are stored in the bill's
payment_detailsJSON, and each line carriescash_session_id(main/routes/bills.ts~L3772-3785). - No route changes the method of a recorded payment. Bills routes: list/get/print-history, generate, split-check, payment(s), applyDiscount, markPrinted, print,
PATCH /:id/charges. There is noUPDATE ... paymentpath anywhere. - Expected cash per shift comes from payment lines and drawer movements by
cash_session_id(main/routes/cash-closures.ts~L615-740).
Decisions (made by maintainer, 23 Oct)
- Only an owner or manager, authorized with their Staff Approval PIN (same approver selection as refunds and overrides).
- Allowed only while the payment's cash shift is still open. Once that shift is closed (or the day is closed) the correction is refused with a clear reason.
- The amount never changes: only the method (and the method id / card transaction id) on one payment line.
- Every change is audited: old method, new method, actor, approver, reason, timestamp.
- Expected cash is recalculated for the open shift, so the change shows up in variance.
Scope
- New route, for example
PATCH /bills/:id/payments/:index/methodinmain/routes/bills.ts, wrapped in a transaction, with PIN verification outside the write transaction as the existing refund flow does (verifyPinAsync,withPinVerificationLock). - Refuse on refunded lines, split siblings already settled elsewhere, and unknown or inactive methods.
- UI: a "Correct payment method" action on paid bills in
OrderDetailPanel.tsx, with approver picker and PIN prompt. - Update
docs/reference/roles-and-permissions.mdanddocs/reference/api.mdin the same PR.
Acceptance criteria
- Cash to card on an open shift: shift expected cash drops by the amount, and the card total rises by it.
- Closed shift or closed day: 409 with a reason, nothing changed.
- Cashier role, or a wrong or ineligible PIN: refused. A cashier's PIN must never authorize this.
- Audit row written. A replay of the same request is idempotent.
- Receipt reprint shows the corrected method.
Verification
- New
tests/payment-method-correction.test.tscovering the cases above, modelled on the refund PIN tests. npm run lint && npm test
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:backendBackend (Express/SQLite)Backend (Express/SQLite)area:frontendFrontend (React/Next.js)Frontend (React/Next.js)enhancementNew feature or requestNew feature or requeststate:readyScoped and ready for implementationScoped and ready for implementationtype:featureNew capability or enhancement requestNew capability or enhancement request
Activity