Part 4 of 7 · Recurring invoice generator series ~7 min read

How proration and tax get applied

Proration and tax are where invoices quietly go wrong — a half-month billed as a whole one, the wrong VAT rate for the customer’s country, a rounding penny that won’t reconcile. This post does one thing: walks a real invoice through proration and tax line by line, with the actual figures, so you can see exactly how the deterministic arithmetic lands — and why none of it is left to a model.

Key takeaways

  • Proration is a calendar-day calculation: a line is billed for the days it was active over the days in the cycle.
  • Tax is a lookup against the contract’s jurisdiction, applied to the net subtotal — UK 20%, Ireland 23%, a zero-rated state, and so on.
  • The rounding rule is stated once and applied everywhere: each line nets to the penny, tax rounds half-up on the subtotal.
  • Every figure is plain Python operating on the contract’s own numbers — reproducible by hand, never set by a model.
  • The full workings — the proration fraction, the rate used, every rounded figure — are written to the ledger alongside the invoice.

A real invoice, end to end

Proration and tax are where invoices quietly go wrong — a half-month billed as a whole one, the wrong VAT rate for the customer’s country, a stray penny that won’t reconcile against the ledger. The way to trust the arithmetic is to watch it run on a real case, so this whole post is one worked example, with the actual numbers.

The contract: a design studio bills a UK client a £1,500/month retainer, anchored to the 1st. On 16 June the client adds a second service line worth £600/month. It’s now 1 July, and the contract’s schedule has just fired the builder to produce the July invoice. The interesting part is that this invoice has to settle the half-month of June that the new line ran before the next clean cycle, as well as bill July normally.

Step one: proration for the mid-cycle change

The new £600 line started on 16 June, part-way through a cycle that had already been billed at £1,500 on 1 June. So that line owes a catch-up for the days it was active in June. Proration is a plain calendar-day fraction:

days active ÷ days in cycle × line price

June has 30 days. The line was active from the 16th to the 30th inclusive — 15 days. So the June catch-up is £600 × 15/30 = £300.00. The fraction is computed from real calendar days, not an assumed 30, so a line that starts mid-February or mid-July prorates against the correct month length. (Some businesses prefer a fixed 30-day month for retainers; that’s a one-line rule in the settings doc — the point is that it’s a stated, deterministic choice, not a guess.)

Step two: the lines on the July invoice

The builder gathers three lines for this invoice — the two full-month July lines and the one June catch-up:

LineWorkingNet
Monthly retainer — July£1,500 × 1£1,500.00
Additional service — July£600 × 1£600.00
Additional service — June (16–30, prorated)£600 × 15/30£300.00
Net subtotal£2,400.00

Each line is rounded to the penny first, then the lines are summed to the net subtotal. Rounding per line and then summing — rather than carrying fractions of a penny into the total — is the rule that keeps the printed lines adding up to the printed subtotal, which is the first thing anyone checks.

Step three: tax by jurisdiction

The customer’s jurisdiction on the contract is the United Kingdom, so the builder looks up the UK rate in the settings doc — VAT at 20% — and applies it to the net subtotal:

ComponentWorkingAmount
Net subtotal£2,400.00
VAT (UK, 20%)£2,400.00 × 0.20£480.00
Invoice total£2,880.00

Tax is applied to the net subtotal, rounded half-up to the nearest penny. The rate is never hard-coded — it’s read from the rules doc against the jurisdiction, so the same builder produces the right figure for a client anywhere you do business.

The worked example: three lines proration to net subtotal, then jurisdiction tax to the invoice total A left-to-right flow. On the left, three line boxes: monthly retainer for July at 1,500 pounds; additional service for July at 600 pounds; additional service prorated for June, 600 times 15 over 30, equals 300 pounds. The three feed into a Net subtotal box showing 2,400 pounds, with a note that each line is rounded to the penny first then summed. The net subtotal feeds a Tax step, which reads the jurisdiction (United Kingdom) and its rate (VAT 20 percent) from a rules-doc box, and applies 2,400 times 0.20 to get 480 pounds, rounded half-up. That feeds the Invoice total box showing 2,880 pounds. A side panel lists other jurisdictions and rates: Ireland 23 percent, a zero-rated US state 0 percent, illustrating that only the looked-up rate changes. A note reads: every figure is plain code on the contract’s own numbers, and the full workings are written to the ledger. Retainer — July £1,500.00 Add-on — July £600.00 Add-on — June (15/30) £300.00 Net subtotal £2,400.00 round each line, then sum + VAT (UK 20%) £480.00 Total £2,880.00 Rules doc — rate by jurisdiction same code, other rates: Ireland 23% zero-rated US state 0% Every figure is plain code on the contract’s own numbers; the full workings go to the ledger.
Fig 4. The July invoice end to end: three lines (two full, one prorated 15/30) sum to a £2,400.00 net subtotal; UK VAT at 20% adds £480.00 for a £2,880.00 total. Only the looked-up rate changes for another jurisdiction.

The same code, other jurisdictions

Nothing about the arithmetic changes when the customer is somewhere else — only the rate the builder looks up. The identical net subtotal of £2,400.00 produces £552.00 of tax for an Irish client (VAT 23%, total £2,952.00), and £0.00 of tax for a client in a US state that doesn’t tax this service (total £2,400.00). Because the rate lives in the rules doc keyed by jurisdiction, a rate change — or a new jurisdiction — is a doc edit, not a deploy, and it can never be quietly wrong in a way that only some invoices inherit. The one rule worth being strict about is that tax is computed from the jurisdiction on the contract, never inferred — if a contract’s jurisdiction is missing or unknown, the builder stops and flags it rather than guessing a rate.

Why none of this is a model’s job

It would be easy to hand a language model the contract and ask it to “work out the invoice”, and it would usually be right. “Usually right” is exactly the problem with money. Proration is a fraction; tax is a multiplication; rounding is a rule you state once. All three are reproducible by anyone with a calculator, which means an invoice can be defended, reconciled, and audited — and a wrong figure can be traced to a wrong input, not to a model that had an off day. So the builder writes every step into the ledger alongside the invoice: the proration fraction (15/30), the rate used (UK 20%), and each rounded figure. When the client asks why July was £2,880 and not the usual £1,800, the answer isn’t “the system decided” — it’s a three-line explanation anyone can check. That is the whole reason no model goes near the numbers.

Why this shape

  • Proration is calendar days. Active days over days in the cycle, against the real month length unless the rules doc says otherwise.
  • Tax is a lookup, not a guess. The rate comes from the contract’s jurisdiction; a missing jurisdiction stops the build.
  • Round once, the same way. Each line nets to the penny, then tax rounds half-up on the subtotal — so the printed figures add up.
  • The rate lives in a doc. New jurisdictions and rate changes are edits, never deploys.
  • The workings are saved. The fraction, the rate, and every rounded figure go to the ledger, so any invoice can be explained.
All posts