UNPKG

@eristack/tax

Version:

Tax code registry and effective-dated rates — math via @eristack/money Tax ops

100 lines (99 loc) • 2.67 kB
// src/core/errors.ts var TaxCodeNotFoundError = class extends Error { constructor(code) { super(`Tax code not registered: ${code}`); this.code = code; this.name = "TaxCodeNotFoundError"; } code; }; var TaxRateNotFoundError = class extends Error { constructor(code, asOf) { super(`No tax rate for code ${code} effective on or before ${asOf}`); this.code = code; this.asOf = asOf; this.name = "TaxRateNotFoundError"; } code; asOf; }; // src/core/registry.ts import { Tax } from "@eristack/money"; function normalizeWallDate(date) { const trimmed = date.trim(); if (!/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) { throw new Error(`Tax asOf must be wall date YYYY-MM-DD, got "${date}"`); } return trimmed; } function createTaxRegistry(initial) { const codes = /* @__PURE__ */ new Map(); const schedules = []; function registerTaxCode(entry) { const code = entry.code.trim(); if (!code) throw new Error("Tax code cannot be empty"); codes.set(code, { ...entry, code }); } function registerRateSchedule(entry) { const code = entry.code.trim(); if (!codes.has(code)) { throw new TaxCodeNotFoundError(code); } schedules.push({ ...entry, code, effectiveFrom: normalizeWallDate(entry.effectiveFrom), ratePercent: entry.ratePercent.trim() }); schedules.sort((a, b) => { const byCode = a.code.localeCompare(b.code); if (byCode !== 0) return byCode; return a.effectiveFrom.localeCompare(b.effectiveFrom); }); } for (const c of initial?.codes ?? []) registerTaxCode(c); for (const r of initial?.rates ?? []) registerRateSchedule(r); function resolveTaxRate(args) { const code = args.code.trim(); if (!codes.has(code)) { throw new TaxCodeNotFoundError(code); } const asOf = normalizeWallDate(args.asOf); let match; for (const row of schedules) { if (row.code !== code) continue; if (row.effectiveFrom <= asOf) { match = row; } else if (match) { break; } } if (!match) { throw new TaxRateNotFoundError(code, asOf); } return { code: match.code, effectiveFrom: match.effectiveFrom, ratePercent: match.ratePercent }; } function applyTaxToAmount(base, ratePercent) { return base.with(Tax.onExclusive(ratePercent)); } function listTaxCodes() { return [...codes.values()]; } return { registerTaxCode, registerRateSchedule, resolveTaxRate, applyTaxToAmount, listTaxCodes }; } export { TaxCodeNotFoundError, TaxRateNotFoundError, createTaxRegistry }; //# sourceMappingURL=index.js.map