construction.day-rate-quote@1.0.0
impl/typescript.ts
1,847 bytes · the TypeScript implementation · view raw
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
import { markupPrice } from "./finance_markup_price.ts"; ← from finance.markup-price ^1.0.0 · built alongside by fune
import { addVat } from "./finance_tax_add_vat.ts"; ← from finance.tax.add-vat ^1.0.0 · built alongside by fune
import { roundDiv } from "./math_round_div.ts"; ← from math.round-div ^1.0.0 · built alongside by fune
import { addMoney } from "./money_add.ts"; ← from money.add ^1.0.0 · built alongside by fune
import { type Money, money } from "./money_amount.ts"; ← from money.amount ^1.0.0 · built alongside by fune
import { type DayRateQuote } from "./construction_day_rate_quote_types.ts";
/**
* A quote from labour days, a day rate, marked-up materials and VAT.
*
* The markup goes on the materials only: the day rate already is the price of
* labour. Labour is rounded once, to the penny, from days x rate; VAT is one
* rounding on the net total, as on the invoice that follows.
*/
export function dayRateQuote(
labourDaysHundredths: number,
dayRate: Money,
materialsCost: Money,
materialsMarkupBasisPoints: number,
vatCategory: string | null,
onDate: string
): DayRateQuote {
if (!Number.isInteger(labourDaysHundredths) || labourDaysHundredths < 0) {
throw new RangeError(`labourDaysHundredths must be a whole number of hundredths, not negative, received ${labourDaysHundredths}`);
}
if (dayRate.minor < 0) {
throw new RangeError(`dayRate must not be negative, received ${dayRate.minor}`);
}
const product = dayRate.minor * labourDaysHundredths;
if (!Number.isSafeInteger(product)) {
throw new RangeError("the labour calculation exceeds 2^53 - 1");
}
const labour = money(roundDiv(product, 100, "half-up"), dayRate.currency);
const materials = markupPrice(materialsCost, materialsMarkupBasisPoints, "markup", "half-up");
const net = addMoney(labour, materials);
if (vatCategory === null) {
return { labour, materials, net, vat: money(0, net.currency), gross: net, vatBasisPoints: 0 };
}
const vat = addVat(net, "GB", vatCategory, onDate);
return { labour, materials, net, vat: vat.tax, gross: vat.gross, vatBasisPoints: vat.basisPoints };
}