@happyvertical/smrt-commerce 0.57.2 → 0.57.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +17 -0
- package/README.md +130 -0
- package/agents/accounting-snapshot-mapper.md +11 -0
- package/agents/contract-billing-schedules.md +67 -0
- package/agents/contract-money.md +81 -0
- package/agents/customer-funds.md +96 -0
- package/agents/historical-sales.md +132 -0
- package/agents/money-calculator.md +36 -0
- package/agents/money-model.md +6 -3
- package/agents/observed-purchase-prices.md +37 -0
- package/agents/payment-allocations.md +59 -0
- package/agents/received-sales-contract-money.md +38 -0
- package/dist/accounting-snapshot.d.ts +8 -1
- package/dist/accounting-snapshot.d.ts.map +1 -1
- package/dist/allocation-integrity.d.ts.map +1 -1
- package/dist/billing/period-close.d.ts.map +1 -1
- package/dist/chunks/{ContractLineItemCollection-BZcrlrrY.js → ContractLineItemCollection-J4xtRtzE.js} +6 -6
- package/dist/chunks/{ContractLineItemCollection-BZcrlrrY.js.map → ContractLineItemCollection-J4xtRtzE.js.map} +1 -1
- package/dist/chunks/DocumentTaxCollection-C42x0YLW.js +4385 -0
- package/dist/chunks/DocumentTaxCollection-C42x0YLW.js.map +1 -0
- package/dist/chunks/HistoricalCustomerFundsCollections-B5x8gTW3.js +170 -0
- package/dist/chunks/HistoricalCustomerFundsCollections-B5x8gTW3.js.map +1 -0
- package/dist/chunks/{InvoiceCollection-cinzAqt6.js → InvoiceCollection-BIcge9Wl.js} +131 -18
- package/dist/chunks/InvoiceCollection-BIcge9Wl.js.map +1 -0
- package/dist/chunks/{TaxCodeCollection-DaBOPG9c.js → TaxCodeCollection-RWdVaheF.js} +3 -4
- package/dist/chunks/TaxCodeCollection-RWdVaheF.js.map +1 -0
- package/dist/chunks/{TaxComponentCollection-C4zxnyVu.js → TaxComponentCollection-Dt2jeWiC.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-C4zxnyVu.js.map → TaxComponentCollection-Dt2jeWiC.js.map} +1 -1
- package/dist/chunks/{allocation-integrity-WmWyXhtG.js → allocation-integrity-DJ7-LY1j.js} +7 -7
- package/dist/chunks/{allocation-integrity-WmWyXhtG.js.map → allocation-integrity-DJ7-LY1j.js.map} +1 -1
- package/dist/chunks/{contract-money-EuToOghh.js → contract-money-DSRTMoXm.js} +45 -12
- package/dist/chunks/contract-money-DSRTMoXm.js.map +1 -0
- package/dist/chunks/customer-funds-internal-BQzoJXK5.js +24 -0
- package/dist/chunks/customer-funds-internal-BQzoJXK5.js.map +1 -0
- package/dist/chunks/{detect-CY9ufaFb.js → detect-DAE-_NAk.js} +5 -2
- package/dist/chunks/{detect-CY9ufaFb.js.map → detect-DAE-_NAk.js.map} +1 -1
- package/dist/chunks/historical-commerce-internal-C9ButfuH.js +18 -0
- package/dist/chunks/historical-commerce-internal-C9ButfuH.js.map +1 -0
- package/dist/chunks/{invoice-posting-C2i5dOVZ.js → invoice-posting-BeTPw3h9.js} +5 -5
- package/dist/chunks/invoice-posting-BeTPw3h9.js.map +1 -0
- package/dist/chunks/retention-accounting-Brdj9x-V.js +2323 -0
- package/dist/chunks/retention-accounting-Brdj9x-V.js.map +1 -0
- package/dist/chunks/retention-accounting-internal-CBQRvd74.js +17 -0
- package/dist/chunks/retention-accounting-internal-CBQRvd74.js.map +1 -0
- package/dist/chunks/{tenant-money-barrier-6TlqUeVj.js → tenant-money-barrier-DoF6lR8h.js} +5 -5
- package/dist/chunks/{tenant-money-barrier-6TlqUeVj.js.map → tenant-money-barrier-DoF6lR8h.js.map} +1 -1
- package/dist/chunks/types-Bbm0Xflc.js.map +1 -1
- package/dist/collections/DocumentTaxCollection.d.ts +4 -1
- package/dist/collections/DocumentTaxCollection.d.ts.map +1 -1
- package/dist/collections/HistoricalCustomerFundsCollections.d.ts +10 -0
- package/dist/collections/HistoricalCustomerFundsCollections.d.ts.map +1 -0
- package/dist/collections/HistoricalSalesLineCollection.d.ts +6 -0
- package/dist/collections/HistoricalSalesLineCollection.d.ts.map +1 -0
- package/dist/collections/PaymentAllocationCollection.d.ts +2 -6
- package/dist/collections/PaymentAllocationCollection.d.ts.map +1 -1
- package/dist/collections/PurchasePriceObservationCollection.d.ts +6 -0
- package/dist/collections/PurchasePriceObservationCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/contract-billing-schedule.d.ts +83 -0
- package/dist/contract-billing-schedule.d.ts.map +1 -0
- package/dist/contract-money.d.ts +2 -0
- package/dist/contract-money.d.ts.map +1 -1
- package/dist/customer-funds-internal.d.ts +6 -0
- package/dist/customer-funds-internal.d.ts.map +1 -0
- package/dist/customer-funds.d.ts +108 -0
- package/dist/customer-funds.d.ts.map +1 -0
- package/dist/document-money.d.ts +11 -0
- package/dist/document-money.d.ts.map +1 -1
- package/dist/historical-commerce-internal.d.ts +3 -0
- package/dist/historical-commerce-internal.d.ts.map +1 -0
- package/dist/historical-customer-funds-types.d.ts +113 -0
- package/dist/historical-customer-funds-types.d.ts.map +1 -0
- package/dist/historical-customer-funds.d.ts +23 -0
- package/dist/historical-customer-funds.d.ts.map +1 -0
- package/dist/historical-funds-internal.d.ts +5 -0
- package/dist/historical-funds-internal.d.ts.map +1 -0
- package/dist/historical-sales-money.d.ts +22 -0
- package/dist/historical-sales-money.d.ts.map +1 -0
- package/dist/historical-sales-reports.d.ts +31 -0
- package/dist/historical-sales-reports.d.ts.map +1 -0
- package/dist/historical-sales-types.d.ts +106 -0
- package/dist/historical-sales-types.d.ts.map +1 -0
- package/dist/historical-sales-validation.d.ts +12 -0
- package/dist/historical-sales-validation.d.ts.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1685 -1640
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts +0 -1
- package/dist/invoice-accounting-sync.d.ts.map +1 -1
- package/dist/invoice-mcp.d.ts.map +1 -1
- package/dist/invoice-posting.d.ts.map +1 -1
- package/dist/invoice-retention.d.ts +16 -0
- package/dist/invoice-retention.d.ts.map +1 -0
- package/dist/invoices.d.ts +2 -0
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +2 -2
- package/dist/manifest.json +7563 -4419
- package/dist/models/Contract.d.ts +14 -0
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/DocumentTax.d.ts +2 -0
- package/dist/models/DocumentTax.d.ts.map +1 -1
- package/dist/models/HistoricalCustomerFunds.d.ts +36 -0
- package/dist/models/HistoricalCustomerFunds.d.ts.map +1 -0
- package/dist/models/HistoricalCustomerFundsAllocation.d.ts +32 -0
- package/dist/models/HistoricalCustomerFundsAllocation.d.ts.map +1 -0
- package/dist/models/HistoricalSalesLine.d.ts +29 -0
- package/dist/models/HistoricalSalesLine.d.ts.map +1 -0
- package/dist/models/Invoice.d.ts +10 -1
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/Payment.d.ts +7 -1
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/PaymentAllocation.d.ts +3 -1
- package/dist/models/PaymentAllocation.d.ts.map +1 -1
- package/dist/models/PaymentIntent.d.ts.map +1 -1
- package/dist/models/Payout.d.ts.map +1 -1
- package/dist/models/PurchasePriceObservation.d.ts +15 -0
- package/dist/models/PurchasePriceObservation.d.ts.map +1 -0
- package/dist/models/TaxCode.d.ts +1 -1
- package/dist/models/TaxCode.d.ts.map +1 -1
- package/dist/models/index.d.ts +1 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/money.d.ts +5 -1
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +62 -15
- package/dist/money.js.map +1 -1
- package/dist/observed-purchase-price-internal.d.ts +3 -0
- package/dist/observed-purchase-price-internal.d.ts.map +1 -0
- package/dist/observed-purchase-price.d.ts +71 -0
- package/dist/observed-purchase-price.d.ts.map +1 -0
- package/dist/received-purchase-money.d.ts +87 -0
- package/dist/received-purchase-money.d.ts.map +1 -0
- package/dist/recipes.d.ts +4 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/retention-accounting-internal.d.ts +3 -0
- package/dist/retention-accounting-internal.d.ts.map +1 -0
- package/dist/retention-accounting.d.ts +164 -0
- package/dist/retention-accounting.d.ts.map +1 -0
- package/dist/retention-money.d.ts +43 -0
- package/dist/retention-money.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +1866 -113
- package/dist/tax/cookbook.d.ts.map +1 -1
- package/dist/tax-summary.d.ts +1 -0
- package/dist/tax-summary.d.ts.map +1 -1
- package/dist/types/index.d.ts +20 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +16 -16
- package/dist/chunks/CustomerCollection-BIPH2ZUx.js +0 -99
- package/dist/chunks/CustomerCollection-BIPH2ZUx.js.map +0 -1
- package/dist/chunks/DocumentTaxCollection-DDzlywMW.js +0 -1666
- package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +0 -1
- package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +0 -1
- package/dist/chunks/TaxCodeCollection-DaBOPG9c.js.map +0 -1
- package/dist/chunks/VendorCollection-D6ZcUYy8.js +0 -100
- package/dist/chunks/VendorCollection-D6ZcUYy8.js.map +0 -1
- package/dist/chunks/calculations-C9daQLsh.js +0 -82
- package/dist/chunks/calculations-C9daQLsh.js.map +0 -1
- package/dist/chunks/contract-money-EuToOghh.js.map +0 -1
- package/dist/chunks/document-money-DV5t4vlK.js +0 -1186
- package/dist/chunks/document-money-DV5t4vlK.js.map +0 -1
- package/dist/chunks/invoice-posting-C2i5dOVZ.js.map +0 -1
package/dist/money.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.js","names":["tax"],"sources":["../src/money.ts"],"sourcesContent":["/** Exact, transport-neutral commercial document money calculation. */\n\nimport { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport {\n allocateSignedRationals,\n roundSignedRational,\n} from './money-rational.js';\n\n/** Throw unless every named model value is a finite integer minor-unit amount. */\nexport function assertIntegerMinorUnits(\n context: string,\n label: string,\n entries: ReadonlyArray<readonly [string, number]>,\n): void {\n for (const [field, value] of entries) {\n if (!Number.isFinite(value) || !Number.isInteger(value)) {\n throw new Error(\n `${context} ${label}: ${field} must be an integer number of minor ` +\n `units (cents, satoshis) — got ${value}. Money is exact: $19.99 is ` +\n '1999, not 19.99.',\n );\n }\n }\n}\n\nexport type LineAmountType = 'exclusive' | 'inclusive' | 'none';\nexport type TaxRoundingScope = 'line' | 'document';\nexport type TaxCodeKind = 'taxable' | 'zero-rated' | 'exempt' | 'out-of-scope';\nexport type TaxCodeAppliesTo = 'sales' | 'purchases' | 'both';\n\nexport type MoneyValidationCode =\n | 'DISCOUNT_BOTH_FORMS'\n | 'DISCOUNT_EXCEEDS_GROSS'\n | 'DISCOUNT_SIGN'\n | 'PERCENT_OUT_OF_RANGE'\n | 'COMPOUND_UNSUPPORTED'\n | 'INVALID_MONEY_INPUT'\n | 'TAX_CODE_DUPLICATE_COMPONENT'\n | 'TAX_CODE_KIND'\n | 'TAX_CODE_NON_TAXABLE_COMPONENTS'\n | 'TAX_CODE_NOT_FOUND'\n | 'TAX_CODE_TAXABLE_EMPTY'\n | 'TAX_COMPONENT_RATE_CONFLICT'\n | 'TAX_CODE_INACTIVE'\n | 'TAX_CODE_SCOPE'\n | 'UNSAFE_MONEY'\n | 'FROZEN_DOCUMENT'\n | 'CURRENCY_MISMATCH'\n | 'ACCOUNTING_SYNC_IN_PROGRESS'\n | 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED'\n | 'ACCOUNTING_SYNC_UNSUPPORTED'\n | 'CREDIT_EXCEEDS_LINE'\n | 'CREDIT_TARGET_NOT_ISSUED';\n\n/** Stable validation error shared by model, editor, and transport adapters. */\nexport class MoneyValidationError extends Error {\n override readonly name = 'MoneyValidationError';\n /** Explicit marker consumed by public transports that preserve typed errors. */\n readonly publicMessage: string;\n\n constructor(\n readonly code: MoneyValidationCode,\n message: string,\n ) {\n super(message);\n this.publicMessage = message;\n }\n}\n\nexport interface TaxComponentInput {\n taxComponentId: string;\n /** Exact percent: \"7\" means 7%; at most six fractional digits. */\n percent: string;\n compound: boolean;\n}\n\nexport interface MoneyTaxCodeInput {\n id: string;\n kind: TaxCodeKind;\n components: readonly TaxComponentInput[];\n}\n\nexport interface ResolvableTaxCodeInput extends MoneyTaxCodeInput {\n active: boolean;\n appliesTo: TaxCodeAppliesTo;\n}\n\nexport type MoneyDiscountInput =\n | { kind: 'none' }\n | { kind: 'percent'; rate: string }\n | { kind: 'amount'; minor: number };\n\nexport interface MoneyLineInput {\n id: string;\n /** Nonnegative decimal quantity with at most six fractional digits. */\n quantity: number;\n /** Signed safe integer minor units. */\n unitPrice: number;\n discount: MoneyDiscountInput;\n /** Explicit tax-exclusive basis for credit-note amount allocations. */\n netAmountMinor?: number;\n /** Null means no code resolved; `none` pricing requires an out-of-scope code. */\n taxCode: MoneyTaxCodeInput | null;\n}\n\nexport interface MoneyLineResult {\n id: string;\n grossMinor: number;\n discountMinor: number;\n amountMinor: number;\n components: { taxComponentId: string; taxMinor: number }[];\n taxMinor: number;\n netMinor: number;\n}\n\nexport interface MoneyDocumentTaxResult {\n /** Null records an unassigned line without inventing a persisted tax-code ID. */\n taxCodeId: string | null;\n taxComponentId: string | null;\n taxableMinor: number;\n taxMinor: number;\n}\n\nexport interface MoneyDocumentResult {\n lines: MoneyLineResult[];\n subtotalMinor: number;\n discountTotalMinor: number;\n taxMinor: number;\n totalMinor: number;\n taxes: MoneyDocumentTaxResult[];\n}\n\nexport type TaxCodeResolutionSource =\n | 'line'\n | 'exempt-customer'\n | 'product'\n | 'customer'\n | 'app'\n | 'none';\n\nexport interface ResolveLineTaxCodeInput {\n lineAmountType: LineAmountType;\n lineOverride?: string | null;\n}\n\nexport interface ResolveLineTaxCodeContext {\n direction: 'sales' | 'purchases';\n codes: Readonly<Record<string, ResolvableTaxCodeInput>>;\n customerTaxExempt: boolean;\n exemptCodeId?: string | null;\n productCodeId?: string | null;\n partyCodeId?: string | null;\n appDefaultCodeId?: string | null;\n outOfScopeCodeId?: string | null;\n}\n\nexport interface ResolvedLineTaxCode {\n taxCode: ResolvableTaxCodeInput | null;\n source: TaxCodeResolutionSource;\n}\n\nconst PERCENT_SCALE = 1_000_000n;\nconst PERCENT_DENOMINATOR = 100n * PERCENT_SCALE;\nconst MAX_SAFE_MONEY = BigInt(Number.MAX_SAFE_INTEGER);\nconst IDENTIFIER = /^\\S(?:.*\\S)?$/;\n\nfunction validationError(code: MoneyValidationCode, message: string): never {\n throw new MoneyValidationError(code, message);\n}\n\nfunction assertIdentifier(value: string, label: string): void {\n if (typeof value !== 'string' || !IDENTIFIER.test(value))\n validationError(\n 'INVALID_MONEY_INPUT',\n `${label} must be a nonempty string`,\n );\n}\n\nfunction safeMoney(value: bigint): number {\n if (value > MAX_SAFE_MONEY || value < -MAX_SAFE_MONEY)\n validationError('UNSAFE_MONEY', 'Money exceeds safe integer minor units');\n return Number(value);\n}\n\nfunction money(value: number): bigint {\n if (!Number.isSafeInteger(value))\n validationError('UNSAFE_MONEY', 'Money must be safe integer minor units');\n return BigInt(value);\n}\n\ninterface ExactDecimal {\n coefficient: bigint;\n scale: bigint;\n}\n\nfunction numberDecimal(value: number, precision: number): ExactDecimal {\n if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity is outside the supported range',\n );\n const [mantissa, exponentText = '0'] = value.toString().split('e');\n const [whole, fraction = ''] = mantissa.split('.');\n const places = fraction.length - Number(exponentText);\n if (places > precision)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity exceeds the supported decimal precision',\n );\n const coefficient = BigInt(whole + fraction);\n return places < 0\n ? { coefficient: coefficient * 10n ** BigInt(-places), scale: 1n }\n : { coefficient, scale: 10n ** BigInt(places) };\n}\n\nfunction percentUnits(value: string): bigint {\n if (\n typeof value !== 'string' ||\n !/^(?:0|[1-9]\\d{0,2})(?:\\.\\d{1,6})?$/.test(value)\n )\n validationError(\n 'PERCENT_OUT_OF_RANGE',\n 'Percent must be an exact decimal from 0 through 100 with at most six fractional digits',\n );\n const [whole, fraction = ''] = value.split('.');\n const units = BigInt(whole) * PERCENT_SCALE + BigInt(fraction.padEnd(6, '0'));\n if (units > PERCENT_DENOMINATOR)\n validationError('PERCENT_OUT_OF_RANGE', 'Percent exceeds 100');\n return units;\n}\n\nfunction validateTaxCode(\n code: MoneyTaxCodeInput,\n rates: Map<string, bigint>,\n): { taxComponentId: string; rate: bigint }[] {\n if (!code || typeof code !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax code must be an object');\n assertIdentifier(code.id, 'Tax code ID');\n if (\n code.kind !== 'taxable' &&\n code.kind !== 'zero-rated' &&\n code.kind !== 'exempt' &&\n code.kind !== 'out-of-scope'\n )\n validationError('TAX_CODE_KIND', 'Unknown tax code kind');\n if (!Array.isArray(code.components))\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax code components must be an array',\n );\n if (code.kind === 'taxable' && code.components.length === 0)\n validationError(\n 'TAX_CODE_TAXABLE_EMPTY',\n 'Taxable codes require at least one component',\n );\n if (code.kind !== 'taxable' && code.components.length !== 0)\n validationError(\n 'TAX_CODE_NON_TAXABLE_COMPONENTS',\n 'Non-taxable codes cannot contain components',\n );\n const seen = new Set<string>();\n return code.components.map((component) => {\n if (!component || typeof component !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax component must be an object');\n assertIdentifier(component.taxComponentId, 'Tax component ID');\n if (seen.has(component.taxComponentId))\n validationError(\n 'TAX_CODE_DUPLICATE_COMPONENT',\n 'Duplicate tax component within code',\n );\n seen.add(component.taxComponentId);\n if (typeof component.compound !== 'boolean')\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component compound must be boolean',\n );\n if (component.compound)\n validationError(\n 'COMPOUND_UNSUPPORTED',\n 'Compound tax components are not supported',\n );\n const rate = percentUnits(component.percent);\n const existing = rates.get(component.taxComponentId);\n if (existing !== undefined && existing !== rate)\n validationError(\n 'TAX_COMPONENT_RATE_CONFLICT',\n 'Shared tax component has conflicting percentages',\n );\n rates.set(component.taxComponentId, rate);\n return { taxComponentId: component.taxComponentId, rate };\n });\n}\n\nfunction discountFor(gross: bigint, discount: MoneyDiscountInput): bigint {\n if (!discount || typeof discount !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Discount must be a tagged object');\n const runtime = discount as MoneyDiscountInput & {\n rate?: unknown;\n minor?: unknown;\n };\n if (runtime.rate !== undefined && runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A discount cannot include both percent and amount forms',\n );\n let result: bigint;\n if (discount.kind === 'none') {\n if (runtime.rate !== undefined || runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A none discount cannot include percent or amount values',\n );\n result = 0n;\n } else if (discount.kind === 'percent') {\n result = roundSignedRational(\n gross * percentUnits(discount.rate),\n PERCENT_DENOMINATOR,\n );\n } else if (discount.kind === 'amount') {\n result = money(discount.minor);\n } else {\n validationError('INVALID_MONEY_INPUT', 'Unknown discount kind');\n }\n if (result !== 0n && gross !== 0n && result < 0n !== gross < 0n)\n validationError(\n 'DISCOUNT_SIGN',\n 'Discount amount must carry the sign of gross',\n );\n if (gross === 0n && result !== 0n)\n validationError('DISCOUNT_SIGN', 'A zero gross cannot carry a discount');\n const magnitude = (value: bigint) => (value < 0n ? -value : value);\n if (magnitude(result) > magnitude(gross))\n validationError('DISCOUNT_EXCEEDS_GROSS', 'Discount cannot exceed gross');\n return result;\n}\n\nfunction validateDocumentInput(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): void {\n if (!input || typeof input !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money input must be an object');\n if (\n typeof input.currency !== 'string' ||\n !/^[A-Z]{3}$/.test(input.currency) ||\n !ISO_4217_MINOR_UNITS.has(input.currency) ||\n ISO_4217_MINOR_UNITS.get(input.currency) === null\n )\n validationError(\n 'CURRENCY_MISMATCH',\n 'Currency must be a supported uppercase ISO 4217 code with minor units',\n );\n if (\n input.lineAmountType !== 'exclusive' &&\n input.lineAmountType !== 'inclusive' &&\n input.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (input.roundingScope !== 'line' && input.roundingScope !== 'document')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax rounding scope');\n if (!Array.isArray(input.lines))\n validationError('INVALID_MONEY_INPUT', 'Lines must be an array');\n}\n\n/** Calculate exact line amounts, per-component tax, and document totals. */\nexport function calculateMoneyDocument(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): MoneyDocumentResult {\n validateDocumentInput(input);\n const ids = new Set<string>();\n const rates = new Map<string, bigint>();\n const working = input.lines.map((line) => {\n if (!line || typeof line !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money line must be an object');\n assertIdentifier(line.id, 'Line ID');\n if (ids.has(line.id))\n validationError('INVALID_MONEY_INPUT', 'Duplicate money line ID');\n ids.add(line.id);\n const explicitNet =\n line.netAmountMinor === undefined ? null : money(line.netAmountMinor);\n const quantity = numberDecimal(line.quantity, 6);\n const gross =\n explicitNet ??\n roundSignedRational(\n quantity.coefficient * money(line.unitPrice),\n quantity.scale,\n );\n safeMoney(gross);\n const discount =\n explicitNet === null ? discountFor(gross, line.discount) : 0n;\n const amount = gross - discount;\n safeMoney(amount);\n if (input.lineAmountType === 'none' && !line.taxCode)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None pricing requires an out-of-scope tax code',\n );\n if (\n input.lineAmountType === 'none' &&\n line.taxCode?.kind !== 'out-of-scope'\n )\n validationError(\n 'TAX_CODE_KIND',\n 'None pricing requires an out-of-scope tax code',\n );\n const components = line.taxCode ? validateTaxCode(line.taxCode, rates) : [];\n const totalRate = components.reduce(\n (sum, component) => sum + component.rate,\n 0n,\n );\n const denominator =\n explicitNet === null && input.lineAmountType === 'inclusive'\n ? PERCENT_DENOMINATOR + totalRate\n : PERCENT_DENOMINATOR;\n return {\n input: line,\n gross,\n discount,\n amount,\n explicitNet,\n exact:\n input.lineAmountType === 'none'\n ? []\n : components.map((component) => ({\n taxComponentId: component.taxComponentId,\n numerator: amount * component.rate,\n denominator,\n })),\n taxes: new Map<string, bigint>(),\n };\n });\n\n if (input.roundingScope === 'line') {\n for (const line of working)\n for (const component of line.exact)\n line.taxes.set(\n component.taxComponentId,\n roundSignedRational(component.numerator, component.denominator),\n );\n } else {\n for (const componentId of [...rates.keys()].sort()) {\n const eligible = working.flatMap((line) => {\n const exact = line.exact.find(\n (component) => component.taxComponentId === componentId,\n );\n return exact ? [{ line, exact }] : [];\n });\n const allocated = allocateSignedRationals(\n eligible.map(({ line, exact }) => ({\n id: line.input.id,\n numerator: exact.numerator,\n denominator: exact.denominator,\n })),\n );\n for (const allocation of allocated.allocations)\n eligible\n .find(({ line }) => line.input.id === allocation.id)\n ?.line.taxes.set(componentId, allocation.value);\n }\n }\n\n const lines = working.map((line): MoneyLineResult => {\n const components = line.exact.map((component) => ({\n taxComponentId: component.taxComponentId,\n taxMinor: safeMoney(line.taxes.get(component.taxComponentId) ?? 0n),\n }));\n const tax = components.reduce(\n (sum, component) => sum + BigInt(component.taxMinor),\n 0n,\n );\n const net =\n line.explicitNet ??\n (input.lineAmountType === 'inclusive' ? line.amount - tax : line.amount);\n const amount =\n line.explicitNet !== null && input.lineAmountType === 'inclusive'\n ? net + tax\n : line.amount;\n return {\n id: line.input.id,\n grossMinor: safeMoney(line.gross),\n discountMinor: safeMoney(line.discount),\n amountMinor: safeMoney(amount),\n components,\n taxMinor: safeMoney(tax),\n netMinor: safeMoney(net),\n };\n });\n\n const taxRows = new Map<string, MoneyDocumentTaxResult>();\n for (let index = 0; index < working.length; index++) {\n const source = working[index].input;\n const result = lines[index];\n if (\n !source.taxCode ||\n source.taxCode.components.length === 0 ||\n input.lineAmountType === 'none'\n ) {\n const key = `${source.taxCode?.id ?? ''}\\u0000`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode?.id ?? null,\n taxComponentId: null,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) + BigInt(result.netMinor),\n );\n taxRows.set(key, row);\n continue;\n }\n for (const component of result.components) {\n if (!source.taxCode)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component requires a tax code',\n );\n const key = `${source.taxCode.id}\\u0000${component.taxComponentId}`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode.id,\n taxComponentId: component.taxComponentId,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) + BigInt(result.netMinor),\n );\n row.taxMinor = safeMoney(\n BigInt(row.taxMinor) + BigInt(component.taxMinor),\n );\n taxRows.set(key, row);\n }\n }\n const taxes = [...taxRows.values()].sort((left, right) => {\n const leftCode = left.taxCodeId ?? '';\n const rightCode = right.taxCodeId ?? '';\n if (leftCode !== rightCode) return leftCode < rightCode ? -1 : 1;\n const leftComponent = left.taxComponentId ?? '';\n const rightComponent = right.taxComponentId ?? '';\n return leftComponent < rightComponent\n ? -1\n : leftComponent > rightComponent\n ? 1\n : 0;\n });\n const subtotal = lines.reduce((sum, line) => sum + BigInt(line.netMinor), 0n);\n const discountTotal = lines.reduce(\n (sum, line) => sum + BigInt(line.discountMinor),\n 0n,\n );\n const tax = lines.reduce((sum, line) => sum + BigInt(line.taxMinor), 0n);\n return {\n lines,\n subtotalMinor: safeMoney(subtotal),\n discountTotalMinor: safeMoney(discountTotal),\n taxMinor: safeMoney(tax),\n totalMinor: safeMoney(subtotal + tax),\n taxes,\n };\n}\n\nfunction selectedCode(\n id: string | null | undefined,\n source: TaxCodeResolutionSource,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode | null {\n if (!id) return null;\n const taxCode = context.codes[id];\n if (!taxCode)\n validationError('TAX_CODE_NOT_FOUND', `Unknown tax code: ${id}`);\n if (typeof taxCode.active !== 'boolean')\n validationError('INVALID_MONEY_INPUT', `Tax code ${id} has invalid state`);\n if (!taxCode.active)\n validationError('TAX_CODE_INACTIVE', `Tax code ${id} is inactive`);\n if (\n taxCode.appliesTo !== 'sales' &&\n taxCode.appliesTo !== 'purchases' &&\n taxCode.appliesTo !== 'both'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n `Tax code ${id} has invalid applicability`,\n );\n if (taxCode.appliesTo !== 'both' && taxCode.appliesTo !== context.direction)\n validationError(\n 'TAX_CODE_SCOPE',\n `Tax code ${id} does not apply to ${context.direction}`,\n );\n return { taxCode, source };\n}\n\n/** Resolve a line tax code from already-loaded values, without model or I/O access. */\nexport function resolveLineTaxCode(\n line: ResolveLineTaxCodeInput,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode {\n if (\n !line ||\n typeof line !== 'object' ||\n !context ||\n typeof context !== 'object'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax-code resolution inputs must be objects',\n );\n if (!context.codes || typeof context.codes !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax-code map must be an object');\n if (\n line.lineAmountType !== 'exclusive' &&\n line.lineAmountType !== 'inclusive' &&\n line.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (context.direction !== 'sales' && context.direction !== 'purchases')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax-code direction');\n if (line.lineAmountType === 'none') {\n if (!context.outOfScopeCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None mode requires an out-of-scope tax code',\n );\n const resolved = selectedCode(context.outOfScopeCodeId, 'none', context);\n if (resolved?.taxCode?.kind !== 'out-of-scope')\n validationError(\n 'TAX_CODE_KIND',\n 'None mode requires an out-of-scope tax code',\n );\n return resolved;\n }\n if (context.customerTaxExempt && !line.lineOverride) {\n if (!context.exemptCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'An exempt customer requires an exempt tax code',\n );\n const exempt = selectedCode(\n context.exemptCodeId,\n 'exempt-customer',\n context,\n );\n if (exempt?.taxCode?.kind !== 'exempt')\n validationError(\n 'TAX_CODE_KIND',\n 'Customer exemption requires an exempt tax code',\n );\n return exempt;\n }\n const candidates: readonly [\n string | null | undefined,\n TaxCodeResolutionSource,\n ][] = [\n [line.lineOverride, 'line'],\n [context.productCodeId, 'product'],\n [context.partyCodeId, 'customer'],\n [context.appDefaultCodeId, 'app'],\n ];\n for (const [id, source] of candidates) {\n const resolved = selectedCode(id, source, context);\n if (resolved) return resolved;\n }\n return { taxCode: null, source: 'none' };\n}\n"],"mappings":";;;AASO,SAAS,wBACd,SACA,OACA,SACM;CACN,KAAA,MAAW,CAAC,OAAO,UAAU,SAC3B,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,GACpD,MAAM,IAAI,MACR,GAAG,QAAO,GAAI,MAAK,IAAK,MAAK,yEACM,MAAK,6CAE1C;AAGN;AAgCO,IAAM,uBAAN,cAAmC,MAAM;CAK9C,YACW,MACT,SACA;EACA,MAAM,OAAO;EAHJ,KAAA,OAAA;EAIT,KAAK,gBAAgB;CACvB;CALW;CALO,OAAO;;CAEhB;AASX;AA8FA,IAAM,gBAAgB;AACtB,IAAM,sBAAsB,OAAO;AACnC,IAAM,iBAAiB,OAAO,OAAO,gBAAgB;AACrD,IAAM,aAAa;AAEnB,SAAS,gBAAgB,MAA2B,SAAwB;CAC1E,MAAM,IAAI,qBAAqB,MAAM,OAAO;AAC9C;AAEA,SAAS,iBAAiB,OAAe,OAAqB;CAC5D,IAAI,OAAO,UAAU,YAAY,CAAC,WAAW,KAAK,KAAK,GACrD,gBACE,uBACA,GAAG,MAAK,2BACV;AACJ;AAEA,SAAS,UAAU,OAAuB;CACxC,IAAI,QAAQ,kBAAkB,QAAQ,CAAC,gBACrC,gBAAgB,gBAAgB,wCAAwC;CAC1E,OAAO,OAAO,KAAK;AACrB;AAEA,SAAS,MAAM,OAAuB;CACpC,IAAI,CAAC,OAAO,cAAc,KAAK,GAC7B,gBAAgB,gBAAgB,wCAAwC;CAC1E,OAAO,OAAO,KAAK;AACrB;AAOA,SAAS,cAAc,OAAe,WAAiC;CACrE,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,KAAK,QAAQ,OAAO,kBACzD,gBACE,uBACA,yCACF;CACF,MAAM,CAAC,UAAU,eAAe,OAAO,MAAM,SAAS,CAAA,CAAE,MAAM,GAAG;CACjE,MAAM,CAAC,OAAO,WAAW,MAAM,SAAS,MAAM,GAAG;CACjD,MAAM,SAAS,SAAS,SAAS,OAAO,YAAY;CACpD,IAAI,SAAS,WACX,gBACE,uBACA,kDACF;CACF,MAAM,cAAc,OAAO,QAAQ,QAAQ;CAC3C,OAAO,SAAS,IACZ;EAAE,aAAa,cAAc,OAAO,OAAO,CAAC,MAAM;EAAG,OAAO;CAAG,IAC/D;EAAE;EAAa,OAAO,OAAO,OAAO,MAAM;CAAE;AAClD;AAEA,SAAS,aAAa,OAAuB;CAC3C,IACE,OAAO,UAAU,YACjB,CAAC,qCAAqC,KAAK,KAAK,GAEhD,gBACE,wBACA,wFACF;CACF,MAAM,CAAC,OAAO,WAAW,MAAM,MAAM,MAAM,GAAG;CAC9C,MAAM,QAAQ,OAAO,KAAK,IAAI,gBAAgB,OAAO,SAAS,OAAO,GAAG,GAAG,CAAC;CAC5E,IAAI,QAAQ,qBACV,gBAAgB,wBAAwB,qBAAqB;CAC/D,OAAO;AACT;AAEA,SAAS,gBACP,MACA,OAC4C;CAC5C,IAAI,CAAC,QAAQ,OAAO,SAAS,UAC3B,gBAAgB,uBAAuB,4BAA4B;CACrE,iBAAiB,KAAK,IAAI,aAAa;CACvC,IACE,KAAK,SAAS,aACd,KAAK,SAAS,gBACd,KAAK,SAAS,YACd,KAAK,SAAS,gBAEd,gBAAgB,iBAAiB,uBAAuB;CAC1D,IAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,GAChC,gBACE,uBACA,sCACF;CACF,IAAI,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW,GACxD,gBACE,0BACA,8CACF;CACF,IAAI,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW,GACxD,gBACE,mCACA,6CACF;CACF,MAAM,uBAAO,IAAI,IAAY;CAC7B,OAAO,KAAK,WAAW,KAAK,cAAc;EACxC,IAAI,CAAC,aAAa,OAAO,cAAc,UACrC,gBAAgB,uBAAuB,iCAAiC;EAC1E,iBAAiB,UAAU,gBAAgB,kBAAkB;EAC7D,IAAI,KAAK,IAAI,UAAU,cAAc,GACnC,gBACE,gCACA,qCACF;EACF,KAAK,IAAI,UAAU,cAAc;EACjC,IAAI,OAAO,UAAU,aAAa,WAChC,gBACE,uBACA,wCACF;EACF,IAAI,UAAU,UACZ,gBACE,wBACA,2CACF;EACF,MAAM,OAAO,aAAa,UAAU,OAAO;EAC3C,MAAM,WAAW,MAAM,IAAI,UAAU,cAAc;EACnD,IAAI,aAAa,KAAA,KAAa,aAAa,MACzC,gBACE,+BACA,kDACF;EACF,MAAM,IAAI,UAAU,gBAAgB,IAAI;EACxC,OAAO;GAAE,gBAAgB,UAAU;GAAgB;EAAK;CAC1D,CAAC;AACH;AAEA,SAAS,YAAY,OAAe,UAAsC;CACxE,IAAI,CAAC,YAAY,OAAO,aAAa,UACnC,gBAAgB,uBAAuB,kCAAkC;CAC3E,MAAM,UAAU;CAIhB,IAAI,QAAQ,SAAS,KAAA,KAAa,QAAQ,UAAU,KAAA,GAClD,gBACE,uBACA,yDACF;CACF,IAAI;CACJ,IAAI,SAAS,SAAS,QAAQ;EAC5B,IAAI,QAAQ,SAAS,KAAA,KAAa,QAAQ,UAAU,KAAA,GAClD,gBACE,uBACA,yDACF;EACF,SAAS;CACX,OAAA,IAAW,SAAS,SAAS,WAC3B,SAAS,oBACP,QAAQ,aAAa,SAAS,IAAI,GAClC,mBACF;MACF,IAAW,SAAS,SAAS,UAC3B,SAAS,MAAM,SAAS,KAAK;MAE7B,gBAAgB,uBAAuB,uBAAuB;CAEhE,IAAI,WAAW,MAAM,UAAU,MAAM,SAAS,OAAO,QAAQ,IAC3D,gBACE,iBACA,8CACF;CACF,IAAI,UAAU,MAAM,WAAW,IAC7B,gBAAgB,iBAAiB,sCAAsC;CACzE,MAAM,aAAa,UAAmB,QAAQ,KAAK,CAAC,QAAQ;CAC5D,IAAI,UAAU,MAAM,IAAI,UAAU,KAAK,GACrC,gBAAgB,0BAA0B,8BAA8B;CAC1E,OAAO;AACT;AAEA,SAAS,sBAAsB,OAKtB;CACP,IAAI,CAAC,SAAS,OAAO,UAAU,UAC7B,gBAAgB,uBAAuB,+BAA+B;CACxE,IACE,OAAO,MAAM,aAAa,YAC1B,CAAC,aAAa,KAAK,MAAM,QAAQ,KACjC,CAAC,qBAAqB,IAAI,MAAM,QAAQ,KACxC,qBAAqB,IAAI,MAAM,QAAQ,MAAM,MAE7C,gBACE,qBACA,uEACF;CACF,IACE,MAAM,mBAAmB,eACzB,MAAM,mBAAmB,eACzB,MAAM,mBAAmB,QAEzB,gBAAgB,uBAAuB,0BAA0B;CACnE,IAAI,MAAM,kBAAkB,UAAU,MAAM,kBAAkB,YAC5D,gBAAgB,uBAAuB,4BAA4B;CACrE,IAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,GAC5B,gBAAgB,uBAAuB,wBAAwB;AACnE;AAGO,SAAS,uBAAuB,OAKf;CACtB,sBAAsB,KAAK;CAC3B,MAAM,sBAAM,IAAI,IAAY;CAC5B,MAAM,wBAAQ,IAAI,IAAoB;CACtC,MAAM,UAAU,MAAM,MAAM,KAAK,SAAS;EACxC,IAAI,CAAC,QAAQ,OAAO,SAAS,UAC3B,gBAAgB,uBAAuB,8BAA8B;EACvE,iBAAiB,KAAK,IAAI,SAAS;EACnC,IAAI,IAAI,IAAI,KAAK,EAAE,GACjB,gBAAgB,uBAAuB,yBAAyB;EAClE,IAAI,IAAI,KAAK,EAAE;EACf,MAAM,cACJ,KAAK,mBAAmB,KAAA,IAAY,OAAO,MAAM,KAAK,cAAc;EACtE,MAAM,WAAW,cAAc,KAAK,UAAU,CAAC;EAC/C,MAAM,QACJ,eACA,oBACE,SAAS,cAAc,MAAM,KAAK,SAAS,GAC3C,SAAS,KACX;EACF,UAAU,KAAK;EACf,MAAM,WACJ,gBAAgB,OAAO,YAAY,OAAO,KAAK,QAAQ,IAAI;EAC7D,MAAM,SAAS,QAAQ;EACvB,UAAU,MAAM;EAChB,IAAI,MAAM,mBAAmB,UAAU,CAAC,KAAK,SAC3C,gBACE,sBACA,gDACF;EACF,IACE,MAAM,mBAAmB,UACzB,KAAK,SAAS,SAAS,gBAEvB,gBACE,iBACA,gDACF;EACF,MAAM,aAAa,KAAK,UAAU,gBAAgB,KAAK,SAAS,KAAK,IAAI,CAAC;EAC1E,MAAM,YAAY,WAAW,QAC1B,KAAK,cAAc,MAAM,UAAU,MACpC,EACF;EACA,MAAM,cACJ,gBAAgB,QAAQ,MAAM,mBAAmB,cAC7C,sBAAsB,YACtB;EACN,OAAO;GACL,OAAO;GACP;GACA;GACA;GACA;GACA,OACE,MAAM,mBAAmB,SACrB,CAAC,IACD,WAAW,KAAK,eAAe;IAC7B,gBAAgB,UAAU;IAC1B,WAAW,SAAS,UAAU;IAC9B;GACF,EAAE;GACR,uBAAO,IAAI,IAAoB;EACjC;CACF,CAAC;CAED,IAAI,MAAM,kBAAkB,QAC1B,KAAA,MAAW,QAAQ,SACjB,KAAA,MAAW,aAAa,KAAK,OAC3B,KAAK,MAAM,IACT,UAAU,gBACV,oBAAoB,UAAU,WAAW,UAAU,WAAW,CAChE;MAEJ,KAAA,MAAW,eAAe,CAAC,GAAG,MAAM,KAAK,CAAC,CAAA,CAAE,KAAK,GAAG;EAClD,MAAM,WAAW,QAAQ,SAAS,SAAS;GACzC,MAAM,QAAQ,KAAK,MAAM,MACtB,cAAc,UAAU,mBAAmB,WAC9C;GACA,OAAO,QAAQ,CAAC;IAAE;IAAM;GAAM,CAAC,IAAI,CAAC;EACtC,CAAC;EACD,MAAM,YAAY,wBAChB,SAAS,KAAK,EAAE,MAAM,aAAa;GACjC,IAAI,KAAK,MAAM;GACf,WAAW,MAAM;GACjB,aAAa,MAAM;EACrB,EAAE,CACJ;EACA,KAAA,MAAW,cAAc,UAAU,aACjC,SACG,MAAM,EAAE,WAAW,KAAK,MAAM,OAAO,WAAW,EAAE,CAAA,EACjD,KAAK,MAAM,IAAI,aAAa,WAAW,KAAK;CACpD;CAGF,MAAM,QAAQ,QAAQ,KAAK,SAA0B;EACnD,MAAM,aAAa,KAAK,MAAM,KAAK,eAAe;GAChD,gBAAgB,UAAU;GAC1B,UAAU,UAAU,KAAK,MAAM,IAAI,UAAU,cAAc,KAAK,EAAE;EACpE,EAAE;EACF,MAAMA,OAAM,WAAW,QACpB,KAAK,cAAc,MAAM,OAAO,UAAU,QAAQ,GACnD,EACF;EACA,MAAM,MACJ,KAAK,gBACJ,MAAM,mBAAmB,cAAc,KAAK,SAASA,OAAM,KAAK;EACnE,MAAM,SACJ,KAAK,gBAAgB,QAAQ,MAAM,mBAAmB,cAClD,MAAMA,OACN,KAAK;EACX,OAAO;GACL,IAAI,KAAK,MAAM;GACf,YAAY,UAAU,KAAK,KAAK;GAChC,eAAe,UAAU,KAAK,QAAQ;GACtC,aAAa,UAAU,MAAM;GAC7B;GACA,UAAU,UAAUA,IAAG;GACvB,UAAU,UAAU,GAAG;EACzB;CACF,CAAC;CAED,MAAM,0BAAU,IAAI,IAAoC;CACxD,KAAA,IAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;EACnD,MAAM,SAAS,QAAQ,MAAK,CAAE;EAC9B,MAAM,SAAS,MAAM;EACrB,IACE,CAAC,OAAO,WACR,OAAO,QAAQ,WAAW,WAAW,KACrC,MAAM,mBAAmB,QACzB;GACA,MAAM,MAAM,GAAG,OAAO,SAAS,MAAM,GAAE;GACvC,MAAM,MAAM,QAAQ,IAAI,GAAG,KAAK;IAC9B,WAAW,OAAO,SAAS,MAAM;IACjC,gBAAgB;IAChB,cAAc;IACd,UAAU;GACZ;GACA,IAAI,eAAe,UACjB,OAAO,IAAI,YAAY,IAAI,OAAO,OAAO,QAAQ,CACnD;GACA,QAAQ,IAAI,KAAK,GAAG;GACpB;EACF;EACA,KAAA,MAAW,aAAa,OAAO,YAAY;GACzC,IAAI,CAAC,OAAO,SACV,gBACE,uBACA,mCACF;GACF,MAAM,MAAM,GAAG,OAAO,QAAQ,GAAE,IAAS,UAAU;GACnD,MAAM,MAAM,QAAQ,IAAI,GAAG,KAAK;IAC9B,WAAW,OAAO,QAAQ;IAC1B,gBAAgB,UAAU;IAC1B,cAAc;IACd,UAAU;GACZ;GACA,IAAI,eAAe,UACjB,OAAO,IAAI,YAAY,IAAI,OAAO,OAAO,QAAQ,CACnD;GACA,IAAI,WAAW,UACb,OAAO,IAAI,QAAQ,IAAI,OAAO,UAAU,QAAQ,CAClD;GACA,QAAQ,IAAI,KAAK,GAAG;EACtB;CACF;CACA,MAAM,QAAQ,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAA,CAAE,MAAM,MAAM,UAAU;EACxD,MAAM,WAAW,KAAK,aAAa;EACnC,MAAM,YAAY,MAAM,aAAa;EACrC,IAAI,aAAa,WAAW,OAAO,WAAW,YAAY,KAAK;EAC/D,MAAM,gBAAgB,KAAK,kBAAkB;EAC7C,MAAM,iBAAiB,MAAM,kBAAkB;EAC/C,OAAO,gBAAgB,iBACnB,KACA,gBAAgB,iBACd,IACA;CACR,CAAC;CACD,MAAM,WAAW,MAAM,QAAQ,KAAK,SAAS,MAAM,OAAO,KAAK,QAAQ,GAAG,EAAE;CAC5E,MAAM,gBAAgB,MAAM,QACzB,KAAK,SAAS,MAAM,OAAO,KAAK,aAAa,GAC9C,EACF;CACA,MAAM,MAAM,MAAM,QAAQ,KAAK,SAAS,MAAM,OAAO,KAAK,QAAQ,GAAG,EAAE;CACvE,OAAO;EACL;EACA,eAAe,UAAU,QAAQ;EACjC,oBAAoB,UAAU,aAAa;EAC3C,UAAU,UAAU,GAAG;EACvB,YAAY,UAAU,WAAW,GAAG;EACpC;CACF;AACF;AAEA,SAAS,aACP,IACA,QACA,SAC4B;CAC5B,IAAI,CAAC,IAAI,OAAO;CAChB,MAAM,UAAU,QAAQ,MAAM;CAC9B,IAAI,CAAC,SACH,gBAAgB,sBAAsB,qBAAqB,IAAI;CACjE,IAAI,OAAO,QAAQ,WAAW,WAC5B,gBAAgB,uBAAuB,YAAY,GAAE,mBAAoB;CAC3E,IAAI,CAAC,QAAQ,QACX,gBAAgB,qBAAqB,YAAY,GAAE,aAAc;CACnE,IACE,QAAQ,cAAc,WACtB,QAAQ,cAAc,eACtB,QAAQ,cAAc,QAEtB,gBACE,uBACA,YAAY,GAAE,2BAChB;CACF,IAAI,QAAQ,cAAc,UAAU,QAAQ,cAAc,QAAQ,WAChE,gBACE,kBACA,YAAY,GAAE,qBAAsB,QAAQ,WAC9C;CACF,OAAO;EAAE;EAAS;CAAO;AAC3B;AAGO,SAAS,mBACd,MACA,SACqB;CACrB,IACE,CAAC,QACD,OAAO,SAAS,YAChB,CAAC,WACD,OAAO,YAAY,UAEnB,gBACE,uBACA,4CACF;CACF,IAAI,CAAC,QAAQ,SAAS,OAAO,QAAQ,UAAU,UAC7C,gBAAgB,uBAAuB,gCAAgC;CACzE,IACE,KAAK,mBAAmB,eACxB,KAAK,mBAAmB,eACxB,KAAK,mBAAmB,QAExB,gBAAgB,uBAAuB,0BAA0B;CACnE,IAAI,QAAQ,cAAc,WAAW,QAAQ,cAAc,aACzD,gBAAgB,uBAAuB,4BAA4B;CACrE,IAAI,KAAK,mBAAmB,QAAQ;EAClC,IAAI,CAAC,QAAQ,kBACX,gBACE,sBACA,6CACF;EACF,MAAM,WAAW,aAAa,QAAQ,kBAAkB,QAAQ,OAAO;EACvE,IAAI,UAAU,SAAS,SAAS,gBAC9B,gBACE,iBACA,6CACF;EACF,OAAO;CACT;CACA,IAAI,QAAQ,qBAAqB,CAAC,KAAK,cAAc;EACnD,IAAI,CAAC,QAAQ,cACX,gBACE,sBACA,gDACF;EACF,MAAM,SAAS,aACb,QAAQ,cACR,mBACA,OACF;EACA,IAAI,QAAQ,SAAS,SAAS,UAC5B,gBACE,iBACA,gDACF;EACF,OAAO;CACT;CACA,MAAM,aAGA;EACJ,CAAC,KAAK,cAAc,MAAM;EAC1B,CAAC,QAAQ,eAAe,SAAS;EACjC,CAAC,QAAQ,aAAa,UAAU;EAChC,CAAC,QAAQ,kBAAkB,KAAK;CAClC;CACA,KAAA,MAAW,CAAC,IAAI,WAAW,YAAY;EACrC,MAAM,WAAW,aAAa,IAAI,QAAQ,OAAO;EACjD,IAAI,UAAU,OAAO;CACvB;CACA,OAAO;EAAE,SAAS;EAAM,QAAQ;CAAO;AACzC"}
|
|
1
|
+
{"version":3,"file":"money.js","names":["tax"],"sources":["../src/money.ts"],"sourcesContent":["/** Exact, transport-neutral commercial document money calculation. */\n\nimport { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport {\n allocateSignedRationals,\n roundSignedRational,\n} from './money-rational.js';\n\n/** Throw unless every named model value is a finite integer minor-unit amount. */\nexport function assertIntegerMinorUnits(\n context: string,\n label: string,\n entries: ReadonlyArray<readonly [string, number]>,\n): void {\n for (const [field, value] of entries) {\n if (!Number.isFinite(value) || !Number.isInteger(value)) {\n throw new Error(\n `${context} ${label}: ${field} must be an integer number of minor ` +\n `units (cents, satoshis) — got ${value}. Money is exact: $19.99 is ` +\n '1999, not 19.99.',\n );\n }\n }\n}\n\nexport type LineAmountType = 'exclusive' | 'inclusive' | 'none';\nexport type TaxRoundingScope = 'line' | 'document';\nexport type TaxCodeKind = 'taxable' | 'zero-rated' | 'exempt' | 'out-of-scope';\nexport type TaxCodeAppliesTo = 'sales' | 'purchases' | 'both';\n\nexport type MoneyValidationCode =\n | 'DISCOUNT_BOTH_FORMS'\n | 'DISCOUNT_EXCEEDS_GROSS'\n | 'DISCOUNT_SIGN'\n | 'PERCENT_OUT_OF_RANGE'\n | 'COMPOUND_UNSUPPORTED'\n | 'TAX_COMPONENT_DEPENDENCY_CYCLE'\n | 'INVALID_MONEY_INPUT'\n | 'TAX_CODE_DUPLICATE_COMPONENT'\n | 'TAX_CODE_KIND'\n | 'TAX_CODE_NON_TAXABLE_COMPONENTS'\n | 'TAX_CODE_NOT_FOUND'\n | 'TAX_CODE_TAXABLE_EMPTY'\n | 'TAX_COMPONENT_RATE_CONFLICT'\n | 'TAX_CODE_INACTIVE'\n | 'TAX_CODE_SCOPE'\n | 'UNSAFE_MONEY'\n | 'FROZEN_DOCUMENT'\n | 'CURRENCY_MISMATCH'\n | 'ACCOUNTING_SYNC_IN_PROGRESS'\n | 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED'\n | 'ACCOUNTING_SYNC_UNSUPPORTED'\n | 'CREDIT_EXCEEDS_LINE'\n | 'CREDIT_TARGET_NOT_ISSUED';\n\n/** Stable validation error shared by model, editor, and transport adapters. */\nexport class MoneyValidationError extends Error {\n override readonly name = 'MoneyValidationError';\n /** Explicit marker consumed by public transports that preserve typed errors. */\n readonly publicMessage: string;\n\n constructor(\n readonly code: MoneyValidationCode,\n message: string,\n ) {\n super(message);\n this.publicMessage = message;\n }\n}\n\nexport interface TaxComponentInput {\n taxComponentId: string;\n /** Exact percent: \"7\" means 7%; at most six fractional digits. */\n percent: string;\n compound: boolean;\n}\n\nexport interface MoneyTaxCodeInput {\n id: string;\n kind: TaxCodeKind;\n components: readonly TaxComponentInput[];\n}\n\nexport interface ResolvableTaxCodeInput extends MoneyTaxCodeInput {\n active: boolean;\n appliesTo: TaxCodeAppliesTo;\n}\n\nexport type MoneyDiscountInput =\n | { kind: 'none' }\n | { kind: 'percent'; rate: string }\n | { kind: 'amount'; minor: number };\n\nexport interface MoneyLineInput {\n id: string;\n /** Nonnegative decimal quantity with at most six fractional digits. */\n quantity: number;\n /** Signed safe integer minor units. */\n unitPrice: number;\n discount: MoneyDiscountInput;\n /** Explicit tax-exclusive basis for credit-note amount allocations. */\n netAmountMinor?: number;\n /** Null means no code resolved; `none` pricing requires an out-of-scope code. */\n taxCode: MoneyTaxCodeInput | null;\n}\n\nexport interface MoneyLineResult {\n id: string;\n grossMinor: number;\n discountMinor: number;\n amountMinor: number;\n components: {\n taxComponentId: string;\n taxMinor: number;\n compound?: boolean;\n taxableMinor?: number;\n }[];\n taxMinor: number;\n netMinor: number;\n}\n\nexport interface MoneyDocumentTaxResult {\n /** Null records an unassigned line without inventing a persisted tax-code ID. */\n taxCodeId: string | null;\n taxComponentId: string | null;\n taxableMinor: number;\n /** Net basis separately from a compound component's actual taxable basis. */\n netMinor?: number;\n taxMinor: number;\n}\n\nexport interface MoneyDocumentResult {\n lines: MoneyLineResult[];\n subtotalMinor: number;\n discountTotalMinor: number;\n taxMinor: number;\n totalMinor: number;\n taxes: MoneyDocumentTaxResult[];\n}\n\nexport type TaxCodeResolutionSource =\n | 'line'\n | 'exempt-customer'\n | 'product'\n | 'customer'\n | 'app'\n | 'none';\n\nexport interface ResolveLineTaxCodeInput {\n lineAmountType: LineAmountType;\n lineOverride?: string | null;\n}\n\nexport interface ResolveLineTaxCodeContext {\n direction: 'sales' | 'purchases';\n codes: Readonly<Record<string, ResolvableTaxCodeInput>>;\n customerTaxExempt: boolean;\n exemptCodeId?: string | null;\n productCodeId?: string | null;\n partyCodeId?: string | null;\n appDefaultCodeId?: string | null;\n outOfScopeCodeId?: string | null;\n}\n\nexport interface ResolvedLineTaxCode {\n taxCode: ResolvableTaxCodeInput | null;\n source: TaxCodeResolutionSource;\n}\n\nconst PERCENT_SCALE = 1_000_000n;\nconst PERCENT_DENOMINATOR = 100n * PERCENT_SCALE;\nconst MAX_SAFE_MONEY = BigInt(Number.MAX_SAFE_INTEGER);\nconst IDENTIFIER = /^\\S(?:.*\\S)?$/;\n\nfunction validationError(code: MoneyValidationCode, message: string): never {\n throw new MoneyValidationError(code, message);\n}\n\nfunction assertIdentifier(value: string, label: string): void {\n if (typeof value !== 'string' || !IDENTIFIER.test(value))\n validationError(\n 'INVALID_MONEY_INPUT',\n `${label} must be a nonempty string`,\n );\n}\n\nfunction safeMoney(value: bigint): number {\n if (value > MAX_SAFE_MONEY || value < -MAX_SAFE_MONEY)\n validationError('UNSAFE_MONEY', 'Money exceeds safe integer minor units');\n return Number(value);\n}\n\nfunction money(value: number): bigint {\n if (!Number.isSafeInteger(value))\n validationError('UNSAFE_MONEY', 'Money must be safe integer minor units');\n return BigInt(value);\n}\n\ninterface ExactDecimal {\n coefficient: bigint;\n scale: bigint;\n}\n\nfunction numberDecimal(value: number, precision: number): ExactDecimal {\n if (!Number.isFinite(value) || value < 0 || value > Number.MAX_SAFE_INTEGER)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity is outside the supported range',\n );\n const [mantissa, exponentText = '0'] = value.toString().split('e');\n const [whole, fraction = ''] = mantissa.split('.');\n const places = fraction.length - Number(exponentText);\n if (places > precision)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Quantity exceeds the supported decimal precision',\n );\n const coefficient = BigInt(whole + fraction);\n return places < 0\n ? { coefficient: coefficient * 10n ** BigInt(-places), scale: 1n }\n : { coefficient, scale: 10n ** BigInt(places) };\n}\n\nfunction percentUnits(value: string): bigint {\n if (\n typeof value !== 'string' ||\n !/^(?:0|[1-9]\\d{0,2})(?:\\.\\d{1,6})?$/.test(value)\n )\n validationError(\n 'PERCENT_OUT_OF_RANGE',\n 'Percent must be an exact decimal from 0 through 100 with at most six fractional digits',\n );\n const [whole, fraction = ''] = value.split('.');\n const units = BigInt(whole) * PERCENT_SCALE + BigInt(fraction.padEnd(6, '0'));\n if (units > PERCENT_DENOMINATOR)\n validationError('PERCENT_OUT_OF_RANGE', 'Percent exceeds 100');\n return units;\n}\n\nfunction validateTaxCode(\n code: MoneyTaxCodeInput,\n rates: Map<string, bigint>,\n): { taxComponentId: string; rate: bigint; compound: boolean }[] {\n if (!code || typeof code !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax code must be an object');\n assertIdentifier(code.id, 'Tax code ID');\n if (\n code.kind !== 'taxable' &&\n code.kind !== 'zero-rated' &&\n code.kind !== 'exempt' &&\n code.kind !== 'out-of-scope'\n )\n validationError('TAX_CODE_KIND', 'Unknown tax code kind');\n if (!Array.isArray(code.components))\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax code components must be an array',\n );\n if (code.kind === 'taxable' && code.components.length === 0)\n validationError(\n 'TAX_CODE_TAXABLE_EMPTY',\n 'Taxable codes require at least one component',\n );\n if (code.kind !== 'taxable' && code.components.length !== 0)\n validationError(\n 'TAX_CODE_NON_TAXABLE_COMPONENTS',\n 'Non-taxable codes cannot contain components',\n );\n const seen = new Set<string>();\n return code.components.map((component) => {\n if (!component || typeof component !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax component must be an object');\n assertIdentifier(component.taxComponentId, 'Tax component ID');\n if (seen.has(component.taxComponentId))\n validationError(\n 'TAX_CODE_DUPLICATE_COMPONENT',\n 'Duplicate tax component within code',\n );\n seen.add(component.taxComponentId);\n if (typeof component.compound !== 'boolean')\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component compound must be boolean',\n );\n const rate = percentUnits(component.percent);\n const existing = rates.get(component.taxComponentId);\n if (existing !== undefined && existing !== rate)\n validationError(\n 'TAX_COMPONENT_RATE_CONFLICT',\n 'Shared tax component has conflicting percentages',\n );\n rates.set(component.taxComponentId, rate);\n return {\n taxComponentId: component.taxComponentId,\n rate,\n compound: component.compound,\n };\n });\n}\n\nfunction discountFor(gross: bigint, discount: MoneyDiscountInput): bigint {\n if (!discount || typeof discount !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Discount must be a tagged object');\n const runtime = discount as MoneyDiscountInput & {\n rate?: unknown;\n minor?: unknown;\n };\n if (runtime.rate !== undefined && runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A discount cannot include both percent and amount forms',\n );\n let result: bigint;\n if (discount.kind === 'none') {\n if (runtime.rate !== undefined || runtime.minor !== undefined)\n validationError(\n 'DISCOUNT_BOTH_FORMS',\n 'A none discount cannot include percent or amount values',\n );\n result = 0n;\n } else if (discount.kind === 'percent') {\n result = roundSignedRational(\n gross * percentUnits(discount.rate),\n PERCENT_DENOMINATOR,\n );\n } else if (discount.kind === 'amount') {\n result = money(discount.minor);\n } else {\n validationError('INVALID_MONEY_INPUT', 'Unknown discount kind');\n }\n if (result !== 0n && gross !== 0n && result < 0n !== gross < 0n)\n validationError(\n 'DISCOUNT_SIGN',\n 'Discount amount must carry the sign of gross',\n );\n if (gross === 0n && result !== 0n)\n validationError('DISCOUNT_SIGN', 'A zero gross cannot carry a discount');\n const magnitude = (value: bigint) => (value < 0n ? -value : value);\n if (magnitude(result) > magnitude(gross))\n validationError('DISCOUNT_EXCEEDS_GROSS', 'Discount cannot exceed gross');\n return result;\n}\n\nfunction validateDocumentInput(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): void {\n if (!input || typeof input !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money input must be an object');\n if (\n typeof input.currency !== 'string' ||\n !/^[A-Z]{3}$/.test(input.currency) ||\n !ISO_4217_MINOR_UNITS.has(input.currency) ||\n ISO_4217_MINOR_UNITS.get(input.currency) === null\n )\n validationError(\n 'CURRENCY_MISMATCH',\n 'Currency must be a supported uppercase ISO 4217 code with minor units',\n );\n if (\n input.lineAmountType !== 'exclusive' &&\n input.lineAmountType !== 'inclusive' &&\n input.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (input.roundingScope !== 'line' && input.roundingScope !== 'document')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax rounding scope');\n if (!Array.isArray(input.lines))\n validationError('INVALID_MONEY_INPUT', 'Lines must be an array');\n}\n\n/** Calculate exact line amounts, per-component tax, and document totals. */\nexport function calculateMoneyDocument(input: {\n currency: string;\n lineAmountType: LineAmountType;\n roundingScope: TaxRoundingScope;\n lines: readonly MoneyLineInput[];\n}): MoneyDocumentResult {\n validateDocumentInput(input);\n const ids = new Set<string>();\n const rates = new Map<string, bigint>();\n const working = input.lines.map((line) => {\n if (!line || typeof line !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Money line must be an object');\n assertIdentifier(line.id, 'Line ID');\n if (ids.has(line.id))\n validationError('INVALID_MONEY_INPUT', 'Duplicate money line ID');\n ids.add(line.id);\n const explicitNet =\n line.netAmountMinor === undefined ? null : money(line.netAmountMinor);\n const quantity = numberDecimal(line.quantity, 6);\n const gross =\n explicitNet ??\n roundSignedRational(\n quantity.coefficient * money(line.unitPrice),\n quantity.scale,\n );\n safeMoney(gross);\n const discount =\n explicitNet === null ? discountFor(gross, line.discount) : 0n;\n const amount = gross - discount;\n safeMoney(amount);\n if (input.lineAmountType === 'none' && !line.taxCode)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None pricing requires an out-of-scope tax code',\n );\n if (\n input.lineAmountType === 'none' &&\n line.taxCode?.kind !== 'out-of-scope'\n )\n validationError(\n 'TAX_CODE_KIND',\n 'None pricing requires an out-of-scope tax code',\n );\n const components = line.taxCode ? validateTaxCode(line.taxCode, rates) : [];\n // Inclusive extraction uses exact ordered factors; exclusive calculation\n // below uses previously rounded/allocated taxes, not these exact factors.\n let totalNumerator = 1n;\n let totalDenominator = 1n;\n const factors = components.map((component) => {\n const numerator =\n component.rate *\n (component.compound ? totalNumerator : totalDenominator);\n const denominator = PERCENT_DENOMINATOR * totalDenominator;\n totalNumerator = totalNumerator * PERCENT_DENOMINATOR + numerator;\n totalDenominator = denominator;\n return { ...component, numerator, denominator };\n });\n const inclusive =\n explicitNet === null && input.lineAmountType === 'inclusive';\n return {\n input: line,\n gross,\n discount,\n amount,\n explicitNet,\n inclusive,\n exact:\n input.lineAmountType === 'none'\n ? []\n : factors.map((component, index) => ({\n ...component,\n priorIds: component.compound\n ? components\n .slice(0, index)\n .map((prior) => prior.taxComponentId)\n : [],\n numerator: amount * component.numerator * totalDenominator,\n denominator: component.denominator * totalNumerator,\n })),\n taxes: new Map<string, bigint>(),\n bases: new Map<string, bigint>(),\n };\n });\n\n const dependencies = new Map(\n [...rates.keys()].map((id) => [id, new Set<string>()]),\n );\n for (const line of working)\n for (const component of line.exact)\n for (const prior of component.priorIds)\n dependencies.get(component.taxComponentId)?.add(prior);\n const order: string[] = [];\n while (dependencies.size) {\n const ready = [...dependencies]\n .filter(([, prior]) => prior.size === 0)\n .map(([id]) => id)\n .sort();\n if (!ready.length)\n validationError(\n 'TAX_COMPONENT_DEPENDENCY_CYCLE',\n 'Tax codes impose contradictory compound component order',\n );\n for (const id of ready) {\n order.push(id);\n dependencies.delete(id);\n for (const prior of dependencies.values()) prior.delete(id);\n }\n }\n const exactTax = (\n line: (typeof working)[number],\n component: (typeof working)[number]['exact'][number],\n ) => {\n if (line.inclusive) return component;\n const basis =\n line.amount +\n component.priorIds.reduce(\n (sum, id) => sum + (line.taxes.get(id) ?? 0n),\n 0n,\n );\n safeMoney(basis);\n line.bases.set(component.taxComponentId, basis);\n return {\n numerator: basis * component.rate,\n denominator: PERCENT_DENOMINATOR,\n };\n };\n if (input.roundingScope === 'line') {\n for (const line of working)\n for (const component of line.exact) {\n const exact = exactTax(line, component);\n line.taxes.set(\n component.taxComponentId,\n roundSignedRational(exact.numerator, exact.denominator),\n );\n }\n } else {\n for (const componentId of order) {\n const eligible = working.flatMap((line) => {\n const component = line.exact.find(\n (item) => item.taxComponentId === componentId,\n );\n return component ? [{ line, exact: exactTax(line, component) }] : [];\n });\n const allocated = allocateSignedRationals(\n eligible.map(({ line, exact }) => ({\n id: line.input.id,\n numerator: exact.numerator,\n denominator: exact.denominator,\n })),\n );\n for (const allocation of allocated.allocations)\n eligible\n .find(({ line }) => line.input.id === allocation.id)\n ?.line.taxes.set(componentId, allocation.value);\n }\n }\n\n const lines = working.map((line): MoneyLineResult => {\n const components = line.exact.map((component) => ({\n taxComponentId: component.taxComponentId,\n taxMinor: safeMoney(line.taxes.get(component.taxComponentId) ?? 0n),\n }));\n const tax = components.reduce(\n (sum, component) => sum + BigInt(component.taxMinor),\n 0n,\n );\n const net =\n line.explicitNet ??\n (input.lineAmountType === 'inclusive' ? line.amount - tax : line.amount);\n for (let index = 0; index < components.length; index++) {\n const source = line.exact[index];\n if (source.compound)\n Object.assign(components[index], {\n compound: true,\n taxableMinor: safeMoney(\n line.inclusive\n ? net +\n source.priorIds.reduce(\n (sum, id) => sum + (line.taxes.get(id) ?? 0n),\n 0n,\n )\n : (line.bases.get(source.taxComponentId) ?? net),\n ),\n });\n }\n const amount =\n line.explicitNet !== null && input.lineAmountType === 'inclusive'\n ? net + tax\n : line.amount;\n return {\n id: line.input.id,\n grossMinor: safeMoney(line.gross),\n discountMinor: safeMoney(line.discount),\n amountMinor: safeMoney(amount),\n components,\n taxMinor: safeMoney(tax),\n netMinor: safeMoney(net),\n };\n });\n\n const taxRows = new Map<string, MoneyDocumentTaxResult>();\n for (let index = 0; index < working.length; index++) {\n const source = working[index].input;\n const result = lines[index];\n if (\n !source.taxCode ||\n source.taxCode.components.length === 0 ||\n input.lineAmountType === 'none'\n ) {\n const key = `${source.taxCode?.id ?? ''}\\u0000`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode?.id ?? null,\n taxComponentId: null,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) + BigInt(result.netMinor),\n );\n taxRows.set(key, row);\n continue;\n }\n for (const component of result.components) {\n if (!source.taxCode)\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax component requires a tax code',\n );\n const key = `${source.taxCode.id}\\u0000${component.taxComponentId}`;\n const row = taxRows.get(key) ?? {\n taxCodeId: source.taxCode.id,\n taxComponentId: component.taxComponentId,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor = safeMoney(\n BigInt(row.taxableMinor) +\n BigInt(component.taxableMinor ?? result.netMinor),\n );\n if (component.compound)\n row.netMinor = safeMoney(\n BigInt(row.netMinor ?? 0) + BigInt(result.netMinor),\n );\n row.taxMinor = safeMoney(\n BigInt(row.taxMinor) + BigInt(component.taxMinor),\n );\n taxRows.set(key, row);\n }\n }\n const taxes = [...taxRows.values()].sort((left, right) => {\n const leftCode = left.taxCodeId ?? '';\n const rightCode = right.taxCodeId ?? '';\n if (leftCode !== rightCode) return leftCode < rightCode ? -1 : 1;\n const leftComponent = left.taxComponentId ?? '';\n const rightComponent = right.taxComponentId ?? '';\n return leftComponent < rightComponent\n ? -1\n : leftComponent > rightComponent\n ? 1\n : 0;\n });\n const subtotal = lines.reduce((sum, line) => sum + BigInt(line.netMinor), 0n);\n const discountTotal = lines.reduce(\n (sum, line) => sum + BigInt(line.discountMinor),\n 0n,\n );\n const tax = lines.reduce((sum, line) => sum + BigInt(line.taxMinor), 0n);\n return {\n lines,\n subtotalMinor: safeMoney(subtotal),\n discountTotalMinor: safeMoney(discountTotal),\n taxMinor: safeMoney(tax),\n totalMinor: safeMoney(subtotal + tax),\n taxes,\n };\n}\n\nfunction selectedCode(\n id: string | null | undefined,\n source: TaxCodeResolutionSource,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode | null {\n if (!id) return null;\n const taxCode = context.codes[id];\n if (!taxCode)\n validationError('TAX_CODE_NOT_FOUND', `Unknown tax code: ${id}`);\n if (typeof taxCode.active !== 'boolean')\n validationError('INVALID_MONEY_INPUT', `Tax code ${id} has invalid state`);\n if (!taxCode.active)\n validationError('TAX_CODE_INACTIVE', `Tax code ${id} is inactive`);\n if (\n taxCode.appliesTo !== 'sales' &&\n taxCode.appliesTo !== 'purchases' &&\n taxCode.appliesTo !== 'both'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n `Tax code ${id} has invalid applicability`,\n );\n if (taxCode.appliesTo !== 'both' && taxCode.appliesTo !== context.direction)\n validationError(\n 'TAX_CODE_SCOPE',\n `Tax code ${id} does not apply to ${context.direction}`,\n );\n return { taxCode, source };\n}\n\n/** Resolve a line tax code from already-loaded values, without model or I/O access. */\nexport function resolveLineTaxCode(\n line: ResolveLineTaxCodeInput,\n context: ResolveLineTaxCodeContext,\n): ResolvedLineTaxCode {\n if (\n !line ||\n typeof line !== 'object' ||\n !context ||\n typeof context !== 'object'\n )\n validationError(\n 'INVALID_MONEY_INPUT',\n 'Tax-code resolution inputs must be objects',\n );\n if (!context.codes || typeof context.codes !== 'object')\n validationError('INVALID_MONEY_INPUT', 'Tax-code map must be an object');\n if (\n line.lineAmountType !== 'exclusive' &&\n line.lineAmountType !== 'inclusive' &&\n line.lineAmountType !== 'none'\n )\n validationError('INVALID_MONEY_INPUT', 'Unknown line amount type');\n if (context.direction !== 'sales' && context.direction !== 'purchases')\n validationError('INVALID_MONEY_INPUT', 'Unknown tax-code direction');\n if (line.lineAmountType === 'none') {\n if (!context.outOfScopeCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'None mode requires an out-of-scope tax code',\n );\n const resolved = selectedCode(context.outOfScopeCodeId, 'none', context);\n if (resolved?.taxCode?.kind !== 'out-of-scope')\n validationError(\n 'TAX_CODE_KIND',\n 'None mode requires an out-of-scope tax code',\n );\n return resolved;\n }\n if (context.customerTaxExempt && !line.lineOverride) {\n if (!context.exemptCodeId)\n validationError(\n 'TAX_CODE_NOT_FOUND',\n 'An exempt customer requires an exempt tax code',\n );\n const exempt = selectedCode(\n context.exemptCodeId,\n 'exempt-customer',\n context,\n );\n if (exempt?.taxCode?.kind !== 'exempt')\n validationError(\n 'TAX_CODE_KIND',\n 'Customer exemption requires an exempt tax code',\n );\n return exempt;\n }\n const candidates: readonly [\n string | null | undefined,\n TaxCodeResolutionSource,\n ][] = [\n [line.lineOverride, 'line'],\n [context.productCodeId, 'product'],\n [context.partyCodeId, 'customer'],\n [context.appDefaultCodeId, 'app'],\n ];\n for (const [id, source] of candidates) {\n const resolved = selectedCode(id, source, context);\n if (resolved) return resolved;\n }\n return { taxCode: null, source: 'none' };\n}\n"],"mappings":";;;AASO,SAAS,wBACd,SACA,OACA,SACM;CACN,KAAA,MAAW,CAAC,OAAO,UAAU,SAC3B,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,CAAC,OAAO,UAAU,KAAK,GACpD,MAAM,IAAI,MACR,GAAG,QAAO,GAAI,MAAK,IAAK,MAAK,yEACM,MAAK,6CAE1C;AAGN;AAiCO,IAAM,uBAAN,cAAmC,MAAM;CAK9C,YACW,MACT,SACA;EACA,MAAM,OAAO;EAHJ,KAAA,OAAA;EAIT,KAAK,gBAAgB;CACvB;CALW;CALO,OAAO;;CAEhB;AASX;AAqGA,IAAM,gBAAgB;AACtB,IAAM,sBAAsB,OAAO;AACnC,IAAM,iBAAiB,OAAO,OAAO,gBAAgB;AACrD,IAAM,aAAa;AAEnB,SAAS,gBAAgB,MAA2B,SAAwB;CAC1E,MAAM,IAAI,qBAAqB,MAAM,OAAO;AAC9C;AAEA,SAAS,iBAAiB,OAAe,OAAqB;CAC5D,IAAI,OAAO,UAAU,YAAY,CAAC,WAAW,KAAK,KAAK,GACrD,gBACE,uBACA,GAAG,MAAK,2BACV;AACJ;AAEA,SAAS,UAAU,OAAuB;CACxC,IAAI,QAAQ,kBAAkB,QAAQ,CAAC,gBACrC,gBAAgB,gBAAgB,wCAAwC;CAC1E,OAAO,OAAO,KAAK;AACrB;AAEA,SAAS,MAAM,OAAuB;CACpC,IAAI,CAAC,OAAO,cAAc,KAAK,GAC7B,gBAAgB,gBAAgB,wCAAwC;CAC1E,OAAO,OAAO,KAAK;AACrB;AAOA,SAAS,cAAc,OAAe,WAAiC;CACrE,IAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,KAAK,QAAQ,OAAO,kBACzD,gBACE,uBACA,yCACF;CACF,MAAM,CAAC,UAAU,eAAe,OAAO,MAAM,SAAS,CAAA,CAAE,MAAM,GAAG;CACjE,MAAM,CAAC,OAAO,WAAW,MAAM,SAAS,MAAM,GAAG;CACjD,MAAM,SAAS,SAAS,SAAS,OAAO,YAAY;CACpD,IAAI,SAAS,WACX,gBACE,uBACA,kDACF;CACF,MAAM,cAAc,OAAO,QAAQ,QAAQ;CAC3C,OAAO,SAAS,IACZ;EAAE,aAAa,cAAc,OAAO,OAAO,CAAC,MAAM;EAAG,OAAO;CAAG,IAC/D;EAAE;EAAa,OAAO,OAAO,OAAO,MAAM;CAAE;AAClD;AAEA,SAAS,aAAa,OAAuB;CAC3C,IACE,OAAO,UAAU,YACjB,CAAC,qCAAqC,KAAK,KAAK,GAEhD,gBACE,wBACA,wFACF;CACF,MAAM,CAAC,OAAO,WAAW,MAAM,MAAM,MAAM,GAAG;CAC9C,MAAM,QAAQ,OAAO,KAAK,IAAI,gBAAgB,OAAO,SAAS,OAAO,GAAG,GAAG,CAAC;CAC5E,IAAI,QAAQ,qBACV,gBAAgB,wBAAwB,qBAAqB;CAC/D,OAAO;AACT;AAEA,SAAS,gBACP,MACA,OAC+D;CAC/D,IAAI,CAAC,QAAQ,OAAO,SAAS,UAC3B,gBAAgB,uBAAuB,4BAA4B;CACrE,iBAAiB,KAAK,IAAI,aAAa;CACvC,IACE,KAAK,SAAS,aACd,KAAK,SAAS,gBACd,KAAK,SAAS,YACd,KAAK,SAAS,gBAEd,gBAAgB,iBAAiB,uBAAuB;CAC1D,IAAI,CAAC,MAAM,QAAQ,KAAK,UAAU,GAChC,gBACE,uBACA,sCACF;CACF,IAAI,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW,GACxD,gBACE,0BACA,8CACF;CACF,IAAI,KAAK,SAAS,aAAa,KAAK,WAAW,WAAW,GACxD,gBACE,mCACA,6CACF;CACF,MAAM,uBAAO,IAAI,IAAY;CAC7B,OAAO,KAAK,WAAW,KAAK,cAAc;EACxC,IAAI,CAAC,aAAa,OAAO,cAAc,UACrC,gBAAgB,uBAAuB,iCAAiC;EAC1E,iBAAiB,UAAU,gBAAgB,kBAAkB;EAC7D,IAAI,KAAK,IAAI,UAAU,cAAc,GACnC,gBACE,gCACA,qCACF;EACF,KAAK,IAAI,UAAU,cAAc;EACjC,IAAI,OAAO,UAAU,aAAa,WAChC,gBACE,uBACA,wCACF;EACF,MAAM,OAAO,aAAa,UAAU,OAAO;EAC3C,MAAM,WAAW,MAAM,IAAI,UAAU,cAAc;EACnD,IAAI,aAAa,KAAA,KAAa,aAAa,MACzC,gBACE,+BACA,kDACF;EACF,MAAM,IAAI,UAAU,gBAAgB,IAAI;EACxC,OAAO;GACL,gBAAgB,UAAU;GAC1B;GACA,UAAU,UAAU;EACtB;CACF,CAAC;AACH;AAEA,SAAS,YAAY,OAAe,UAAsC;CACxE,IAAI,CAAC,YAAY,OAAO,aAAa,UACnC,gBAAgB,uBAAuB,kCAAkC;CAC3E,MAAM,UAAU;CAIhB,IAAI,QAAQ,SAAS,KAAA,KAAa,QAAQ,UAAU,KAAA,GAClD,gBACE,uBACA,yDACF;CACF,IAAI;CACJ,IAAI,SAAS,SAAS,QAAQ;EAC5B,IAAI,QAAQ,SAAS,KAAA,KAAa,QAAQ,UAAU,KAAA,GAClD,gBACE,uBACA,yDACF;EACF,SAAS;CACX,OAAA,IAAW,SAAS,SAAS,WAC3B,SAAS,oBACP,QAAQ,aAAa,SAAS,IAAI,GAClC,mBACF;MACF,IAAW,SAAS,SAAS,UAC3B,SAAS,MAAM,SAAS,KAAK;MAE7B,gBAAgB,uBAAuB,uBAAuB;CAEhE,IAAI,WAAW,MAAM,UAAU,MAAM,SAAS,OAAO,QAAQ,IAC3D,gBACE,iBACA,8CACF;CACF,IAAI,UAAU,MAAM,WAAW,IAC7B,gBAAgB,iBAAiB,sCAAsC;CACzE,MAAM,aAAa,UAAmB,QAAQ,KAAK,CAAC,QAAQ;CAC5D,IAAI,UAAU,MAAM,IAAI,UAAU,KAAK,GACrC,gBAAgB,0BAA0B,8BAA8B;CAC1E,OAAO;AACT;AAEA,SAAS,sBAAsB,OAKtB;CACP,IAAI,CAAC,SAAS,OAAO,UAAU,UAC7B,gBAAgB,uBAAuB,+BAA+B;CACxE,IACE,OAAO,MAAM,aAAa,YAC1B,CAAC,aAAa,KAAK,MAAM,QAAQ,KACjC,CAAC,qBAAqB,IAAI,MAAM,QAAQ,KACxC,qBAAqB,IAAI,MAAM,QAAQ,MAAM,MAE7C,gBACE,qBACA,uEACF;CACF,IACE,MAAM,mBAAmB,eACzB,MAAM,mBAAmB,eACzB,MAAM,mBAAmB,QAEzB,gBAAgB,uBAAuB,0BAA0B;CACnE,IAAI,MAAM,kBAAkB,UAAU,MAAM,kBAAkB,YAC5D,gBAAgB,uBAAuB,4BAA4B;CACrE,IAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,GAC5B,gBAAgB,uBAAuB,wBAAwB;AACnE;AAGO,SAAS,uBAAuB,OAKf;CACtB,sBAAsB,KAAK;CAC3B,MAAM,sBAAM,IAAI,IAAY;CAC5B,MAAM,wBAAQ,IAAI,IAAoB;CACtC,MAAM,UAAU,MAAM,MAAM,KAAK,SAAS;EACxC,IAAI,CAAC,QAAQ,OAAO,SAAS,UAC3B,gBAAgB,uBAAuB,8BAA8B;EACvE,iBAAiB,KAAK,IAAI,SAAS;EACnC,IAAI,IAAI,IAAI,KAAK,EAAE,GACjB,gBAAgB,uBAAuB,yBAAyB;EAClE,IAAI,IAAI,KAAK,EAAE;EACf,MAAM,cACJ,KAAK,mBAAmB,KAAA,IAAY,OAAO,MAAM,KAAK,cAAc;EACtE,MAAM,WAAW,cAAc,KAAK,UAAU,CAAC;EAC/C,MAAM,QACJ,eACA,oBACE,SAAS,cAAc,MAAM,KAAK,SAAS,GAC3C,SAAS,KACX;EACF,UAAU,KAAK;EACf,MAAM,WACJ,gBAAgB,OAAO,YAAY,OAAO,KAAK,QAAQ,IAAI;EAC7D,MAAM,SAAS,QAAQ;EACvB,UAAU,MAAM;EAChB,IAAI,MAAM,mBAAmB,UAAU,CAAC,KAAK,SAC3C,gBACE,sBACA,gDACF;EACF,IACE,MAAM,mBAAmB,UACzB,KAAK,SAAS,SAAS,gBAEvB,gBACE,iBACA,gDACF;EACF,MAAM,aAAa,KAAK,UAAU,gBAAgB,KAAK,SAAS,KAAK,IAAI,CAAC;EAG1E,IAAI,iBAAiB;EACrB,IAAI,mBAAmB;EACvB,MAAM,UAAU,WAAW,KAAK,cAAc;GAC5C,MAAM,YACJ,UAAU,QACT,UAAU,WAAW,iBAAiB;GACzC,MAAM,cAAc,sBAAsB;GAC1C,iBAAiB,iBAAiB,sBAAsB;GACxD,mBAAmB;GACnB,OAAO;IAAE,GAAG;IAAW;IAAW;GAAY;EAChD,CAAC;EAGD,OAAO;GACL,OAAO;GACP;GACA;GACA;GACA;GACA,WAPA,gBAAgB,QAAQ,MAAM,mBAAmB;GAQjD,OACE,MAAM,mBAAmB,SACrB,CAAC,IACD,QAAQ,KAAK,WAAW,WAAW;IACjC,GAAG;IACH,UAAU,UAAU,WAChB,WACG,MAAM,GAAG,KAAK,CAAA,CACd,KAAK,UAAU,MAAM,cAAc,IACtC,CAAC;IACL,WAAW,SAAS,UAAU,YAAY;IAC1C,aAAa,UAAU,cAAc;GACvC,EAAE;GACR,uBAAO,IAAI,IAAoB;GAC/B,uBAAO,IAAI,IAAoB;EACjC;CACF,CAAC;CAED,MAAM,eAAe,IAAI,IACvB,CAAC,GAAG,MAAM,KAAK,CAAC,CAAA,CAAE,KAAK,OAAO,CAAC,oBAAI,IAAI,IAAY,CAAC,CAAC,CACvD;CACA,KAAA,MAAW,QAAQ,SACjB,KAAA,MAAW,aAAa,KAAK,OAC3B,KAAA,MAAW,SAAS,UAAU,UAC5B,aAAa,IAAI,UAAU,cAAc,CAAA,EAAG,IAAI,KAAK;CAC3D,MAAM,QAAkB,CAAC;CACzB,OAAO,aAAa,MAAM;EACxB,MAAM,QAAQ,CAAC,GAAG,YAAY,CAAA,CAC3B,QAAQ,GAAG,WAAW,MAAM,SAAS,CAAC,CAAA,CACtC,KAAK,CAAC,QAAQ,EAAE,CAAA,CAChB,KAAK;EACR,IAAI,CAAC,MAAM,QACT,gBACE,kCACA,yDACF;EACF,KAAA,MAAW,MAAM,OAAO;GACtB,MAAM,KAAK,EAAE;GACb,aAAa,OAAO,EAAE;GACtB,KAAA,MAAW,SAAS,aAAa,OAAO,GAAG,MAAM,OAAO,EAAE;EAC5D;CACF;CACA,MAAM,YACJ,MACA,cACG;EACH,IAAI,KAAK,WAAW,OAAO;EAC3B,MAAM,QACJ,KAAK,SACL,UAAU,SAAS,QAChB,KAAK,OAAO,OAAO,KAAK,MAAM,IAAI,EAAE,KAAK,KAC1C,EACF;EACF,UAAU,KAAK;EACf,KAAK,MAAM,IAAI,UAAU,gBAAgB,KAAK;EAC9C,OAAO;GACL,WAAW,QAAQ,UAAU;GAC7B,aAAa;EACf;CACF;CACA,IAAI,MAAM,kBAAkB,QAC1B,KAAA,MAAW,QAAQ,SACjB,KAAA,MAAW,aAAa,KAAK,OAAO;EAClC,MAAM,QAAQ,SAAS,MAAM,SAAS;EACtC,KAAK,MAAM,IACT,UAAU,gBACV,oBAAoB,MAAM,WAAW,MAAM,WAAW,CACxD;CACF;MAEF,KAAA,MAAW,eAAe,OAAO;EAC/B,MAAM,WAAW,QAAQ,SAAS,SAAS;GACzC,MAAM,YAAY,KAAK,MAAM,MAC1B,SAAS,KAAK,mBAAmB,WACpC;GACA,OAAO,YAAY,CAAC;IAAE;IAAM,OAAO,SAAS,MAAM,SAAS;GAAE,CAAC,IAAI,CAAC;EACrE,CAAC;EACD,MAAM,YAAY,wBAChB,SAAS,KAAK,EAAE,MAAM,aAAa;GACjC,IAAI,KAAK,MAAM;GACf,WAAW,MAAM;GACjB,aAAa,MAAM;EACrB,EAAE,CACJ;EACA,KAAA,MAAW,cAAc,UAAU,aACjC,SACG,MAAM,EAAE,WAAW,KAAK,MAAM,OAAO,WAAW,EAAE,CAAA,EACjD,KAAK,MAAM,IAAI,aAAa,WAAW,KAAK;CACpD;CAGF,MAAM,QAAQ,QAAQ,KAAK,SAA0B;EACnD,MAAM,aAAa,KAAK,MAAM,KAAK,eAAe;GAChD,gBAAgB,UAAU;GAC1B,UAAU,UAAU,KAAK,MAAM,IAAI,UAAU,cAAc,KAAK,EAAE;EACpE,EAAE;EACF,MAAMA,OAAM,WAAW,QACpB,KAAK,cAAc,MAAM,OAAO,UAAU,QAAQ,GACnD,EACF;EACA,MAAM,MACJ,KAAK,gBACJ,MAAM,mBAAmB,cAAc,KAAK,SAASA,OAAM,KAAK;EACnE,KAAA,IAAS,QAAQ,GAAG,QAAQ,WAAW,QAAQ,SAAS;GACtD,MAAM,SAAS,KAAK,MAAM;GAC1B,IAAI,OAAO,UACT,OAAO,OAAO,WAAW,QAAQ;IAC/B,UAAU;IACV,cAAc,UACZ,KAAK,YACD,MACE,OAAO,SAAS,QACb,KAAK,OAAO,OAAO,KAAK,MAAM,IAAI,EAAE,KAAK,KAC1C,EACF,IACD,KAAK,MAAM,IAAI,OAAO,cAAc,KAAK,GAChD;GACF,CAAC;EACL;EACA,MAAM,SACJ,KAAK,gBAAgB,QAAQ,MAAM,mBAAmB,cAClD,MAAMA,OACN,KAAK;EACX,OAAO;GACL,IAAI,KAAK,MAAM;GACf,YAAY,UAAU,KAAK,KAAK;GAChC,eAAe,UAAU,KAAK,QAAQ;GACtC,aAAa,UAAU,MAAM;GAC7B;GACA,UAAU,UAAUA,IAAG;GACvB,UAAU,UAAU,GAAG;EACzB;CACF,CAAC;CAED,MAAM,0BAAU,IAAI,IAAoC;CACxD,KAAA,IAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;EACnD,MAAM,SAAS,QAAQ,MAAK,CAAE;EAC9B,MAAM,SAAS,MAAM;EACrB,IACE,CAAC,OAAO,WACR,OAAO,QAAQ,WAAW,WAAW,KACrC,MAAM,mBAAmB,QACzB;GACA,MAAM,MAAM,GAAG,OAAO,SAAS,MAAM,GAAE;GACvC,MAAM,MAAM,QAAQ,IAAI,GAAG,KAAK;IAC9B,WAAW,OAAO,SAAS,MAAM;IACjC,gBAAgB;IAChB,cAAc;IACd,UAAU;GACZ;GACA,IAAI,eAAe,UACjB,OAAO,IAAI,YAAY,IAAI,OAAO,OAAO,QAAQ,CACnD;GACA,QAAQ,IAAI,KAAK,GAAG;GACpB;EACF;EACA,KAAA,MAAW,aAAa,OAAO,YAAY;GACzC,IAAI,CAAC,OAAO,SACV,gBACE,uBACA,mCACF;GACF,MAAM,MAAM,GAAG,OAAO,QAAQ,GAAE,IAAS,UAAU;GACnD,MAAM,MAAM,QAAQ,IAAI,GAAG,KAAK;IAC9B,WAAW,OAAO,QAAQ;IAC1B,gBAAgB,UAAU;IAC1B,cAAc;IACd,UAAU;GACZ;GACA,IAAI,eAAe,UACjB,OAAO,IAAI,YAAY,IACrB,OAAO,UAAU,gBAAgB,OAAO,QAAQ,CACpD;GACA,IAAI,UAAU,UACZ,IAAI,WAAW,UACb,OAAO,IAAI,YAAY,CAAC,IAAI,OAAO,OAAO,QAAQ,CACpD;GACF,IAAI,WAAW,UACb,OAAO,IAAI,QAAQ,IAAI,OAAO,UAAU,QAAQ,CAClD;GACA,QAAQ,IAAI,KAAK,GAAG;EACtB;CACF;CACA,MAAM,QAAQ,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAA,CAAE,MAAM,MAAM,UAAU;EACxD,MAAM,WAAW,KAAK,aAAa;EACnC,MAAM,YAAY,MAAM,aAAa;EACrC,IAAI,aAAa,WAAW,OAAO,WAAW,YAAY,KAAK;EAC/D,MAAM,gBAAgB,KAAK,kBAAkB;EAC7C,MAAM,iBAAiB,MAAM,kBAAkB;EAC/C,OAAO,gBAAgB,iBACnB,KACA,gBAAgB,iBACd,IACA;CACR,CAAC;CACD,MAAM,WAAW,MAAM,QAAQ,KAAK,SAAS,MAAM,OAAO,KAAK,QAAQ,GAAG,EAAE;CAC5E,MAAM,gBAAgB,MAAM,QACzB,KAAK,SAAS,MAAM,OAAO,KAAK,aAAa,GAC9C,EACF;CACA,MAAM,MAAM,MAAM,QAAQ,KAAK,SAAS,MAAM,OAAO,KAAK,QAAQ,GAAG,EAAE;CACvE,OAAO;EACL;EACA,eAAe,UAAU,QAAQ;EACjC,oBAAoB,UAAU,aAAa;EAC3C,UAAU,UAAU,GAAG;EACvB,YAAY,UAAU,WAAW,GAAG;EACpC;CACF;AACF;AAEA,SAAS,aACP,IACA,QACA,SAC4B;CAC5B,IAAI,CAAC,IAAI,OAAO;CAChB,MAAM,UAAU,QAAQ,MAAM;CAC9B,IAAI,CAAC,SACH,gBAAgB,sBAAsB,qBAAqB,IAAI;CACjE,IAAI,OAAO,QAAQ,WAAW,WAC5B,gBAAgB,uBAAuB,YAAY,GAAE,mBAAoB;CAC3E,IAAI,CAAC,QAAQ,QACX,gBAAgB,qBAAqB,YAAY,GAAE,aAAc;CACnE,IACE,QAAQ,cAAc,WACtB,QAAQ,cAAc,eACtB,QAAQ,cAAc,QAEtB,gBACE,uBACA,YAAY,GAAE,2BAChB;CACF,IAAI,QAAQ,cAAc,UAAU,QAAQ,cAAc,QAAQ,WAChE,gBACE,kBACA,YAAY,GAAE,qBAAsB,QAAQ,WAC9C;CACF,OAAO;EAAE;EAAS;CAAO;AAC3B;AAGO,SAAS,mBACd,MACA,SACqB;CACrB,IACE,CAAC,QACD,OAAO,SAAS,YAChB,CAAC,WACD,OAAO,YAAY,UAEnB,gBACE,uBACA,4CACF;CACF,IAAI,CAAC,QAAQ,SAAS,OAAO,QAAQ,UAAU,UAC7C,gBAAgB,uBAAuB,gCAAgC;CACzE,IACE,KAAK,mBAAmB,eACxB,KAAK,mBAAmB,eACxB,KAAK,mBAAmB,QAExB,gBAAgB,uBAAuB,0BAA0B;CACnE,IAAI,QAAQ,cAAc,WAAW,QAAQ,cAAc,aACzD,gBAAgB,uBAAuB,4BAA4B;CACrE,IAAI,KAAK,mBAAmB,QAAQ;EAClC,IAAI,CAAC,QAAQ,kBACX,gBACE,sBACA,6CACF;EACF,MAAM,WAAW,aAAa,QAAQ,kBAAkB,QAAQ,OAAO;EACvE,IAAI,UAAU,SAAS,SAAS,gBAC9B,gBACE,iBACA,6CACF;EACF,OAAO;CACT;CACA,IAAI,QAAQ,qBAAqB,CAAC,KAAK,cAAc;EACnD,IAAI,CAAC,QAAQ,cACX,gBACE,sBACA,gDACF;EACF,MAAM,SAAS,aACb,QAAQ,cACR,mBACA,OACF;EACA,IAAI,QAAQ,SAAS,SAAS,UAC5B,gBACE,iBACA,gDACF;EACF,OAAO;CACT;CACA,MAAM,aAGA;EACJ,CAAC,KAAK,cAAc,MAAM;EAC1B,CAAC,QAAQ,eAAe,SAAS;EACjC,CAAC,QAAQ,aAAa,UAAU;EAChC,CAAC,QAAQ,kBAAkB,KAAK;CAClC;CACA,KAAA,MAAW,CAAC,IAAI,WAAW,YAAY;EACrC,MAAM,WAAW,aAAa,IAAI,QAAQ,OAAO;EACjD,IAAI,UAAU,OAAO;CACvB;CACA,OAAO;EAAE,SAAS;EAAM,QAAQ;CAAO;AACzC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observed-purchase-price-internal.d.ts","sourceRoot":"","sources":["../src/observed-purchase-price-internal.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,eAAO,MAAM,uBAAuB,eAA2C,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
|
|
2
|
+
import { type ReceivedPurchaseMoneyFacts } from './received-purchase-money.js';
|
|
3
|
+
/** Null means absent from source evidence. No missing value is inferred as zero. */
|
|
4
|
+
export interface ObservedPurchaseAmounts {
|
|
5
|
+
netMinor: number | null;
|
|
6
|
+
taxMinor: number | null;
|
|
7
|
+
grossMinor: number | null;
|
|
8
|
+
}
|
|
9
|
+
export interface ObservedPurchaseLine extends ObservedPurchaseAmounts {
|
|
10
|
+
sourceKey: string;
|
|
11
|
+
description: string;
|
|
12
|
+
quantityText?: string;
|
|
13
|
+
unitRateText?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface ObservedPurchasePriceFacts extends ObservedPurchaseAmounts {
|
|
16
|
+
currency: string;
|
|
17
|
+
detail: {
|
|
18
|
+
kind: 'header-only';
|
|
19
|
+
} | {
|
|
20
|
+
kind: 'lines';
|
|
21
|
+
lines: ObservedPurchaseLine[];
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export interface PurchasePriceObservationSnapshot {
|
|
25
|
+
version: 1;
|
|
26
|
+
requestId: string;
|
|
27
|
+
sourceNamespace: string;
|
|
28
|
+
sourceKey: string;
|
|
29
|
+
kind: 'supplier-quote' | 'purchase-order';
|
|
30
|
+
vendorId: string;
|
|
31
|
+
/** Source status is retained text, never current approval or acceptance. */
|
|
32
|
+
sourceStatus: string;
|
|
33
|
+
effectiveOn: string;
|
|
34
|
+
evidenceRef: string;
|
|
35
|
+
facts: ObservedPurchasePriceFacts;
|
|
36
|
+
}
|
|
37
|
+
export interface PurchasePriceCompletion {
|
|
38
|
+
requestId: string;
|
|
39
|
+
reviewEvidenceRef: string;
|
|
40
|
+
contractId: string;
|
|
41
|
+
facts: ReceivedPurchaseMoneyFacts;
|
|
42
|
+
}
|
|
43
|
+
export interface PurchasePriceObservationView {
|
|
44
|
+
id: string;
|
|
45
|
+
snapshot: PurchasePriceObservationSnapshot;
|
|
46
|
+
completion: PurchasePriceCompletion | null;
|
|
47
|
+
/** Complete, usable aggregates exist only on the explicitly completed Contract. */
|
|
48
|
+
monetaryAggregate: null;
|
|
49
|
+
}
|
|
50
|
+
export declare function validateObservedPurchasePriceFacts(raw: unknown): ObservedPurchasePriceFacts;
|
|
51
|
+
/** Host authorizes import/recording; source approval never becomes current contract acceptance. */
|
|
52
|
+
export declare function recordPurchasePriceObservation(input: {
|
|
53
|
+
db: DatabaseInterface;
|
|
54
|
+
tenantId: string;
|
|
55
|
+
snapshot: PurchasePriceObservationSnapshot;
|
|
56
|
+
}): Promise<PurchasePriceObservationView>;
|
|
57
|
+
export declare function readPurchasePriceObservation(input: {
|
|
58
|
+
db: DatabaseInterface;
|
|
59
|
+
tenantId: string;
|
|
60
|
+
id: string;
|
|
61
|
+
}): Promise<PurchasePriceObservationView>;
|
|
62
|
+
/** Explicit reviewed completion creates a separate draft; no source status implies approval. */
|
|
63
|
+
export declare function completePurchasePriceObservation(input: {
|
|
64
|
+
db: DatabaseInterface;
|
|
65
|
+
tenantId: string;
|
|
66
|
+
id: string;
|
|
67
|
+
requestId: string;
|
|
68
|
+
reviewEvidenceRef: string;
|
|
69
|
+
facts: ReceivedPurchaseMoneyFacts;
|
|
70
|
+
}): Promise<PurchasePriceObservationView>;
|
|
71
|
+
//# sourceMappingURL=observed-purchase-price.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observed-purchase-price.d.ts","sourceRoot":"","sources":["../src/observed-purchase-price.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAS7E,OAAO,EAEL,KAAK,0BAA0B,EAGhC,MAAM,8BAA8B,CAAC;AAGtC,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AACD,MAAM,WAAW,oBAAqB,SAAQ,uBAAuB;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AACD,MAAM,WAAW,0BAA2B,SAAQ,uBAAuB;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EACF;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,GACvB;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,oBAAoB,EAAE,CAAA;KAAE,CAAC;CACtD;AACD,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,CAAC,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,gBAAgB,GAAG,gBAAgB,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,0BAA0B,CAAC;CACnC;AACD,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,0BAA0B,CAAC;CACnC;AACD,MAAM,WAAW,4BAA4B;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,gCAAgC,CAAC;IAC3C,UAAU,EAAE,uBAAuB,GAAG,IAAI,CAAC;IAC3C,mFAAmF;IACnF,iBAAiB,EAAE,IAAI,CAAC;CACzB;AA2CD,wBAAgB,kCAAkC,CAChD,GAAG,EAAE,OAAO,GACX,0BAA0B,CAgD5B;AAwED,mGAAmG;AACnG,wBAAsB,8BAA8B,CAAC,KAAK,EAAE;IAC1D,EAAE,EAAE,iBAAiB,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,gCAAgC,CAAC;CAC5C,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAmCxC;AACD,wBAAsB,4BAA4B,CAAC,KAAK,EAAE;IACxD,EAAE,EAAE,iBAAiB,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAQxC;AAQD,gGAAgG;AAChG,wBAAsB,gCAAgC,CAAC,KAAK,EAAE;IAC5D,EAAE,EAAE,iBAAiB,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,KAAK,EAAE,0BAA0B,CAAC;CACnC,GAAG,OAAO,CAAC,4BAA4B,CAAC,CAoGxC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/** Exact monetary evidence received from a supplier, independent of calculated pricing. */
|
|
2
|
+
import type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
|
|
3
|
+
import { type Contract } from './models/Contract.js';
|
|
4
|
+
import { type TaxCodeKind } from './money.js';
|
|
5
|
+
/** A supplier tax component. Null explicitly retains an unknown fact. */
|
|
6
|
+
export interface ReceivedPurchaseTaxComponent {
|
|
7
|
+
sourceKey: string;
|
|
8
|
+
label: string;
|
|
9
|
+
amountMinor: number;
|
|
10
|
+
classification: TaxCodeKind | null;
|
|
11
|
+
/** Explicit report identity/basis; omission retains unknown, never implies a rate. */
|
|
12
|
+
taxCodeId?: string | null;
|
|
13
|
+
taxComponentId?: string | null;
|
|
14
|
+
taxableMinor?: number | null;
|
|
15
|
+
/** Explicit net allocation when supplier taxable basis includes prior taxes. */
|
|
16
|
+
netMinor?: number | null;
|
|
17
|
+
recoverableMinor: number | null;
|
|
18
|
+
}
|
|
19
|
+
/** Complete source line money; optional source decimal text is evidence, not a calculator input. */
|
|
20
|
+
export interface ReceivedPurchaseMoneyLine {
|
|
21
|
+
sourceKey: string;
|
|
22
|
+
description: string;
|
|
23
|
+
netMinor: number;
|
|
24
|
+
taxMinor: number;
|
|
25
|
+
grossMinor: number;
|
|
26
|
+
quantityText?: string;
|
|
27
|
+
unitRateText?: string;
|
|
28
|
+
}
|
|
29
|
+
/** Monetary evidence without a fabricated rate, quantity, or line allocation. */
|
|
30
|
+
export interface ReceivedPurchaseMoneyFacts {
|
|
31
|
+
currency: string;
|
|
32
|
+
netMinor: number;
|
|
33
|
+
taxMinor: number;
|
|
34
|
+
grossMinor: number;
|
|
35
|
+
taxComponents: ReceivedPurchaseTaxComponent[] | null;
|
|
36
|
+
detail: {
|
|
37
|
+
kind: 'header-only';
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'lines';
|
|
40
|
+
lines: ReceivedPurchaseMoneyLine[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** Immutable request and supplier evidence identity retained with the amounts. */
|
|
44
|
+
export interface ReceivedPurchaseMoneySnapshot {
|
|
45
|
+
version: 1;
|
|
46
|
+
requestId: string;
|
|
47
|
+
evidenceRef: string;
|
|
48
|
+
facts: ReceivedPurchaseMoneyFacts;
|
|
49
|
+
sourceQuote: ReceivedPurchaseQuoteSource | null;
|
|
50
|
+
}
|
|
51
|
+
export interface ReceivedPurchaseQuoteSource {
|
|
52
|
+
contractId: string;
|
|
53
|
+
relationship: 'copy' | 'negotiated';
|
|
54
|
+
}
|
|
55
|
+
/** Public command input. The host authorizes the human before calling this command. */
|
|
56
|
+
export interface RecordReceivedPurchaseMoneyInput {
|
|
57
|
+
db: DatabaseInterface;
|
|
58
|
+
tenantId: string;
|
|
59
|
+
contractId: string;
|
|
60
|
+
requestId: string;
|
|
61
|
+
evidenceRef: string;
|
|
62
|
+
facts: ReceivedPurchaseMoneyFacts;
|
|
63
|
+
sourceQuote?: ReceivedPurchaseQuoteSource;
|
|
64
|
+
}
|
|
65
|
+
/** Complete received sales agreement evidence; recording is not revenue/tax recognition. */
|
|
66
|
+
export type ReceivedSalesContractMoneyFacts = ReceivedPurchaseMoneyFacts;
|
|
67
|
+
export type ReceivedSalesContractMoneySnapshot = ReceivedPurchaseMoneySnapshot;
|
|
68
|
+
export type RecordReceivedSalesContractMoneyInput = Omit<RecordReceivedPurchaseMoneyInput, 'sourceQuote'>;
|
|
69
|
+
/** Record supplied complete facts on one empty draft Order/Agreement. */
|
|
70
|
+
export declare function recordReceivedSalesContractMoney(input: RecordReceivedSalesContractMoneyInput): Promise<ReceivedSalesContractMoneySnapshot>;
|
|
71
|
+
/** Read exact sales agreement evidence without calculating or recognizing an invoice. */
|
|
72
|
+
export declare function getReceivedSalesContractMoney(contract: Contract): ReceivedSalesContractMoneySnapshot | null;
|
|
73
|
+
/** Validate and canonicalize exact received money, retaining unknowns as null. */
|
|
74
|
+
export declare function validateReceivedPurchaseMoneyFacts(value: unknown): ReceivedPurchaseMoneyFacts;
|
|
75
|
+
/** Read validated received evidence; calculated contracts return null. */
|
|
76
|
+
export declare function getReceivedPurchaseMoney(contract: Pick<Contract, 'moneyAuthority' | 'receivedPurchaseMoneyJson'>): ReceivedPurchaseMoneySnapshot | null;
|
|
77
|
+
/** Record immutable source facts on one empty draft SupplierQuote or PurchaseOrder, retry safely. */
|
|
78
|
+
export declare function recordReceivedPurchaseMoney(input: RecordReceivedPurchaseMoneyInput): Promise<ReceivedPurchaseMoneySnapshot>;
|
|
79
|
+
/** A received order cannot silently disappear from tax reporting when facts are unknown. */
|
|
80
|
+
export declare class ReceivedPurchaseTaxClassificationRequired extends Error {
|
|
81
|
+
readonly contractId: string;
|
|
82
|
+
readonly code = "RECEIVED_PURCHASE_TAX_CLASSIFICATION_REQUIRED";
|
|
83
|
+
constructor(contractId: string);
|
|
84
|
+
}
|
|
85
|
+
/** @internal Project explicitly classified source facts without inventing DocumentTax rates. */
|
|
86
|
+
export declare function receivedPurchaseReportFacts(contract: Contract): import('./collections/DocumentTaxCollection.js').DocumentTaxReportFact[];
|
|
87
|
+
//# sourceMappingURL=received-purchase-money.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"received-purchase-money.d.ts","sourceRoot":"","sources":["../src/received-purchase-money.ts"],"names":[],"mappings":"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"}
|
package/dist/recipes.d.ts
CHANGED
|
@@ -382,6 +382,9 @@ export declare class InvoicingRecipe extends SmrtRecipe {
|
|
|
382
382
|
static options: {
|
|
383
383
|
readonly Invoice: {
|
|
384
384
|
readonly fields: {
|
|
385
|
+
readonly historicalSourceKeyHash: {
|
|
386
|
+
readonly visibility: "hidden";
|
|
387
|
+
};
|
|
385
388
|
readonly providerTaxAmount: {
|
|
386
389
|
readonly visibility: "hidden";
|
|
387
390
|
};
|
|
@@ -567,7 +570,7 @@ export declare class AgreementsRecipe extends SmrtRecipe {
|
|
|
567
570
|
icon: string;
|
|
568
571
|
description: string;
|
|
569
572
|
};
|
|
570
|
-
static models: (typeof
|
|
573
|
+
static models: (typeof ContractLineItem | typeof Contract)[];
|
|
571
574
|
static nav: {
|
|
572
575
|
label: string;
|
|
573
576
|
model: typeof Contract;
|
package/dist/recipes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../src/recipes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function withRetentionAccountingAuthority<T>(tenantId: string, invoiceId: string, operation: () => Promise<T>): Promise<T>;
|
|
2
|
+
export declare function hasRetentionAccountingAuthority(tenantId: string | null | undefined, invoiceId: string | null | undefined): boolean;
|
|
3
|
+
//# sourceMappingURL=retention-accounting-internal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-accounting-internal.d.ts","sourceRoot":"","sources":["../src/retention-accounting-internal.ts"],"names":[],"mappings":"AAOA,wBAAgB,gCAAgC,CAAC,CAAC,EAChD,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC,CAEZ;AACD,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACnC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACnC,OAAO,CAOT"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { type AccountingProvider, type CreditMemoInput, type QuickBooksReceivableMapping, type QuickBooksReceivableReadback, type QuickBooksReceivableRequest } from '@happyvertical/accounting';
|
|
2
|
+
import type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';
|
|
3
|
+
import { type FrozenInvoiceAccountingInput, type QuickBooksFrozenInvoiceMapping, type ReconcileFrozenInvoiceAccountingInput } from './invoice-accounting-sync.js';
|
|
4
|
+
import type { Invoice } from './models/Invoice.js';
|
|
5
|
+
import { type InvoiceRetentionEvidence } from './retention-money.js';
|
|
6
|
+
import { type AccountingInvoiceInput } from './types/index.js';
|
|
7
|
+
type Provider = Pick<AccountingProvider, 'type' | 'invoices' | 'creditMemos' | 'receivableTransfers'>;
|
|
8
|
+
interface Scope {
|
|
9
|
+
db: DatabaseInterface;
|
|
10
|
+
tenantId: string;
|
|
11
|
+
invoiceId: string;
|
|
12
|
+
provider: Provider;
|
|
13
|
+
}
|
|
14
|
+
interface ReconciliationEvidence {
|
|
15
|
+
outcome: 'found' | 'absent';
|
|
16
|
+
evidenceRef?: string;
|
|
17
|
+
externalId?: string;
|
|
18
|
+
recordedAt: string;
|
|
19
|
+
interruptedOwnerStopped: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface Step {
|
|
22
|
+
key: string;
|
|
23
|
+
status: 'in_flight' | 'unknown' | 'rejected' | 'confirmed';
|
|
24
|
+
attemptId: string;
|
|
25
|
+
request: QuickBooksReceivableRequest;
|
|
26
|
+
startedAt: string;
|
|
27
|
+
result?: QuickBooksReceivableReadback;
|
|
28
|
+
reconciliation?: ReconciliationEvidence;
|
|
29
|
+
priorAttempts?: {
|
|
30
|
+
attemptId: string;
|
|
31
|
+
status: string;
|
|
32
|
+
startedAt: string;
|
|
33
|
+
reconciliation?: ReconciliationEvidence;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
interface RefundRecording {
|
|
37
|
+
paymentId: string;
|
|
38
|
+
creditId: string;
|
|
39
|
+
requestId: string;
|
|
40
|
+
evidenceRef: string;
|
|
41
|
+
effectiveOn: string;
|
|
42
|
+
amountMinor: number;
|
|
43
|
+
paymentFingerprint: string;
|
|
44
|
+
committed: boolean;
|
|
45
|
+
}
|
|
46
|
+
interface CreditAdjustment {
|
|
47
|
+
creditId: string;
|
|
48
|
+
moneySnapshotId: string;
|
|
49
|
+
requestId: string;
|
|
50
|
+
evidenceRef: string;
|
|
51
|
+
effectiveOn: string;
|
|
52
|
+
grossMinor: number;
|
|
53
|
+
retainedMinor: number;
|
|
54
|
+
appliedMinor: number;
|
|
55
|
+
mapping: QuickBooksFrozenInvoiceMapping;
|
|
56
|
+
committed: boolean;
|
|
57
|
+
}
|
|
58
|
+
interface Release extends InvoiceRetentionEvidence {
|
|
59
|
+
amountMinor: number;
|
|
60
|
+
effectiveOn: string;
|
|
61
|
+
dueOn: string;
|
|
62
|
+
stepKey: string;
|
|
63
|
+
committed: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface RetainedInvoiceAccountingState {
|
|
66
|
+
version: 1;
|
|
67
|
+
invoiceId: string;
|
|
68
|
+
moneySnapshotId: string;
|
|
69
|
+
requestId: string;
|
|
70
|
+
evidenceRef: string;
|
|
71
|
+
currency: string;
|
|
72
|
+
grossMinor: number;
|
|
73
|
+
retainedMinor: number;
|
|
74
|
+
retentionAgreementHash: string;
|
|
75
|
+
effectiveOn: string;
|
|
76
|
+
mapping: QuickBooksReceivableMapping;
|
|
77
|
+
invoiceMapping: QuickBooksFrozenInvoiceMapping;
|
|
78
|
+
status: 'pending' | 'ready';
|
|
79
|
+
steps: Step[];
|
|
80
|
+
releases: Release[];
|
|
81
|
+
credits: CreditAdjustment[];
|
|
82
|
+
refunds: RefundRecording[];
|
|
83
|
+
}
|
|
84
|
+
export interface SyncRetainedInvoiceToAccountingInput extends Scope {
|
|
85
|
+
requestId: string;
|
|
86
|
+
evidenceRef: string;
|
|
87
|
+
effectiveOn: string;
|
|
88
|
+
mapping: QuickBooksReceivableMapping;
|
|
89
|
+
invoiceMapping: QuickBooksFrozenInvoiceMapping;
|
|
90
|
+
}
|
|
91
|
+
export interface ReleaseRetainedInvoiceToAccountingInput extends Scope, InvoiceRetentionEvidence {
|
|
92
|
+
amountMinor: number;
|
|
93
|
+
effectiveOn: string;
|
|
94
|
+
dueOn: string;
|
|
95
|
+
expectedUpdatedAt: string;
|
|
96
|
+
}
|
|
97
|
+
export declare function readRetainedInvoiceAccountingState(invoice: Invoice): RetainedInvoiceAccountingState | null;
|
|
98
|
+
/** Read-only review of the exact retained document; generic export stays blocked.
|
|
99
|
+
* The host supplies authorization, and every read stays on the caller's executor.
|
|
100
|
+
*/
|
|
101
|
+
export declare function loadRetainedInvoiceAccountingSnapshot(input: Omit<FrozenInvoiceAccountingInput, 'mapping'>): Promise<import("./invoice-accounting-sync.js").FrozenInvoiceAccountingSnapshot>;
|
|
102
|
+
/** Validate reviewed realm item/tax mapping without creating a provider operation. */
|
|
103
|
+
export declare function toRetainedInvoiceAccountingInput(input: FrozenInvoiceAccountingInput): Promise<AccountingInvoiceInput>;
|
|
104
|
+
type RetainedCreditReviewScope = Omit<FrozenInvoiceAccountingInput, 'mapping'> & {
|
|
105
|
+
creditInvoiceId: string;
|
|
106
|
+
};
|
|
107
|
+
/** Read an issued retained-first credit without permitting generic credit export. */
|
|
108
|
+
export declare function loadRetainedCreditAccountingSnapshot(input: RetainedCreditReviewScope): Promise<import("./invoice-accounting-sync.js").FrozenInvoiceAccountingSnapshot>;
|
|
109
|
+
/** Map a retained-first credit using the existing frozen reader's realm/lineage checks. */
|
|
110
|
+
export declare function toRetainedCreditAccountingInput(input: RetainedCreditReviewScope & {
|
|
111
|
+
mapping: QuickBooksFrozenInvoiceMapping;
|
|
112
|
+
}): Promise<CreditMemoInput>;
|
|
113
|
+
/** Export unchanged gross/tax, then reclassify and apply its exact retained amount. */
|
|
114
|
+
export declare function syncRetainedInvoiceToAccounting(input: SyncRetainedInvoiceToAccountingInput): Promise<RetainedInvoiceAccountingState>;
|
|
115
|
+
/** Release date is provider TxnDate; dueOn remains explicit host collection policy. */
|
|
116
|
+
export declare function releaseRetainedInvoiceToAccounting(input: ReleaseRetainedInvoiceToAccountingInput): Promise<RetainedInvoiceAccountingState>;
|
|
117
|
+
export interface ReconcileRetainedAccountingStepInput extends Scope {
|
|
118
|
+
stepKey: string;
|
|
119
|
+
requestId: string;
|
|
120
|
+
attemptId: string;
|
|
121
|
+
confirmInterruptedOwnerStopped?: true;
|
|
122
|
+
outcome: {
|
|
123
|
+
status: 'found';
|
|
124
|
+
externalId: string;
|
|
125
|
+
} | {
|
|
126
|
+
status: 'absent';
|
|
127
|
+
evidenceRef: string;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/** Unknown remote outcomes never reset on a guessed absence or an unobserved owner. */
|
|
131
|
+
export declare function reconcileRetainedAccountingStep(input: ReconcileRetainedAccountingStepInput): Promise<RetainedInvoiceAccountingState>;
|
|
132
|
+
/** Reconcile the existing frozen invoice step using its established owner proof. */
|
|
133
|
+
export declare function reconcileRetainedBaseInvoice(input: ReconcileFrozenInvoiceAccountingInput & {
|
|
134
|
+
provider: Provider;
|
|
135
|
+
}): Promise<import("./invoice-accounting-sync.js").FrozenAccountingSyncResult | import("./invoice-accounting-sync.js").FrozenAccountingReconciliationReady>;
|
|
136
|
+
export interface SyncRetainedCreditToAccountingInput extends Scope {
|
|
137
|
+
creditInvoiceId: string;
|
|
138
|
+
creditMapping: QuickBooksFrozenInvoiceMapping;
|
|
139
|
+
requestId: string;
|
|
140
|
+
evidenceRef: string;
|
|
141
|
+
effectiveOn: string;
|
|
142
|
+
}
|
|
143
|
+
/** Apply retained-first credit to the retained asset, then to the original due balance. */
|
|
144
|
+
export declare function syncRetainedCreditToAccounting(input: SyncRetainedCreditToAccountingInput): Promise<RetainedInvoiceAccountingState>;
|
|
145
|
+
export interface SyncRetainedRefundToAccountingInput extends Scope {
|
|
146
|
+
paymentId: string;
|
|
147
|
+
creditInvoiceId: string;
|
|
148
|
+
requestId: string;
|
|
149
|
+
evidenceRef: string;
|
|
150
|
+
effectiveOn: string;
|
|
151
|
+
}
|
|
152
|
+
/** Record an already settled local refund and consume its existing remote credit. No bank I/O. */
|
|
153
|
+
export declare function syncRetainedRefundToAccounting(input: SyncRetainedRefundToAccountingInput): Promise<RetainedInvoiceAccountingState>;
|
|
154
|
+
export interface ReconcileRetainedCreditAccountingInput extends Scope {
|
|
155
|
+
creditInvoiceId: string;
|
|
156
|
+
requestId: string;
|
|
157
|
+
attemptId: string;
|
|
158
|
+
confirmInterruptedOwnerStopped?: true;
|
|
159
|
+
outcome: ReconcileFrozenInvoiceAccountingInput['outcome'];
|
|
160
|
+
}
|
|
161
|
+
/** Resolve an interrupted credit-memo export before its retained-first applications resume. */
|
|
162
|
+
export declare function reconcileRetainedCreditAccounting(input: ReconcileRetainedCreditAccountingInput): Promise<import("./invoice-accounting-sync.js").FrozenAccountingSyncResult | import("./invoice-accounting-sync.js").FrozenAccountingReconciliationReady>;
|
|
163
|
+
export {};
|
|
164
|
+
//# sourceMappingURL=retention-accounting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-accounting.d.ts","sourceRoot":"","sources":["../src/retention-accounting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface InvoiceRetentionEvidence {
|
|
2
|
+
requestId: string;
|
|
3
|
+
policyVersion: string;
|
|
4
|
+
evidenceRef: string;
|
|
5
|
+
actorId: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
/** Explicit business calendar date for original or current evidence; recordedAt stays actual record time. */
|
|
8
|
+
effectiveOn?: string;
|
|
9
|
+
sameDayCreditOrder?: 'credit-before-release' | 'release-before-credit' | null;
|
|
10
|
+
}
|
|
11
|
+
export interface InvoiceRetentionRelease extends InvoiceRetentionEvidence {
|
|
12
|
+
amountMinor: number;
|
|
13
|
+
recordedAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface InvoiceRetentionState extends InvoiceRetentionEvidence {
|
|
16
|
+
version: 1;
|
|
17
|
+
currency: string;
|
|
18
|
+
creditPolicy: 'retained-first';
|
|
19
|
+
retainedMinor: number;
|
|
20
|
+
recordedAt: string;
|
|
21
|
+
releases: InvoiceRetentionRelease[];
|
|
22
|
+
}
|
|
23
|
+
export interface InvoicePayableFacts {
|
|
24
|
+
grossMinor: number;
|
|
25
|
+
retainedMinor: number;
|
|
26
|
+
releasedMinor: number;
|
|
27
|
+
creditedRetentionMinor: number;
|
|
28
|
+
retainedRemainingMinor: number;
|
|
29
|
+
allocationCapMinor: number;
|
|
30
|
+
grossBalanceMinor: number;
|
|
31
|
+
currentlyDueMinor: number;
|
|
32
|
+
}
|
|
33
|
+
export declare function assertRetentionMinor(amount: number, label: string): void;
|
|
34
|
+
export declare function validateRetentionEvidence(input: InvoiceRetentionEvidence): void;
|
|
35
|
+
export declare function parseInvoiceRetention(json: string): InvoiceRetentionState | null;
|
|
36
|
+
export declare function calculateInvoicePayable(input: {
|
|
37
|
+
totalAmount: number;
|
|
38
|
+
creditedAmount: number;
|
|
39
|
+
amountPaid: number;
|
|
40
|
+
currency: string;
|
|
41
|
+
retentionStateJson?: string;
|
|
42
|
+
}): InvoicePayableFacts;
|
|
43
|
+
//# sourceMappingURL=retention-money.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retention-money.d.ts","sourceRoot":"","sources":["../src/retention-money.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,6GAA6G;IAC7G,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,uBAAuB,GAAG,uBAAuB,GAAG,IAAI,CAAC;CAC/E;AACD,MAAM,WAAW,uBAAwB,SAAQ,wBAAwB;IACvE,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,qBAAsB,SAAQ,wBAAwB;IACrE,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,uBAAuB,EAAE,CAAC;CACrC;AACD,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,sBAAsB,EAAE,MAAM,CAAC;IAC/B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAID,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAGxE;AACD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,wBAAwB,GAC9B,IAAI,CAYN;AACD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,GACX,qBAAqB,GAAG,IAAI,CAgD9B;AACD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,mBAAmB,CA2CtB"}
|