@happyvertical/smrt-commerce 0.56.2 → 0.57.0
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 +24 -11
- package/README.md +137 -89
- package/agents/accounting-snapshot-mapper.md +3 -3
- package/agents/commercial-ui.md +2 -2
- package/agents/contract-money.md +9 -12
- package/agents/cost-billing.md +3 -6
- package/agents/customer-vendor-ui.md +1 -2
- package/agents/document-money.md +58 -31
- package/agents/invoice-calculations.md +31 -56
- package/agents/invoice-preparation.md +62 -73
- package/agents/invoice-quantity.md +9 -21
- package/agents/minor-unit-migration.md +4 -4
- package/agents/money-calculator.md +7 -8
- package/agents/money-model.md +18 -22
- package/agents/money-upgrade.md +92 -0
- package/agents/revenue-journal.md +2 -2
- package/agents/tax-codes.md +17 -14
- package/agents/tax-summary.md +8 -6
- package/dist/billing/period-close.d.ts.map +1 -1
- package/dist/billing/runtime.d.ts +5 -2
- package/dist/billing/runtime.d.ts.map +1 -1
- package/dist/chunks/{ContractLineItemCollection--BrGMtNz.js → ContractLineItemCollection-BZcrlrrY.js} +19 -24
- package/dist/chunks/ContractLineItemCollection-BZcrlrrY.js.map +1 -0
- package/dist/chunks/{CustomerCollection-CjGaZSpf.js → CustomerCollection-BIPH2ZUx.js} +2 -2
- package/dist/chunks/{CustomerCollection-CjGaZSpf.js.map → CustomerCollection-BIPH2ZUx.js.map} +1 -1
- package/dist/chunks/{DocumentTaxCollection-KOkaQT2M.js → DocumentTaxCollection-DDzlywMW.js} +14 -7
- package/dist/chunks/DocumentTaxCollection-DDzlywMW.js.map +1 -0
- package/dist/chunks/{InvoiceCollection-BUe_8FT1.js → InvoiceCollection-cinzAqt6.js} +50 -161
- package/dist/chunks/InvoiceCollection-cinzAqt6.js.map +1 -0
- package/dist/chunks/{TaxCodeCollection-DF2eaJed.js → TaxCodeCollection-DaBOPG9c.js} +11 -4
- package/dist/chunks/{TaxCodeCollection-DF2eaJed.js.map → TaxCodeCollection-DaBOPG9c.js.map} +1 -1
- package/dist/chunks/{TaxComponentCollection-3x24xSNh.js → TaxComponentCollection-C4zxnyVu.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-3x24xSNh.js.map → TaxComponentCollection-C4zxnyVu.js.map} +1 -1
- package/dist/chunks/VendorCollection-D6ZcUYy8.js +100 -0
- package/dist/chunks/VendorCollection-D6ZcUYy8.js.map +1 -0
- package/dist/chunks/{allocation-integrity-Cq0g6CfO.js → allocation-integrity-WmWyXhtG.js} +6 -6
- package/dist/chunks/{allocation-integrity-Cq0g6CfO.js.map → allocation-integrity-WmWyXhtG.js.map} +1 -1
- package/dist/chunks/calculations-C9daQLsh.js +82 -0
- package/dist/chunks/calculations-C9daQLsh.js.map +1 -0
- package/dist/chunks/contract-money-EuToOghh.js +301 -0
- package/dist/chunks/contract-money-EuToOghh.js.map +1 -0
- package/dist/chunks/detect-CY9ufaFb.js +328 -0
- package/dist/chunks/detect-CY9ufaFb.js.map +1 -0
- package/dist/chunks/{document-money-oUDvdjOf.js → document-money-DV5t4vlK.js} +388 -62
- package/dist/chunks/document-money-DV5t4vlK.js.map +1 -0
- package/dist/chunks/{invoice-posting-CF3fE_Ec.js → invoice-posting-C2i5dOVZ.js} +20 -22
- package/dist/chunks/invoice-posting-C2i5dOVZ.js.map +1 -0
- package/dist/chunks/{revenue-journal-DY9fro8E.js → revenue-journal-LLA9Kh_i.js} +3 -14
- package/dist/chunks/revenue-journal-LLA9Kh_i.js.map +1 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js +255 -0
- package/dist/chunks/tenant-money-barrier-6TlqUeVj.js.map +1 -0
- package/dist/chunks/types-Bbm0Xflc.js.map +1 -1
- package/dist/chunks/{units-CNcjH_eE.js → units-8ElbjVZK.js} +18 -3
- package/dist/chunks/units-8ElbjVZK.js.map +1 -0
- package/dist/collections/ContractCollection.d.ts.map +1 -1
- package/dist/collections/ContractLineItemCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceCollection.d.ts.map +1 -1
- package/dist/collections/InvoiceLineItemCollection.d.ts +0 -30
- package/dist/collections/InvoiceLineItemCollection.d.ts.map +1 -1
- package/dist/collections/TaxCodeCollection.d.ts +5 -1
- package/dist/collections/TaxCodeCollection.d.ts.map +1 -1
- package/dist/collections/TaxSettingsCollection.d.ts +15 -8
- package/dist/collections/TaxSettingsCollection.d.ts.map +1 -1
- package/dist/collections/TaxSummaryReportCollection.d.ts +3 -3
- package/dist/collections/TaxSummaryReportCollection.d.ts.map +1 -1
- package/dist/collections/index.d.ts +0 -1
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/commerce-money-tools.d.ts.map +1 -1
- package/dist/contract-money.d.ts +1 -13
- package/dist/contract-money.d.ts.map +1 -1
- package/dist/document-money-internal.d.ts +7 -3
- package/dist/document-money-internal.d.ts.map +1 -1
- package/dist/document-money.d.ts +1 -11
- package/dist/document-money.d.ts.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +667 -1650
- package/dist/index.js.map +1 -1
- package/dist/invoice-accounting-sync.d.ts.map +1 -1
- package/dist/invoice-mcp.d.ts +3 -3
- package/dist/invoice-mcp.d.ts.map +1 -1
- package/dist/invoice-posting.d.ts +11 -5
- package/dist/invoice-posting.d.ts.map +1 -1
- package/dist/invoice-record-screen.d.ts +1 -1
- package/dist/invoice-record-screen.d.ts.map +1 -1
- package/dist/invoices.d.ts +6 -1
- package/dist/invoices.d.ts.map +1 -1
- package/dist/invoices.js +2 -2
- package/dist/manifest.json +37 -765
- package/dist/migrations/invoiceEditorStorage.d.ts +2 -4
- package/dist/migrations/invoiceEditorStorage.d.ts.map +1 -1
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/ContractLineItem.d.ts +6 -22
- package/dist/models/ContractLineItem.d.ts.map +1 -1
- package/dist/models/Invoice.d.ts +18 -48
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/InvoiceLineItem.d.ts +8 -37
- package/dist/models/InvoiceLineItem.d.ts.map +1 -1
- package/dist/models/TaxSettings.d.ts +0 -10
- package/dist/models/TaxSettings.d.ts.map +1 -1
- package/dist/models/index.d.ts +0 -1
- package/dist/models/index.d.ts.map +1 -1
- package/dist/playground.js +1 -1
- package/dist/playground.js.map +1 -1
- package/dist/recipes.d.ts +8 -11
- package/dist/recipes.d.ts.map +1 -1
- package/dist/revenue-journal.d.ts +0 -8
- package/dist/revenue-journal.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +79 -661
- package/dist/svelte/components/InvoiceEditor.svelte +7 -148
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts +4 -1
- package/dist/svelte/components/InvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/components/InvoiceTotals.svelte +14 -118
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts +4 -27
- package/dist/svelte/components/InvoiceTotals.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MoneyInvoiceEditor.svelte +3 -23
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts +3 -26
- package/dist/svelte/components/MoneyInvoiceEditor.svelte.d.ts.map +1 -1
- package/dist/svelte/index.d.ts +2 -3
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +1 -2
- package/dist/svelte/invoices/calculations.d.ts +3 -108
- package/dist/svelte/invoices/calculations.d.ts.map +1 -1
- package/dist/svelte/invoices/calculations.js +12 -309
- package/dist/svelte/invoices/messages.d.ts +1 -37
- package/dist/svelte/invoices/messages.d.ts.map +1 -1
- package/dist/svelte/invoices/messages.js +1 -37
- package/dist/svelte/invoices/money-editor.d.ts +1 -1
- package/dist/svelte/invoices/money-editor.d.ts.map +1 -1
- package/dist/svelte/invoices/types.d.ts +14 -114
- package/dist/svelte/invoices/types.d.ts.map +1 -1
- package/dist/svelte/playground/InvoicePreparationPreview.svelte +85 -94
- package/dist/svelte/playground/InvoicePreparationPreview.svelte.d.ts.map +1 -1
- package/dist/svelte/playground.js +1 -1
- package/dist/tax/index.d.ts +2 -1
- package/dist/tax/index.d.ts.map +1 -1
- package/dist/tax/standard-codes.d.ts +12 -0
- package/dist/tax/standard-codes.d.ts.map +1 -0
- package/dist/tax/tenant-bootstrap.d.ts +29 -0
- package/dist/tax/tenant-bootstrap.d.ts.map +1 -0
- package/dist/tenant-money-barrier.d.ts +12 -44
- package/dist/tenant-money-barrier.d.ts.map +1 -1
- package/dist/types/index.d.ts +10 -23
- package/dist/types/index.d.ts.map +1 -1
- package/dist/ui.js +1 -1
- package/dist/ui.js.map +1 -1
- package/dist/upgrade/detect.d.ts +129 -0
- package/dist/upgrade/detect.d.ts.map +1 -0
- package/dist/upgrade/money-v2.d.ts +81 -0
- package/dist/upgrade/money-v2.d.ts.map +1 -0
- package/package.json +14 -13
- package/agents/line-amount-migration.md +0 -50
- package/dist/chunks/ContractLineItemCollection--BrGMtNz.js.map +0 -1
- package/dist/chunks/DocumentTaxCollection-KOkaQT2M.js.map +0 -1
- package/dist/chunks/InvoiceCollection-BUe_8FT1.js.map +0 -1
- package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js +0 -468
- package/dist/chunks/InvoiceLineItemCollection-CPQGghyd.js.map +0 -1
- package/dist/chunks/TaxSettingsCollection-DYYF-In-.js +0 -319
- package/dist/chunks/TaxSettingsCollection-DYYF-In-.js.map +0 -1
- package/dist/chunks/calculations-DaHR17il.js +0 -333
- package/dist/chunks/calculations-DaHR17il.js.map +0 -1
- package/dist/chunks/document-money-oUDvdjOf.js.map +0 -1
- package/dist/chunks/invoice-posting-CF3fE_Ec.js.map +0 -1
- package/dist/chunks/revenue-journal-DY9fro8E.js.map +0 -1
- package/dist/chunks/tenant-money-barrier-y6EAa6vY.js +0 -135
- package/dist/chunks/tenant-money-barrier-y6EAa6vY.js.map +0 -1
- package/dist/chunks/units-CNcjH_eE.js.map +0 -1
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts +0 -12
- package/dist/collections/MoneyMigrationDocumentCollection.d.ts.map +0 -1
- package/dist/migrations/commerceLineAmounts.d.ts +0 -84
- package/dist/migrations/commerceLineAmounts.d.ts.map +0 -1
- package/dist/models/MoneyMigrationDocument.d.ts +0 -28
- package/dist/models/MoneyMigrationDocument.d.ts.map +0 -1
- package/dist/svelte/components/InvoiceLineEditor.svelte +0 -92
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts +0 -8
- package/dist/svelte/components/InvoiceLineEditor.svelte.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.d.ts +0 -6
- package/dist/svelte/invoices/fields.d.ts.map +0 -1
- package/dist/svelte/invoices/fields.js +0 -22
- package/dist/tax/legacy.d.ts +0 -48
- package/dist/tax/legacy.d.ts.map +0 -1
|
@@ -1,319 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { MoneyValidationError } from "../money.js";
|
|
3
|
-
import { SmrtCollection, SmrtObject, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
4
|
-
import { TenantScoped, getTenantId, tenantId } from "@happyvertical/smrt-tenancy";
|
|
5
|
-
//#region src/document-money-internal.ts
|
|
6
|
-
var activeMoneyTransactions = /* @__PURE__ */ new WeakSet();
|
|
7
|
-
var DOCUMENT_MONEY_WRITE = /* @__PURE__ */ Symbol("commerce.documentMoneyWrite");
|
|
8
|
-
var MONEY_MIGRATION_WRITE = /* @__PURE__ */ Symbol("commerce.moneyMigrationWrite");
|
|
9
|
-
var DOCUMENT_MONEY_READ_REBIND = /* @__PURE__ */ Symbol("commerce.documentMoneyReadRebind");
|
|
10
|
-
function compareCodeUnits(left, right) {
|
|
11
|
-
return left < right ? -1 : left > right ? 1 : 0;
|
|
12
|
-
}
|
|
13
|
-
function quoteIdentifier(identifier) {
|
|
14
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(identifier)) throw new MoneyValidationError("INVALID_MONEY_INPUT", `Unsafe money parent table identifier: ${identifier}`);
|
|
15
|
-
return `"${identifier}"`;
|
|
16
|
-
}
|
|
17
|
-
function assertIdentifier(value, label) {
|
|
18
|
-
if (typeof value !== "string" || value.trim() !== value || value.length === 0) throw new MoneyValidationError("INVALID_MONEY_INPUT", `${label} must be a nonempty identifier`);
|
|
19
|
-
}
|
|
20
|
-
async function withDocumentMoneyTransaction(db, operation) {
|
|
21
|
-
if (activeMoneyTransactions.has(db)) return operation(db);
|
|
22
|
-
if (!db.transaction) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Document money persistence requires transaction support");
|
|
23
|
-
return db.transaction(async (tx) => {
|
|
24
|
-
activeMoneyTransactions.add(tx);
|
|
25
|
-
try {
|
|
26
|
-
return await operation(tx);
|
|
27
|
-
} finally {
|
|
28
|
-
activeMoneyTransactions.delete(tx);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
async function withDocumentMoneyObjectTransaction(input, operation) {
|
|
33
|
-
if (activeMoneyTransactions.has(input.db)) return operation(input, input.db);
|
|
34
|
-
return input.withTransaction(async (bound) => {
|
|
35
|
-
const tx = bound.db;
|
|
36
|
-
activeMoneyTransactions.add(tx);
|
|
37
|
-
try {
|
|
38
|
-
return await operation(bound, tx);
|
|
39
|
-
} finally {
|
|
40
|
-
activeMoneyTransactions.delete(tx);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
async function lockDocumentMoneyParents(targets) {
|
|
45
|
-
const sorted = [...targets].sort((left, right) => compareCodeUnits(left.id, right.id) || compareCodeUnits(left.collection.tableName, right.collection.tableName));
|
|
46
|
-
const identities = /* @__PURE__ */ new Set();
|
|
47
|
-
for (const target of sorted) {
|
|
48
|
-
assertIdentifier(target.id, "Money parent id");
|
|
49
|
-
assertIdentifier(target.tenantId, "Money parent tenant id");
|
|
50
|
-
const identity = `${target.collection.tableName}\0${target.id}`;
|
|
51
|
-
if (identities.has(identity)) throw new MoneyValidationError("INVALID_MONEY_INPUT", `Duplicate money parent lock target: ${target.id}`);
|
|
52
|
-
identities.add(identity);
|
|
53
|
-
const table = quoteIdentifier(target.collection.tableName);
|
|
54
|
-
if ((await target.collection.query(`UPDATE ${table}
|
|
55
|
-
SET "updated_at" = "updated_at"
|
|
56
|
-
WHERE "id" = ? AND "tenant_id" = ?
|
|
57
|
-
RETURNING "id"`, [target.id, target.tenantId], { allowRawOnTenantScoped: true })).length !== 1) throw new MoneyValidationError("INVALID_MONEY_INPUT", `Money parent ${target.id} was not found in tenant ${target.tenantId}`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/models/TaxSettings.ts
|
|
62
|
-
var __defProp = Object.defineProperty;
|
|
63
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
64
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
65
|
-
enumerable: true,
|
|
66
|
-
configurable: true,
|
|
67
|
-
writable: true,
|
|
68
|
-
value
|
|
69
|
-
}) : obj[key] = value;
|
|
70
|
-
var __decorateClass = (decorators, target, key, kind) => {
|
|
71
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
72
|
-
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
73
|
-
if (kind && result) __defProp(target, key, result);
|
|
74
|
-
return result;
|
|
75
|
-
};
|
|
76
|
-
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
77
|
-
var TaxSettings = class extends SmrtObject {
|
|
78
|
-
tenantId = "";
|
|
79
|
-
defaultSalesTaxCodeId = "";
|
|
80
|
-
defaultPurchaseTaxCodeId = "";
|
|
81
|
-
defaultLineAmountType = "exclusive";
|
|
82
|
-
taxRoundingScope = "line";
|
|
83
|
-
/** Stored JSON is guarded through the typed accessor below. */
|
|
84
|
-
taxRegistrationsJson = "[]";
|
|
85
|
-
/** Server-owned runtime semantics gate. Never exposed as a generated write. */
|
|
86
|
-
moneyModel = "legacy";
|
|
87
|
-
/** Opaque owner token while a tenant migration is in progress. */
|
|
88
|
-
moneyMigrationId = "";
|
|
89
|
-
get taxRegistrations() {
|
|
90
|
-
try {
|
|
91
|
-
const value = JSON.parse(this.taxRegistrationsJson);
|
|
92
|
-
if (!Array.isArray(value)) return [];
|
|
93
|
-
return value.filter((entry) => !!entry && typeof entry === "object" && typeof entry.taxComponentId === "string" && typeof entry.number === "string" && typeof entry.label === "string");
|
|
94
|
-
} catch {
|
|
95
|
-
return [];
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
set taxRegistrations(value) {
|
|
99
|
-
this.taxRegistrationsJson = typeof value === "string" ? value : JSON.stringify(value);
|
|
100
|
-
}
|
|
101
|
-
constructor(options = {}) {
|
|
102
|
-
super(options);
|
|
103
|
-
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
104
|
-
if (options.defaultSalesTaxCodeId !== void 0) this.defaultSalesTaxCodeId = options.defaultSalesTaxCodeId;
|
|
105
|
-
if (options.defaultPurchaseTaxCodeId !== void 0) this.defaultPurchaseTaxCodeId = options.defaultPurchaseTaxCodeId;
|
|
106
|
-
if (options.defaultLineAmountType !== void 0) this.defaultLineAmountType = options.defaultLineAmountType;
|
|
107
|
-
if (options.taxRoundingScope !== void 0) this.taxRoundingScope = options.taxRoundingScope;
|
|
108
|
-
if (options.taxRegistrations !== void 0) this.taxRegistrations = structuredClone(options.taxRegistrations);
|
|
109
|
-
if (options.moneyModel !== void 0) this.moneyModel = options.moneyModel;
|
|
110
|
-
if (options.moneyMigrationId !== void 0) this.moneyMigrationId = options.moneyMigrationId;
|
|
111
|
-
}
|
|
112
|
-
async save() {
|
|
113
|
-
return this.saveValidated(false);
|
|
114
|
-
}
|
|
115
|
-
/** @internal Money migration owns marker transitions. */
|
|
116
|
-
async saveMoneyModel(capability) {
|
|
117
|
-
if (capability !== MONEY_MIGRATION_WRITE) throw new MoneyValidationError("FROZEN_DOCUMENT", "Tenant money model requires the migration capability");
|
|
118
|
-
return this.saveValidated(true);
|
|
119
|
-
}
|
|
120
|
-
/** @internal Caller already owns the transaction-bound migration barrier. */
|
|
121
|
-
async saveMoneyModelOnTransaction(capability) {
|
|
122
|
-
if (capability !== MONEY_MIGRATION_WRITE) throw new MoneyValidationError("FROZEN_DOCUMENT", "Tenant money model requires the migration capability");
|
|
123
|
-
return this.saveValidated(true, true);
|
|
124
|
-
}
|
|
125
|
-
async saveValidated(allowMoneyModelWrite, transactionBound = false) {
|
|
126
|
-
if (![
|
|
127
|
-
"exclusive",
|
|
128
|
-
"inclusive",
|
|
129
|
-
"none"
|
|
130
|
-
].includes(this.defaultLineAmountType)) throw new Error("Tax settings defaultLineAmountType is invalid");
|
|
131
|
-
if (!["line", "document"].includes(this.taxRoundingScope)) throw new Error("Tax settings taxRoundingScope is invalid");
|
|
132
|
-
if (![
|
|
133
|
-
"legacy",
|
|
134
|
-
"migrating",
|
|
135
|
-
"v2"
|
|
136
|
-
].includes(this.moneyModel)) throw new Error("Tax settings moneyModel is invalid");
|
|
137
|
-
if (this.moneyModel === "migrating" !== !!this.moneyMigrationId) throw new Error("Tax settings migrating state requires exactly one migration owner");
|
|
138
|
-
const registrations = this.parsedRegistrations();
|
|
139
|
-
if (!registrations) throw new Error("Tax registrations must be a valid JSON array");
|
|
140
|
-
if (registrations.some((entry) => !entry.taxComponentId || !entry.number.trim() || !entry.label.trim())) throw new Error("Tax registrations require component, number and label");
|
|
141
|
-
const persist = async () => {
|
|
142
|
-
const { TaxCodeCollection } = await import("./TaxCodeCollection-DF2eaJed.js").then((n) => n.n);
|
|
143
|
-
const { TaxComponentCollection } = await import("./TaxComponentCollection-3x24xSNh.js").then((n) => n.n);
|
|
144
|
-
const codes = await TaxCodeCollection.create({ db: this.db });
|
|
145
|
-
const components = await TaxComponentCollection.create({ db: this.db });
|
|
146
|
-
if (!allowMoneyModelWrite) {
|
|
147
|
-
const tenantKey = this.tenantId || getTenantId() || "";
|
|
148
|
-
const { TaxSettingsCollection } = await Promise.resolve().then(() => TaxSettingsCollection_exports);
|
|
149
|
-
const persistedByTenant = tenantKey ? await (await TaxSettingsCollection.create({ db: this.db })).lockForTenant(tenantKey, false) : null;
|
|
150
|
-
const persistedById = this.id ? await this.db.get(this.tableName, { id: this.id }) : null;
|
|
151
|
-
if (persistedByTenant && (persistedByTenant.moneyModel !== this.moneyModel || persistedByTenant.moneyMigrationId !== this.moneyMigrationId) || persistedById && (persistedById.money_model !== this.moneyModel || (persistedById.money_migration_id ?? "") !== this.moneyMigrationId)) throw new MoneyValidationError("FROZEN_DOCUMENT", "Tenant money model is server-managed");
|
|
152
|
-
if (!persistedByTenant && !this.isPersisted) this.requireInsertOnSave();
|
|
153
|
-
}
|
|
154
|
-
for (const id of [this.defaultSalesTaxCodeId, this.defaultPurchaseTaxCodeId].filter(Boolean)) {
|
|
155
|
-
const code = await codes.get({ id }, { cache: false });
|
|
156
|
-
if (!code || code.tenantId !== this.tenantId) throw new Error("Tax setting default codes must belong to its tenant");
|
|
157
|
-
}
|
|
158
|
-
for (const registration of registrations) {
|
|
159
|
-
const component = await components.get({ id: registration.taxComponentId }, { cache: false });
|
|
160
|
-
if (!component || component.tenantId !== this.tenantId) throw new Error("Tax setting registrations must belong to its tenant");
|
|
161
|
-
}
|
|
162
|
-
return await super.save();
|
|
163
|
-
};
|
|
164
|
-
return transactionBound ? persist() : this.withTransaction(persist);
|
|
165
|
-
}
|
|
166
|
-
parsedRegistrations() {
|
|
167
|
-
try {
|
|
168
|
-
const value = JSON.parse(this.taxRegistrationsJson);
|
|
169
|
-
if (!Array.isArray(value)) return null;
|
|
170
|
-
if (value.some((entry) => !entry || typeof entry !== "object" || typeof entry.taxComponentId !== "string" || typeof entry.number !== "string" || typeof entry.label !== "string")) return null;
|
|
171
|
-
return value;
|
|
172
|
-
} catch {
|
|
173
|
-
return null;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
__publicField(TaxSettings, "__smrtPackage__", "@happyvertical/smrt-commerce");
|
|
178
|
-
__decorateClass([tenantId()], TaxSettings.prototype, "tenantId", 2);
|
|
179
|
-
__decorateClass([foreignKey("TaxCode", { description: "The default tax code for sales documents." })], TaxSettings.prototype, "defaultSalesTaxCodeId", 2);
|
|
180
|
-
__decorateClass([foreignKey("TaxCode", { description: "The default tax code for purchase documents." })], TaxSettings.prototype, "defaultPurchaseTaxCodeId", 2);
|
|
181
|
-
__decorateClass([field({ description: "Whether new document amounts are exclusive, inclusive or out of scope." })], TaxSettings.prototype, "defaultLineAmountType", 2);
|
|
182
|
-
__decorateClass([field({ description: "Whether components round per line or per document." })], TaxSettings.prototype, "taxRoundingScope", 2);
|
|
183
|
-
__decorateClass([field({
|
|
184
|
-
sensitive: true,
|
|
185
|
-
transient: true,
|
|
186
|
-
description: "Registration numbers by tax component, for issued-document snapshots."
|
|
187
|
-
})], TaxSettings.prototype, "taxRegistrations", 1);
|
|
188
|
-
TaxSettings = __decorateClass([TenantScoped({ mode: "required" }), smrt({
|
|
189
|
-
conflictColumns: ["tenant_id"],
|
|
190
|
-
api: {
|
|
191
|
-
include: [
|
|
192
|
-
"get",
|
|
193
|
-
"create",
|
|
194
|
-
"update"
|
|
195
|
-
],
|
|
196
|
-
writable: [
|
|
197
|
-
"defaultSalesTaxCodeId",
|
|
198
|
-
"defaultPurchaseTaxCodeId",
|
|
199
|
-
"defaultLineAmountType",
|
|
200
|
-
"taxRoundingScope",
|
|
201
|
-
"taxRegistrations"
|
|
202
|
-
]
|
|
203
|
-
},
|
|
204
|
-
mcp: { include: ["get"] },
|
|
205
|
-
cli: { skipApiCheck: true }
|
|
206
|
-
})], TaxSettings);
|
|
207
|
-
//#endregion
|
|
208
|
-
//#region src/tax/identity.ts
|
|
209
|
-
async function deterministicTaxId(tenantId, kind, key) {
|
|
210
|
-
if (!tenantId.trim() || !key.trim()) throw new Error("Tax bootstrap identity requires tenant and key");
|
|
211
|
-
const bytes = new TextEncoder().encode(JSON.stringify([
|
|
212
|
-
"commerce-tax",
|
|
213
|
-
tenantId,
|
|
214
|
-
kind,
|
|
215
|
-
key
|
|
216
|
-
]));
|
|
217
|
-
const uuid = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)).slice(0, 16);
|
|
218
|
-
uuid[6] = uuid[6] & 15 | 80;
|
|
219
|
-
uuid[8] = uuid[8] & 63 | 128;
|
|
220
|
-
const joined = Array.from(uuid, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
221
|
-
return `${joined.slice(0, 8)}-${joined.slice(8, 12)}-${joined.slice(12, 16)}-${joined.slice(16, 20)}-${joined.slice(20)}`;
|
|
222
|
-
}
|
|
223
|
-
async function createOrLoadTaxSeed(create, load) {
|
|
224
|
-
for (let attempt = 0; attempt < 3; attempt++) try {
|
|
225
|
-
return await create();
|
|
226
|
-
} catch (error) {
|
|
227
|
-
const code = error?.code;
|
|
228
|
-
if (code === "RUNTIME_REVISION_CONFLICT" && attempt < 2) continue;
|
|
229
|
-
if (code !== "VALIDATION_UNIQUE_CONSTRAINT" && code !== "23505") throw error;
|
|
230
|
-
const winner = await load();
|
|
231
|
-
if (!winner) throw error;
|
|
232
|
-
return winner;
|
|
233
|
-
}
|
|
234
|
-
throw new Error("Tax seed retry exhausted");
|
|
235
|
-
}
|
|
236
|
-
//#endregion
|
|
237
|
-
//#region src/collections/TaxSettingsCollection.ts
|
|
238
|
-
var TaxSettingsCollection_exports = /* @__PURE__ */ __exportAll({ TaxSettingsCollection: () => TaxSettingsCollection });
|
|
239
|
-
var TaxSettingsCollection = class TaxSettingsCollection extends SmrtCollection {
|
|
240
|
-
static _itemClass = TaxSettings;
|
|
241
|
-
async getOrCreateForTenant(tenantId) {
|
|
242
|
-
const existing = await this.getForTenant(tenantId);
|
|
243
|
-
if (existing) return existing;
|
|
244
|
-
const id = await deterministicTaxId(tenantId, "settings", "default");
|
|
245
|
-
return createOrLoadTaxSeed(() => this.create({
|
|
246
|
-
id,
|
|
247
|
-
tenantId
|
|
248
|
-
}), async () => (await this.list({
|
|
249
|
-
where: { tenantId },
|
|
250
|
-
limit: 1
|
|
251
|
-
}))[0] ?? null);
|
|
252
|
-
}
|
|
253
|
-
async getForTenant(tenantId) {
|
|
254
|
-
const listed = (await this.list({
|
|
255
|
-
where: { tenantId },
|
|
256
|
-
limit: 1
|
|
257
|
-
}))[0];
|
|
258
|
-
if (!listed?.id) return listed ?? null;
|
|
259
|
-
return await this.get({ id: listed.id }, { cache: false }) ?? null;
|
|
260
|
-
}
|
|
261
|
-
/** @internal Lock and re-read the one tenant marker on this transaction. */
|
|
262
|
-
async lockForTenant(tenantId, create = true) {
|
|
263
|
-
const first = create ? await this.getOrCreateForTenant(tenantId) : await this.getForTenant(tenantId);
|
|
264
|
-
if (!first?.id) return null;
|
|
265
|
-
await lockDocumentMoneyParents([{
|
|
266
|
-
id: first.id,
|
|
267
|
-
tenantId,
|
|
268
|
-
collection: this
|
|
269
|
-
}]);
|
|
270
|
-
const locked = await this.getForTenant(tenantId);
|
|
271
|
-
if (!locked || locked.id !== first.id) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Tenant money settings changed while acquiring the barrier");
|
|
272
|
-
return locked;
|
|
273
|
-
}
|
|
274
|
-
/** Claim exclusive runtime maintenance before any per-document rewrite. */
|
|
275
|
-
async beginMoneyMigration(tenantId, requestedMigrationId) {
|
|
276
|
-
if (requestedMigrationId !== void 0 && !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(requestedMigrationId)) throw new MoneyValidationError("INVALID_MONEY_INPUT", "Migration owner identity must be a UUID");
|
|
277
|
-
return withDocumentMoneyTransaction(this.db, async (tx) => {
|
|
278
|
-
const { lockTenantMoneyMigrationClaim } = await import("./tenant-money-barrier-y6EAa6vY.js").then((n) => n.r);
|
|
279
|
-
const current = await lockTenantMoneyMigrationClaim(tx, tenantId);
|
|
280
|
-
const migrationId = requestedMigrationId ?? crypto.randomUUID();
|
|
281
|
-
current.moneyModel = "migrating";
|
|
282
|
-
current.moneyMigrationId = migrationId;
|
|
283
|
-
await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);
|
|
284
|
-
return migrationId;
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
async activateMoneyV2(tenantId, migrationId) {
|
|
288
|
-
await withDocumentMoneyTransaction(this.db, async (tx) => {
|
|
289
|
-
const { lockTenantMoneyMigrationOwner } = await import("./tenant-money-barrier-y6EAa6vY.js").then((n) => n.r);
|
|
290
|
-
const current = await lockTenantMoneyMigrationOwner(tx, tenantId, migrationId);
|
|
291
|
-
current.moneyModel = "v2";
|
|
292
|
-
current.moneyMigrationId = "";
|
|
293
|
-
await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
async restoreLegacyMoneyModel(tenantId, migrationId) {
|
|
297
|
-
await withDocumentMoneyTransaction(this.db, async (tx) => {
|
|
298
|
-
const { lockTenantMoneyMigrationOwner } = await import("./tenant-money-barrier-y6EAa6vY.js").then((n) => n.r);
|
|
299
|
-
const current = await lockTenantMoneyMigrationOwner(tx, tenantId, migrationId);
|
|
300
|
-
current.moneyModel = "legacy";
|
|
301
|
-
current.moneyMigrationId = "";
|
|
302
|
-
await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);
|
|
303
|
-
});
|
|
304
|
-
}
|
|
305
|
-
/** Claim a previously completed migration for checksum-guarded rollback. */
|
|
306
|
-
async beginMoneyRollback(tenantId, migrationId) {
|
|
307
|
-
await withDocumentMoneyTransaction(this.db, async (tx) => {
|
|
308
|
-
const current = await (await TaxSettingsCollection.create({ db: tx })).lockForTenant(tenantId, false);
|
|
309
|
-
if (current?.moneyModel !== "v2") throw new MoneyValidationError("FROZEN_DOCUMENT", "Money rollback requires an active v2 tenant marker");
|
|
310
|
-
current.moneyModel = "migrating";
|
|
311
|
-
current.moneyMigrationId = migrationId;
|
|
312
|
-
await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
};
|
|
316
|
-
//#endregion
|
|
317
|
-
export { DOCUMENT_MONEY_READ_REBIND as a, lockDocumentMoneyParents as c, TaxSettings as i, withDocumentMoneyObjectTransaction as l, createOrLoadTaxSeed as n, DOCUMENT_MONEY_WRITE as o, deterministicTaxId as r, MONEY_MIGRATION_WRITE as s, TaxSettingsCollection as t, withDocumentMoneyTransaction as u };
|
|
318
|
-
|
|
319
|
-
//# sourceMappingURL=TaxSettingsCollection-DYYF-In-.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"TaxSettingsCollection-DYYF-In-.js","names":[],"sources":["../../src/document-money-internal.ts","../../src/models/TaxSettings.ts","../../src/tax/identity.ts","../../src/collections/TaxSettingsCollection.ts"],"sourcesContent":["/** Internal capabilities shared by commerce document-money persistence. */\n\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { MoneyValidationError } from './money.js';\n\nconst activeMoneyTransactions = new WeakSet<object>();\n\n/**\n * Capability required by derived money rows. This module is intentionally not\n * exported from the package root; aggregate persistence owns every mutation.\n */\nexport const DOCUMENT_MONEY_WRITE = Symbol('commerce.documentMoneyWrite');\n\nexport type DocumentMoneyWriteCapability = typeof DOCUMENT_MONEY_WRITE;\n\n/** Internal capability for the server-owned tenant money migration marker. */\nexport const MONEY_MIGRATION_WRITE = Symbol('commerce.moneyMigrationWrite');\n\nexport type MoneyMigrationWriteCapability = typeof MONEY_MIGRATION_WRITE;\n\n/** Internal capability for returning a locked snapshot on its root executor. */\nexport const DOCUMENT_MONEY_READ_REBIND = Symbol(\n 'commerce.documentMoneyReadRebind',\n);\n\nexport type DocumentMoneyReadRebindCapability =\n typeof DOCUMENT_MONEY_READ_REBIND;\n\nexport interface MoneyParentLockCollection {\n readonly tableName: string;\n query(\n sql: string,\n params: unknown[],\n options: { allowRawOnTenantScoped: true },\n ): Promise<unknown[]>;\n}\nexport interface MoneyParentLockTarget {\n id: string;\n tenantId: string;\n collection: MoneyParentLockCollection;\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction quoteIdentifier(identifier: string): string {\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(identifier)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Unsafe money parent table identifier: ${identifier}`,\n );\n }\n return `\"${identifier}\"`;\n}\n\nfunction assertIdentifier(value: string, label: string): void {\n if (\n typeof value !== 'string' ||\n value.trim() !== value ||\n value.length === 0\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `${label} must be a nonempty identifier`,\n );\n }\n}\n/** Run aggregate work on one transaction-bound database executor. */\nexport async function withDocumentMoneyTransaction<T>(\n db: DatabaseInterface,\n operation: (tx: DatabaseInterface) => Promise<T>,\n): Promise<T> {\n if (activeMoneyTransactions.has(db as object)) return operation(db);\n if (!db.transaction) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Document money persistence requires transaction support',\n );\n }\n return db.transaction(async (tx) => {\n activeMoneyTransactions.add(tx as object);\n try {\n return await operation(tx);\n } finally {\n activeMoneyTransactions.delete(tx as object);\n }\n });\n}\n\ninterface DocumentMoneyTransactionalObject {\n readonly db: DatabaseInterface;\n withTransaction<T>(operation: (bound: this) => Promise<T>): Promise<T>;\n}\n\n/**\n * Run aggregate work through the model's root transaction so rejected writes\n * restore the instance's persistence revision before callers retry it.\n */\nexport async function withDocumentMoneyObjectTransaction<\n TObject extends DocumentMoneyTransactionalObject,\n TResult,\n>(\n input: TObject,\n operation: (bound: TObject, tx: DatabaseInterface) => Promise<TResult>,\n): Promise<TResult> {\n if (activeMoneyTransactions.has(input.db as object)) {\n return operation(input, input.db);\n }\n return input.withTransaction(async (bound) => {\n const tx = bound.db;\n activeMoneyTransactions.add(tx as object);\n try {\n return await operation(bound as TObject, tx);\n } finally {\n activeMoneyTransactions.delete(tx as object);\n }\n });\n}\n\n/**\n * Serialize aggregate writers by touching each tenant-owned parent first.\n * Parents are locked sequentially in stable code-unit ID order. Callers must\n * re-read authoritative parent and child state on the same executor afterward.\n */\nexport async function lockDocumentMoneyParents(\n targets: readonly MoneyParentLockTarget[],\n): Promise<void> {\n const sorted = [...targets].sort(\n (left, right) =>\n compareCodeUnits(left.id, right.id) ||\n compareCodeUnits(left.collection.tableName, right.collection.tableName),\n );\n const identities = new Set<string>();\n for (const target of sorted) {\n assertIdentifier(target.id, 'Money parent id');\n assertIdentifier(target.tenantId, 'Money parent tenant id');\n const identity = `${target.collection.tableName}\\u0000${target.id}`;\n if (identities.has(identity)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Duplicate money parent lock target: ${target.id}`,\n );\n }\n identities.add(identity);\n const table = quoteIdentifier(target.collection.tableName);\n const locked = await target.collection.query(\n `UPDATE ${table}\n SET \"updated_at\" = \"updated_at\"\n WHERE \"id\" = ? AND \"tenant_id\" = ?\n RETURNING \"id\"`,\n [target.id, target.tenantId],\n { allowRawOnTenantScoped: true },\n );\n if (locked.length !== 1) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Money parent ${target.id} was not found in tenant ${target.tenantId}`,\n );\n }\n }\n}\n","import { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n TenantScoped,\n tenantId,\n} from '@happyvertical/smrt-tenancy';\nimport {\n MONEY_MIGRATION_WRITE,\n type MoneyMigrationWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError } from '../money.js';\nimport type { TaxSettingsOptions } from '../types/index.js';\n\nexport interface TaxRegistration {\n taxComponentId: string;\n number: string;\n label: string;\n}\n\n/** Tenant-level defaults and registration numbers for tax determination. */\n@TenantScoped({ mode: 'required' })\n@smrt({\n conflictColumns: ['tenant_id'],\n api: {\n include: ['get', 'create', 'update'],\n writable: [\n 'defaultSalesTaxCodeId',\n 'defaultPurchaseTaxCodeId',\n 'defaultLineAmountType',\n 'taxRoundingScope',\n 'taxRegistrations',\n ],\n },\n mcp: { include: ['get'] },\n cli: { skipApiCheck: true },\n})\nexport class TaxSettings extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @tenantId()\n tenantId = '';\n\n @foreignKey('TaxCode', {\n description: 'The default tax code for sales documents.',\n })\n defaultSalesTaxCodeId = '';\n\n @foreignKey('TaxCode', {\n description: 'The default tax code for purchase documents.',\n })\n defaultPurchaseTaxCodeId = '';\n\n @field({\n description:\n 'Whether new document amounts are exclusive, inclusive or out of scope.',\n })\n defaultLineAmountType: 'exclusive' | 'inclusive' | 'none' = 'exclusive';\n\n @field({ description: 'Whether components round per line or per document.' })\n taxRoundingScope: 'line' | 'document' = 'line';\n\n /** Stored JSON is guarded through the typed accessor below. */\n taxRegistrationsJson = '[]';\n\n /** Server-owned runtime semantics gate. Never exposed as a generated write. */\n moneyModel: 'legacy' | 'migrating' | 'v2' = 'legacy';\n\n /** Opaque owner token while a tenant migration is in progress. */\n moneyMigrationId = '';\n\n @field({\n sensitive: true,\n transient: true,\n description:\n 'Registration numbers by tax component, for issued-document snapshots.',\n })\n get taxRegistrations(): TaxRegistration[] {\n try {\n const value: unknown = JSON.parse(this.taxRegistrationsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is TaxRegistration =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as TaxRegistration).taxComponentId === 'string' &&\n typeof (entry as TaxRegistration).number === 'string' &&\n typeof (entry as TaxRegistration).label === 'string',\n );\n } catch {\n return [];\n }\n }\n\n set taxRegistrations(value: TaxRegistration[] | string) {\n this.taxRegistrationsJson =\n typeof value === 'string' ? value : JSON.stringify(value);\n }\n\n constructor(options: TaxSettingsOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.defaultSalesTaxCodeId !== undefined)\n this.defaultSalesTaxCodeId = options.defaultSalesTaxCodeId;\n if (options.defaultPurchaseTaxCodeId !== undefined)\n this.defaultPurchaseTaxCodeId = options.defaultPurchaseTaxCodeId;\n if (options.defaultLineAmountType !== undefined)\n this.defaultLineAmountType = options.defaultLineAmountType;\n if (options.taxRoundingScope !== undefined)\n this.taxRoundingScope = options.taxRoundingScope;\n if (options.taxRegistrations !== undefined)\n this.taxRegistrations = structuredClone(options.taxRegistrations);\n if (options.moneyModel !== undefined) this.moneyModel = options.moneyModel;\n if (options.moneyMigrationId !== undefined)\n this.moneyMigrationId = options.moneyMigrationId;\n }\n\n override async save(): Promise<this> {\n return this.saveValidated(false);\n }\n\n /** @internal Money migration owns marker transitions. */\n async saveMoneyModel(\n capability: MoneyMigrationWriteCapability,\n ): Promise<this> {\n if (capability !== MONEY_MIGRATION_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Tenant money model requires the migration capability',\n );\n }\n return this.saveValidated(true);\n }\n\n /** @internal Caller already owns the transaction-bound migration barrier. */\n async saveMoneyModelOnTransaction(\n capability: MoneyMigrationWriteCapability,\n ): Promise<this> {\n if (capability !== MONEY_MIGRATION_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Tenant money model requires the migration capability',\n );\n }\n return this.saveValidated(true, true);\n }\n\n private async saveValidated(\n allowMoneyModelWrite: boolean,\n transactionBound = false,\n ): Promise<this> {\n if (\n !['exclusive', 'inclusive', 'none'].includes(this.defaultLineAmountType)\n )\n throw new Error('Tax settings defaultLineAmountType is invalid');\n if (!['line', 'document'].includes(this.taxRoundingScope))\n throw new Error('Tax settings taxRoundingScope is invalid');\n if (!['legacy', 'migrating', 'v2'].includes(this.moneyModel))\n throw new Error('Tax settings moneyModel is invalid');\n if ((this.moneyModel === 'migrating') !== !!this.moneyMigrationId)\n throw new Error(\n 'Tax settings migrating state requires exactly one migration owner',\n );\n const registrations = this.parsedRegistrations();\n if (!registrations)\n throw new Error('Tax registrations must be a valid JSON array');\n if (\n registrations.some(\n (entry) =>\n !entry.taxComponentId || !entry.number.trim() || !entry.label.trim(),\n )\n )\n throw new Error('Tax registrations require component, number and label');\n const persist = async (): Promise<this> => {\n const { TaxCodeCollection } = await import(\n '../collections/TaxCodeCollection.js'\n );\n const { TaxComponentCollection } = await import(\n '../collections/TaxComponentCollection.js'\n );\n const codes = await TaxCodeCollection.create({ db: this.db });\n const components = await TaxComponentCollection.create({ db: this.db });\n if (!allowMoneyModelWrite) {\n // A new instance upserts on the tenant_id natural key, so the marker\n // row may be found by tenant rather than by this instance's id. Lock\n // and re-read that row on this save transaction so a migration claim\n // cannot commit between this check and the natural-key upsert.\n const tenantKey = this.tenantId || getTenantId() || '';\n const { TaxSettingsCollection } = await import(\n '../collections/TaxSettingsCollection.js'\n );\n const persistedByTenant = tenantKey\n ? await (\n await TaxSettingsCollection.create({ db: this.db })\n ).lockForTenant(tenantKey, false)\n : null;\n const persistedById = this.id\n ? await this.db.get(this.tableName, { id: this.id })\n : null;\n if (\n (persistedByTenant &&\n (persistedByTenant.moneyModel !== this.moneyModel ||\n persistedByTenant.moneyMigrationId !== this.moneyMigrationId)) ||\n (persistedById &&\n (persistedById.money_model !== this.moneyModel ||\n (persistedById.money_migration_id ?? '') !==\n this.moneyMigrationId))\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Tenant money model is server-managed',\n );\n // With no marker row to lock, a normal natural-key upsert could race\n // the migration's first marker insert and overwrite its claimed state.\n // Keep the first ordinary save insert-only so that collision refuses\n // the stale save instead of updating the newly committed marker.\n if (!persistedByTenant && !this.isPersisted) this.requireInsertOnSave();\n }\n for (const id of [\n this.defaultSalesTaxCodeId,\n this.defaultPurchaseTaxCodeId,\n ].filter(Boolean)) {\n const code = await codes.get({ id }, { cache: false });\n if (!code || code.tenantId !== this.tenantId)\n throw new Error(\n 'Tax setting default codes must belong to its tenant',\n );\n }\n for (const registration of registrations) {\n const component = await components.get(\n { id: registration.taxComponentId },\n { cache: false },\n );\n if (!component || component.tenantId !== this.tenantId)\n throw new Error(\n 'Tax setting registrations must belong to its tenant',\n );\n }\n return (await super.save()) as this;\n };\n return transactionBound ? persist() : this.withTransaction(persist);\n }\n\n private parsedRegistrations(): TaxRegistration[] | null {\n try {\n const value: unknown = JSON.parse(this.taxRegistrationsJson);\n if (!Array.isArray(value)) return null;\n if (\n value.some(\n (entry) =>\n !entry ||\n typeof entry !== 'object' ||\n typeof (entry as TaxRegistration).taxComponentId !== 'string' ||\n typeof (entry as TaxRegistration).number !== 'string' ||\n typeof (entry as TaxRegistration).label !== 'string',\n )\n )\n return null;\n return value as TaxRegistration[];\n } catch {\n return null;\n }\n }\n}\n","/** Stable UUID identities make tenant tax bootstrap retry and race safe. */\nexport async function deterministicTaxId(\n tenantId: string,\n kind: 'code' | 'component' | 'settings' | 'report',\n key: string,\n): Promise<string> {\n if (!tenantId.trim() || !key.trim())\n throw new Error('Tax bootstrap identity requires tenant and key');\n const bytes = new TextEncoder().encode(\n JSON.stringify(['commerce-tax', tenantId, kind, key]),\n );\n const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));\n const uuid = digest.slice(0, 16);\n uuid[6] = (uuid[6] & 0x0f) | 0x50;\n uuid[8] = (uuid[8] & 0x3f) | 0x80;\n const hex = Array.from(uuid, (byte) => byte.toString(16).padStart(2, '0'));\n const joined = hex.join('');\n return `${joined.slice(0, 8)}-${joined.slice(8, 12)}-${joined.slice(12, 16)}-${joined.slice(16, 20)}-${joined.slice(20)}`;\n}\n\n/** A racing deterministic insert loses safely and reloads the committed row. */\nexport async function createOrLoadTaxSeed<T>(\n create: () => Promise<T>,\n load: () => Promise<T | null | undefined>,\n): Promise<T> {\n for (let attempt = 0; attempt < 3; attempt++) {\n try {\n return await create();\n } catch (error) {\n const code = (error as { code?: unknown } | null)?.code;\n if (code === 'RUNTIME_REVISION_CONFLICT' && attempt < 2) continue;\n if (code !== 'VALIDATION_UNIQUE_CONSTRAINT' && code !== '23505')\n throw error;\n const winner = await load();\n if (!winner) throw error;\n return winner;\n }\n }\n throw new Error('Tax seed retry exhausted');\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n lockDocumentMoneyParents,\n MONEY_MIGRATION_WRITE,\n withDocumentMoneyTransaction,\n} from '../document-money-internal.js';\nimport { TaxSettings } from '../models/TaxSettings.js';\nimport { MoneyValidationError } from '../money.js';\nimport { createOrLoadTaxSeed, deterministicTaxId } from '../tax/identity.js';\n\nexport class TaxSettingsCollection extends SmrtCollection<TaxSettings> {\n static readonly _itemClass = TaxSettings;\n\n async getOrCreateForTenant(tenantId: string): Promise<TaxSettings> {\n const existing = await this.getForTenant(tenantId);\n if (existing) return existing;\n const id = await deterministicTaxId(tenantId, 'settings', 'default');\n return createOrLoadTaxSeed(\n () => this.create({ id, tenantId }),\n async () =>\n (await this.list({ where: { tenantId }, limit: 1 }))[0] ?? null,\n );\n }\n\n async getForTenant(tenantId: string): Promise<TaxSettings | null> {\n const listed = (await this.list({ where: { tenantId }, limit: 1 }))[0];\n if (!listed?.id) return listed ?? null;\n return (await this.get({ id: listed.id }, { cache: false })) ?? null;\n }\n\n /** @internal Lock and re-read the one tenant marker on this transaction. */\n async lockForTenant(\n tenantId: string,\n create = true,\n ): Promise<TaxSettings | null> {\n const first = create\n ? await this.getOrCreateForTenant(tenantId)\n : await this.getForTenant(tenantId);\n if (!first?.id) return null;\n await lockDocumentMoneyParents([\n { id: first.id, tenantId, collection: this },\n ]);\n const locked = await this.getForTenant(tenantId);\n if (!locked || locked.id !== first.id)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Tenant money settings changed while acquiring the barrier',\n );\n return locked;\n }\n\n /** Claim exclusive runtime maintenance before any per-document rewrite. */\n async beginMoneyMigration(\n tenantId: string,\n requestedMigrationId?: string,\n ): Promise<string> {\n if (\n requestedMigrationId !== undefined &&\n !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n requestedMigrationId,\n )\n )\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Migration owner identity must be a UUID',\n );\n return withDocumentMoneyTransaction(this.db, async (tx) => {\n const { lockTenantMoneyMigrationClaim } = await import(\n '../tenant-money-barrier.js'\n );\n const current = await lockTenantMoneyMigrationClaim(tx, tenantId);\n const migrationId = requestedMigrationId ?? crypto.randomUUID();\n current.moneyModel = 'migrating';\n current.moneyMigrationId = migrationId;\n await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);\n return migrationId;\n });\n }\n\n async activateMoneyV2(tenantId: string, migrationId: string): Promise<void> {\n await withDocumentMoneyTransaction(this.db, async (tx) => {\n const { lockTenantMoneyMigrationOwner } = await import(\n '../tenant-money-barrier.js'\n );\n const current = await lockTenantMoneyMigrationOwner(\n tx,\n tenantId,\n migrationId,\n );\n current.moneyModel = 'v2';\n current.moneyMigrationId = '';\n await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);\n });\n }\n\n async restoreLegacyMoneyModel(\n tenantId: string,\n migrationId: string,\n ): Promise<void> {\n await withDocumentMoneyTransaction(this.db, async (tx) => {\n const { lockTenantMoneyMigrationOwner } = await import(\n '../tenant-money-barrier.js'\n );\n const current = await lockTenantMoneyMigrationOwner(\n tx,\n tenantId,\n migrationId,\n );\n current.moneyModel = 'legacy';\n current.moneyMigrationId = '';\n await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);\n });\n }\n\n /** Claim a previously completed migration for checksum-guarded rollback. */\n async beginMoneyRollback(\n tenantId: string,\n migrationId: string,\n ): Promise<void> {\n await withDocumentMoneyTransaction(this.db, async (tx) => {\n const current = await (\n await TaxSettingsCollection.create({ db: tx })\n ).lockForTenant(tenantId, false);\n if (current?.moneyModel !== 'v2')\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Money rollback requires an active v2 tenant marker',\n );\n current.moneyModel = 'migrating';\n current.moneyMigrationId = migrationId;\n await current.saveMoneyModelOnTransaction(MONEY_MIGRATION_WRITE);\n });\n }\n}\n"],"mappings":"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"}
|