Decision record + implementation spec — 2026-09-08 (Matthew + Hermes). Triggered by live financial testing findings (private payments absent from ERPNext; co-pay Payment Entry 417s; claims-without-invoices state) and resolved against the real FP17 process (reference: the FP17 research capture on this wiki). This page is the single source of truth for the redesign. Companion: Financial & Billing live test plan.
The app's billing choreography diverges from real NHS dental practice in three ways:
- Billable point = reception check-in (shipped 2026-09-07, b181a295): an appointment is billed the moment it is marked ATTENDED — before any treatment has happened. Real process: charges arise from a completed course of treatment.
- Invented two-invoice split: an NHS course was modelled as a private-style "course total" (e.g. £95) split into an "NHS reimbursable share" (£76.60) + "patient co-pay" (£18.40), invoiced at claim reconcile. Split payments of this kind do not occur in real practice — an NHS patient pays the statutory band charge (or is exempt); NHS income flows from claim acceptance → UDA credit → contract payment. The split model is retired entirely.
- Claims without invoices (and invoice creation gated on ACCEPTED) created an orphan-claim state and a "will it/won't it be accepted" grey area that should not exist: rejection is a deterministic data-error bounce, preventable by validating before transmission.
- D1 — Charges follow treatment, not attendance. Reception check-in marks ATTENDED only. The charge point moves to course-of-treatment completion. (Supersedes b181a295's check-in billing.)
- D2 — Course of Treatment (CoT) is the billing unit (standard practice per the FP17 research: a course is opened at examination, treatment is delivered over one or more appointments and charted, ONE FP17 is generated when all planned items are complete). Build the CoT model now rather than deferring.
- D3 — Clinicians confirm completion of each appointment's treatment; the course closes when its planned treatment is done, and closure triggers the claim/charges.
- D4 — No split payments. The patient co-pay / NHS-reimbursable two-invoice construction is removed. NHS patient charging = statutory band charge for non-exempt patients (Band 1 £27.90 / Band 2 £76.60 / Band 3 £332.10 / Urgent £27.90 — 2026/27, from the band-charge table), £0 for exempt patients with exemption code + evidence (FP17PR captured at intake). Private treatment = price-list charge (unchanged basis, new trigger).
- D5 — No acceptance grey area. A claim cannot be transmitted unless it is valid (clinical dataset complete, band coherent with treatment, exemption info present). Accepted follows deterministically; REJECTED is an exceptional data-error path (amend → resubmit), not a normal money-flow stage.
- D6 — Demo re-prep after the build (claims 214–218, the £95/£18.40 construct, and check-in-created data are re-created under the new flow).
[Booking] → nothing financial
[Reception check-in] → status ATTENDED only (no billing)
[Exam/plan] → CoT OPEN (band determined by charted treatment as it accrues)
FP17PR exemption status captured at intake (patient record)
[Treatment visits] → clinician charts items; clinician completes each appointment
[Course completed] → clinician closes the CoT →
NHS: FP17 generated (clinical dataset from charts; band from
banding engine; patient charge = statutory band charge
or £0-exempt) + patient-charge invoice/transaction
(non-exempt) raised + collectable
Private: price-list transaction/invoice raised
[Validate → Transmit]→ claim cannot leave DRAFT unless valid (D5)
[ACCEPTED] → UDA credit; NHS money via contract/schedule (D4) — NOT an
ERPNext invoice to an "NHS customer"
[REJECTED] → exceptional: error codes → amend → resubmit (D5)
Claim state machine (aligned with the FP17 research): OPEN/In-progress → COMPLETED → VALIDATED/Ready to send → TRANSMITTED → ACCEPTED | REJECTED, then reconciled against the NHS schedule (DCS127/129 concept) for UDA/contract tracking (Phase-6 UDA dashboard is the home for the NHS income side).
split_co_payment and the patient-co-pay construction (dental/fp17.py).
- The two-invoice ERPNext sync for claims (NHS_REIMBURSABLE + PATIENT_COPAY invoices; ACC-SINV-2026-00026/27/28 demo rows are legacy).
- Confirm-arrival billing (check-in no longer creates transactions/claims; keep attendance marking).
- The "£95 course / £18.40 co-pay" demo data and semantics.
- NHS_REIMBURSABLE invoice type usage (enum value may remain unused; decide deletion or retention for history).
- CoT entity (migration): patient, practice, open date (date of acceptance), band (derived/updated as items are charted), completion date, clinician/performer; appointments and chart entries linked to the course; one open NHS course per patient per band context (continuation rules = later phase).
- Banding engine: band from charted treatment list (per FP17 research): only exams/X-rays/scale-polish → Band 1; fillings/root-canal/extractions → Band 2; laboratory-fabricated items → Band 3; urgent flag; £0-charge-but-UDA treatments (arrest of bleeding, denture repairs) noted as edge cases.
- FP17PR / exemption capture at intake: exemption category code + evidence-seen flag on the patient record (drives £0 vs band charge).
- Clinical dataset completeness: claim generation requires BPE, decayed/missing counts, endodontic counts for B2/3 — derived from existing charting where possible (build_fp17_payload already aggregates chart markers).
- Charge application at course completion (moves from check-in): NHS → claim + patient-charge transaction/invoice (statutory band charge, or £0-exempt); Private → price-list transaction/invoice. Take Payment queue / record-payment now collect outstanding patient charges.
- ERPNext leg:
- Patient charges (NHS non-exempt + private) → Sales Invoices to the patient customer (mirrors the private-income decision; trigger = course completion). GBP precision fix on the sites is a prerequisite (see the 2026-09-08 417 bug note).
- NHS contract income is NOT per-claim invoiced to an "NHS customer"; it is tracked via claim acceptance/UDAs in the UDA module. Open question: whether/how ERPNext should represent schedule payments (e.g. periodic credit notes) — later phase, Matthew to decide.
- Claims list "Fee" column → shows total amount due for the claim (sum of its invoices; patient charge for NHS) — resolves the £0.00/£N/A bugs (total_nhs_fee population) and the £74.80-vs-£70.70 confusion class.
- NHS band charges table stays the source of statutory patient charges (2025/26 + 2026/27 rows already seeded and date-resolved).
- Phase 1 — CoT + completion billing: CoT entity/migration; clinician appointment-completion; course close → claim/charge creation at the new point; attendance no longer bills; banding engine; demo re-prep.
- Phase 2 — Charges & ERPNext truth: exemption capture (FP17PR); remove split/co-pay code paths and the two-invoice claim sync; patient-charge invoices to ERPNext (incl. private from D-this-morning); GBP precision site fix (dental + GP); claims-list amount fixes; retire NHS customer invoicing.
- Phase 3 — NHS income side (later): schedule reconciliation (DCS127/129 concept), continuation rules, urgent/free-repair edges, UDA dashboard £ integration (already partly built).
- Research: FP17 Claims (gp_booking_app)
- Live test plan: financial-billing-test-plan
- OpenCode inbox notes 2026-09-08: private income → ERPNext; 417 co-pay sync bugs (GBP precision + amount basis); this redesign.
- Doc impact (Hermes, after build, one page at a time): private-ledger-billing, co-payment-splitting (likely retired or rewritten), invoicing, fp17-claim-submission, uda-auditing + finance intro page.