On this page
Area 1 — Treasury persists on diagnostic fee (mobile)Area 2 — Step-payment allocation & paid-in-full (server)Non-goals to verify (negative tests)Reference data in the sandboxFor Quality
What to test, and where the edges are. Two independent fixes — test them separately, then together.
Area 1 — Treasury persists on diagnostic fee (mobile)
Files: NewAppointmentScreen.js:445-460, with root cause in SelectScreen.js:151-160 and rendering in TreasuryField.js.
Core cases
- Happy path (mobile): New Appointment → Diagnostic Fees → Collected →
open the Treasury picker → select a non-default treasury. Expect: the chosen treasury shows in the field and stays after the picker closes.
- Save & verify posting: save the appointment; open the auto-created
invoice/payment and confirm it is tied to the selected treasury, not the default.
- Default untouched: select Collected but don't change the treasury.
Expect: the branch's default treasury is pre-filled and saves correctly.
- Switch treasuries twice: pick treasury A, reopen picker, pick treasury B.
Expect: field reflects B.
- Validation: with a required treasury empty, confirm the "required" error
shows, then clears once a treasury is chosen (shouldValidate: true).
Edge / regression cases
- Other pickers still work: confirm the same effect still handles
doctor and room correctly (they use setDoctor / setRoom plus the generic setValue branch) — the fix added a treasury branch alongside them.
- Web unchanged: repeat case 1 on the web app — treasury already
displayed; confirm no regression.
- Edit vs. create: open an existing appointment and change the treasury;
confirm it persists.
Area 2 — Step-payment allocation & paid-in-full (server)
Files: addOperationStep.js:285-293 (new step paid), paymentUtils.js:206 & :214-224 (paid-in-full check).
Core cases
- New step, operation already partly paid: operation with total > 0,
paid > 0, one or more existing steps. Add a new step. Expect: new step's paid = min(operation.paid − Σ existing steps.paid, step's own toPay) — not a proportional slice. Σ of all steps' paid must never exceed operation.paid.
- New step, operation fully unpaid:
operation.paid = 0.
Expect: new step paid = 0.
- New step, already-allocated paid: existing steps'
paidalready sum to
operation.paid. Add another step. Expect: leftToPayForStep = 0 → new step paid = 0 (clamped at 0).
- Pay off a multi-step operation: apply a payment that clears the balance.
Expect: one stepPayment record per settled step (no spurious extra record); operation and steps flip to Paid in Full (paymentUtils.js:226-236).
- Doctor commission: on the settling payment, confirm the
salaryAdjustment is created for the doctor on the paid step(s) (paymentUtils.js:160-176) — full commission, not half.
Edge cases — this is where it breaks
- Discount on the operation: operation with a real
discount. Confirm
paid-in-full uses operation.total − operation.discount + operation.tax (paymentUtils.js:217), so the operation is marked paid at the right amount — the exact value that was wrong before (it used the step's discount/tax).
- Tax on the operation: same, with
tax> 0. - Rounding boundary: amounts where
.toFixed()rounding could tip the
paid >= toPay comparison (e.g. 999.995). Confirm paid-in-full fires as intended.
- Insurance operations: operations with
insuranceandtaxApplied;
confirm insurance step allocation (fromInvoice && insurance branch, paymentUtils.js:108-114) is unaffected.
- Null/undefined guards: step with
paid = null. Confirm
Number(step.paid) || 0 treats it as 0 (addOperationStep.js:290).
Combined
- Add step then pay: partly-paid operation → add a step → take a payment
that clears it. End state: honest per-step paid, single records, paid in full, full commission.
Non-goals to verify (negative tests)
- No retroactive correction: payments recorded before the fix should be
unchanged. Confirm the deploy does not rewrite historical records.
- No schema change: confirm no migration ships with this PR.
Reference data in the sandbox
- Patient 006 (
Cash · VAT-Exempt) has operations with Pulses / Sessions
(Composite veneer, Socket Preservation) — a starting point for Area 2.
- Invoices #6 (2,000 / 300 paid) and #7 (insured 60%) are handy Add-Payment
targets, including an insured case for edge testing.