@happyvertical/accounting 0.104.0 → 0.104.1
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/README.md +81 -0
- package/dist/chunks/{errors-BHWEFjkq.js → errors-DIqXkm4s.js} +4 -1
- package/dist/chunks/errors-DIqXkm4s.js.map +1 -0
- package/dist/chunks/{quickbooks-CIedOmSC.js → quickbooks-T3C4dO8R.js} +158 -7
- package/dist/chunks/quickbooks-T3C4dO8R.js.map +1 -0
- package/dist/chunks/{invoice-request-D5fbd6Id.js → receivable-transfer-Ciy9jFYu.js} +177 -5
- package/dist/chunks/receivable-transfer-Ciy9jFYu.js.map +1 -0
- package/dist/chunks/{stripe-CECceZH5.js → stripe-DOJLldVK.js} +2 -2
- package/dist/chunks/{stripe-CECceZH5.js.map → stripe-DOJLldVK.js.map} +1 -1
- package/dist/errors.d.ts +3 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/providers/quickbooks/index.d.ts +5 -7
- package/dist/providers/quickbooks/index.d.ts.map +1 -1
- package/dist/providers/quickbooks/receivable-operations.d.ts +22 -0
- package/dist/providers/quickbooks/receivable-operations.d.ts.map +1 -0
- package/dist/providers/quickbooks/receivable-transfer.d.ts +89 -0
- package/dist/providers/quickbooks/receivable-transfer.d.ts.map +1 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/chunks/errors-BHWEFjkq.js.map +0 -1
- package/dist/chunks/invoice-request-D5fbd6Id.js.map +0 -1
- package/dist/chunks/quickbooks-CIedOmSC.js.map +0 -1
|
@@ -86,13 +86,13 @@ function prepareRequest(mapped, identity, kind) {
|
|
|
86
86
|
validateRequest(request, identity.realmId, identity.environment, payload, kind);
|
|
87
87
|
return Object.freeze(request);
|
|
88
88
|
}
|
|
89
|
-
function hash(payload) {
|
|
89
|
+
function hash$1(payload) {
|
|
90
90
|
return createHash("sha256").update(payload).digest("hex");
|
|
91
91
|
}
|
|
92
92
|
/** Bind a credit memo's immutable source invoice without sending it to QBO. */
|
|
93
93
|
function hashDescriptorPayload(payload, request, kind) {
|
|
94
|
-
if (kind === "invoice") return hash(payload);
|
|
95
|
-
return hash(JSON.stringify({
|
|
94
|
+
if (kind === "invoice") return hash$1(payload);
|
|
95
|
+
return hash$1(JSON.stringify({
|
|
96
96
|
payload,
|
|
97
97
|
linkage: { creditedInvoiceExternalId: request.creditedInvoiceExternalId }
|
|
98
98
|
}));
|
|
@@ -474,6 +474,178 @@ function mapCreditMemoToQBO(creditMemo) {
|
|
|
474
474
|
return basePayload(creditMemo, creditMemo.creditMemoNumber);
|
|
475
475
|
}
|
|
476
476
|
//#endregion
|
|
477
|
-
|
|
477
|
+
//#region src/providers/quickbooks/receivable-transfer.ts
|
|
478
|
+
/** Exact, explicit receivable reclassification. No sales, tax or bank-transfer approximation. */
|
|
479
|
+
var hash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
480
|
+
function text(value, label, max = 1e3) {
|
|
481
|
+
if (typeof value !== "string" || !value || value !== value.trim() || value.length > max) throw new Error(`${label} must be explicit trimmed text`);
|
|
482
|
+
}
|
|
483
|
+
function id(value, label) {
|
|
484
|
+
text(value, label, 100);
|
|
485
|
+
if (!/^[A-Za-z0-9._-]+$/.test(value)) throw new Error(`${label} is not a supported provider reference`);
|
|
486
|
+
}
|
|
487
|
+
function date(value) {
|
|
488
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || !Number.isFinite(Date.parse(value)) || new Date(value).toISOString().slice(0, 10) !== value) throw new Error("Receivable effective date is invalid");
|
|
489
|
+
}
|
|
490
|
+
function minor(value, currency) {
|
|
491
|
+
const factor = currencyMinorUnitFactor(currency);
|
|
492
|
+
if (!factor || !Number.isSafeInteger(value) || value <= 0) throw new Error("Receivable amount must be positive safe integer currency minor units");
|
|
493
|
+
const major = value / factor;
|
|
494
|
+
if (!isCurrencyMinorUnit(major, currency) || Math.round(major * factor) !== value) throw new Error("Receivable amount cannot be represented exactly by the provider");
|
|
495
|
+
return major;
|
|
496
|
+
}
|
|
497
|
+
function validateQuickBooksReceivableMapping(mapping) {
|
|
498
|
+
id(mapping.realmId, "Realm");
|
|
499
|
+
id(mapping.customerRef, "Customer");
|
|
500
|
+
text(mapping.version, "Mapping version");
|
|
501
|
+
text(mapping.reviewEvidenceRef, "Mapping review evidence");
|
|
502
|
+
if (!["sandbox", "production"].includes(mapping.environment) || mapping.accountingBasis !== "accrual" || mapping.taxTiming !== "invoice-tax-point" || mapping.releaseDueDates !== "host-managed") throw new Error("Receivable transfers support explicit accrual, invoice-tax-point and host-managed release due dates only");
|
|
503
|
+
if (!/^[A-Z]{3}$/.test(mapping.currency) || !currencyMinorUnitFactor(mapping.currency)) throw new Error("Unsupported receivable currency");
|
|
504
|
+
const refs = [
|
|
505
|
+
mapping.receivablesAccountRef,
|
|
506
|
+
mapping.retainedAssetAccountRef,
|
|
507
|
+
...mapping.cashAccountRef === null ? [] : [mapping.cashAccountRef]
|
|
508
|
+
];
|
|
509
|
+
for (const ref of refs) id(ref, "Posting account");
|
|
510
|
+
if (new Set(refs).size !== refs.length) throw new Error("Receivable posting accounts must be distinct");
|
|
511
|
+
}
|
|
512
|
+
function validate(input) {
|
|
513
|
+
validateQuickBooksReceivableMapping(input.mapping);
|
|
514
|
+
id(input.requestId, "Request");
|
|
515
|
+
if (input.requestId.length > 50) throw new Error("QuickBooks requestId must contain at most 50 characters");
|
|
516
|
+
date(input.effectiveOn);
|
|
517
|
+
text(input.evidenceRef, "Operation evidence", 1e3);
|
|
518
|
+
if (![
|
|
519
|
+
"Invoice",
|
|
520
|
+
"CreditMemo",
|
|
521
|
+
"JournalEntry"
|
|
522
|
+
].includes(input.source.type)) throw new Error("Unsupported source transaction type");
|
|
523
|
+
id(input.source.id, "Source transaction");
|
|
524
|
+
id(input.source.customerRef, "Source customer");
|
|
525
|
+
text(input.source.evidenceRef, "Source evidence");
|
|
526
|
+
if (input.source.customerRef !== input.mapping.customerRef) throw new Error("Source customer differs from receivable mapping");
|
|
527
|
+
minor(input.amountMinor, input.mapping.currency);
|
|
528
|
+
if (input.kind === "application") {
|
|
529
|
+
if (!["Invoice", "JournalEntry"].includes(input.debit.type) || !["CreditMemo", "JournalEntry"].includes(input.credit.type)) throw new Error("Unsupported noncash application transaction types");
|
|
530
|
+
id(input.debit.id, "Debit transaction");
|
|
531
|
+
id(input.credit.id, "Credit transaction");
|
|
532
|
+
if (input.debit.type === input.credit.type && input.debit.id === input.credit.id) throw new Error("Cannot apply a journal to itself");
|
|
533
|
+
} else if (![
|
|
534
|
+
"withhold",
|
|
535
|
+
"release",
|
|
536
|
+
"cash-refund",
|
|
537
|
+
"reverse-cash-refund"
|
|
538
|
+
].includes(input.kind)) throw new Error("Unsupported receivable transfer direction");
|
|
539
|
+
else if (input.kind.includes("cash-refund") && !input.mapping.cashAccountRef) throw new Error("Cash refund recording requires an explicit cash account");
|
|
540
|
+
}
|
|
541
|
+
function mapQuickBooksReceivableRequest(input) {
|
|
542
|
+
validate(input);
|
|
543
|
+
const amount = minor(input.amountMinor, input.mapping.currency);
|
|
544
|
+
const source = `${input.source.type}:${input.source.id}; customer:${input.source.customerRef}; evidence:${input.source.evidenceRef}`;
|
|
545
|
+
const note = `${input.kind}; ${source}; operation:${input.evidenceRef}; mapping:${input.mapping.version}; request:${input.requestId}`;
|
|
546
|
+
if (note.length > 4e3) throw new Error("Receivable provenance exceeds the provider note limit");
|
|
547
|
+
const base = {
|
|
548
|
+
TxnDate: input.effectiveOn,
|
|
549
|
+
CurrencyRef: { value: input.mapping.currency },
|
|
550
|
+
PrivateNote: note
|
|
551
|
+
};
|
|
552
|
+
if (input.kind === "application") return {
|
|
553
|
+
...base,
|
|
554
|
+
CustomerRef: { value: input.mapping.customerRef },
|
|
555
|
+
TotalAmt: 0,
|
|
556
|
+
ProcessPayment: false,
|
|
557
|
+
Line: [input.debit, input.credit].map((ref) => ({
|
|
558
|
+
Amount: amount,
|
|
559
|
+
LinkedTxn: [{
|
|
560
|
+
TxnType: ref.type,
|
|
561
|
+
TxnId: ref.id
|
|
562
|
+
}]
|
|
563
|
+
}))
|
|
564
|
+
};
|
|
565
|
+
const arDebit = input.kind === "release" || input.kind === "cash-refund";
|
|
566
|
+
const counterpart = input.kind.includes("cash-refund") ? input.mapping.cashAccountRef : input.mapping.retainedAssetAccountRef;
|
|
567
|
+
return {
|
|
568
|
+
...base,
|
|
569
|
+
Line: [{
|
|
570
|
+
account: input.mapping.receivablesAccountRef,
|
|
571
|
+
debit: arDebit
|
|
572
|
+
}, {
|
|
573
|
+
account: counterpart,
|
|
574
|
+
debit: !arDebit
|
|
575
|
+
}].map((line, index) => ({
|
|
576
|
+
LineNum: index + 1,
|
|
577
|
+
Description: source,
|
|
578
|
+
Amount: amount,
|
|
579
|
+
DetailType: "JournalEntryLineDetail",
|
|
580
|
+
JournalEntryLineDetail: {
|
|
581
|
+
PostingType: line.debit ? "Debit" : "Credit",
|
|
582
|
+
AccountRef: { value: line.account },
|
|
583
|
+
Entity: {
|
|
584
|
+
Type: "Customer",
|
|
585
|
+
EntityRef: { value: input.mapping.customerRef }
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
}))
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
/** Pure preparation. Persist before sending; the hash does not prove a remote write occurred once. */
|
|
592
|
+
function prepareQuickBooksReceivableRequest(input) {
|
|
593
|
+
const frozenInput = structuredClone(input), body = mapQuickBooksReceivableRequest(frozenInput);
|
|
594
|
+
return Object.freeze({
|
|
595
|
+
version: 1,
|
|
596
|
+
endpoint: input.kind === "application" ? "payment" : "journalentry",
|
|
597
|
+
realmId: input.mapping.realmId,
|
|
598
|
+
environment: input.mapping.environment,
|
|
599
|
+
requestId: input.requestId,
|
|
600
|
+
payloadHash: hash({
|
|
601
|
+
input: frozenInput,
|
|
602
|
+
body
|
|
603
|
+
}),
|
|
604
|
+
input: frozenInput
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
function validateQuickBooksReceivableRequest(request, realmId, environment, serializedBody) {
|
|
608
|
+
const expected = prepareQuickBooksReceivableRequest(request.input);
|
|
609
|
+
if (request.version !== 1 || request.realmId !== realmId || request.environment !== environment || request.endpoint !== expected.endpoint || request.requestId !== expected.requestId || request.payloadHash !== expected.payloadHash || request.realmId !== expected.realmId || request.environment !== expected.environment || serializedBody !== void 0 && serializedBody !== JSON.stringify(mapQuickBooksReceivableRequest(request.input))) throw new Error("Receivable request scope, provenance or frozen payload changed");
|
|
610
|
+
}
|
|
611
|
+
/** Exact readback validation; provider-added IDs/names are allowed, omitted financial facts are not. */
|
|
612
|
+
function reconcileQuickBooksReceivableRecord(request, value) {
|
|
613
|
+
validateQuickBooksReceivableRequest(request, request.realmId, request.environment);
|
|
614
|
+
const raw = value, expected = mapQuickBooksReceivableRequest(request.input), input = request.input;
|
|
615
|
+
if (!raw || typeof raw !== "object") throw new Error("Receivable provider record is missing");
|
|
616
|
+
id(raw.Id, "Provider record");
|
|
617
|
+
text(raw.SyncToken, "Provider sync token", 100);
|
|
618
|
+
if (raw.TxnDate !== expected.TxnDate || raw.CurrencyRef?.value !== input.mapping.currency || raw.PrivateNote !== expected.PrivateNote || !Array.isArray(raw.Line) || raw.Line.length !== 2) throw new Error("Receivable provider identity, currency, date or evidence differs");
|
|
619
|
+
if (raw.ExchangeRate !== void 0 && raw.ExchangeRate !== 1 || raw.TxnTaxDetail !== void 0 && raw.TxnTaxDetail?.TotalTax !== 0) throw new Error("Receivable readback contains unsupported exchange or tax effects");
|
|
620
|
+
const expectedLines = expected.Line;
|
|
621
|
+
for (let i = 0; i < 2; i++) {
|
|
622
|
+
const line = raw.Line[i], wanted = expectedLines[i];
|
|
623
|
+
if (line.Amount !== wanted.Amount) throw new Error("Receivable provider line amount differs");
|
|
624
|
+
if (input.kind === "application") {
|
|
625
|
+
if (!Array.isArray(line.LinkedTxn) || line.LinkedTxn.length !== 1 || line.LinkedTxn[0].TxnType !== wanted.LinkedTxn[0].TxnType || line.LinkedTxn[0].TxnId !== wanted.LinkedTxn[0].TxnId) throw new Error("Receivable application linkage differs");
|
|
626
|
+
} else {
|
|
627
|
+
const details = line.JournalEntryLineDetail, required = wanted.JournalEntryLineDetail;
|
|
628
|
+
if (line.DetailType !== "JournalEntryLineDetail" || line.Description !== wanted.Description || details?.PostingType !== required.PostingType || details?.AccountRef?.value !== required.AccountRef.value || details?.Entity?.Type !== "Customer" || details?.Entity?.EntityRef?.value !== input.mapping.customerRef || details?.TaxAmount !== void 0 || details?.TaxCodeRef !== void 0) throw new Error("Receivable journal posting authority differs");
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if (input.kind === "application" && (raw.TotalAmt !== 0 || raw.UnappliedAmt !== 0 || raw.CustomerRef?.value !== input.mapping.customerRef || raw.ProcessPayment === true)) throw new Error("Noncash application must have zero cash and no unapplied balance");
|
|
632
|
+
return {
|
|
633
|
+
externalId: raw.Id,
|
|
634
|
+
syncToken: raw.SyncToken,
|
|
635
|
+
kind: input.kind,
|
|
636
|
+
customerRef: input.mapping.customerRef,
|
|
637
|
+
currency: input.mapping.currency,
|
|
638
|
+
effectiveOn: input.effectiveOn,
|
|
639
|
+
amountMinor: input.amountMinor,
|
|
640
|
+
nonCashAppliedMinor: input.kind === "application" ? input.amountMinor : 0,
|
|
641
|
+
recordedCashChangeMinor: input.kind === "cash-refund" ? -input.amountMinor : input.kind === "reverse-cash-refund" ? input.amountMinor : 0,
|
|
642
|
+
providerProcessedCashMinor: 0,
|
|
643
|
+
bankSettlementVerified: false,
|
|
644
|
+
source: structuredClone(input.source),
|
|
645
|
+
payloadHash: request.payloadHash
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
//#endregion
|
|
649
|
+
export { validateQuickBooksReceivableRequest as a, prepareQuickBooksCreditMemoRequest as c, validateQuickBooksInvoiceRequest as d, currencyMinorUnitFactor as f, validateQuickBooksReceivableMapping as i, prepareQuickBooksInvoiceRequest as l, prepareQuickBooksReceivableRequest as n, mapCreditMemoToQBO as o, isCurrencyMinorUnit as p, reconcileQuickBooksReceivableRecord as r, mapInvoiceToQBO as s, mapQuickBooksReceivableRequest as t, validateQuickBooksCreditMemoRequest as u };
|
|
478
650
|
|
|
479
|
-
//# sourceMappingURL=
|
|
651
|
+
//# sourceMappingURL=receivable-transfer-Ciy9jFYu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receivable-transfer-Ciy9jFYu.js","names":[],"sources":["../../src/providers/quickbooks/line-amount.ts","../../src/providers/quickbooks/invoice-request.ts","../../src/providers/quickbooks/receivable-transfer.ts"],"sourcesContent":["/** ISO 4217 List One, published 2026-09-17. Do not use Intl display digits:\n * ICU differs for e.g. IQD, MGA and RSD, and omits fund codes CLF/UYW.\n * https://www.six-group.com/dam/download/financial-information/data-center/iso-currrency/lists/list-one.xml\n * N.A., unknown and missing codes cannot authorize currency rounding.\n */\nconst precisionGroups: readonly (readonly [number, string])[] = [\n [0, 'BIF CLP DJF GNF ISK JPY KMF KRW PYG RWF UGX UYI VND VUV XAF XOF XPF'],\n [\n 2,\n 'AED AFN ALL AMD AOA ARS AUD AWG AZN BAM BBD BDT BMD BND BOB BOV BRL BSD BTN BWP BYN BZD CAD CDF CHE CHF CHW CNY COP COU CRC CUP CVE CZK DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GTQ GYD HKD HNL HTG HUF IDR ILS INR IRR JMD KES KGS KHR KPW KYD KZT LAK LBP LKR LRD LSL MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN MXV MYR MZN NAD NGN NIO NOK NPR NZD PAB PEN PGK PHP PKR PLN QAR RON RSD RUB SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD SSP STN SVC SYP SZL THB TJS TMT TOP TRY TTD TWD TZS UAH USD USN UYU UZS VED VES WST XAD XCD XCG YER ZAR ZMW ZWG',\n ],\n [3, 'BHD IQD JOD KWD LYD OMR TND'],\n [4, 'CLF UYW'],\n];\nconst currencyPrecision = new Map(\n precisionGroups.flatMap(([precision, codes]) =>\n codes.split(' ').map((code) => [code, precision] as const),\n ),\n);\n\n/** ISO minor-unit factor, or undefined when the code is unknown or omitted. */\nexport function currencyMinorUnitFactor(\n currency: string | undefined,\n): number | undefined {\n if (typeof currency !== 'string') return undefined;\n const precision = currencyPrecision.get(currency.toUpperCase());\n return precision === undefined ? undefined : 10 ** precision;\n}\n\n/** True only for a finite amount exactly representable on the ISO minor-unit grid. */\nexport function isCurrencyMinorUnit(\n amount: number,\n currency: string | undefined,\n): boolean {\n if (!Number.isFinite(amount) || typeof currency !== 'string') return false;\n const precision = currencyPrecision.get(currency.toUpperCase());\n if (precision === undefined) return false;\n const value = decimalRatio(Math.abs(amount));\n return (\n (value.numerator * 10n ** BigInt(precision)) % value.denominator === 0n\n );\n}\n\n/** Round a finite major-unit amount half-up to a known ISO currency grid. */\nexport function roundCurrencyAmount(\n amount: number,\n currency: string | undefined,\n): number | undefined {\n if (!Number.isFinite(amount) || typeof currency !== 'string')\n return undefined;\n const precision = currencyPrecision.get(currency.toUpperCase());\n if (precision === undefined) return undefined;\n const sign = amount < 0 ? -1n : 1n;\n const value = decimalRatio(Math.abs(amount));\n const scale = 10n ** BigInt(precision);\n const numerator = value.numerator * scale;\n const rounded =\n numerator / value.denominator +\n ((numerator % value.denominator) * 2n >= value.denominator ? 1n : 0n);\n return Number(sign * rounded) / Number(scale);\n}\n\n/** Exact decimal interpretation of the finite nonnegative public number value. */\nfunction decimalRatio(value: number): {\n numerator: bigint;\n denominator: bigint;\n} {\n const [significand, exponent = '0'] = value.toString().split('e');\n const [whole, fraction = ''] = significand.split('.');\n const coefficient = BigInt(whole + fraction);\n const scale = fraction.length - Number(exponent);\n return scale >= 0\n ? { numerator: coefficient, denominator: 10n ** BigInt(scale) }\n : { numerator: coefficient * 10n ** BigInt(-scale), denominator: 1n };\n}\n\n/** Admit only the exact half-up minor-unit result; never rewrite caller money. */\nexport function matchesCurrencyRoundedLineAmount(\n quantity: number,\n unitPrice: number,\n amount: number,\n currency: string | undefined,\n): boolean {\n if (typeof currency !== 'string') return false;\n const precision = currencyPrecision.get(currency.toUpperCase());\n if (precision === undefined) return false;\n const minorScale = 10n ** BigInt(precision);\n const retained = decimalRatio(amount);\n const retainedMinor = retained.numerator * minorScale;\n // An off-grid caller amount is not permission to round their supplied money.\n if (retainedMinor % retained.denominator !== 0n) return false;\n const qty = decimalRatio(quantity);\n const price = decimalRatio(unitPrice);\n const numerator = qty.numerator * price.numerator * minorScale;\n const denominator = qty.denominator * price.denominator;\n const quotient = numerator / denominator;\n const rounded =\n quotient + ((numerator % denominator) * 2n >= denominator ? 1n : 0n);\n return retainedMinor / retained.denominator === rounded;\n}\n","import { createHash } from 'node:crypto';\nimport type {\n CreditMemoInput,\n InvoiceInput,\n InvoiceLineItemInput,\n QuickBooksCreditMemoRequest,\n QuickBooksInvoiceRequest,\n} from '../../types.js';\nimport {\n currencyMinorUnitFactor,\n isCurrencyMinorUnit,\n matchesCurrencyRoundedLineAmount,\n roundCurrencyAmount,\n} from './line-amount.js';\n\ntype QuickBooksCreateRequest =\n | QuickBooksInvoiceRequest\n | QuickBooksCreditMemoRequest;\n\ninterface QuickBooksSalesLine {\n LineNum: number;\n Description: string;\n Amount: number;\n DetailType: 'SalesItemLineDetail';\n SalesItemLineDetail: {\n Qty: number;\n UnitPrice: number;\n ItemRef?: { value: string };\n TaxCodeRef?: { value: string };\n TaxInclusiveAmt?: number;\n };\n}\n\ninterface QuickBooksTaxLine {\n Amount: number;\n DetailType: 'TaxLineDetail';\n TaxLineDetail: {\n TaxRateRef: { value: string };\n TaxPercent: number;\n PercentBased: true;\n NetAmountTaxable?: number;\n };\n}\n\ninterface FrozenTaxComponent {\n taxRateRef: string;\n rate: DecimalRate;\n taxMinor: bigint;\n compound: boolean;\n basisMinor: bigint;\n explicitBasis: boolean;\n}\n\ninterface DecimalRate {\n numerator: bigint;\n denominator: bigint;\n value: number;\n}\n\n/** Prepare once, persist before sending, and reuse unchanged. Performs no I/O. */\nexport function prepareQuickBooksInvoiceRequest(\n invoice: InvoiceInput,\n identity: Omit<QuickBooksInvoiceRequest, 'payloadHash'>,\n): QuickBooksInvoiceRequest {\n if (invoice.externalId)\n throw new Error('QuickBooks request identity is only for invoice creation');\n return prepareRequest(mapInvoiceToQBO(invoice), identity, 'invoice');\n}\n\n/** Prepare once, persist before sending, and reuse unchanged. Performs no I/O. */\nexport function prepareQuickBooksCreditMemoRequest(\n creditMemo: CreditMemoInput,\n identity: Omit<\n QuickBooksCreditMemoRequest,\n 'payloadHash' | 'creditedInvoiceExternalId'\n >,\n): QuickBooksCreditMemoRequest {\n if (creditMemo.externalId)\n throw new Error(\n 'QuickBooks request identity is only for credit memo creation',\n );\n return prepareRequest(\n mapCreditMemoToQBO(creditMemo),\n {\n ...identity,\n creditedInvoiceExternalId: creditMemo.creditedInvoiceExternalId,\n },\n 'credit memo',\n );\n}\n\nfunction prepareRequest<T extends QuickBooksCreateRequest>(\n mapped: unknown,\n identity: Omit<T, 'payloadHash'>,\n kind: 'invoice' | 'credit memo',\n): T {\n const payload = JSON.stringify(mapped);\n const request = {\n ...identity,\n payloadHash: hashDescriptorPayload(payload, identity, kind),\n } as T;\n validateRequest(\n request,\n identity.realmId,\n identity.environment,\n payload,\n kind,\n );\n return Object.freeze(request);\n}\n\nfunction hash(payload: string): string {\n return createHash('sha256').update(payload).digest('hex');\n}\n\n/** Bind a credit memo's immutable source invoice without sending it to QBO. */\nfunction hashDescriptorPayload(\n payload: string,\n request:\n | QuickBooksCreateRequest\n | Omit<QuickBooksCreateRequest, 'payloadHash'>,\n kind: 'invoice' | 'credit memo',\n): string {\n if (kind === 'invoice') return hash(payload);\n const creditMemoRequest = request as QuickBooksCreditMemoRequest;\n return hash(\n JSON.stringify({\n payload,\n linkage: {\n creditedInvoiceExternalId: creditMemoRequest.creditedInvoiceExternalId,\n },\n }),\n );\n}\n\nexport function validateQuickBooksInvoiceRequest(\n request: QuickBooksInvoiceRequest,\n realmId: string,\n environment: 'sandbox' | 'production',\n payload: string | undefined,\n): void {\n validateRequest(request, realmId, environment, payload, 'invoice');\n}\n\nexport function validateQuickBooksCreditMemoRequest(\n request: QuickBooksCreditMemoRequest,\n realmId: string,\n environment: 'sandbox' | 'production',\n payload: string | undefined,\n): void {\n validateRequest(request, realmId, environment, payload, 'credit memo');\n}\n\nfunction validateRequest(\n request: QuickBooksCreateRequest,\n realmId: string,\n environment: 'sandbox' | 'production',\n payload: string | undefined,\n kind: 'invoice' | 'credit memo',\n): void {\n if (\n !request ||\n typeof request.requestId !== 'string' ||\n !/^[A-Za-z0-9._-]{1,50}$/.test(request.requestId)\n ) {\n throw new Error(\n 'QuickBooks requestId must contain 1–50 URL-safe letters, digits, dots, underscores or hyphens',\n );\n }\n if (\n !request.realmId ||\n request.realmId !== realmId ||\n !['sandbox', 'production'].includes(request.environment) ||\n request.environment !== environment\n ) {\n throw new Error(`QuickBooks ${kind} request realm/environment mismatch`);\n }\n if (\n !payload ||\n request.payloadHash !== hashDescriptorPayload(payload, request, kind)\n ) {\n throw new Error(\n `QuickBooks ${kind} request payload mismatch; reconcile the original request`,\n );\n }\n if (\n kind === 'credit memo' &&\n (!('creditedInvoiceExternalId' in request) ||\n !request.creditedInvoiceExternalId ||\n request.creditedInvoiceExternalId.trim() !==\n request.creditedInvoiceExternalId)\n ) {\n throw new Error(\n 'QuickBooks credit memo request requires a credited invoice external ID',\n );\n }\n const parsed = JSON.parse(payload);\n if (parsed.Id !== undefined || parsed.SyncToken !== undefined) {\n throw new Error(`QuickBooks request identity is only for ${kind} creation`);\n }\n}\n\nfunction formatLocalDate(date: Date): string {\n const year = date.getFullYear();\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${year}-${month}-${day}`;\n}\n\nfunction close(a: number, b: number): boolean {\n return (\n Number.isFinite(a) &&\n Number.isFinite(b) &&\n Math.abs(a - b) <=\n Number.EPSILON * Math.max(1, Math.abs(a), Math.abs(b)) * 8\n );\n}\n\nfunction finite(value: number, label: string, allowNegative = false): number {\n if (!Number.isFinite(value) || (!allowNegative && value < 0))\n throw new Error(\n `QuickBooks ${label} must be a finite ${allowNegative ? '' : 'non-negative '}amount`,\n );\n return value;\n}\n\nfunction reference(value: string | undefined, label: string) {\n if (!value || value.trim() !== value || value.length > 255)\n throw new Error(`QuickBooks ${label} must be a non-empty realm reference`);\n return { value };\n}\n\nfunction canonicalRateNumber(value: number): string {\n // Number inputs can carry an adjacent binary representation of the exact\n // frozen decimal (for example 0.1 + 0.2). Prefer the shortest nearby decimal\n // through the calculator's supported precision, without changing a value\n // whose additional digits are materially distinct.\n for (let places = 0; places <= 12; places++) {\n const candidate = Number(value.toFixed(places));\n if (close(value, candidate)) return candidate.toString();\n }\n return value.toString();\n}\n\nfunction decimalRate(\n value: number | string | undefined,\n label: string,\n): DecimalRate {\n const text =\n typeof value === 'string' && /^\\d+(?:\\.\\d+)?$/.test(value)\n ? value\n : typeof value === 'number' && Number.isFinite(value) && value >= 0\n ? canonicalRateNumber(value)\n : undefined;\n if (!text || !/^\\d+(?:\\.\\d+)?$/.test(text))\n throw new Error(\n `QuickBooks ${label} needs a frozen component rate from 0 through 1`,\n );\n const [whole, fraction = ''] = text.split('.');\n const denominator = 10n ** BigInt(fraction.length);\n const numerator = BigInt(`${whole}${fraction}`);\n if (numerator > denominator)\n throw new Error(\n `QuickBooks ${label} needs a frozen component rate from 0 through 1`,\n );\n return { numerator, denominator, value: Number(text) };\n}\n\nfunction ratesEqual(left: DecimalRate, right: DecimalRate): boolean {\n return (\n left.numerator * right.denominator === right.numerator * left.denominator\n );\n}\n\nfunction addRates(left: DecimalRate, right: DecimalRate): DecimalRate {\n const numerator =\n left.numerator * right.denominator + right.numerator * left.denominator;\n const denominator = left.denominator * right.denominator;\n return {\n numerator,\n denominator,\n value: Number(numerator) / Number(denominator),\n };\n}\n\nfunction taxPercent(rate: DecimalRate): number {\n return Number(rate.numerator * 100n) / Number(rate.denominator);\n}\n\nfunction currencyMinor(\n amount: number,\n currency: string | undefined,\n label: string,\n): bigint {\n const factor = currencyMinorUnitFactor(currency);\n const rounded = roundCurrencyAmount(amount, currency);\n if (\n factor === undefined ||\n rounded === undefined ||\n (!isCurrencyMinorUnit(amount, currency) && !close(amount, rounded))\n )\n throw new Error(\n `QuickBooks ${label} must fit the explicitly supplied currency's ISO 4217 minor-unit grid`,\n );\n // Match frozenCurrencyAmount: only a value already admitted as ordinary\n // binary noise is normalized before exact minor-unit aggregation. A genuine\n // off-grid value still refuses before any request is mapped.\n return BigInt(\n Math.round(\n (isCurrencyMinorUnit(amount, currency) ? amount : rounded) * factor,\n ),\n );\n}\n\nfunction currencyMajor(minor: bigint, currency: string | undefined): number {\n const factor = currencyMinorUnitFactor(currency);\n if (factor === undefined)\n throw new Error('QuickBooks needs a known currency');\n return Number(minor) / factor;\n}\n\nfunction taxMinorMatchesAllocation(\n taxMinor: bigint,\n numerator: bigint,\n denominator: bigint,\n): boolean {\n const floor = numerator / denominator;\n const remainder = numerator % denominator;\n return taxMinor === floor || (remainder !== 0n && taxMinor === floor + 1n);\n}\n\n/** Exact per-component factors relative to net; component order is significant. */\nfunction orderedFactors(components: readonly FrozenTaxComponent[]): {\n factors: DecimalRate[];\n total: DecimalRate;\n} {\n let total: DecimalRate = { numerator: 0n, denominator: 1n, value: 0 };\n const factors = components.map((component) => {\n const basis = component.compound\n ? addRates({ numerator: 1n, denominator: 1n, value: 1 }, total)\n : { numerator: 1n, denominator: 1n, value: 1 };\n const numerator = component.rate.numerator * basis.numerator;\n const denominator = component.rate.denominator * basis.denominator;\n const factor = {\n numerator,\n denominator,\n value: Number(numerator) / Number(denominator),\n };\n total = addRates(total, factor);\n return factor;\n });\n return { factors, total };\n}\n\nfunction validateFrozenComponentRates(\n components: readonly FrozenTaxComponent[],\n taxableAmount: number,\n currency: string | undefined,\n inclusive: boolean,\n label: string,\n): void {\n const taxableMinor = currencyMinor(\n taxableAmount,\n currency,\n `${label} taxable amount`,\n );\n const { factors, total } = orderedFactors(components);\n for (const [index, component] of components.entries()) {\n const factor = factors[index];\n const numerator = inclusive\n ? taxableMinor * factor.numerator * total.denominator\n : component.basisMinor * component.rate.numerator;\n const denominator = inclusive\n ? factor.denominator * (total.denominator + total.numerator)\n : component.rate.denominator;\n if (!taxMinorMatchesAllocation(component.taxMinor, numerator, denominator))\n throw new Error(\n `QuickBooks ${label} tax component rate is inconsistent with its frozen tax amount`,\n );\n }\n}\n\nfunction frozenCurrencyAmount(\n value: number,\n label: string,\n currency: string | undefined,\n allowNegative = false,\n): number {\n finite(value, label, allowNegative);\n const rounded = roundCurrencyAmount(value, currency);\n // Stored decimal money can reach JavaScript as an adjacent binary value\n // (for example 0.1 * 3). Accept that representation only when the known\n // currency round-trip differs by ordinary floating-point noise; this never\n // authorizes a real off-grid amount such as CAD 0.005 or JPY 100.5.\n if (\n !isCurrencyMinorUnit(value, currency) &&\n (rounded === undefined || !close(value, rounded))\n )\n throw new Error(\n `QuickBooks ${label} must fit the explicitly supplied currency's ISO 4217 minor-unit grid`,\n );\n return value;\n}\n\nfunction hasFrozenSnapshots(\n input: Pick<InvoiceInput, 'quickbooksMapping' | 'lineItems'>,\n): boolean {\n return (\n input.quickbooksMapping?.globalTaxCalculation === 'TaxInclusive' ||\n input.lineItems.some(\n (item) =>\n item.taxAmount !== undefined ||\n item.taxComponents !== undefined ||\n item.taxInclusiveAmount !== undefined ||\n (item.discount !== undefined && item.discount !== 0),\n )\n );\n}\n\n/** Limit accumulated binary error when a valid document has many decimal lines. */\nfunction compensatedSum(values: readonly number[]): number {\n let sum = 0;\n let compensation = 0;\n for (const value of values) {\n const adjusted = value - compensation;\n const next = sum + adjusted;\n compensation = next - sum - adjusted;\n sum = next;\n }\n return sum;\n}\n\nfunction mapDocumentLines(\n input: Pick<\n InvoiceInput,\n | 'lineItems'\n | 'subtotal'\n | 'taxAmount'\n | 'totalAmount'\n | 'currency'\n | 'quickbooksMapping'\n >,\n): { lines: QuickBooksSalesLine[]; taxLines: QuickBooksTaxLine[] } {\n const mode = input.quickbooksMapping?.globalTaxCalculation;\n if (mode && !['TaxExcluded', 'TaxInclusive', 'NotApplicable'].includes(mode))\n throw new Error(\n 'QuickBooks globalTaxCalculation must be TaxExcluded, TaxInclusive or NotApplicable',\n );\n const frozen = hasFrozenSnapshots(input);\n const validateAmount = (value: number, label: string) =>\n frozen\n ? frozenCurrencyAmount(value, label, input.currency)\n : finite(value, label);\n validateAmount(input.subtotal, 'subtotal');\n validateAmount(input.taxAmount, 'tax amount');\n validateAmount(input.totalAmount, 'total amount');\n if (input.lineItems.length === 0)\n throw new Error('QuickBooks invoices require at least one sales line');\n const hasLineMapping = input.lineItems.some((item) => item.quickbooksMapping);\n if ((input.taxAmount > 0 || hasLineMapping) && !input.quickbooksMapping)\n throw new Error(\n 'QuickBooks mapped or nonzero-tax invoices require explicit globalTaxCalculation',\n );\n if (\n input.quickbooksMapping &&\n input.lineItems.some((item) => !item.quickbooksMapping)\n )\n throw new Error(\n 'QuickBooks mapped invoices require itemRef and taxCodeRef on every line',\n );\n if (input.taxAmount > 0 && mode === 'NotApplicable')\n throw new Error(\n 'QuickBooks nonzero tax cannot use NotApplicable global tax calculation',\n );\n\n const mapped: QuickBooksSalesLine[] = [];\n const taxLines = new Map<\n string,\n {\n rate: DecimalRate;\n amountMinor: bigint;\n basisMinor: bigint;\n explicitBasis: boolean;\n }\n >();\n const snapshotLineTaxes: number[] = [];\n let hasAnyLineTax = false;\n let hasCompleteLineTax = true;\n const lineTaxSnapshots: Array<{\n taxAmount: number | undefined;\n taxComponents: readonly FrozenTaxComponent[];\n }> = [];\n for (const [index, item] of input.lineItems.entries()) {\n const line = mapLine(item, index, input.currency, mode, frozen);\n mapped.push(...line.lines);\n lineTaxSnapshots.push({\n taxAmount: line.taxAmount,\n taxComponents: line.taxComponents,\n });\n if (line.taxAmount === undefined) hasCompleteLineTax = false;\n else {\n hasAnyLineTax = true;\n snapshotLineTaxes.push(line.taxAmount);\n }\n for (const component of line.taxComponents) {\n const existing = taxLines.get(component.taxRateRef);\n if (existing) {\n if (!ratesEqual(existing.rate, component.rate))\n throw new Error(\n `QuickBooks tax rate ${component.taxRateRef} has inconsistent frozen rates`,\n );\n existing.amountMinor += component.taxMinor;\n existing.basisMinor += component.basisMinor;\n existing.explicitBasis ||= component.explicitBasis;\n if (\n existing.explicitBasis &&\n !Number.isSafeInteger(Number(existing.basisMinor))\n )\n throw new Error(\n 'QuickBooks aggregate taxable basis exceeds safe minor units',\n );\n } else {\n taxLines.set(component.taxRateRef, {\n rate: component.rate,\n amountMinor: component.taxMinor,\n basisMinor: component.basisMinor,\n explicitBasis: component.explicitBasis,\n });\n }\n }\n }\n const mappedSubtotal = compensatedSum(mapped.map((line) => line.Amount));\n if (!close(mappedSubtotal, input.subtotal))\n throw new Error('QuickBooks line amounts must equal the invoice subtotal');\n if (!close(input.subtotal + input.taxAmount, input.totalAmount))\n throw new Error(\n 'QuickBooks subtotal plus tax must equal the invoice total',\n );\n if (taxLines.size > 0) {\n if (\n lineTaxSnapshots.some(\n (line) =>\n line.taxAmount === undefined ||\n (line.taxAmount > 0 && line.taxComponents.length === 0),\n )\n )\n throw new Error(\n 'QuickBooks component tax detail requires components on every taxed line',\n );\n const totalTaxMinor = currencyMinor(\n input.taxAmount,\n input.currency,\n 'tax amount',\n );\n const detailTaxMinor = [...taxLines.values()].reduce(\n (sum, line) => sum + line.amountMinor,\n 0n,\n );\n if (detailTaxMinor !== totalTaxMinor)\n throw new Error(\n 'QuickBooks component tax detail must equal the invoice tax amount',\n );\n }\n if (hasAnyLineTax && !hasCompleteLineTax)\n throw new Error(\n 'QuickBooks stored line tax must be supplied on every line when any line supplies it',\n );\n if (\n hasAnyLineTax &&\n !close(compensatedSum(snapshotLineTaxes), input.taxAmount)\n )\n throw new Error(\n 'QuickBooks stored line tax must equal the invoice tax amount',\n );\n return {\n lines: mapped,\n taxLines: [...taxLines.entries()].map(([taxRateRef, detail]) => ({\n Amount: currencyMajor(detail.amountMinor, input.currency),\n DetailType: 'TaxLineDetail',\n TaxLineDetail: {\n TaxRateRef: { value: taxRateRef },\n TaxPercent: taxPercent(detail.rate),\n PercentBased: true,\n ...(detail.explicitBasis\n ? {\n NetAmountTaxable: currencyMajor(\n detail.basisMinor,\n input.currency,\n ),\n }\n : {}),\n },\n })),\n };\n}\n\nfunction mapLine(\n item: InvoiceLineItemInput,\n index: number,\n currency: string | undefined,\n mode: 'TaxExcluded' | 'TaxInclusive' | 'NotApplicable' | undefined,\n enforceCurrencyGrid: boolean,\n): {\n lines: QuickBooksSalesLine[];\n taxAmount?: number;\n taxComponents: FrozenTaxComponent[];\n} {\n const label = `line ${index + 1}`;\n if (item.taxRate !== undefined && item.taxRate !== 0)\n throw new Error(\n 'QuickBooks numeric taxRate is not supported; use a realm taxCodeRef',\n );\n if (item.taxCode !== undefined)\n throw new Error(\n 'QuickBooks generic taxCode is not a realm tax reference; use quickbooksMapping.taxCodeRef',\n );\n finite(item.quantity, `${label} quantity`);\n if (item.quantity <= 0)\n throw new Error(`QuickBooks ${label} quantity must be greater than zero`);\n finite(item.unitPrice, `${label} unit price`);\n const baseDocumentAmount = item.quantity * item.unitPrice;\n finite(baseDocumentAmount, `${label} pre-discount amount`);\n const validateAmount = (\n value: number,\n amountLabel: string,\n allowNegative = false,\n ) =>\n enforceCurrencyGrid\n ? frozenCurrencyAmount(value, amountLabel, currency, allowNegative)\n : finite(value, amountLabel, allowNegative);\n const discount = validateAmount(item.discount ?? 0, `${label} discount`);\n if (discount > baseDocumentAmount && !close(discount, baseDocumentAmount))\n throw new Error(\n `QuickBooks ${label} discount cannot exceed quantity times unit price`,\n );\n const netAmount = validateAmount(\n item.amount ?? baseDocumentAmount - discount,\n `${label} amount`,\n );\n const taxAmount =\n item.taxAmount === undefined\n ? undefined\n : validateAmount(item.taxAmount, `${label} tax amount`);\n const taxComponents: FrozenTaxComponent[] = [];\n const componentIds = new Set<string>();\n const componentRateRefs = new Set<string>();\n if (item.taxComponents !== undefined) {\n if (taxAmount === undefined)\n throw new Error(\n `QuickBooks ${label} tax components require a line tax amount`,\n );\n const componentTax = item.taxComponents.reduce(\n (sum, component, componentIndex) => {\n if (\n !component ||\n typeof component !== 'object' ||\n Object.keys(component).some(\n (key) =>\n ![\n 'taxCode',\n 'rate',\n 'quickbooksTaxRateRef',\n 'taxAmount',\n 'compound',\n 'taxableAmount',\n ].includes(key),\n )\n )\n throw new Error(\n `QuickBooks ${label} tax component has unsupported fields`,\n );\n if (\n component.compound !== undefined &&\n typeof component.compound !== 'boolean'\n )\n throw new Error(`QuickBooks ${label} compound must be boolean`);\n if (component.compound && component.taxableAmount === undefined)\n throw new Error(\n `QuickBooks ${label} compound tax requires its frozen taxableAmount`,\n );\n if (\n !component.taxCode ||\n component.taxCode.trim() !== component.taxCode\n )\n throw new Error(\n `QuickBooks ${label} tax component ${componentIndex + 1} needs a tax code`,\n );\n const rate = decimalRate(\n component.rate,\n `${label} tax component ${componentIndex + 1}`,\n );\n const taxRateRef = reference(\n component.quickbooksTaxRateRef,\n `${label} tax component ${componentIndex + 1} quickbooksTaxRateRef`,\n ).value;\n const componentAmount = validateAmount(\n component.taxAmount,\n `${label} tax component ${componentIndex + 1}`,\n );\n if (\n componentIds.has(component.taxCode) ||\n componentRateRefs.has(taxRateRef)\n )\n throw new Error(\n `QuickBooks ${label} repeats a tax component or rate reference`,\n );\n componentIds.add(component.taxCode);\n componentRateRefs.add(taxRateRef);\n const expectedBasis =\n currencyMinor(netAmount, currency, `${label} net amount`) +\n (component.compound\n ? taxComponents.reduce((sum, prior) => sum + prior.taxMinor, 0n)\n : 0n);\n const basisMinor =\n component.taxableAmount === undefined\n ? expectedBasis\n : currencyMinor(\n validateAmount(\n component.taxableAmount,\n `${label} taxable basis`,\n ),\n currency,\n `${label} taxable basis`,\n );\n if (!Number.isSafeInteger(Number(basisMinor)))\n throw new Error(\n `QuickBooks ${label} taxable basis exceeds safe minor units`,\n );\n if (basisMinor !== expectedBasis)\n throw new Error(\n `QuickBooks ${label} frozen taxable basis does not match its ordered components`,\n );\n taxComponents.push({\n taxRateRef,\n rate,\n compound: component.compound ?? false,\n basisMinor,\n explicitBasis: component.taxableAmount !== undefined,\n taxMinor: currencyMinor(\n componentAmount,\n currency,\n `${label} tax component ${componentIndex + 1}`,\n ),\n });\n return sum + componentAmount;\n },\n 0,\n );\n if (!close(componentTax, taxAmount))\n throw new Error(\n `QuickBooks ${label} tax components must equal the line tax amount`,\n );\n }\n\n const inclusive = mode === 'TaxInclusive';\n const grossAmount = item.taxInclusiveAmount;\n if (!inclusive && grossAmount !== undefined)\n throw new Error(\n `QuickBooks ${label} tax-inclusive amount requires TaxInclusive global tax calculation`,\n );\n if (inclusive) {\n if (\n grossAmount === undefined ||\n taxAmount === undefined ||\n (taxAmount > 0 && !item.taxComponents?.length)\n )\n throw new Error(\n `QuickBooks ${label} TaxInclusive snapshots require gross amount, line tax and tax components for nonzero tax`,\n );\n validateAmount(grossAmount, `${label} tax-inclusive amount`);\n if (!close(netAmount + taxAmount, grossAmount))\n throw new Error(\n `QuickBooks ${label} net amount plus tax must equal gross amount`,\n );\n if (!close(baseDocumentAmount - discount, grossAmount))\n throw new Error(\n `QuickBooks ${label} gross amount must equal quantity times gross unit price less gross discount`,\n );\n } else if (\n !close(netAmount, baseDocumentAmount - discount) &&\n !matchesCurrencyRoundedLineAmount(\n item.quantity,\n item.unitPrice,\n netAmount + discount,\n currency,\n )\n ) {\n throw new Error(\n `QuickBooks ${label} amount must equal quantity times unit price less discount`,\n );\n }\n const mappedComponents = item.quickbooksMapping?.taxComponents;\n if (\n taxComponents.some((component) => component.compound) &&\n mappedComponents === undefined\n )\n throw new Error(\n `QuickBooks ${label} compound tax requires caller-verified ordered tax-code mapping`,\n );\n if (mappedComponents !== undefined) {\n if (\n !Array.isArray(mappedComponents) ||\n mappedComponents.length !== taxComponents.length\n )\n throw new Error(\n `QuickBooks ${label} ordered tax-code mapping must match every frozen component`,\n );\n const refs = new Set<string>();\n for (const [position, mapped] of mappedComponents.entries()) {\n if (\n !mapped ||\n typeof mapped !== 'object' ||\n Object.keys(mapped).some(\n (key) => !['taxRateRef', 'compound'].includes(key),\n ) ||\n typeof mapped.compound !== 'boolean'\n )\n throw new Error(\n `QuickBooks ${label} ordered tax-code mapping has unknown order metadata`,\n );\n const ref = reference(\n mapped.taxRateRef,\n `${label} mapped tax rate`,\n ).value;\n const component = taxComponents[position];\n if (\n refs.has(ref) ||\n ref !== component.taxRateRef ||\n mapped.compound !== component.compound\n )\n throw new Error(\n `QuickBooks ${label} ordered tax-code mapping does not match frozen components`,\n );\n refs.add(ref);\n }\n }\n if (taxComponents.length > 0)\n validateFrozenComponentRates(\n taxComponents,\n inclusive ? (grossAmount as number) : netAmount,\n currency,\n inclusive,\n label,\n );\n\n const itemRef = item.quickbooksMapping\n ? reference(item.quickbooksMapping.itemRef, `${label} itemRef`)\n : undefined;\n const taxCodeRef = item.quickbooksMapping\n ? reference(item.quickbooksMapping.taxCodeRef, `${label} taxCodeRef`)\n : undefined;\n const line = (\n amount: number,\n quantity: number,\n unitPrice: number,\n description: string,\n taxInclusiveAmount?: number,\n ) => ({\n LineNum: index + 1,\n Description: description,\n Amount: amount,\n DetailType: 'SalesItemLineDetail' as const,\n SalesItemLineDetail: {\n Qty: quantity,\n UnitPrice: unitPrice,\n ItemRef: itemRef,\n TaxCodeRef: taxCodeRef,\n ...(taxInclusiveAmount === undefined\n ? {}\n : { TaxInclusiveAmt: taxInclusiveAmount }),\n },\n });\n\n if (discount === 0 && !inclusive) {\n return {\n lines: [line(netAmount, item.quantity, item.unitPrice, item.description)],\n taxAmount,\n taxComponents,\n };\n }\n if (\n discount === 0 ||\n isCurrencyMinorUnit(netAmount / item.quantity, currency)\n ) {\n return {\n lines: [\n line(\n netAmount,\n item.quantity,\n netAmount / item.quantity,\n item.description,\n inclusive ? grossAmount : undefined,\n ),\n ],\n taxAmount,\n taxComponents,\n };\n }\n\n let preDiscountAmount = netAmount + discount;\n let negativeAmount = -discount;\n const preDiscountGross = inclusive ? baseDocumentAmount : undefined;\n if (inclusive) {\n const components = item.taxComponents;\n const exemptSnapshot = taxAmount === 0 && !components?.length;\n if (!components?.length && !exemptSnapshot)\n throw new Error(\n `QuickBooks ${label} needs frozen component rates for an inclusive negative discount line`,\n );\n const rate = exemptSnapshot\n ? 0\n : (components ?? []).reduce(\n (sum, component, componentIndex) =>\n sum +\n decimalRate(\n component.rate,\n `${label} tax component ${componentIndex + 1}`,\n ).value,\n 0,\n );\n let discountNet = roundCurrencyAmount(discount / (1 + rate), currency);\n if (taxComponents.some((component) => component.compound)) {\n const { total } = orderedFactors(taxComponents);\n const numerator =\n currencyMinor(discount, currency, `${label} discount`) *\n total.denominator;\n const denominator = total.denominator + total.numerator;\n discountNet = currencyMajor(\n (2n * numerator + denominator) / (2n * denominator),\n currency,\n );\n }\n if (discountNet === undefined)\n throw new Error(\n `QuickBooks ${label} needs a recognized currency to map an inclusive fractional-unit discount`,\n );\n preDiscountAmount = netAmount + discountNet;\n negativeAmount = -discountNet;\n }\n if (enforceCurrencyGrid) {\n frozenCurrencyAmount(\n preDiscountAmount,\n `${label} generated pre-discount amount`,\n currency,\n );\n frozenCurrencyAmount(\n negativeAmount,\n `${label} generated discount amount`,\n currency,\n true,\n );\n }\n let negativeGross: number | undefined;\n if (inclusive) {\n if (grossAmount === undefined || preDiscountGross === undefined)\n throw new Error(\n `QuickBooks ${label} needs frozen gross amounts for an inclusive negative discount line`,\n );\n const unroundedNegativeGross = grossAmount - preDiscountGross;\n negativeGross =\n roundCurrencyAmount(unroundedNegativeGross, currency) ??\n unroundedNegativeGross;\n }\n if (enforceCurrencyGrid && negativeGross !== undefined) {\n frozenCurrencyAmount(\n negativeGross,\n `${label} generated gross discount amount`,\n currency,\n true,\n );\n }\n return {\n lines: [\n line(\n preDiscountAmount,\n item.quantity,\n preDiscountAmount / item.quantity,\n item.description,\n preDiscountGross,\n ),\n line(\n negativeAmount,\n 1,\n negativeAmount,\n `Discount on line ${index + 1}`,\n negativeGross,\n ),\n ],\n taxAmount,\n taxComponents,\n };\n}\n\nfunction basePayload(\n input: Pick<\n InvoiceInput,\n | 'customerId'\n | 'customerExternalId'\n | 'issueDate'\n | 'subtotal'\n | 'taxAmount'\n | 'totalAmount'\n | 'currency'\n | 'memo'\n | 'lineItems'\n | 'quickbooksMapping'\n >,\n number: string,\n dueDate?: Date,\n) {\n const { lines, taxLines } = mapDocumentLines(input);\n return {\n CustomerRef: { value: input.customerExternalId || input.customerId },\n DocNumber: number,\n TxnDate: formatLocalDate(input.issueDate),\n ...(dueDate ? { DueDate: formatLocalDate(dueDate) } : {}),\n Line: lines,\n GlobalTaxCalculation: input.quickbooksMapping?.globalTaxCalculation,\n TxnTaxDetail: input.quickbooksMapping\n ? {\n TotalTax: input.taxAmount,\n ...(taxLines.length > 0 ? { TaxLine: taxLines } : {}),\n }\n : undefined,\n CurrencyRef: input.currency ? { value: input.currency } : undefined,\n CustomerMemo: input.memo ? { value: input.memo } : undefined,\n };\n}\n\nexport function mapInvoiceToQBO(invoice: InvoiceInput) {\n if (invoice.collectionMethod === 'charge_automatically')\n throw new Error(\n 'QuickBooks does not support charge_automatically invoice collection',\n );\n if (invoice.automaticTax)\n throw new Error(\n 'QuickBooks does not support automaticTax invoice calculation',\n );\n return basePayload(\n invoice,\n invoice.invoiceNumber,\n invoice.dueDate,\n ) as ReturnType<typeof basePayload> & { DueDate: string };\n}\n\nexport function mapCreditMemoToQBO(creditMemo: CreditMemoInput) {\n if (\n !creditMemo.creditedInvoiceExternalId ||\n creditMemo.creditedInvoiceExternalId.trim() !==\n creditMemo.creditedInvoiceExternalId\n )\n throw new Error(\n 'QuickBooks credit memos require a credited invoice external ID',\n );\n return basePayload(creditMemo, creditMemo.creditMemoNumber);\n}\n","/** Exact, explicit receivable reclassification. No sales, tax or bank-transfer approximation. */\nimport { createHash } from 'node:crypto';\nimport { currencyMinorUnitFactor, isCurrencyMinorUnit } from './line-amount.js';\n\nexport interface QuickBooksReceivableMapping {\n realmId: string;\n environment: 'sandbox' | 'production';\n version: string;\n reviewEvidenceRef: string;\n accountingBasis: 'accrual';\n taxTiming: 'invoice-tax-point';\n releaseDueDates: 'host-managed';\n currency: string;\n customerRef: string;\n receivablesAccountRef: string;\n retainedAssetAccountRef: string;\n cashAccountRef: string | null;\n}\nexport interface QuickBooksReceivableSource {\n type: 'Invoice' | 'CreditMemo' | 'JournalEntry';\n id: string;\n customerRef: string;\n /** Immutable host snapshot/agreement/release reference, never a guessed provider field. */\n evidenceRef: string;\n}\ninterface TransferEvidence {\n mapping: QuickBooksReceivableMapping;\n source: QuickBooksReceivableSource;\n requestId: string;\n effectiveOn: string;\n evidenceRef: string;\n}\nexport interface QuickBooksReceivableTransferInput extends TransferEvidence {\n kind: 'withhold' | 'release' | 'cash-refund' | 'reverse-cash-refund';\n amountMinor: number;\n}\nexport interface QuickBooksNonCashApplicationInput extends TransferEvidence {\n kind: 'application';\n amountMinor: number;\n debit: { type: 'Invoice' | 'JournalEntry'; id: string };\n credit: { type: 'CreditMemo' | 'JournalEntry'; id: string };\n}\nexport type QuickBooksReceivableInput =\n | QuickBooksReceivableTransferInput\n | QuickBooksNonCashApplicationInput;\nexport interface QuickBooksReceivableRequest {\n version: 1;\n endpoint: 'journalentry' | 'payment';\n realmId: string;\n environment: 'sandbox' | 'production';\n requestId: string;\n payloadHash: string;\n input: QuickBooksReceivableInput;\n}\nexport interface QuickBooksReceivableReadback {\n externalId: string;\n syncToken: string;\n kind: QuickBooksReceivableInput['kind'];\n customerRef: string;\n currency: string;\n effectiveOn: string;\n amountMinor: number;\n /** Noncash application amount is never counted as a customer cash receipt. */\n nonCashAppliedMinor: number;\n /** A cash journal is a record, not evidence of provider bank settlement. */\n recordedCashChangeMinor: number;\n providerProcessedCashMinor: 0;\n bankSettlementVerified: false;\n source: QuickBooksReceivableSource;\n payloadHash: string;\n}\nexport interface QuickBooksReceivableTransferOperations {\n verifyMapping(\n mapping: QuickBooksReceivableMapping,\n ): Promise<{ mappingHash: string; homeCurrency: string }>;\n execute(\n request: QuickBooksReceivableRequest,\n ): Promise<QuickBooksReceivableReadback>;\n /** Reconcile a known remote ID against the complete prepared contract, not just its total. */\n read(\n request: QuickBooksReceivableRequest,\n externalId: string,\n ): Promise<QuickBooksReceivableReadback>;\n}\n\nconst hash = (value: unknown) =>\n createHash('sha256').update(JSON.stringify(value)).digest('hex');\nfunction text(\n value: unknown,\n label: string,\n max = 1000,\n): asserts value is string {\n if (\n typeof value !== 'string' ||\n !value ||\n value !== value.trim() ||\n value.length > max\n )\n throw new Error(`${label} must be explicit trimmed text`);\n}\nfunction id(value: unknown, label: string): asserts value is string {\n text(value, label, 100);\n if (!/^[A-Za-z0-9._-]+$/.test(value))\n throw new Error(`${label} is not a supported provider reference`);\n}\nfunction date(value: string) {\n if (\n !/^\\d{4}-\\d{2}-\\d{2}$/.test(value) ||\n !Number.isFinite(Date.parse(value)) ||\n new Date(value).toISOString().slice(0, 10) !== value\n )\n throw new Error('Receivable effective date is invalid');\n}\nfunction minor(value: number, currency: string): number {\n const factor = currencyMinorUnitFactor(currency);\n if (!factor || !Number.isSafeInteger(value) || value <= 0)\n throw new Error(\n 'Receivable amount must be positive safe integer currency minor units',\n );\n const major = value / factor;\n if (\n !isCurrencyMinorUnit(major, currency) ||\n Math.round(major * factor) !== value\n )\n throw new Error(\n 'Receivable amount cannot be represented exactly by the provider',\n );\n return major;\n}\nexport function validateQuickBooksReceivableMapping(\n mapping: QuickBooksReceivableMapping,\n) {\n id(mapping.realmId, 'Realm');\n id(mapping.customerRef, 'Customer');\n text(mapping.version, 'Mapping version');\n text(mapping.reviewEvidenceRef, 'Mapping review evidence');\n if (\n !['sandbox', 'production'].includes(mapping.environment) ||\n mapping.accountingBasis !== 'accrual' ||\n mapping.taxTiming !== 'invoice-tax-point' ||\n mapping.releaseDueDates !== 'host-managed'\n )\n throw new Error(\n 'Receivable transfers support explicit accrual, invoice-tax-point and host-managed release due dates only',\n );\n if (\n !/^[A-Z]{3}$/.test(mapping.currency) ||\n !currencyMinorUnitFactor(mapping.currency)\n )\n throw new Error('Unsupported receivable currency');\n const refs = [\n mapping.receivablesAccountRef,\n mapping.retainedAssetAccountRef,\n ...(mapping.cashAccountRef === null ? [] : [mapping.cashAccountRef]),\n ];\n for (const ref of refs) id(ref, 'Posting account');\n if (new Set(refs).size !== refs.length)\n throw new Error('Receivable posting accounts must be distinct');\n}\nfunction validate(input: QuickBooksReceivableInput) {\n validateQuickBooksReceivableMapping(input.mapping);\n id(input.requestId, 'Request');\n if (input.requestId.length > 50)\n throw new Error('QuickBooks requestId must contain at most 50 characters');\n date(input.effectiveOn);\n text(input.evidenceRef, 'Operation evidence', 1000);\n if (!['Invoice', 'CreditMemo', 'JournalEntry'].includes(input.source.type))\n throw new Error('Unsupported source transaction type');\n id(input.source.id, 'Source transaction');\n id(input.source.customerRef, 'Source customer');\n text(input.source.evidenceRef, 'Source evidence');\n if (input.source.customerRef !== input.mapping.customerRef)\n throw new Error('Source customer differs from receivable mapping');\n minor(input.amountMinor, input.mapping.currency);\n if (input.kind === 'application') {\n if (\n !['Invoice', 'JournalEntry'].includes(input.debit.type) ||\n !['CreditMemo', 'JournalEntry'].includes(input.credit.type)\n )\n throw new Error('Unsupported noncash application transaction types');\n id(input.debit.id, 'Debit transaction');\n id(input.credit.id, 'Credit transaction');\n if (\n input.debit.type === input.credit.type &&\n input.debit.id === input.credit.id\n )\n throw new Error('Cannot apply a journal to itself');\n } else if (\n !['withhold', 'release', 'cash-refund', 'reverse-cash-refund'].includes(\n input.kind,\n )\n )\n throw new Error('Unsupported receivable transfer direction');\n else if (input.kind.includes('cash-refund') && !input.mapping.cashAccountRef)\n throw new Error('Cash refund recording requires an explicit cash account');\n}\nexport function mapQuickBooksReceivableRequest(\n input: QuickBooksReceivableInput,\n): Record<string, unknown> {\n validate(input);\n const amount = minor(input.amountMinor, input.mapping.currency);\n const source = `${input.source.type}:${input.source.id}; customer:${input.source.customerRef}; evidence:${input.source.evidenceRef}`;\n const note = `${input.kind}; ${source}; operation:${input.evidenceRef}; mapping:${input.mapping.version}; request:${input.requestId}`;\n if (note.length > 4000)\n throw new Error('Receivable provenance exceeds the provider note limit');\n const base = {\n TxnDate: input.effectiveOn,\n CurrencyRef: { value: input.mapping.currency },\n PrivateNote: note,\n };\n if (input.kind === 'application')\n return {\n ...base,\n CustomerRef: { value: input.mapping.customerRef },\n TotalAmt: 0,\n ProcessPayment: false,\n Line: [input.debit, input.credit].map((ref) => ({\n Amount: amount,\n LinkedTxn: [{ TxnType: ref.type, TxnId: ref.id }],\n })),\n };\n const arDebit = input.kind === 'release' || input.kind === 'cash-refund';\n const counterpart = input.kind.includes('cash-refund')\n ? input.mapping.cashAccountRef\n : input.mapping.retainedAssetAccountRef;\n return {\n ...base,\n Line: [\n { account: input.mapping.receivablesAccountRef, debit: arDebit },\n { account: counterpart, debit: !arDebit },\n ].map((line, index) => ({\n LineNum: index + 1,\n Description: source,\n Amount: amount,\n DetailType: 'JournalEntryLineDetail',\n JournalEntryLineDetail: {\n PostingType: line.debit ? 'Debit' : 'Credit',\n AccountRef: { value: line.account },\n Entity: {\n Type: 'Customer',\n EntityRef: { value: input.mapping.customerRef },\n },\n },\n })),\n };\n}\n/** Pure preparation. Persist before sending; the hash does not prove a remote write occurred once. */\nexport function prepareQuickBooksReceivableRequest(\n input: QuickBooksReceivableInput,\n): QuickBooksReceivableRequest {\n const frozenInput = structuredClone(input),\n body = mapQuickBooksReceivableRequest(frozenInput);\n return Object.freeze({\n version: 1,\n endpoint: input.kind === 'application' ? 'payment' : 'journalentry',\n realmId: input.mapping.realmId,\n environment: input.mapping.environment,\n requestId: input.requestId,\n payloadHash: hash({ input: frozenInput, body }),\n input: frozenInput,\n });\n}\nexport function validateQuickBooksReceivableRequest(\n request: QuickBooksReceivableRequest,\n realmId: string,\n environment: string,\n serializedBody?: string,\n) {\n const expected = prepareQuickBooksReceivableRequest(request.input);\n if (\n request.version !== 1 ||\n request.realmId !== realmId ||\n request.environment !== environment ||\n request.endpoint !== expected.endpoint ||\n request.requestId !== expected.requestId ||\n request.payloadHash !== expected.payloadHash ||\n request.realmId !== expected.realmId ||\n request.environment !== expected.environment ||\n (serializedBody !== undefined &&\n serializedBody !==\n JSON.stringify(mapQuickBooksReceivableRequest(request.input)))\n )\n throw new Error(\n 'Receivable request scope, provenance or frozen payload changed',\n );\n}\n\n/** Exact readback validation; provider-added IDs/names are allowed, omitted financial facts are not. */\nexport function reconcileQuickBooksReceivableRecord(\n request: QuickBooksReceivableRequest,\n value: unknown,\n): QuickBooksReceivableReadback {\n validateQuickBooksReceivableRequest(\n request,\n request.realmId,\n request.environment,\n );\n const raw = value as Record<string, any>,\n expected = mapQuickBooksReceivableRequest(request.input),\n input = request.input;\n if (!raw || typeof raw !== 'object')\n throw new Error('Receivable provider record is missing');\n id(raw.Id, 'Provider record');\n text(raw.SyncToken, 'Provider sync token', 100);\n if (\n raw.TxnDate !== expected.TxnDate ||\n raw.CurrencyRef?.value !== input.mapping.currency ||\n raw.PrivateNote !== expected.PrivateNote ||\n !Array.isArray(raw.Line) ||\n raw.Line.length !== 2\n )\n throw new Error(\n 'Receivable provider identity, currency, date or evidence differs',\n );\n if (\n (raw.ExchangeRate !== undefined && raw.ExchangeRate !== 1) ||\n (raw.TxnTaxDetail !== undefined && raw.TxnTaxDetail?.TotalTax !== 0)\n )\n throw new Error(\n 'Receivable readback contains unsupported exchange or tax effects',\n );\n const expectedLines = expected.Line as Record<string, any>[];\n for (let i = 0; i < 2; i++) {\n const line = raw.Line[i],\n wanted = expectedLines[i];\n if (line.Amount !== wanted.Amount)\n throw new Error('Receivable provider line amount differs');\n if (input.kind === 'application') {\n if (\n !Array.isArray(line.LinkedTxn) ||\n line.LinkedTxn.length !== 1 ||\n line.LinkedTxn[0].TxnType !== wanted.LinkedTxn[0].TxnType ||\n line.LinkedTxn[0].TxnId !== wanted.LinkedTxn[0].TxnId\n )\n throw new Error('Receivable application linkage differs');\n } else {\n const details = line.JournalEntryLineDetail,\n required = wanted.JournalEntryLineDetail;\n if (\n line.DetailType !== 'JournalEntryLineDetail' ||\n line.Description !== wanted.Description ||\n details?.PostingType !== required.PostingType ||\n details?.AccountRef?.value !== required.AccountRef.value ||\n details?.Entity?.Type !== 'Customer' ||\n details?.Entity?.EntityRef?.value !== input.mapping.customerRef ||\n details?.TaxAmount !== undefined ||\n details?.TaxCodeRef !== undefined\n )\n throw new Error('Receivable journal posting authority differs');\n }\n }\n if (\n input.kind === 'application' &&\n (raw.TotalAmt !== 0 ||\n raw.UnappliedAmt !== 0 ||\n raw.CustomerRef?.value !== input.mapping.customerRef ||\n raw.ProcessPayment === true)\n )\n throw new Error(\n 'Noncash application must have zero cash and no unapplied balance',\n );\n return {\n externalId: raw.Id,\n syncToken: raw.SyncToken,\n kind: input.kind,\n customerRef: input.mapping.customerRef,\n currency: input.mapping.currency,\n effectiveOn: input.effectiveOn,\n amountMinor: input.amountMinor,\n nonCashAppliedMinor: input.kind === 'application' ? input.amountMinor : 0,\n recordedCashChangeMinor:\n input.kind === 'cash-refund'\n ? -input.amountMinor\n : input.kind === 'reverse-cash-refund'\n ? input.amountMinor\n : 0,\n providerProcessedCashMinor: 0,\n bankSettlementVerified: false,\n source: structuredClone(input.source),\n payloadHash: request.payloadHash,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as StripeApiError } from "./errors-
|
|
1
|
+
import { r as StripeApiError } from "./errors-DIqXkm4s.js";
|
|
2
2
|
import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
3
3
|
//#region src/providers/stripe/index.ts
|
|
4
4
|
/**
|
|
@@ -1298,4 +1298,4 @@ function sleep(ms) {
|
|
|
1298
1298
|
//#endregion
|
|
1299
1299
|
export { StripeProvider };
|
|
1300
1300
|
|
|
1301
|
-
//# sourceMappingURL=stripe-
|
|
1301
|
+
//# sourceMappingURL=stripe-DOJLldVK.js.map
|