Dentolize · Treasury & Step Payments Fixes Walkthrough
On this pageArea 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 sandbox

For 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

  1. 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.

  1. Save & verify posting: save the appointment; open the auto-created

invoice/payment and confirm it is tied to the selected treasury, not the default.

  1. Default untouched: select Collected but don't change the treasury.

Expect: the branch's default treasury is pre-filled and saves correctly.

  1. Switch treasuries twice: pick treasury A, reopen picker, pick treasury B.

Expect: field reflects B.

  1. Validation: with a required treasury empty, confirm the "required" error

shows, then clears once a treasury is chosen (shouldValidate: true).

Edge / regression cases

  1. 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.

  1. Web unchanged: repeat case 1 on the web app — treasury already

displayed; confirm no regression.

  1. 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

  1. 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.

  1. New step, operation fully unpaid: operation.paid = 0.

Expect: new step paid = 0.

  1. New step, already-allocated paid: existing steps' paid already sum to

operation.paid. Add another step. Expect: leftToPayForStep = 0 → new step paid = 0 (clamped at 0).

  1. 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).

  1. 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

  1. 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).

  1. Tax on the operation: same, with tax > 0.
  2. Rounding boundary: amounts where .toFixed() rounding could tip the

paid >= toPay comparison (e.g. 999.995). Confirm paid-in-full fires as intended.

  1. Insurance operations: operations with insurance and taxApplied;

confirm insurance step allocation (fromInvoice && insurance branch, paymentUtils.js:108-114) is unaffected.

  1. Null/undefined guards: step with paid = null. Confirm

Number(step.paid) || 0 treats it as 0 (addOperationStep.js:290).

Combined

  1. 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.