Skip to content

F21: Customer payments + balances — order-attached payments, outstanding per order/customer (admin-only) #89

Description

@mforce

Phase 1.1 slice of spec §10.11 (payments) + the "customer payments and balances" phase line. Money data → admin-only end to end, matching #87's split.

Model

Payment: sales order (required, spec shape), customer (denormalized from the order at creation), payment date (not future, ≥2000), amount in minor units (> 0), currency copied from the sales order (never editable), method (Cash / Check / Card / BankTransfer / MobilePayment / Other), optional reference number (≤50) and note (≤500), Version.

Rules

  • Payments attach to Confirmed orders only (Draft/Cancelled/Voided refuse; Shipped/Invoiced don't exist yet).
  • No overpayment: Σ non-voided payments ≤ order total — refused with a deterministic 422 naming the outstanding amount. Partial payments are the normal case.
  • Void payment (admin, reason required, F13 pattern): compensating status flip, never delete; voided payments keep their history and leave the balance.
  • Order void ↔ payments: voiding a confirmed order with non-voided payments is refused ("void its payments first") — mirrors the sold-stock refusal on entry void.
  • Race rules per AGENTS.md: version-guarded void; parallel record-vs-record on one order must not overshoot the total (transactional outstanding check with the order row locked).

API (/api/v1/..., all AdminOnly)

  • POST /sales/{orderId}/payments (idempotency key), GET /sales/{orderId}/payments (list + paid/outstanding summary)
  • POST /payments/{id}/void (version + reason)
  • GET /customers/balances — per-customer: confirmed total, paid, outstanding (server-side sums)

SPA

  • Sales order panel: payments section — list (method, date, amount, reference, Voided badge), add form, outstanding line; void via prompt (F13).
  • Customers page: outstanding balance column (admins only see it; the API refuses workers regardless).

Docs (same PR)

Help (Sales section + Who-can-do-what money bullet + Fixing-mistakes row), GLOSSARY (Payment, Outstanding balance).

Out of scope

Refunds/credit notes, overpayment-as-credit, statements/receipts, payment reports (→ core reports), bulk import.

Part of #14.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions