# Milestone 4 — Money (Implementation Notes)

## Invoices
- Created from a treatment plan (non-cancelled items + its discount, one open
  invoice per plan) or built custom. Per-tenant per-year numbering
  `INV-2026-0001` (lock + unique index, race-safe).
- Lifecycle: draft → issued → partially_paid → paid; void only while unpaid.
- Arabic mPDF rendering incl. the installment schedule and a PAID stamp —
  the same renderer feeds WhatsApp attachments in M5.

## Installments — the flagship
- Schedule = optional down payment due today (seq 0) + N monthly parts.
  Parts rounded to **250 IQD** (smallest practical note); the last part
  absorbs the remainder so the schedule always sums exactly. Live preview
  in the UI ("≈ 6 × 125,000").
- Collections screen: overdue (red, with diffForHumans) + next-30-days, each
  row carrying the one-click collect form.
- `reminder_sent_at` already on installments → M5 sends due-date WhatsApps
  with zero schema change.

## Payments — append-only ledger
- One entry point (`PaymentService::record`): validates open invoice +
  remainder cap; methods cash / Zain Cash / card / bank transfer (reference
  REQUIRED for Zain Cash & transfers, enforced server-side and staged in the
  quick-pay UI). No edits or deletes — the cash history stays trustworthy.
- Allocation: installment-targeted payments fill the target then spill
  forward (oldest due first); invoice-level payments spill the same way.
  Invoice paid/status, patient total_paid and outstanding_balance stay in
  sync in one transaction.

## Quick payment (receptionist one-click)
`_quickpay` partial everywhere money is collected (invoice page, every
installment row, collections screen): amount prefilled with the remainder,
four method buttons, single tap. Zain Cash/transfer intercepts the first tap
to reveal the reference field. Gated by `recordPayment` policy
(installments.manage OR invoices.manage — receptionists qualify).

## Dashboards & analytics
- Outstanding widgets (Due today / Due this week / Overdue / Total
  outstanding) on the main dashboard (invoices.view) and the collections
  screen, all clickable into collections.
- Revenue screen: COLLECTED (payments) totals, by method, 30-day chart;
  BILLED (issued invoice items) by category (doughnut) and per procedure →
  top performing services. The two lenses are labelled in the UI; per-
  procedure attribution follows billing because payments are invoice-level.

## Patient debt indicators
`patients.outstanding_balance` recalculated on issue/void/payment; red badge
in the patient list, red banner on every patient tab page (via `_tabs`),
linking to the patient's invoices.

## Tests (22 new)
Invoices: plan→invoice fidelity, cancelled-item exclusion, per-tenant
numbering, double-invoice guard, issue rules, balance recalc. Installments:
exact-sum schedules with rounding, remainder-on-last, date advancement,
double-schedule/oversized-down rejection, widget math. Payments: full/partial
flows, overpayment guard, spill allocation (targeted + invoice-level),
receptionist endpoint, Zain Cash reference rule. Revenue: collected vs billed,
by method/category/procedure, top service.
