UNPKG

@eristack/tax

Version:

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

129 lines (126 loc) • 3.84 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { TaxCodeNotFoundError: () => TaxCodeNotFoundError, TaxRateNotFoundError: () => TaxRateNotFoundError, createTaxRegistry: () => createTaxRegistry }); module.exports = __toCommonJS(index_exports); // 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 var import_money = require("@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(import_money.Tax.onExclusive(ratePercent)); } function listTaxCodes() { return [...codes.values()]; } return { registerTaxCode, registerRateSchedule, resolveTaxRate, applyTaxToAmount, listTaxCodes }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { TaxCodeNotFoundError, TaxRateNotFoundError, createTaxRegistry }); //# sourceMappingURL=index.cjs.map