Functional Weave
Code in Rust

payroll.net-to-gross@1.0.2

README.md

3,147 bytes · view raw

# payroll.net-to-gross

Status: needs review by a qualified payroll professional before it is published.

Grossing up: the gross pay that gives an employee at least a target take-home
pay in one period, with everything else about them as for
`payroll.gross-to-net` (the `gross` in `input` is ignored).

## Why a search

Net pay has no clean inverse. Tax is charged on whole pounds, student loans
are rounded down to whole pounds, pension and National Insurance thresholds
switch on and off, and the income tax band a penny falls in depends on the
year to date. Algebra that inverts the rates works for the middle of a band
and is a penny or a pound out at every edge. So this runs `grossToNet` itself
and searches.

The search is a plain bisection on whole pence: start at 0 and at the target,
double the upper bound until its net reaches the target, then halve the gap
until it is one penny. Every step is integer arithmetic with fixed midpoints,
so the three languages take identical steps and return identical answers.

## What "the" answer is

The result is a gross `G` whose net is at least the target and where `G - 1p`
nets less than the target. Net pay does not only ever rise with gross: tax is
charged on whole pounds of taxable pay, so the penny that takes taxable pay
into the next pound adds 20p or more of tax and net pay dips; one more penny
can also cost a whole pound of student loan. Where the target sits clear of
those dips (the usual case, and every vector here) `G` is the smallest gross
that reaches it. Where it falls inside one, the bisection still returns a
penny-exact boundary, but a smaller gross elsewhere could also reach the
target, and the net may exceed the target by up to about £1. Check `net` on the
returned payslip rather than assuming it equals the target.

If a tax refund makes the net at zero gross already reach the target, the
payslip for zero gross is returned. The search refuses to look above
£10,000,000 for one period.

Sources: as `payroll.gross-to-net`.

1.0.1 adds tests; behaviour unchanged.

## Before you rely on this

**Not professional advice.** This capability calculates payroll figures from published rules. It is a software component for developers, not tax or legal advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have a payroll professional review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.

**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified payroll professional has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.

1.0.2 marks it unreviewed. The code and the tests are unchanged.