Amortance  ·  worked example  ·  dental  ·  the dealer one is here

A treatment plan, three changes to the order, and every number explained

A practice finances $3,600 of its own production over twelve months. Insurance lands differently than estimated, perio treatment is added in May, and an implant comes off the plan in October. That last event has two defensible readings, and they are $102.92 apart.

Nothing below is an adjustment typed into a ledger. Each change is an event on the order, the obligation is replayed from it, and every figure carries the rule and the inputs it came from. The data is synthetic; the mechanics are not. The complete input — order, terms, every posting — is published as a file, and the numbers here come from nothing else. Two of the rules are yours to switch as you read: the page recomputes in your browser, nothing is typed in and nothing leaves the page.

The order

CodeDescriptionFee Est. benefitPatient share
D2740Crown, porcelain/ceramic — #14 1,450.00435.001,015.00
D2740Crown, porcelain/ceramic — #15 1,450.00435.001,015.00
D6010Implant body, endosteal — #19 2,100.00315.001,785.00
D0367CBCT capture, both jaws 260.0075.00185.00
Total 5,260.001,260.004,000.00

The obligation is built from these four lines, not from a single total of $4,000. Everything further down this page follows from that one decision.

The terms

Every line above is an input, not a law of nature. The dealer example runs the same engine on actual/365, biweekly dates, and the opposite rule on change — there the payment holds and the term moves, because a buy-here-pay-here payment has to keep fitting a paycheck.

As signed, the instalment is $316.33 and the plan carries $195.97 of interest over its life:

DuePaymentInterestPrincipalBalance
2026-04-01316.3329.70286.633,313.37
2026-05-01316.3327.34288.993,024.38
2026-06-01316.3324.95291.382,733.00
2027-03-01316.342.59313.750.00

What happened

Event 1 — the adjudication

Policy: a correction of the patient's share, effective the date of service. The share was always $3,130; the estimate was wrong. Reading the same EOB effective when the money posts is an equally legitimate contract term — it is simply a different one, and it has to be written down before it can be honoured.

Instalment 1 was collected on 1 April and stays collected. The replay does not reverse it; it re-splits it against a principal that was $2,730.00 all along:

Instalment 1, 2026-04-01As chargedAs replayedDifference
Interest29.7022.52−7.18
Principal286.63293.817.18
Balance after3,313.372,436.19−877.18
$22.52 — interest, 2026-03-01 → 2026-04-01.
Rule: simple interest on outstanding principal, 30/360, no compounding, rounded half up at posting.
Inputs: principal $3,600.00 less $870.00 effective 2026-03-01; APR 9.90%; 30 days of 360.
$2,730.00 × 0.0990 × 30 ÷ 360 = $22.5225$22.52

From 1 May the instalment is repriced on the balance as it stands on 23 April: $2,436.19 plus $14.74 accrued, amortised over the eleven remaining dates → $233.99.

The repricing rule, stated in full, because this one has a tail. The instalment is the =PMT value on the balance and accrued interest as at the date of the event, at the nominal periodic rate, over the dates that remain. It does not discount the part-period before the next instalment separately, so the schedule is level everywhere except the end: with nothing further changing, the final instalment would fall to $217.87. A contract that wants the tail level instead prices it at $232.59 — the smallest cent whose repetition retires the balance without the last payment exceeding the others. Both are defensible. This page runs the first, and says which.

Event 2 — production added

Policy: effective the date performed. The practice extended credit for the perio treatment on 14 May, not in March, so this one does not reach back. Same engine, different effective date — which is the entire point of keeping the date on the event rather than in the code.

$238.00 joins the principal on 14 May; $7.94 of interest accrued over the 13 days before it and stays accrued until the next payment. From 1 June the instalment is $258.16 over the ten remaining dates.

Event 3 — production removed, and the fork

By 5 October the patient has paid $2,241.12: $400.00 down, $316.33, $233.99, then five instalments of $258.16. With the implant off the plan, the corrected patient share is $1,583.00. The plan has collected $658.12 more than the order now contains.

Two readings, both defensible, and they are not worth the same money:

A — effective today

The credit facility existed and the patient had it; interest already charged stands. Principal goes to zero on 5 October, the $1.38 accrued since the last payment is settled out of the credit.

