Functional Weave
Code in TypeScript

agri.milk-price@1.0.0

README.md

2,148 bytes · view raw

# agri.milk-price

The price a dairy farmer is paid for one period's milk under a buyer's
contract: a base price for milk at standard constituents, adjusted for the
butterfat and protein actually delivered, plus a volume bonus and a seasonal
adjustment, and the payment for the litres collected.

Contracts differ between buyers and change often, so every term is supplied
by the caller in a `MilkContract`; nothing about any buyer is built in.

## Units

Prices are integers in **thousandths of a minor unit per litre**: 38.25 pence
per litre (ppl) is `38250`, 0.035 ppl is `35`. Buyers quote to 0.01 or 0.001
ppl, which a whole-penny price cannot hold and a float cannot hold exactly.
Constituents are in basis points of the milk: 4.12% butterfat is `412`.

## How it is worked out

1. **Butterfat and protein**: (actual - standard) in 0.1 percentage points,
   times the contract's value per 0.1%, pro rata. 4.20% butterfat against a
   4.00% standard at 0.25 ppl per 0.1% is +0.500 ppl. Each adjustment is
   rounded to a thousandth of a penny, half away from zero, so a deficit
   costs exactly what the same surplus earns.
2. **Volume bonus**: the tiers are in ascending order of `minimumLitres`; the
   highest tier the period's litres reach applies (not a sum of tiers). No
   tier reached, or no tiers, is 0.
3. **Seasonality**: twelve monthly adjustments, January first, and `month`
   picks one; an empty list means none.
4. The price per litre is the sum of the five components, and the payment is
   litres x price, rounded once, half up, to the minor unit.

A price that comes out negative is refused rather than paid.

## What it does not do

It does not apply hygiene or cell-count penalties, deductions (levies,
haulage, membership), a pence-per-kg-of-solids (A+B-C) schedule, or retrospective
price changes; model those as separate lines. Some contracts adjust per
complete 0.1% step rather than pro rata; this one is pro rata.

## Limits

Prices and adjustments within ±1,000,000 (±10 major units per litre), the
base and the final price from 0; constituents 0 to 10,000 basis points;
litres 0 to 1,000,000,000; month 1 to 12.