Interest charged over the life124.81
Plan closes2026-10-05
Due back to the patient533.31

B — effective at origination

The implant was never performed, so it was never owed. The plan financed it from acceptance on 1 March — the date the credit arose, not a date of service — so the replay removes it from there. Whether a plan should carry planned treatment from acceptance at all, or pick it up only when it is done, is itself a setting; Open Dental exposes that exact choice. Replayed, the plan was paid off at instalment 5, and instalments 6 and 7 met a zero balance.

Interest charged over the life21.89
Plan closes2026-08-01
Due back to the patient636.23

The gap is $102.92, and every cent of it is interest charged on production that was never performed. It is also two different answers to "when did this plan end" — August or October — which is the version the bookkeeper closes the month on.

Neither reading is a bug. Which one runs is a term of the practice's contract. What an engine owes you is that it runs the one the contract names, returns the same number every time, and can still say which rule it used when someone asks eighteen months later.

What the incumbents document

Open Dental — the deepest engine in the category, and the one that documents itself best — states the forward-only rule outright: insurance payments or adjustments applied after a plan was created "automatically update future PayPlan Charges." Future charges only. The same manual notes that automatic changes caused by insurance estimate changes or procedure adjustments "are not tracked in the Audit Trail," and suggests keeping a printout of the original plan. It also ships a separate report whose whole job is to find plans that have charged more than the production behind them. (Open Dental manual, Dynamic Payment Plans.)

One vertical over, the disclosure itself is a sold feature: TouchNet's tuition plans "automatically adjust the plan installments, save a complete disclosure reflecting plan changes, and notify the user" — and there too the adjustment runs forward only, with a lock window before the next instalment. (TouchNet, payment plans.)

Forward-only is a perfectly defensible policy, and for many practices it is the right one. Forward-only by default, unrecorded, is not a policy — it is an accident of implementation that someone has to defend to a patient.

Check it yourself

The engine is a pure function of the terms and the event log: same inputs, same numbers, on any machine, including for periods already past. The block below is a summary of the state you are looking at. dental.json is the whole of it — the order line by line, every convention named, the posting log, and the expected outputs for all four policy sets these controls select. That file is generated from the same engine this page runs; the page does not read it back, so it is a published input, not a source of truth about itself. What makes it worth anything is verify.py: a second implementation written from the specification rather than shared with the engine. Save it next to the file and run python3 verify.py; it checks whichever of the two specifications it finds beside it, and either one on its own is enough.

{
  "terms": {
    "apr": "0.0990",
    "day_count": "30/360",
    "compounding": "none",
    "periods": 12,
    "first_due": "2026-04-01",
    "amount_financed": "3600.00",
    "instalment_as_signed": "316.33",
    "on_change": "dates hold, instalment moves",
    "allocation": "accrued interest, then principal"
  },
  "events": [
    { "on": "2026-04-23", "type": "adjudication",
      "patient_share": "-870.00", "policy": "the date of service" },
    { "on": "2026-05-14", "type": "production_added",
      "patient_share": "238.00", "policy": "the date performed" },
    { "on": "2026-10-05", "type": "production_removed",
      "patient_share": "-1785.00", "policy": "POLICY FORK" }
  ],
  "expected": {
    "instalment_after_adjudication": "233.99",
    "instalment_after_addition": "258.16",
    "paid_to_date": "2,241.12",
    "corrected_patient_share": "1,583.00",
    "A_effective_today": { "interest_charged": "124.81", "credit_due_patient": "533.31" },
    "B_effective_at_origination": { "interest_charged": "21.89", "credit_due_patient": "636.23" }
  }
}

If your numbers come out differently, the disagreement is in a named rule — the day count, the allocation order, the effective date, the rounding step — and that is a conversation worth having before anyone integrates anything.


Amortance computes obligations for platforms whose merchants finance their own sales. It does not move money, hold borrower identity data, or make credit decisions. What it is · the same engine on a buy-here-pay-here deal.

If your platform carries practice-financed plans: when the order changes after the plan starts, which of these two readings does your ledger run, and where is that choice written down? I would rather have the answer in writing than on a call — hello@amortance.com.