@happyvertical/smrt-commerce 0.57.9 → 0.57.11
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 +1 -0
- package/README.md +61 -0
- package/agents/connected-payments.md +135 -0
- package/agents/contract-billing-schedules.md +6 -0
- package/agents/money-upgrade.md +5 -0
- package/dist/chunks/{ContractLineItemCollection-DQZqRiZi.js → ContractLineItemCollection-DkBeBR7a.js} +4 -4
- package/dist/chunks/{ContractLineItemCollection-DQZqRiZi.js.map → ContractLineItemCollection-DkBeBR7a.js.map} +1 -1
- package/dist/chunks/{DocumentTaxCollection-Dg942m_Z.js → DocumentTaxCollection-D85ut-Fo.js} +14 -10
- package/dist/chunks/{DocumentTaxCollection-Dg942m_Z.js.map → DocumentTaxCollection-D85ut-Fo.js.map} +1 -1
- package/dist/chunks/{InvoiceCollection-XPcPyibo.js → InvoiceCollection-Datg_eZM.js} +9 -9
- package/dist/chunks/{InvoiceCollection-XPcPyibo.js.map → InvoiceCollection-Datg_eZM.js.map} +1 -1
- package/dist/chunks/{TaxCodeCollection-CbTBWO8z.js → TaxCodeCollection-CIC1skxr.js} +2 -2
- package/dist/chunks/{TaxCodeCollection-CbTBWO8z.js.map → TaxCodeCollection-CIC1skxr.js.map} +1 -1
- package/dist/chunks/{TaxComponentCollection-VZ_cGr2n.js → TaxComponentCollection-BHBV-_1J.js} +3 -3
- package/dist/chunks/{TaxComponentCollection-VZ_cGr2n.js.map → TaxComponentCollection-BHBV-_1J.js.map} +1 -1
- package/dist/chunks/{allocation-integrity-Kr8uceRx.js → allocation-integrity-B2SyO1mu.js} +6 -6
- package/dist/chunks/{allocation-integrity-Kr8uceRx.js.map → allocation-integrity-B2SyO1mu.js.map} +1 -1
- package/dist/chunks/{contract-money-DGNqQwf0.js → contract-money-C61kGBkU.js} +7 -6
- package/dist/chunks/contract-money-C61kGBkU.js.map +1 -0
- package/dist/chunks/{invoice-posting-DVSkfSUm.js → invoice-posting-uLfdyLIi.js} +3 -3
- package/dist/chunks/{invoice-posting-DVSkfSUm.js.map → invoice-posting-uLfdyLIi.js.map} +1 -1
- package/dist/chunks/{retention-accounting-Ct5Df6xx.js → retention-accounting-DGuXzt9g.js} +149 -11
- package/dist/chunks/retention-accounting-DGuXzt9g.js.map +1 -0
- package/dist/chunks/{tenant-money-barrier-CG78Xxja.js → tenant-money-barrier-DXnJWxiZ.js} +3 -3
- package/dist/chunks/{tenant-money-barrier-CG78Xxja.js.map → tenant-money-barrier-DXnJWxiZ.js.map} +1 -1
- package/dist/chunks/types-Bbm0Xflc.js.map +1 -1
- package/dist/collections/TenantPaymentAccountCollection.d.ts +28 -0
- package/dist/collections/TenantPaymentAccountCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +1 -0
- package/dist/collections/index.d.ts.map +1 -1
- package/dist/connected-payments-internal.d.ts +5 -0
- package/dist/connected-payments-internal.d.ts.map +1 -0
- package/dist/connected-payments.d.ts +361 -0
- package/dist/connected-payments.d.ts.map +1 -0
- package/dist/contract-money.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1241 -160
- package/dist/index.js.map +1 -1
- package/dist/invoices.js +1 -1
- package/dist/manifest.json +1404 -129
- package/dist/models/Contract.d.ts +5 -1
- package/dist/models/Contract.d.ts.map +1 -1
- package/dist/models/Payment.d.ts +33 -0
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/PaymentIntent.d.ts +35 -0
- package/dist/models/PaymentIntent.d.ts.map +1 -1
- package/dist/models/TenantPaymentAccount.d.ts +121 -0
- package/dist/models/TenantPaymentAccount.d.ts.map +1 -0
- package/dist/models/TenantPaymentWebhookEvent.d.ts +50 -0
- package/dist/models/TenantPaymentWebhookEvent.d.ts.map +1 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/recipes.d.ts +15 -0
- package/dist/recipes.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +622 -27
- package/dist/types/index.d.ts +16 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/upgrade/money-v2.d.ts +2 -0
- package/dist/upgrade/money-v2.d.ts.map +1 -1
- package/package.json +16 -16
- package/dist/chunks/contract-money-DGNqQwf0.js.map +0 -1
- package/dist/chunks/retention-accounting-Ct5Df6xx.js.map +0 -1
package/dist/chunks/{DocumentTaxCollection-Dg942m_Z.js.map → DocumentTaxCollection-D85ut-Fo.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentTaxCollection-Dg942m_Z.js","names":["field","revision","saved","input","netMinor","taxMinor","grossMinor"],"sources":["../../src/party-contacts.ts","../../src/models/Customer.ts","../../src/collections/CustomerCollection.ts","../../src/models/InvoiceLineItem.ts","../../src/collections/InvoiceLineItemCollection.ts","../../src/models/HistoricalSalesLine.ts","../../src/collections/HistoricalSalesLineCollection.ts","../../src/models/Vendor.ts","../../src/models/Contract.ts","../../src/collections/PurchaseContractCollection.ts","../../src/collections/SalesContractCollection.ts","../../src/collections/ContractCollection.ts","../../src/contract-billing-schedule.ts","../../src/document-money.ts","../../src/historical-sales-validation.ts","../../src/historical-sales-money.ts","../../src/historical-sales-reports.ts","../../src/models/DocumentTax.ts","../../src/collections/VendorCollection.ts","../../src/received-purchase-money.ts","../../src/collections/DocumentTaxCollection.ts"],"sourcesContent":["/**\n * Contact rows for customers and vendors (#3501).\n *\n * `CustomerForm` and `VendorForm` (`./svelte`) post contacts as repeated\n * field names in DOM order, one value per row for each of `contactId`,\n * `contactName`, `contactLabel`, `contactEmail`, `contactPhone`, and\n * `contactAddress` (all overridable through the forms' `fieldNames`). The\n * helpers here read that payload, apply the native add/remove intents, and\n * write the rows to `Customer.contacts` / `Vendor.contacts`.\n *\n * @packageDocumentation\n */\n\nimport type { CustomerCollection } from './collections/CustomerCollection.js';\nimport type { VendorCollection } from './collections/VendorCollection.js';\nimport type { Customer } from './models/Customer.js';\nimport type { Vendor } from './models/Vendor.js';\nimport type { PartyContact } from './types/index.js';\n\n/** One submitted contact row, exactly as posted (untrimmed strings). */\nexport type PartyContactInput = Partial<PartyContact>;\n\n/** The text fields of a contact, which are also its error keys. */\nexport type PartyContactField = Exclude<keyof PartyContact, 'id'>;\n\n/** HTML names of the repeated contact fields; defaults match the forms. */\nexport interface PartyContactFieldNames {\n contactId: string;\n contactName: string;\n contactLabel: string;\n contactEmail: string;\n contactPhone: string;\n contactAddress: string;\n /** Hidden presence marker: the number of contact rows the form rendered. */\n contactCount: string;\n}\n\n/** Default contact field names, matching `DEFAULT_PARTY_FIELD_NAMES` in `./svelte`. */\nexport const DEFAULT_PARTY_CONTACT_FIELD_NAMES: PartyContactFieldNames = {\n contactId: 'contactId',\n contactName: 'contactName',\n contactLabel: 'contactLabel',\n contactEmail: 'contactEmail',\n contactPhone: 'contactPhone',\n contactAddress: 'contactAddress',\n contactCount: 'contactCount',\n};\n\n/** Maximum lengths, matching the form controls' `maxlength`. */\nexport const PARTY_CONTACT_MAX_LENGTHS: Readonly<\n Record<PartyContactField, number>\n> = {\n name: 160,\n label: 80,\n email: 320,\n phone: 80,\n address: 500,\n};\n\n/**\n * Per-row validation error codes, keyed by field. `unknown_contact` (on\n * `id`) means the posted id is not one of the party's saved contacts — a\n * stale or altered form; reload the party and show its current rows.\n */\nexport type PartyContactErrorCode =\n | 'too_long'\n | 'invalid_email'\n | 'unknown_contact';\n\n/** Errors for one submitted row; indexes match the submitted rows. */\nexport type PartyContactRowErrors = Partial<\n Record<PartyContactField | 'id', PartyContactErrorCode>\n>;\n\nconst FIELDS: readonly PartyContactField[] = [\n 'name',\n 'label',\n 'email',\n 'phone',\n 'address',\n];\n\n/** Thrown by {@link savePartyContacts} when any row is invalid; nothing is written. */\nexport class PartyContactValidationError extends Error {\n /** Errors aligned with the submitted rows; `undefined` for a valid row. */\n readonly errors: Array<PartyContactRowErrors | undefined>;\n\n constructor(errors: Array<PartyContactRowErrors | undefined>) {\n super('One or more contact rows are invalid');\n this.name = 'PartyContactValidationError';\n this.errors = errors;\n }\n}\n\n/**\n * Thrown by {@link readPartyContactRows} (and so {@link savePartyContacts}\n * given a form) when the posted contact payload cannot be trusted:\n * `missing` — no `contactCount` marker, so the editable contact block did\n * not render or was posted under other field names (treating that as \"no\n * contacts\" would delete them all); `misaligned` — the repeated fields or\n * the marker disagree on the row count. Nothing is written.\n */\nexport class PartyContactPayloadError extends Error {\n readonly reason: 'missing' | 'misaligned';\n\n constructor(reason: 'missing' | 'misaligned', message: string) {\n super(message);\n this.name = 'PartyContactPayloadError';\n this.reason = reason;\n }\n}\n\n/** Thrown by {@link savePartyContacts} when the party is not visible in the current tenant. */\nexport class PartyContactPartyNotFoundError extends Error {\n constructor(partyId: string) {\n super(`Customer or vendor ${partyId} was not found`);\n this.name = 'PartyContactPartyNotFoundError';\n }\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * Normalize stored contacts (an array, a JSON string, or nothing) into\n * well-formed {@link PartyContact} rows. Non-object entries and non-string\n * values are dropped; a row without an id is given one.\n */\nexport function normalizePartyContacts(value: unknown): PartyContact[] {\n let input = value;\n if (typeof input === 'string') {\n try {\n input = JSON.parse(input);\n } catch {\n return [];\n }\n }\n if (!Array.isArray(input)) return [];\n const contacts: PartyContact[] = [];\n for (const entry of input) {\n if (!entry || typeof entry !== 'object') continue;\n const row = entry as Record<string, unknown>;\n contacts.push({\n id: text(row.id) || globalThis.crypto.randomUUID(),\n name: text(row.name),\n label: text(row.label),\n email: text(row.email),\n phone: text(row.phone),\n address: text(row.address),\n });\n }\n return contacts;\n}\n\n/** Minimal form-data reader; `FormData` and `URLSearchParams` both satisfy it. */\nexport interface PartyContactFormSource {\n getAll(name: string): unknown[];\n}\n\n/**\n * Read the contact rows a party form posted, in DOM order. The editable\n * contact block always posts a `contactCount` marker with its row count, and\n * every row renders all six fields. A missing marker (the block did not\n * render, or `fieldNames` differ from the form's) or any disagreeing count\n * throws {@link PartyContactPayloadError}, so zero rows is only ever read\n * when the form really posted an empty contact list.\n */\nexport function readPartyContactRows(\n form: PartyContactFormSource,\n fieldNames: Partial<PartyContactFieldNames> = {},\n): PartyContactInput[] {\n const names = { ...DEFAULT_PARTY_CONTACT_FIELD_NAMES, ...fieldNames };\n const column = (name: string) => form.getAll(name).map(text);\n const columns = {\n id: column(names.contactId),\n name: column(names.contactName),\n label: column(names.contactLabel),\n email: column(names.contactEmail),\n phone: column(names.contactPhone),\n address: column(names.contactAddress),\n };\n const markers = column(names.contactCount);\n if (markers.length !== 1)\n throw new PartyContactPayloadError(\n markers.length === 0 ? 'missing' : 'misaligned',\n markers.length === 0\n ? `Contact payload has no ${names.contactCount} marker; the contact fields were not posted under these names`\n : `Contact payload has ${markers.length} ${names.contactCount} markers`,\n );\n const count = columns.id.length;\n if (markers[0] !== String(count))\n throw new PartyContactPayloadError(\n 'misaligned',\n `Contact payload is misaligned: ${names.contactCount} is ${markers[0]} but ${count} contact ids were posted`,\n );\n for (const [key, values] of Object.entries(columns)) {\n if (values.length !== count)\n throw new PartyContactPayloadError(\n 'misaligned',\n `Contact payload is misaligned: ${count} contact ids but ${values.length} ${key} values`,\n );\n }\n return columns.id.map((id, index) => ({\n id,\n name: columns.name[index],\n label: columns.label[index],\n email: columns.email[index],\n phone: columns.phone[index],\n address: columns.address[index],\n }));\n}\n\n/** Submitter values for the forms' native contact row actions. */\nexport interface PartyContactIntents {\n /** Defaults to the forms' `addContact`. */\n addIntent?: string;\n /** Parses a remove submitter into a row index; defaults to `removeContact:<index>`. */\n parseRemoveIntent?: (intent: string) => number | undefined;\n}\n\nfunction defaultParseRemoveIntent(intent: string): number | undefined {\n const match = /^removeContact:(\\d+)$/.exec(intent);\n return match ? Number(match[1]) : undefined;\n}\n\n/**\n * Apply an add or remove submitter to the posted rows and return the rows\n * to render back into the form. Nothing is persisted: a row action is a\n * round trip, and only the save intent writes. `handled` is `false` for any\n * other intent (including save), with the rows unchanged; when it is `true`,\n * render the returned rows and do not save.\n */\nexport function applyPartyContactIntent(\n rows: readonly PartyContactInput[],\n intent: string,\n intents: PartyContactIntents = {},\n): { contacts: PartyContactInput[]; handled: boolean } {\n if (intent === (intents.addIntent ?? 'addContact'))\n return { contacts: [...rows, {}], handled: true };\n const index = (intents.parseRemoveIntent ?? defaultParseRemoveIntent)(intent);\n // A stale index (the row is already gone) is still a remove: it must not\n // fall through to a save.\n if (index !== undefined)\n return {\n contacts: rows.filter((_, position) => position !== index),\n handled: true,\n };\n return { contacts: [...rows], handled: false };\n}\n\n// Deliberately permissive: one \"@\" with text on both sides and no spaces.\n// Deliverability is the caller's concern.\nconst EMAIL = /^[^\\s@]+@[^\\s@]+$/;\n\n/**\n * Validate posted rows without persisting them. Returns the trimmed rows\n * that would be written (blank rows dropped) and, when any row is invalid,\n * errors aligned with the submitted rows. Ids are checked against the\n * party's saved contacts only by {@link savePartyContacts}.\n */\nexport function validatePartyContactRows(rows: readonly PartyContactInput[]): {\n contacts: PartyContactInput[];\n errors?: Array<PartyContactRowErrors | undefined>;\n} {\n const contacts: PartyContactInput[] = [];\n const errors: Array<PartyContactRowErrors | undefined> = [];\n let invalid = false;\n rows.forEach((row, index) => {\n const trimmed: PartyContactInput = { id: text(row.id).trim() };\n let rowErrors: PartyContactRowErrors | undefined;\n for (const field of FIELDS) {\n const value = text(row[field]).trim();\n trimmed[field] = value;\n if (value.length > PARTY_CONTACT_MAX_LENGTHS[field])\n rowErrors = { ...rowErrors, [field]: 'too_long' };\n }\n if (trimmed.email && !rowErrors?.email && !EMAIL.test(trimmed.email))\n rowErrors = { ...rowErrors, email: 'invalid_email' };\n errors[index] = rowErrors;\n if (rowErrors) invalid = true;\n if (FIELDS.some((field) => trimmed[field])) contacts.push(trimmed);\n });\n return invalid ? { contacts, errors } : { contacts };\n}\n\n/** Options for {@link savePartyContacts}. */\nexport interface SavePartyContactsOptions {\n /** Field names used to read a posted form; must match the form's `fieldNames`. */\n fieldNames?: Partial<PartyContactFieldNames>;\n /**\n * When set, the party must belong to this tenant. Use it to bind a form's\n * posted tenant to the loaded row in addition to the active tenant\n * context, which already scopes the lookup.\n */\n expectedTenantId?: string | null;\n}\n\n/**\n * Replace a customer's or vendor's contacts with the rows its form posted.\n *\n * Pass the posted `FormData` (with `options.fieldNames` when the form\n * overrides them): it is read with {@link readPartyContactRows}, so a payload\n * without the contact block's presence marker throws\n * {@link PartyContactPayloadError} instead of removing every contact. An\n * array is taken as rows the caller already read through that function.\n *\n * The party is loaded through `collection.get()`, so the active tenant\n * context scopes it: a party in another tenant is not found. Rows are\n * validated ({@link validatePartyContactRows}), blank rows dropped, kept\n * rows matched to saved contacts by id (new rows get a fresh id), and rows\n * that were not posted are removed. A posted id the party does not have is\n * an `unknown_contact` error. On any error nothing is written and a\n * {@link PartyContactValidationError} is thrown.\n *\n * This is a read-modify-write of one row: concurrent saves of the same party\n * are last-writer-wins, like any other field edit.\n *\n * @returns The saved contacts, in submitted order.\n */\nexport async function savePartyContacts(\n collection: CustomerCollection | VendorCollection,\n partyId: string,\n posted: PartyContactFormSource | readonly PartyContactInput[],\n options: SavePartyContactsOptions = {},\n): Promise<PartyContact[]> {\n // Reading the form here (rather than trusting a caller's array) keeps the\n // presence-marker check on the write path.\n const rows = Array.isArray(posted)\n ? (posted as readonly PartyContactInput[])\n : readPartyContactRows(\n posted as PartyContactFormSource,\n options.fieldNames,\n );\n const party: Customer | Vendor | null = await collection.get({\n id: partyId,\n });\n if (\n !party ||\n (options.expectedTenantId !== undefined &&\n party.tenantId !== options.expectedTenantId)\n )\n throw new PartyContactPartyNotFoundError(partyId);\n\n const validation = validatePartyContactRows(rows);\n const { contacts } = validation;\n const errors = validation.errors ?? rows.map(() => undefined);\n const saved = new Set(\n normalizePartyContacts(party.contacts).map((c) => c.id),\n );\n let invalid = validation.errors !== undefined;\n rows.forEach((row, index) => {\n const id = text(row.id).trim();\n if (id && !saved.has(id)) {\n errors[index] = { ...errors[index], id: 'unknown_contact' };\n invalid = true;\n }\n });\n if (invalid) throw new PartyContactValidationError(errors);\n\n const seen = new Set<string>();\n party.contacts = contacts.map((row) => {\n // A duplicated posted id (two rows claiming one contact) keeps the id\n // on the first row only, so stored ids stay unique.\n const id =\n row.id && !seen.has(row.id) ? row.id : globalThis.crypto.randomUUID();\n seen.add(id);\n return {\n id,\n name: row.name ?? '',\n label: row.label ?? '',\n email: row.email ?? '',\n phone: row.phone ?? '',\n address: row.address ?? '',\n };\n });\n await party.save();\n return party.contacts;\n}\n","/**\n * Customer model - links to Profile with customer-specific data\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { normalizePartyContacts } from '../party-contacts.js';\nimport {\n type Address,\n type CustomerOptions,\n CustomerStatus,\n CustomerType,\n type PartyContact,\n} from '../types/index.js';\n\n/**\n * Customer represents the customer role for a Profile.\n *\n * One Profile can have multiple Customer records (e.g., different business contexts).\n * Customer stores customer-specific data like credit limits and payment terms.\n *\n * @example\n * ```typescript\n * const customer = await customers.create({\n * profileId: 'profile-uuid',\n * creditLimit: 10000,\n * paymentTerms: 'Net 30'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Customer extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global customers\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Reference to smrt-profiles Profile\n * Plain string for cross-package reference\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', {\n description:\n 'Links this customer to their profile record, where their name and contact details are kept.',\n })\n profileId: string = '';\n\n /**\n * Maximum credit extended to this customer, in **integer minor units**\n * (cents, satoshis).\n *\n * Converts with the rest of commerce because\n * {@link Customer.hasAvailableCredit} compares it directly against a money\n * amount; a dollars-vs-cents split there would approve every request off by\n * a factor of 100 (#2401).\n */\n @field({\n description:\n 'The most this customer may owe you at one time. Leave it at zero if you do not set limits.',\n ui: { format: 'money' },\n })\n creditLimit: number = 0;\n\n /**\n * Payment terms (e.g., \"Net 30\", \"Due on receipt\", \"2/10 Net 30\")\n */\n @field({\n description:\n 'How long the customer has to pay, written the way you would say it, for example \"Net 30\".',\n })\n paymentTerms: string = '';\n\n /**\n * Whether customer is exempt from tax\n */\n @field({\n description: 'Turn this on if you do not charge this customer sales tax.',\n })\n taxExempt: boolean = false;\n\n /**\n * Tax identification number\n *\n * Sensitive (#1540): PII excluded from generated API/MCP responses and\n * rejected as a `where` filter key.\n */\n @field({\n sensitive: true,\n description:\n 'The tax or VAT number of the customer, kept on file for tax-exempt sales.',\n })\n taxId: string = '';\n\n /**\n * Tax code normally used for this customer's sales.\n *\n * An exempt customer always resolves to the tenant's exempt code before\n * this preference is considered.\n */\n @foreignKey('TaxCode', {\n description: 'The tax code normally used when selling to this customer.',\n })\n defaultTaxCodeId: string = '';\n\n /**\n * Default shipping address\n */\n @field({\n description:\n 'Where you usually send goods to this customer, so you do not retype it on every order.',\n })\n defaultShippingAddress: Address = {};\n\n /**\n * Default billing address\n */\n @field({ description: 'Where you send invoices to this customer.' })\n defaultBillingAddress: Address = {};\n\n /**\n * Customer status\n */\n @field({\n description:\n 'Whether you are still dealing with this customer: active, inactive or suspended.',\n })\n status: CustomerStatus = CustomerStatus.ACTIVE;\n\n /**\n * Customer classification — DTC, wholesale, or retail.\n *\n * Drives channel access (wholesale portal vs. storefront vs. POS), default\n * price tier, and credit terms. Defaults to DTC for backwards compatibility.\n */\n @field({\n description:\n 'The kind of customer: a direct shopper, a wholesale buyer or a retail customer.',\n })\n customerType: CustomerType = CustomerType.DTC;\n\n /**\n * Internal notes about this customer\n */\n @field({\n description: 'Anything worth remembering about this customer.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * People to reach at this customer, stored as a JSON column (#3501). Write\n * form rows through `savePartyContacts()`; every save normalizes the shape.\n */\n @field({\n description:\n 'The people you deal with at this customer, with their role and how to reach them.',\n })\n contacts: PartyContact[] = [];\n\n constructor(options: CustomerOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.creditLimit !== undefined)\n this.creditLimit = options.creditLimit;\n if (options.paymentTerms !== undefined)\n this.paymentTerms = options.paymentTerms;\n if (options.taxExempt !== undefined) this.taxExempt = options.taxExempt;\n if (options.taxId !== undefined) this.taxId = options.taxId;\n if (options.defaultTaxCodeId !== undefined)\n this.defaultTaxCodeId = options.defaultTaxCodeId;\n if (options.defaultShippingAddress !== undefined)\n this.defaultShippingAddress = options.defaultShippingAddress;\n if (options.defaultBillingAddress !== undefined)\n this.defaultBillingAddress = options.defaultBillingAddress;\n if (options.status !== undefined) this.status = options.status;\n // Treat `null` the same as `undefined` here. Customers loaded from\n // rows written before the `customer_type` column existed will\n // hydrate with the field as SQL `NULL`; without this guard the\n // SmrtObject loader would overwrite the `CustomerType.DTC`\n // initializer with `null`, breaking the documented\n // backwards-compatible default. Explicit string values (including\n // any future custom flavour) still take precedence.\n if (options.customerType !== undefined && options.customerType !== null) {\n this.customerType = options.customerType;\n }\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.contacts !== undefined)\n this.contacts = normalizePartyContacts(options.contacts);\n }\n\n /**\n * Re-normalize contacts after the framework's option-override pass, which\n * re-applies raw option values (including a stored JSON string).\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n this.contacts = normalizePartyContacts(this.contacts);\n return this;\n }\n\n /** Save with a final contacts normalization against direct assignment. */\n override async save(): Promise<this> {\n this.contacts = normalizePartyContacts(this.contacts);\n return super.save() as Promise<this>;\n }\n\n /**\n * Convenience predicate: is this a wholesale customer?\n */\n isWholesale(): boolean {\n return this.customerType === CustomerType.WHOLESALE;\n }\n\n /**\n * Check if customer is active\n */\n isActive(): boolean {\n return this.status === CustomerStatus.ACTIVE;\n }\n\n /**\n * Check if customer has available credit\n */\n hasAvailableCredit(amount: number): boolean {\n // In a full implementation, this would check against outstanding balances\n return this.creditLimit >= amount;\n }\n\n /**\n * Get the profile ID for external lookup.\n *\n * To get the actual Profile object, use the ProfileCollection from smrt-profiles:\n * ```typescript\n * const profiles = await ProfileCollection.create(options);\n * const profile = await profiles.get({ id: customer.profileId });\n * ```\n *\n * @returns The profile ID or empty string if not set\n */\n getProfileId(): string {\n return this.profileId;\n }\n}\n\nexport default Customer;\n","/**\n * CustomerCollection - Collection manager for Customer objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Customer } from '../models/Customer.js';\nimport { CustomerStatus } from '../types/index.js';\n\nexport class CustomerCollection extends SmrtCollection<Customer> {\n static readonly _itemClass = Customer;\n\n /**\n * Find customers by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of customers linked to this profile\n */\n async findByProfile(profileId: string): Promise<Customer[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active customers\n *\n * @returns Array of active customers\n */\n async findActive(): Promise<Customer[]> {\n return await this.list({\n where: { status: CustomerStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find customers by status\n *\n * @param status - Customer status\n * @returns Array of customers\n */\n async findByStatus(status: CustomerStatus): Promise<Customer[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a customer for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Customer\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n creditLimit: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Customer> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const customer = await this.create({\n profileId,\n creditLimit: defaults.creditLimit ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: CustomerStatus.ACTIVE,\n });\n await customer.save();\n return customer;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all customers belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of customers for the tenant\n */\n async findByTenant(tenantId: string): Promise<Customer[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global customers (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global customers\n */\n async findGlobal(): Promise<Customer[]> {\n return queryGlobal<Customer>(this);\n }\n\n /**\n * Find customers for a tenant including global customers.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global customers\n */\n async findWithGlobals(tenantId: string): Promise<Customer[]> {\n return queryWithGlobals<Customer>(\n this,\n tenantId,\n 'Customer.findWithGlobals',\n );\n }\n}\n","/**\n * InvoiceLineItem model - individual items on an invoice\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_READ_REBIND,\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyReadRebindCapability,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError } from '../money.js';\nimport type {\n InvoiceCreditCalculationBasis,\n InvoiceLineItemOptions,\n InvoiceTaxComponentSnapshot,\n} from '../types/index.js';\n\n/**\n * InvoiceLineItem represents a single line item on an invoice.\n *\n * Line items contain details of what is being billed, including\n * quantity, pricing, and optional source tracking (e.g., from ad campaigns).\n *\n * @example\n * ```typescript\n * const lineItem = await lineItems.create({\n * invoiceId: invoice.id,\n * description: 'Display Advertising - Summer Campaign',\n * quantity: 50000, // impressions\n * unitPrice: 1, // 1 cent per impression (minor units)\n * taxRate: 0.05,\n * sourceType: 'campaign',\n * sourceId: 'campaign-uuid',\n * periodStart: new Date('2025-06-01'),\n * periodEnd: new Date('2025-06-30')\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n writable: [\n 'invoiceId',\n 'description',\n 'sku',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discount',\n 'discountType',\n 'discountRate',\n 'taxRate',\n 'taxMode',\n 'taxCodeId',\n 'sourceType',\n 'sourceId',\n 'periodStart',\n 'periodEnd',\n 'revenueAccountId',\n 'sortOrder',\n ],\n },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class InvoiceLineItem extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /** @internal Collection read guard returns this snapshot on its root DB. */\n rebindMoneyRead(\n capability: DocumentMoneyReadRebindCapability,\n db: DatabaseInterface,\n ): this {\n if (capability !== DOCUMENT_MONEY_READ_REBIND)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice line read rebinding requires the owning capability',\n );\n this._db = db;\n this.options.db = db;\n return this;\n }\n\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global invoice line items\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Parent invoice\n */\n @field({ description: 'The invoice this line belongs to.' })\n @foreignKey('Invoice', { role: 'items' })\n invoiceId: string = '';\n\n @foreignKey('InvoiceLineItem', { nullable: true })\n creditedLineId: string | null = null;\n\n @field({\n description:\n 'Frozen source basis used to cap and reproduce an issued credit line.',\n })\n creditCalculationBasisJson = '';\n\n get creditCalculationBasis(): InvoiceCreditCalculationBasis | null {\n try {\n const value: unknown = JSON.parse(this.creditCalculationBasisJson);\n if (!value || typeof value !== 'object' || !('kind' in value))\n return null;\n const basis = value as Record<string, unknown>;\n if (\n (basis.kind !== 'quantity' && basis.kind !== 'net_amount') ||\n typeof basis.sourceQuantity !== 'string' ||\n !Number.isSafeInteger(basis.sourceUnitPrice) ||\n (basis.sourceDiscountType !== 'none' &&\n basis.sourceDiscountType !== 'percent' &&\n basis.sourceDiscountType !== 'amount') ||\n typeof basis.sourceDiscountRate !== 'string' ||\n !Number.isSafeInteger(basis.sourceDiscountMinor) ||\n (basis.kind === 'quantity' && typeof basis.quantity !== 'string') ||\n (basis.kind === 'net_amount' && !Number.isSafeInteger(basis.netMinor))\n )\n return null;\n return basis as unknown as InvoiceCreditCalculationBasis;\n } catch {\n return null;\n }\n }\n\n set creditCalculationBasis(value: InvoiceCreditCalculationBasis | null) {\n this.creditCalculationBasisJson = value ? JSON.stringify(value) : '';\n }\n\n /**\n * Item description\n */\n @field({ description: 'What is being billed on this line.' })\n description: string = '';\n\n /**\n * SKU or item code\n */\n sku: string = '';\n\n @crossPackageRef('@happyvertical/smrt-products:Product', { nullable: true })\n productId: string | null = null;\n\n /** Nonnegative decimal quantity (hours, weight, units), up to six fractional digits. */\n @field({ description: 'How many.' })\n quantity: number = 1.0;\n\n /**\n * Unit price before discount, in **integer minor units** (cents, satoshis),\n * in the document's pricing mode: tax-inclusive when its `lineAmountType`\n * is `inclusive`.\n *\n * Money is exact, so it is stored as minor units and never as a float —\n * `$19.99` is `1999`. An integer literal is what maps this to an INTEGER\n * column (#2361).\n */\n @field({\n description:\n \"The price of one, before discount; includes tax when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n unitPrice: number = 0;\n\n /**\n * Discount amount (flat, not percentage), in integer minor units (#2361).\n */\n @field({ ui: { format: 'money' } })\n discount: number = 0;\n\n discountType: 'none' | 'percent' | 'amount' = 'none';\n\n @field({ type: 'decimal' })\n discountRate = '0.0';\n\n /**\n * Tax rate as a decimal fraction (e.g., 0.05 for 5%).\n *\n * A genuine rate, not money: it is inherently fractional, so the `0.0`\n * initializer is load-bearing and maps it to a DECIMAL column. INTEGER would\n * truncate every rate to 0 (#2361).\n */\n @field({\n description:\n 'The stored fractional tax rate for this line (0.05 means 5%).',\n })\n taxRate: number = 0.0;\n\n taxMode: 'inherit' | 'override' = 'inherit';\n\n @foreignKey('TaxCode', { nullable: true })\n taxCodeId: string | null = null;\n\n taxCodeCode: string | null = null;\n\n taxCodeName: string | null = null;\n\n taxComponentsJson: string | null = null;\n\n get taxComponents(): InvoiceTaxComponentSnapshot[] {\n if (this.taxComponentsJson === null) return [];\n try {\n const value: unknown = JSON.parse(this.taxComponentsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is InvoiceTaxComponentSnapshot =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as InvoiceTaxComponentSnapshot).taxComponentId ===\n 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).name === 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).percent === 'string' &&\n Number.isSafeInteger((entry as InvoiceTaxComponentSnapshot).taxMinor),\n );\n } catch {\n return [];\n }\n }\n\n set taxComponents(value: InvoiceTaxComponentSnapshot[]) {\n this.taxComponentsJson = JSON.stringify(value);\n }\n\n /** Exact sum of frozen component taxes, in integer minor units. */\n @field({ ui: { format: 'money' } })\n taxAmount = 0;\n\n /** Stable document snapshot identity; ordinary lifecycle saves do not change it. */\n moneySnapshotId = '';\n\n /**\n * Calculated line amount, in integer minor units (#2361): net of discount\n * and before tax for `exclusive` / `none` documents, and tax-inclusive for\n * `inclusive` ones; {@link taxAmount} holds the tax.\n */\n @field({\n description:\n \"The line amount: net of discount, and including tax only when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n amount: number = 0;\n\n // ============================================================================\n // Source Tracking\n // ============================================================================\n\n /**\n * Type of source ('campaign' | 'contract' | 'manual' | etc.)\n */\n sourceType: string = '';\n\n /**\n * ID of the source (e.g., campaign ID, contract ID)\n */\n sourceId: string = '';\n\n /**\n * Service period start (for time-based billing)\n */\n periodStart: Date | null = null;\n\n /**\n * Service period end (for time-based billing)\n */\n periodEnd: Date | null = null;\n\n // ============================================================================\n // Accounting\n // ============================================================================\n\n /**\n * Revenue account ID (cross-package ref to smrt-ledgers)\n * Used for revenue recognition to specific accounts\n */\n @crossPackageRef('@happyvertical/smrt-ledgers:Account', { nullable: true })\n revenueAccountId: string | null = null;\n\n /**\n * Sort order within the invoice\n */\n sortOrder: number = 0;\n\n constructor(options: InvoiceLineItemOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.invoiceId !== undefined) this.invoiceId = options.invoiceId;\n if (options.creditedLineId !== undefined)\n this.creditedLineId = options.creditedLineId;\n if (options.creditCalculationBasisJson !== undefined)\n this.creditCalculationBasisJson = options.creditCalculationBasisJson;\n if (options.creditCalculationBasis !== undefined)\n this.creditCalculationBasis = structuredClone(\n options.creditCalculationBasis,\n );\n if (options.description !== undefined)\n this.description = options.description;\n if (options.sku !== undefined) this.sku = options.sku;\n if (options.productId !== undefined) this.productId = options.productId;\n if (options.quantity !== undefined) this.quantity = options.quantity;\n if (options.unitPrice !== undefined) this.unitPrice = options.unitPrice;\n if (options.discount !== undefined) this.discount = options.discount;\n if (options.discountType !== undefined)\n this.discountType = options.discountType;\n if (options.discountRate !== undefined)\n this.discountRate = options.discountRate;\n if (options.taxRate !== undefined) this.taxRate = options.taxRate;\n if (options.taxMode !== undefined) this.taxMode = options.taxMode;\n if (options.taxCodeId !== undefined) this.taxCodeId = options.taxCodeId;\n if (options.taxCodeCode !== undefined)\n this.taxCodeCode = options.taxCodeCode;\n if (options.taxCodeName !== undefined)\n this.taxCodeName = options.taxCodeName;\n if (options.taxComponentsJson !== undefined)\n this.taxComponentsJson = options.taxComponentsJson;\n if (options.taxComponents !== undefined)\n this.taxComponents = structuredClone(options.taxComponents);\n if (options.taxAmount !== undefined) this.taxAmount = options.taxAmount;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.amount !== undefined) this.amount = options.amount;\n if (options.sourceType !== undefined) this.sourceType = options.sourceType;\n if (options.sourceId !== undefined) this.sourceId = options.sourceId;\n if (options.periodStart !== undefined)\n this.periodStart = options.periodStart;\n if (options.periodEnd !== undefined) this.periodEnd = options.periodEnd;\n if (options.revenueAccountId !== undefined)\n this.revenueAccountId = options.revenueAccountId;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n /** Refuse an old-format row read from the database. */\n override async initialize(): Promise<this> {\n await super.initialize();\n // A row read from the database must not be old-format money data.\n if (this.isPersisted) {\n const { assertHydratedMoneyRowCurrent } = await import(\n '../upgrade/detect.js'\n );\n await assertHydratedMoneyRowCurrent(this);\n }\n return this;\n }\n\n /** Persist through the invoice money aggregate. */\n override async save(): Promise<this> {\n const { saveInvoiceLineItem } = await import('../document-money.js');\n return (await saveInvoiceLineItem(this)) as this;\n }\n\n /** @internal Aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Invoice line money write capability is required');\n // Money is integer minor units: refuse a major-unit price before it can\n // reach the database (#2401), ahead of the aggregate recompute.\n for (const [field, value] of [\n ['unitPrice', this.unitPrice],\n ['discount', this.discount],\n ] as const)\n if (!Number.isSafeInteger(value))\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n `Invoice line ${field} ${value} must be a safe integer number of minor units`,\n );\n return (await super.save()) as this;\n }\n\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteInvoiceLineItem } = await import('../document-money.js');\n await deleteInvoiceLineItem(this, options);\n }\n\n /** @internal Aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Invoice line money write capability is required');\n await super.delete(options);\n }\n\n /**\n * Check if line item has source tracking\n */\n hasSource(): boolean {\n return !!this.sourceType && !!this.sourceId;\n }\n\n /**\n * Check if line item has a service period\n */\n hasPeriod(): boolean {\n return !!this.periodStart && !!this.periodEnd;\n }\n}\n\nexport default InvoiceLineItem;\n","/**\n * InvoiceLineItemCollection - Collection manager for InvoiceLineItem objects\n * @packageDocumentation\n */\n\nimport {\n SmrtCollection,\n type SmrtListOptions,\n type SmrtObject,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n type SmrtWhereClause,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n queryGlobal,\n queryWithGlobals,\n} from '@happyvertical/smrt-tenancy';\nimport { DOCUMENT_MONEY_READ_REBIND } from '../document-money-internal.js';\nimport { InvoiceLineItem } from '../models/InvoiceLineItem.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport { assertCommerceMoneySchemaCurrent } from '../upgrade/detect.js';\n\nexport class InvoiceLineItemCollection extends SmrtCollection<InvoiceLineItem> {\n static readonly _itemClass = InvoiceLineItem;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) {\n // Without a tenant, still refuse a database with old money storage.\n await assertCommerceMoneySchemaCurrent(rootDb);\n return operation();\n }\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof InvoiceLineItem)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof InvoiceLineItem)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<InvoiceLineItem>,\n options: Parameters<SmrtCollection<InvoiceLineItem>['get']>[1] = {},\n ): Promise<InvoiceLineItem | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<InvoiceLineItem, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<InvoiceLineItem[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<InvoiceLineItem[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<InvoiceLineItem>, 'select'> & {\n select?: undefined;\n })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find line items by invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Array of line items, sorted by sortOrder\n */\n async findByInvoice(invoiceId: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { invoiceId },\n orderBy: 'sortOrder ASC',\n });\n }\n\n /**\n * Find line items by source\n *\n * @param sourceType - Source type (e.g., 'campaign', 'contract')\n * @param sourceId - Source ID\n * @returns Array of line items\n */\n async findBySource(\n sourceType: string,\n sourceId: string,\n ): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType, sourceId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find line items by source type only\n *\n * @param sourceType - Source type (e.g., 'campaign')\n * @returns Array of line items\n */\n async findBySourceType(sourceType: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Calculate total amount for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Total amount\n */\n async getTotalForInvoice(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.reduce((sum, item) => sum + item.amount, 0);\n }\n\n /**\n * Get the next sort order for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Next sort order number\n */\n async getNextSortOrder(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n if (lineItems.length === 0) return 0;\n\n const maxSortOrder = Math.max(...lineItems.map((item) => item.sortOrder));\n return maxSortOrder + 1;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all invoice line items belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of invoice line items for the tenant\n */\n async findByTenant(tenantId: string): Promise<InvoiceLineItem[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global invoice line items (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global invoice line items\n */\n async findGlobal(): Promise<InvoiceLineItem[]> {\n return queryGlobal<InvoiceLineItem>(this);\n }\n\n /**\n * Find invoice line items for a tenant including global line items.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global invoice line items\n */\n async findWithGlobals(tenantId: string): Promise<InvoiceLineItem[]> {\n return queryWithGlobals<InvoiceLineItem>(\n this,\n tenantId,\n 'InvoiceLineItem.findWithGlobals',\n );\n }\n}\n","import {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n type SmrtSaveOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { assertHistoricalCommerceWrite } from '../historical-commerce-internal.js';\nimport type { HistoricalSalesLineInput } from '../historical-sales-types.js';\nexport interface HistoricalSalesLineOptions\n extends SmrtObjectOptions,\n Partial<HistoricalSalesLineInput> {\n tenantId?: string;\n invoiceId?: string;\n sourceKeyHash?: string;\n sourceFieldsJson?: string;\n moneySnapshotId?: string;\n}\n/** An immutable source line with explicit unknowns, never a calculated InvoiceLineItem. */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'historical_sales_lines',\n indexes: [\n {\n name: 'historical_sales_line_source_key',\n columns: ['tenantId', 'invoiceId', 'sourceKeyHash'],\n unique: true,\n },\n ],\n api: { include: ['get', 'list'] },\n cli: { include: ['get', 'list'] },\n mcp: { include: ['get', 'list'] },\n})\nexport class HistoricalSalesLine extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @tenantId() tenantId = '';\n @foreignKey('Invoice') invoiceId = '';\n @foreignKey('HistoricalSalesLine', { nullable: true }) creditedLineId:\n | string\n | null = null;\n sourceKey = '';\n sourceKeyHash = '';\n description = '';\n @field({ ui: { format: 'money' } }) netMinor = 0;\n @field({ type: 'integer', nullable: true, ui: { format: 'money' } }) taxMinor:\n | number\n | null = null;\n @field({ type: 'integer', nullable: true, ui: { format: 'money' } })\n grossMinor: number | null = null;\n @field({ type: 'text', nullable: true }) quantityText: string | null = null;\n @field({ type: 'text', nullable: true }) unitRateText: string | null = null;\n sourceFieldsJson = '{}';\n moneySnapshotId = '';\n constructor(options: HistoricalSalesLineOptions = {}) {\n super(options);\n for (const key of [\n 'tenantId',\n 'invoiceId',\n 'creditedLineId',\n 'sourceKey',\n 'sourceKeyHash',\n 'description',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'quantityText',\n 'unitRateText',\n 'sourceFieldsJson',\n 'moneySnapshotId',\n ] as const)\n if (options[key] !== undefined)\n Object.assign(this, { [key]: options[key] });\n if (options.sourceFields !== undefined)\n this.sourceFieldsJson = JSON.stringify(options.sourceFields);\n }\n override async save(options?: SmrtSaveOptions): Promise<this> {\n assertHistoricalCommerceWrite(this);\n if (\n !this.tenantId ||\n !this.invoiceId ||\n !this.sourceKey ||\n !this.sourceKeyHash ||\n !this.moneySnapshotId\n )\n throw new Error('Historical source line identity is incomplete');\n if (this.id && (await this.db.get(this.tableName, { id: this.id })))\n throw new Error('Historical sales source lines are immutable');\n return super.save(options);\n }\n override async delete(): Promise<void> {\n throw new Error('Historical sales source lines cannot be deleted');\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { HistoricalSalesLine } from '../models/HistoricalSalesLine.js';\nexport class HistoricalSalesLineCollection extends SmrtCollection<HistoricalSalesLine> {\n static readonly _itemClass = HistoricalSalesLine;\n}\n","/**\n * Vendor model - links to Profile with vendor-specific data\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { normalizePartyContacts } from '../party-contacts.js';\nimport {\n type PartyContact,\n type VendorOptions,\n VendorStatus,\n} from '../types/index.js';\n\n/**\n * Vendor represents the vendor/supplier role for a Profile.\n *\n * One Profile can have both Customer and Vendor records - e.g., a company\n * you both buy from and sell to.\n *\n * @example\n * ```typescript\n * const vendor = await vendors.create({\n * profileId: 'profile-uuid',\n * leadTimeDays: 14,\n * minimumOrderAmount: 500,\n * paymentTerms: 'Net 60'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Vendor extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global vendors\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Reference to smrt-profiles Profile\n * Plain string for cross-package reference\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', {\n description:\n 'Links this vendor to their profile record, where their name and contact details are kept.',\n })\n profileId: string = '';\n\n /**\n * Typical lead time in days for orders\n */\n @field({\n description:\n 'How many days the vendor usually takes between your order and delivery.',\n })\n leadTimeDays: number = 0;\n\n /**\n * Minimum order amount required, in **integer minor units** (cents,\n * satoshis). Compared against `Contract.totalAmount`, which is also minor\n * units (#2401).\n */\n @field({\n description: 'The smallest order the vendor will accept.',\n ui: { format: 'money' },\n })\n minimumOrderAmount: number = 0;\n\n /**\n * Payment terms for this vendor (e.g., \"Net 60\")\n */\n @field({\n description:\n 'How long you have to pay this vendor, written the way you would say it, for example \"Net 30\".',\n })\n paymentTerms: string = '';\n\n /**\n * Default currency for transactions with this vendor\n */\n @field({\n description: 'The currency this vendor bills you in.',\n ui: { widget: 'currency' },\n })\n currency: string = 'USD';\n\n /**\n * Supplier registration number.\n *\n * Sensitive for the same reason as a customer's tax ID: it is identifying\n * business information and must not enter generated list/search surfaces.\n */\n @field({\n sensitive: true,\n description: 'The vendor tax or VAT registration number kept on file.',\n })\n taxId: string = '';\n\n /** Tax code normally used for purchases from this vendor. */\n @foreignKey('TaxCode', {\n description: 'The tax code normally used when buying from this vendor.',\n })\n defaultTaxCodeId: string = '';\n\n /**\n * Default contact email for orders\n */\n @field({\n description: 'The email address you normally use to reach this vendor.',\n ui: { widget: 'email' },\n })\n defaultContactEmail: string = '';\n\n /**\n * Default contact phone for orders\n */\n @field({\n description: 'The phone number you normally use to reach this vendor.',\n ui: { widget: 'phone' },\n })\n defaultContactPhone: string = '';\n\n /**\n * Vendor status\n */\n @field({\n description:\n 'Whether you still buy from this vendor: active, inactive or suspended.',\n })\n status: VendorStatus = VendorStatus.ACTIVE;\n\n /**\n * Internal notes about this vendor\n */\n @field({\n description: 'Anything worth remembering about this vendor.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * Per-currency payout destinations for this vendor.\n *\n * Stored as a JSON column. Keys are payout-rail-qualified currency codes —\n * the code must encode both the asset and the rail (e.g. `USDC-base`,\n * `USDC-solana`, `BTC`, `USD-stripe`, `USD-wire`). Values are whatever the\n * receiving rail needs as a destination (EVM address, BTC address, Stripe\n * Connect account id, IBAN, etc.).\n *\n * MVP shape: a flat map on the vendor row. A vendor with no entry for a\n * given currency cannot be paid in that currency — filtering is the\n * consumer's responsibility (the upstream `PaymentIntent` builder filters\n * `paymentOptions` at quote time against this map).\n *\n * Use {@link getPayoutAddress} for a `Map.get`-style lookup that returns\n * `undefined` for missing entries; direct property access is also fine.\n *\n * Sensitive (#1540): payout destinations are excluded from generated API/MCP\n * responses and rejected as a `where` filter key.\n */\n @field({\n sensitive: true,\n description: 'Where payments to this vendor should be sent.',\n })\n payoutAddresses: Record<string, string> = {};\n\n /**\n * People to reach at this vendor, stored as a JSON column (#3501). Write\n * form rows through `savePartyContacts()`; every save normalizes the shape.\n */\n @field({\n description:\n 'The people you deal with at this vendor, with their role and how to reach them.',\n })\n contacts: PartyContact[] = [];\n\n constructor(options: VendorOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.leadTimeDays !== undefined)\n this.leadTimeDays = options.leadTimeDays;\n if (options.minimumOrderAmount !== undefined)\n this.minimumOrderAmount = options.minimumOrderAmount;\n if (options.paymentTerms !== undefined)\n this.paymentTerms = options.paymentTerms;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.taxId !== undefined) this.taxId = options.taxId;\n if (options.defaultTaxCodeId !== undefined)\n this.defaultTaxCodeId = options.defaultTaxCodeId;\n if (options.defaultContactEmail !== undefined)\n this.defaultContactEmail = options.defaultContactEmail;\n if (options.defaultContactPhone !== undefined)\n this.defaultContactPhone = options.defaultContactPhone;\n if (options.status !== undefined) this.status = options.status;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.payoutAddresses !== undefined) {\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n options.payoutAddresses,\n );\n }\n if (options.contacts !== undefined)\n this.contacts = normalizePartyContacts(options.contacts);\n }\n\n /**\n * The framework's {@link SmrtObject.initialize} re-applies `options` keys on\n * top of constructor-set values so option data always wins over field\n * initializers. That means our constructor's normalization runs *before*\n * `initializePropertiesFromOptions` overwrites `payoutAddresses` with the\n * raw cloned value. Re-normalize once super has finished so consumers\n * who pass a string, a partially-typed map, or `null` end up with a\n * clean `Record<string, string>` before any save / read happens.\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n this.payoutAddresses as unknown,\n );\n this.contacts = normalizePartyContacts(this.contacts);\n return this;\n }\n\n /**\n * Save with a final normalization pass so direct field assignments\n * (`vendor.payoutAddresses = somethingFunny`) can't smuggle non-string\n * values into the persisted row.\n */\n override async save(): Promise<this> {\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n this.payoutAddresses as unknown,\n );\n this.contacts = normalizePartyContacts(this.contacts);\n return super.save() as Promise<this>;\n }\n\n /**\n * Check if vendor is active\n */\n isActive(): boolean {\n return this.status === VendorStatus.ACTIVE;\n }\n\n /**\n * Check if order meets minimum requirements\n */\n meetsMinimumOrder(amount: number): boolean {\n return amount >= this.minimumOrderAmount;\n }\n\n /**\n * Get the profile ID for external lookup.\n *\n * To get the actual Profile object, use the ProfileCollection from smrt-profiles:\n * ```typescript\n * const profiles = await ProfileCollection.create(options);\n * const profile = await profiles.get({ id: vendor.profileId });\n * ```\n *\n * @returns The profile ID or empty string if not set\n */\n getProfileId(): string {\n return this.profileId;\n }\n\n /**\n * Look up the payout destination for a single currency. Returns\n * `undefined` if the vendor has no entry for that currency — caller's\n * job to decide whether that means \"skip the option\" or \"raise a\n * configuration error\". The lookup is case-sensitive; the contract is\n * that the currency code passed in matches exactly what was stored\n * (`USDC-base`, not `usdc-base`).\n */\n getPayoutAddress(currency: string): string | undefined {\n const map = this.payoutAddresses;\n if (!map || typeof map !== 'object') return undefined;\n const value = (map as Record<string, unknown>)[currency];\n return typeof value === 'string' ? value : undefined;\n }\n\n /**\n * Set the payout destination for a single currency. Mutates the live\n * map and returns `this` for chaining. Use {@link clearPayoutAddress}\n * to remove a single entry.\n */\n setPayoutAddress(currency: string, destination: string): this {\n this.payoutAddresses = {\n ...(this.payoutAddresses ?? {}),\n [currency]: destination,\n };\n return this;\n }\n\n /**\n * Remove a single currency entry from the payout map. No-op if the\n * currency was already absent.\n */\n clearPayoutAddress(currency: string): this {\n if (!this.payoutAddresses || !(currency in this.payoutAddresses)) {\n return this;\n }\n const next = { ...this.payoutAddresses };\n delete next[currency];\n this.payoutAddresses = next;\n return this;\n }\n\n /**\n * Normalize an input value (object, pre-serialized JSON string, or\n * `null`/`undefined`) into a plain `Record<string, string>`. Used by\n * the constructor so consumers can pass either shape into\n * `VendorCollection.create({ payoutAddresses: ... })`.\n *\n * Non-string values inside an input object are silently dropped — a\n * `Record<string, string>` invariant is what consumers downstream\n * (`PaymentIntent` builders, payout SDK adapters) rely on.\n */\n private static normalizePayoutAddresses(\n value: unknown,\n ): Record<string, string> {\n if (value == null) return {};\n let parsed: unknown = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n return {};\n }\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {};\n }\n const out: Record<string, string> = {};\n for (const [key, v] of Object.entries(parsed as Record<string, unknown>)) {\n if (typeof v === 'string') out[key] = v;\n }\n return out;\n }\n}\n\nexport default Vendor;\n","/**\n * Contract model with STI for different contract types\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n type Meta,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_READ_REBIND,\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyReadRebindCapability,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { assertIntegerMinorUnits } from '../money.js';\nimport {\n type ContractOptions,\n ContractStatus,\n ContractType,\n type LicenseSaleOptions,\n type PurchaseContractOptions,\n type PurchaseOrderOptions,\n type SalesContractOptions,\n type TaxRegistrationOptions,\n} from '../types/index.js';\nimport { Customer } from './Customer.js';\nimport { Vendor } from './Vendor.js';\n\n/**\n * Legal status transitions for a Contract (and all its STI subtypes), keyed by\n * the prior persisted status. A status re-saved unchanged (no-op) and a\n * brand-new row are always permitted; this map governs *changes* only.\n *\n * Flow: DRAFT → SENT → (ACCEPTED | DECLINED); ACCEPTED → (COMPLETED |\n * CANCELLED). An estimate/order may also be cancelled directly from DRAFT/SENT.\n * DECLINED / COMPLETED / CANCELLED are terminal. This guards against raw\n * mass-assignment forcing, e.g., a DECLINED contract back to ACCEPTED or a\n * COMPLETED one back to DRAFT. See S5 audit #1390.\n */\nconst CONTRACT_STATUS_TRANSITIONS: Record<ContractStatus, ContractStatus[]> = {\n [ContractStatus.DRAFT]: [\n ContractStatus.SENT,\n ContractStatus.ACCEPTED,\n ContractStatus.DECLINED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.SENT]: [\n ContractStatus.ACCEPTED,\n ContractStatus.DECLINED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.ACCEPTED]: [\n ContractStatus.COMPLETED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.DECLINED]: [],\n [ContractStatus.COMPLETED]: [],\n [ContractStatus.CANCELLED]: [],\n};\n\n/**\n * Module-scoped record of the status each Contract instance was loaded with,\n * for the save-time transition guard. WeakMap keeps it out of the schema and\n * GCs with the instance — same pattern as the other commerce models.\n */\nconst loadedContractStatus = new WeakMap<Contract, ContractStatus>();\n\n/** Whether a Contract belongs to the purchase STI branch, including descendants. */\nexport function classifyContractPurchase(contract: Contract): boolean {\n return 'vendorId' in contract;\n}\n\n/** Frozen snapshots are reportable except cancelled contracts and supplier quotes. */\nexport function isContractSnapshotReportEligible(contract: Contract): boolean {\n return (\n !(contract instanceof SupplierQuote) &&\n contract.status !== ContractStatus.DRAFT &&\n contract.status !== ContractStatus.CANCELLED\n );\n}\n\n/**\n * Contract is the base class for all commercial agreements.\n *\n * Uses Single Table Inheritance (STI) for ten leaf types. SalesContract owns\n * the customer link for Estimate, Order, WholesaleOrder, Cart, Lease,\n * Agreement, and LicenseSale. PurchaseContract owns the vendor link for\n * SupplierQuote, PurchaseOrder and ProductionOrder. Both branches share `contracts`.\n *\n * @example\n * ```typescript\n * // Create a customer order\n * const order = await contracts.create({\n * _meta_type: 'Order',\n * customerId: customer.id,\n * totalAmount: 150000, // $1,500.00 in cents\n * status: ContractStatus.DRAFT\n * });\n *\n * // Create a purchase order to vendor\n * const po = await contracts.create({\n * _meta_type: 'PurchaseOrder',\n * vendorId: vendor.id,\n * totalAmount: 500000, // $5,000.00 in cents\n * reference: 'PO-2024-001'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Contract extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /** @internal Collection read guard returns this snapshot on its root DB. */\n rebindMoneyRead(\n capability: DocumentMoneyReadRebindCapability,\n db: DatabaseInterface,\n ): this {\n if (capability !== DOCUMENT_MONEY_READ_REBIND)\n throw new Error('Contract read rebinding requires the owning capability');\n this._db = db;\n this.options.db = db;\n return this;\n }\n\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global contracts\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Contract type discriminator (STI)\n */\n @field({\n description:\n 'The kind of contract: order, estimate, lease, agreement and so on.',\n })\n contractType: ContractType = ContractType.ORDER;\n\n /**\n * Current status of the contract\n */\n @field({\n description:\n 'Where the order or agreement stands, for example draft, sent, accepted or completed.',\n })\n status: ContractStatus = ContractStatus.DRAFT;\n\n /**\n * Subtotal before tax, in **integer minor units** (cents, satoshis).\n *\n * The `= 0` initializer is load-bearing: SMRT maps an integer literal to\n * INTEGER and a decimal literal to DECIMAL. Money is exact, so it is stored\n * as minor units and never as a float — `$19.99` is `1999`, not `19.99`\n * (#2401).\n */\n @field({ description: 'The amount before tax.', ui: { format: 'money' } })\n subtotal: number = 0;\n\n /** Informational sum of resolved line discounts, in integer minor units. */\n @field({ ui: { format: 'money' } })\n discountTotal: number = 0;\n\n /**\n * Tax amount, in integer minor units (#2401).\n */\n @field({ description: 'The tax charged.', ui: { format: 'money' } })\n taxAmount: number = 0;\n\n /**\n * Total amount including tax, in integer minor units (#2401).\n */\n @field({\n description: 'The full amount, tax included.',\n ui: { format: 'money' },\n })\n totalAmount: number = 0;\n\n /**\n * Currency code (ISO 4217)\n */\n @field({\n description: 'The currency of the amounts.',\n ui: { widget: 'currency' },\n })\n currency: string = 'USD';\n\n /** Calculated pricing or immutable source-declared purchase evidence. */\n @field({\n description:\n 'Whether amounts were calculated or recorded from reviewed original paperwork.',\n })\n moneyAuthority: 'calculated' | 'received' = 'calculated';\n\n /** Guarded received evidence; write through the public received purchase/sales contract commands only. */\n receivedPurchaseMoneyJson = '';\n\n /** Append-only approved milestone schedule and issued claim evidence. */\n @field({ type: 'text' })\n billingScheduleJson = '';\n\n /** Pricing interpretation fixed before the Contract leaves draft. */\n lineAmountType: 'exclusive' | 'inclusive' | 'none' = 'exclusive';\n\n /** Component rounding scope fixed before the Contract leaves draft. */\n taxRoundingScope: 'line' | 'document' = 'line';\n\n /** Immutable seller registration snapshot once the Contract leaves draft. */\n sellerTaxRegistrationsJson = '[]';\n\n get sellerTaxRegistrations(): TaxRegistrationOptions[] {\n try {\n const value: unknown = JSON.parse(this.sellerTaxRegistrationsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is TaxRegistrationOptions =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as TaxRegistrationOptions).taxComponentId ===\n 'string' &&\n typeof (entry as TaxRegistrationOptions).number === 'string' &&\n typeof (entry as TaxRegistrationOptions).label === 'string',\n );\n } catch {\n return [];\n }\n }\n\n set sellerTaxRegistrations(value: TaxRegistrationOptions[]) {\n this.sellerTaxRegistrationsJson = JSON.stringify(value);\n }\n\n /** Immutable customer or vendor tax identifier snapshot after issue. */\n partyTaxId = '';\n\n /** Stable issue/freeze identity, independent of lifecycle updated_at. */\n moneySnapshotId = '';\n\n /**\n * Date contract was issued\n */\n @field({\n description: 'The date it was issued or placed.',\n // A business date: the natural time axis of contract reports (#4100).\n ui: { format: 'date' },\n })\n issueDate: Date = new Date();\n\n /**\n * Payment due date\n */\n @field({ description: 'The date payment or delivery is due.' })\n dueDate: Date | null = null;\n\n /**\n * Expiry date (for estimates/quotes)\n */\n @field({ description: 'The last day the price or offer is good for.' })\n expiryDate: Date | null = null;\n\n /**\n * External reference number (PO number, quote number, etc.)\n */\n @field({\n description:\n 'Your own number or note for finding this later, such as a purchase order or quote number.',\n })\n reference: string = '';\n\n /**\n * Internal notes\n */\n @field({\n description: 'Anything worth remembering about this.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * Terms and conditions\n */\n @field({\n description:\n 'The conditions agreed, such as deposits, payment or delivery conditions.',\n ui: { widget: 'textarea' },\n })\n terms: string = '';\n\n /**\n * Sales channel that owns this contract.\n *\n * Plain string so consumers can model their own channels without an enum\n * change (e.g. `dtc-web`, `wholesale-b2b`, `pos-store-1`, `marketplace-faire`).\n * Empty string means \"unattributed / legacy\".\n */\n @field({\n description:\n 'Where it came from, for example your shop, a marketplace or a phone call.',\n })\n channelId: string = '';\n\n /**\n * STI discriminator field\n */\n static readonly _stiField = 'contractType';\n\n constructor(options: ContractOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.contractType !== undefined)\n this.contractType = options.contractType;\n if (options.status !== undefined) this.status = options.status;\n if (options.billingScheduleJson !== undefined)\n this.billingScheduleJson = options.billingScheduleJson;\n if (options.moneyAuthority !== undefined)\n this.moneyAuthority = options.moneyAuthority;\n if (options.receivedPurchaseMoneyJson !== undefined)\n this.receivedPurchaseMoneyJson = options.receivedPurchaseMoneyJson;\n if (options.subtotal !== undefined) this.subtotal = options.subtotal;\n if (options.discountTotal !== undefined)\n this.discountTotal = options.discountTotal;\n if (options.taxAmount !== undefined) this.taxAmount = options.taxAmount;\n if (options.totalAmount !== undefined)\n this.totalAmount = options.totalAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.lineAmountType !== undefined)\n this.lineAmountType = options.lineAmountType;\n if (options.taxRoundingScope !== undefined)\n this.taxRoundingScope = options.taxRoundingScope;\n if (options.sellerTaxRegistrationsJson !== undefined)\n this.sellerTaxRegistrationsJson = options.sellerTaxRegistrationsJson;\n if (options.sellerTaxRegistrations !== undefined)\n this.sellerTaxRegistrations = structuredClone(\n options.sellerTaxRegistrations,\n );\n if (options.partyTaxId !== undefined) this.partyTaxId = options.partyTaxId;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.issueDate !== undefined) this.issueDate = options.issueDate;\n if (options.dueDate !== undefined) this.dueDate = options.dueDate;\n if (options.expiryDate !== undefined) this.expiryDate = options.expiryDate;\n if (options.reference !== undefined) this.reference = options.reference;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.terms !== undefined) this.terms = options.terms;\n if (options.channelId !== undefined) this.channelId = options.channelId;\n }\n\n /**\n * Check if contract is in draft state\n */\n isDraft(): boolean {\n return this.status === ContractStatus.DRAFT;\n }\n\n /**\n * Check if contract is accepted\n */\n isAccepted(): boolean {\n return this.status === ContractStatus.ACCEPTED;\n }\n\n /**\n * Check if contract is completed\n */\n isCompleted(): boolean {\n return this.status === ContractStatus.COMPLETED;\n }\n\n /**\n * Check if contract is expired (for estimates)\n */\n isExpired(): boolean {\n if (!this.expiryDate) return false;\n return new Date() > this.expiryDate;\n }\n\n /**\n * Check if contract is overdue\n */\n isOverdue(): boolean {\n if (!this.dueDate) return false;\n if (this.status === ContractStatus.COMPLETED) return false;\n return new Date() > this.dueDate;\n }\n\n /**\n * Calculate and update totals from line items\n */\n async recalculateTotals(): Promise<void> {\n const { recalculateContractTotals } = await import('../contract-money.js');\n await recalculateContractTotals(this);\n }\n\n /**\n * Capture the status the row was loaded with so the save-time transition\n * guard can reject illegal status flips made via raw field assignment\n * (mass-assignment on the generated update route, a stale caller, etc.).\n * Only persisted rows carry a prior status.\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n // A row read from the database must not be old-format money data.\n if (this.isPersisted) {\n const { assertHydratedMoneyRowCurrent } = await import(\n '../upgrade/detect.js'\n );\n await assertHydratedMoneyRowCurrent(this);\n }\n if (await this.isSaved()) {\n loadedContractStatus.set(this, this.status);\n }\n return this;\n }\n\n /**\n * Validate the amounts and the status transition before persisting, then\n * save. Inherited by every STI subtype (Estimate/Order/Lease/.../LicenseSale),\n * so a forged `status` on any of them is caught here. LicenseSale layers its\n * own rights-immutability guard on top via `super.save()`. See S5 audit\n * #1390.\n *\n * `subtotal` / `taxAmount` / `totalAmount` are mass-assignable on the\n * generated create/update routes, so the minor-units check runs on every\n * write surface (#2401).\n */\n override async save(): Promise<this> {\n const { saveContract } = await import('../contract-money.js');\n return (await saveContract(this)) as this;\n }\n\n /** Received purchase monetary history cannot be deleted. */\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteContract } = await import('../contract-money.js');\n await deleteContract(this, options);\n }\n\n /** @internal Contract aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract money write capability is required');\n await super.delete(options);\n }\n\n /** @internal Contract aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract money write capability is required');\n assertIntegerMinorUnits('Contract', this.reference || this.id || '<new>', [\n ['subtotal', this.subtotal],\n ['discountTotal', this.discountTotal],\n ['taxAmount', this.taxAmount],\n ['totalAmount', this.totalAmount],\n ]);\n const prior = await this.resolvePriorStatus();\n this.assertContractStatusTransition(prior);\n const result = (await super.save()) as this;\n loadedContractStatus.set(this, this.status);\n return result;\n }\n\n /**\n * Reject an illegal status flip done via raw assignment. No-op transitions\n * and brand-new rows are always allowed.\n */\n protected assertContractStatusTransition(\n prior: ContractStatus | undefined,\n ): void {\n if (prior === undefined) return; // new row — any starting status is fine\n if (prior === this.status) return; // no-op re-save\n const allowed = CONTRACT_STATUS_TRANSITIONS[prior] ?? [];\n if (!allowed.includes(this.status)) {\n throw new Error(\n `Contract ${this.reference || this.id}: illegal status transition ` +\n `'${prior}' → '${this.status}'.`,\n );\n }\n }\n\n /**\n * Resolve the AUTHORITATIVE prior status (S5 audit #1390 round 5, codex\n * MEDIUM#2). The WeakMap is only populated when {@link initialize} loaded the\n * row from the DB; it is empty for an instance built via\n * `collection.create({ id: <existing>, _skipLoad: true })` — the upsert path\n * that lets a caller write onto an existing row without hydrating it. Trusting\n * an empty WeakMap there would treat the write as a brand-new row and skip the\n * transition guard entirely (a poisonable prior-state). Mirrors the\n * authoritative-prior-load applied to Payment/PaymentIntent/Invoice/Payout.\n *\n * So when this instance carries an `id`, read the persisted row straight from\n * the database and treat its `status` as the prior — a create-onto-existing is\n * an update. Only when no row exists in the DB (truly new) do we fall back to\n * the WeakMap (which is also empty then), i.e. `undefined` = genuinely new.\n * The raw row's `status` column is single-word (no snake_case transform).\n */\n protected async resolvePriorStatus(): Promise<ContractStatus | undefined> {\n if (this.id) {\n try {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row && row.status != null) {\n return row.status as ContractStatus;\n }\n } catch {\n // DB not ready / table absent — fall through to the in-memory record.\n }\n }\n return loadedContractStatus.get(this);\n }\n}\n\n// Every STI child below MUST repeat the `@TenantScoped` decoration. The\n// tenancy registry keys off the concrete className passed by the\n// collection, not the inheritance chain — `OrderCollection.list()` sends\n// `'Order'` to the interceptor, which then misses the `'Contract'`\n// registration and skips tenant auto-filter/auto-populate. Without an\n// explicit `@TenantScoped` on each subclass, saves end up with\n// `tenantId: null` (the row becomes global / invisible to tenant-scoped\n// queries) and lists return rows across tenants.\n\n/** Customer-side contracts, including orders, estimates, and licenses. */\n@TenantScoped({ mode: 'optional' })\n@smrt({ abstract: true })\nexport abstract class SalesContract extends Contract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, {\n description: 'The customer a sales order or agreement is for.',\n })\n customerId: string | null = null;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/** Supplier-side contracts, including supplier quotes, purchase and production orders. */\n@TenantScoped({ mode: 'optional' })\n@smrt({ abstract: true })\nexport abstract class PurchaseContract extends Contract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, {\n description: 'The vendor supplying this quote or purchase contract.',\n })\n vendorId: string | null = null;\n\n constructor(options: PurchaseContractOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n }\n}\n\n/**\n * Estimate - Quote or proposal for a customer\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Estimate extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.ESTIMATE;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Order - Customer purchase order\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Order extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.ORDER;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Lease - Rental or lease agreement\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Lease extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.LEASE;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Agreement - Service or maintenance agreement\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Agreement extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.AGREEMENT;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/** Supplier quotation received from a vendor; acceptance does not create an order. */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class SupplierQuote extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, { required: true })\n override vendorId: string | null = null;\n override contractType = ContractType.SUPPLIER_QUOTE;\n\n constructor(options: PurchaseContractOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n }\n}\n\n/**\n * PurchaseOrder - Order sent to vendor/supplier\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class PurchaseOrder extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, { required: true })\n override vendorId: string | null = null;\n override contractType = ContractType.PURCHASE_ORDER;\n\n /** Expected delivery calendar date (YYYY-MM-DD), or empty when unspecified. */\n @field({\n description:\n 'The date you expect the delivery, as YYYY-MM-DD. Leave blank if it is not known.',\n })\n expectedDate: Meta<string> = '';\n\n /** Delivery address/instructions snapshot, independent of the vendor address. */\n @field({\n description:\n 'Where this order should be delivered, including any delivery instructions.',\n })\n shipTo: Meta<string> = '';\n\n /** Construct a purchase order with its optional delivery header. */\n constructor(options: PurchaseOrderOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n if (options.expectedDate !== undefined)\n this.expectedDate = options.expectedDate;\n if (options.shipTo !== undefined) this.shipTo = options.shipTo;\n }\n}\n\n/**\n * WholesaleOrder - B2B order placed by a wholesale customer.\n *\n * Behaves like an Order but is conventionally created against a customer with\n * `customerType: 'wholesale'`, uses NET-30/60 payment terms, and is delivered\n * via the wholesale-portal channel rather than retail checkout.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class WholesaleOrder extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.WHOLESALE_ORDER;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * ProductionOrder - instruction to commission goods from an internal or\n * external factory.\n *\n * The manufacturing equivalent of a {@link PurchaseOrder} — but instead of\n * buying finished inventory, you're paying to *make* it. A ProductionOrder\n * consumes raw materials per a Bill of Materials (see\n * `@happyvertical/smrt-manufacturing`) and produces finished SKU stock when\n * posted (see `@happyvertical/smrt-inventory`).\n *\n * Carries two STI-meta fields that `ProductionService.consumeMaterials` /\n * `runProduction` read from the loaded row to resolve which BOM to walk:\n *\n * - `productId` — plain string ref to the upstream `Product` (or any\n * STI subtype, e.g. apparel `Style`). Used to look up the *active*\n * BOM via `BomService.findActiveForProduct` when no explicit\n * revision was pinned at the time the order was placed.\n * - `bomId` — optional pin to a specific BOM revision. When set, the\n * manufacturing service consumes against that exact revision even\n * if a newer BOM has become active in the meantime (keeps a\n * posted run from silently switching recipes mid-flight).\n *\n * Both fields are `Meta<string>` so the scanner routes them into the\n * shared `_meta_data` JSON column on the Contract STI table instead of\n * widening the base schema with manufacturing-specific columns.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class ProductionOrder extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.PRODUCTION_ORDER;\n\n /**\n * Plain string reference to the upstream product the order is asked\n * to make. Cross-package id; never `@foreignKey()`. Required by\n * `ProductionService.consumeMaterials` unless `bomId` is supplied.\n */\n productId: Meta<string> = '';\n\n /**\n * Optional explicit BOM revision the order locked to at posting\n * time. When set, manufacturing uses this exact row even if the\n * product's active BOM has since changed. When empty, falls back\n * to the active BOM for `productId`.\n */\n bomId: Meta<string> = '';\n}\n\n/**\n * Cart - transient order-in-progress for a shopper.\n *\n * Persisted as a Contract so it can hold the same line items, totals, and\n * customer reference as a real Order, then convert in place (the application\n * promotes the row from `_meta_type: Cart` to `_meta_type: Order` at checkout\n * rather than copying data between tables).\n *\n * A Cart starts in {@link ContractStatus.DRAFT} via the base `Contract.status`\n * default — the subclass doesn't need its own override. Application code\n * is responsible for assigning the appropriate Order status at checkout;\n * the framework doesn't enforce a state machine on the cart → order transition.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Cart extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.CART;\n}\n\n/**\n * Snapshot of the rights granted by a {@link LicenseSale}. The fields are\n * intentionally typed (not a generic JSON blob) so they survive schema\n * migrations and downstream consumers (PDF templating, hash-registry\n * publishers) can rely on the shape without re-parsing.\n *\n * Each field is opaque text — the values that make sense vary by\n * industry. A stock-media marketplace might use:\n *\n * - `medium`: `web,print,social`\n * - `distributionScope`: `worldwide` / `territorial`\n * - `exclusivity`: `exclusive` / `non-exclusive`\n * - `duration`: `perpetual` / `12-months` / `event-only`\n * - `territory`: ISO-3166 list or `worldwide`\n *\n * Booleans (`sublicensing`, `derivatives`) are typed as such; everything\n * else is a string so the model doesn't dictate vocabulary.\n */\nexport interface LicenseRightsSnapshot {\n medium: string;\n distributionScope: string;\n exclusivity: string;\n duration: string;\n territory: string;\n sublicensing: boolean;\n derivatives: boolean;\n}\n\n/**\n * Module-scoped WeakMap of \"rights snapshot the row was loaded with\".\n *\n * Used by {@link LicenseSale}'s immutability guard. We can't store the\n * captured snapshot as an instance field because the AST scanner would\n * pick it up as a persisted column; we can't store it as a `Meta<T>`\n * because then it'd round-trip with the row and the comparison would\n * always tautologically succeed. A WeakMap keyed by the instance is\n * the cleanest scope: no schema interaction, garbage-collected with\n * the instance.\n */\nconst issuedRightsSnapshot = new WeakMap<LicenseSale, string>();\n\n/**\n * LicenseSale — industry-neutral licensing primitive.\n *\n * Sits alongside the other Contract STI subtypes (Estimate, Order,\n * Lease, Agreement, PurchaseOrder, WholesaleOrder, ProductionOrder,\n * Cart) and represents a single sale of rights for a fee. A\n * stock-media marketplace selling a one-time license, a music-\n * licensing platform issuing a sync license, a code-asset marketplace\n * granting a redistribution right — all use the same primitive.\n *\n * Immutability invariant: once a `LicenseSale` is saved with\n * {@link ContractStatus.ACCEPTED}, its rights snapshot becomes\n * frozen. Re-saving with mutated rights throws. The only legal\n * transition out of ACCEPTED is `revoke()` (which moves status to\n * CANCELLED without changing the rights). If a different snapshot\n * is genuinely needed, the operator's contract is to issue a *new*\n * LicenseSale row and let the old one stand as historical record.\n *\n * All subtype-specific fields are declared as `Meta<T>` so the\n * scanner routes them into the shared `_meta_data` JSON column on\n * the `contracts` STI table — no migration of the base schema needed\n * to land this subtype.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class LicenseSale extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.LICENSE_SALE;\n\n /**\n * Plain string reference to the upstream `Sku` (from\n * `@happyvertical/smrt-products`) that this license was sold against.\n * Cross-package id; never `@foreignKey()`.\n */\n skuId: Meta<string> = '';\n\n /**\n * Plain string reference to the `Payment` that satisfied the\n * purchase. Cross-model reference matches the rest of the\n * package's convention.\n */\n paymentId: Meta<string> = '';\n\n /**\n * The licensee's email address — the primary identity carried\n * forward into PDF generation and any downstream hash-registry\n * publication. Required; without it, downstream rights cannot be\n * attributed.\n */\n licenseeEmail: Meta<string> = '';\n\n /**\n * Optional legal-entity name of the licensee for purchases that\n * warrant it (typically high-tier B2B licenses). Empty string for\n * individual-buyer licenses where the email *is* the legal identity.\n */\n licenseeLegalEntity: Meta<string> = '';\n\n /**\n * Optional ISO-3166 jurisdiction code of the licensee, captured for\n * tax / disclosure / governing-law purposes. Empty when not\n * required.\n */\n licenseeJurisdiction: Meta<string> = '';\n\n // -------- Rights snapshot (immutable once issued) --------\n\n /** Permitted media — `web,print,social`, `broadcast`, etc. */\n rightsMedium: Meta<string> = '';\n\n /** Distribution scope — `worldwide`, `territorial`, `private`, etc. */\n rightsDistributionScope: Meta<string> = '';\n\n /** Exclusivity — `exclusive` / `non-exclusive` / `co-exclusive`. */\n rightsExclusivity: Meta<string> = '';\n\n /** Duration — `perpetual` / `12-months` / `event-only`, etc. */\n rightsDuration: Meta<string> = '';\n\n /** Territory — ISO-3166 list, `worldwide`, region name, etc. */\n rightsTerritory: Meta<string> = '';\n\n /** Whether the licensee may sublicense the rights. */\n rightsSublicensing: Meta<boolean> = false;\n\n /** Whether the licensee may create derivative works. */\n rightsDerivatives: Meta<boolean> = false;\n\n // -------- Artefacts --------\n\n /** URL of the signed PDF (typically a cloud-storage public URL). */\n pdfUrl: Meta<string> = '';\n\n /**\n * SHA-256 of the signed PDF bytes (hex string, no `0x` prefix).\n * Lets downstream consumers verify the PDF the licensee holds is\n * the one this row was issued for, without re-fetching.\n */\n pdfHash: Meta<string> = '';\n\n /**\n * Optional reference to an on-chain hash-registry entry — set when\n * the LicenseSale's `pdfHash` has been anchored on a public chain\n * for tamper-evidence. Format is whatever the hash-registry\n * service emits (e.g. `chain:tx-hash:log-index`). Empty for\n * deployments that don't publish hashes on-chain.\n */\n onChainHashRegistryRef: Meta<string> = '';\n\n constructor(options: LicenseSaleOptions = {}) {\n super(options);\n if (options.skuId !== undefined) this.skuId = options.skuId;\n if (options.paymentId !== undefined) this.paymentId = options.paymentId;\n if (options.licenseeEmail !== undefined)\n this.licenseeEmail = options.licenseeEmail;\n if (options.licenseeLegalEntity !== undefined)\n this.licenseeLegalEntity = options.licenseeLegalEntity;\n if (options.licenseeJurisdiction !== undefined)\n this.licenseeJurisdiction = options.licenseeJurisdiction;\n if (options.rightsMedium !== undefined)\n this.rightsMedium = options.rightsMedium;\n if (options.rightsDistributionScope !== undefined)\n this.rightsDistributionScope = options.rightsDistributionScope;\n if (options.rightsExclusivity !== undefined)\n this.rightsExclusivity = options.rightsExclusivity;\n if (options.rightsDuration !== undefined)\n this.rightsDuration = options.rightsDuration;\n if (options.rightsTerritory !== undefined)\n this.rightsTerritory = options.rightsTerritory;\n if (options.rightsSublicensing !== undefined)\n this.rightsSublicensing = options.rightsSublicensing;\n if (options.rightsDerivatives !== undefined)\n this.rightsDerivatives = options.rightsDerivatives;\n if (options.pdfUrl !== undefined) this.pdfUrl = options.pdfUrl;\n if (options.pdfHash !== undefined) this.pdfHash = options.pdfHash;\n if (options.onChainHashRegistryRef !== undefined)\n this.onChainHashRegistryRef = options.onChainHashRegistryRef;\n }\n\n /**\n * Once `super.initialize()` has applied the framework's option-\n * override pass, capture the rights snapshot if (and only if) the\n * row arrived already issued. That's how the immutability guard\n * tells \"freshly drafting a license\" (snapshot still mutable) apart\n * from \"loaded an already-issued row\" (snapshot frozen).\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n if (this.status === ContractStatus.ACCEPTED && (await this.isSaved())) {\n issuedRightsSnapshot.set(this, this.serializeRightsSnapshot());\n }\n return this;\n }\n\n /**\n * Return the current rights snapshot as a typed object. Read-only\n * for callers — mutation should go through assignment to the\n * individual `rights*` fields, gated by the issued-immutability\n * guard.\n */\n getRightsSnapshot(): LicenseRightsSnapshot {\n return {\n medium: this.rightsMedium,\n distributionScope: this.rightsDistributionScope,\n exclusivity: this.rightsExclusivity,\n duration: this.rightsDuration,\n territory: this.rightsTerritory,\n sublicensing: this.rightsSublicensing,\n derivatives: this.rightsDerivatives,\n };\n }\n\n /**\n * Revoke an issued license — moves status to `CANCELLED` without\n * touching the rights snapshot (which stays frozen). Throws if\n * called on a non-issued license; a draft license should be\n * deleted, not revoked.\n */\n revoke(): void {\n if (this.status !== ContractStatus.ACCEPTED) {\n throw new Error(\n `LicenseSale ${this.id ?? '<new>'}: cannot revoke from status '${this.status}' — only ACCEPTED licenses can be revoked`,\n );\n }\n this.status = ContractStatus.CANCELLED;\n }\n\n /**\n * Save with the immutability check: if the row was loaded with\n * `ACCEPTED` status, the rights snapshot at save time must match\n * the snapshot at load time. Anything else means an out-of-band\n * mutation crept in and we surface it instead of letting the row\n * drift silently.\n *\n * Newly-drafted licenses (where the row was constructed without\n * `ACCEPTED` status) capture their snapshot at the moment the\n * caller transitions to `ACCEPTED` and saves — `validateImmutable`\n * picks that up post-save on the next call.\n */\n override async save(): Promise<this> {\n this.validateImmutable();\n const result = (await super.save()) as this;\n // If this save transitioned the row to ACCEPTED, freeze the\n // snapshot for future saves.\n if (\n this.status === ContractStatus.ACCEPTED &&\n !issuedRightsSnapshot.has(this)\n ) {\n issuedRightsSnapshot.set(this, this.serializeRightsSnapshot());\n }\n return result;\n }\n\n /**\n * Compare the current rights against the captured snapshot\n * (populated either at load time by `initialize` or at first\n * issuance by `save`). Throws on mismatch.\n */\n private validateImmutable(): void {\n const captured = issuedRightsSnapshot.get(this);\n if (!captured) return;\n const current = this.serializeRightsSnapshot();\n if (captured !== current) {\n throw new Error(\n `LicenseSale ${this.id ?? '<new>'}: rights snapshot is immutable once issued (status=ACCEPTED). ` +\n 'Use revoke() to cancel the existing license and issue a new one with the updated rights.',\n );\n }\n }\n\n private serializeRightsSnapshot(): string {\n // Stable key ordering so a re-serialization after a no-op\n // assignment doesn't trip the equality check.\n return JSON.stringify({\n medium: this.rightsMedium,\n distributionScope: this.rightsDistributionScope,\n exclusivity: this.rightsExclusivity,\n duration: this.rightsDuration,\n territory: this.rightsTerritory,\n sublicensing: this.rightsSublicensing,\n derivatives: this.rightsDerivatives,\n });\n }\n}\n\nexport default Contract;\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PurchaseContract } from '../models/Contract.js';\n\n/** Read supplier-side contracts across every purchase STI subtype. */\nexport class PurchaseContractCollection extends SmrtCollection<PurchaseContract> {\n static readonly _itemClass = PurchaseContract;\n\n async findByVendor(vendorId: string): Promise<PurchaseContract[]> {\n return this.list({\n where: { vendorId },\n orderBy: 'created_at DESC',\n });\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { SalesContract } from '../models/Contract.js';\n\n/** Read customer-side contracts across every sales STI subtype. */\nexport class SalesContractCollection extends SmrtCollection<SalesContract> {\n static readonly _itemClass = SalesContract;\n\n async findByCustomer(customerId: string): Promise<SalesContract[]> {\n return this.list({\n where: { customerId },\n orderBy: 'created_at DESC',\n });\n }\n}\n","/**\n * ContractCollection - Collection manager for Contract objects (STI)\n * @packageDocumentation\n */\n\nimport {\n SmrtCollection,\n type SmrtListOptions,\n type SmrtObject,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n type SmrtWhereClause,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n queryGlobal,\n queryWithGlobals,\n} from '@happyvertical/smrt-tenancy';\nimport { DOCUMENT_MONEY_READ_REBIND } from '../document-money-internal.js';\nimport {\n Contract,\n isContractSnapshotReportEligible,\n} from '../models/Contract.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport { ContractStatus, ContractType } from '../types/index.js';\nimport { assertCommerceMoneySchemaCurrent } from '../upgrade/detect.js';\nimport { PurchaseContractCollection } from './PurchaseContractCollection.js';\nimport { SalesContractCollection } from './SalesContractCollection.js';\n\nexport class ContractCollection extends SmrtCollection<Contract> {\n static readonly _itemClass = Contract;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) {\n // Without a tenant, still refuse a database with old money storage.\n await assertCommerceMoneySchemaCurrent(rootDb);\n return operation();\n }\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof Contract)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof Contract)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<Contract>,\n options: Parameters<SmrtCollection<Contract>['get']>[1] = {},\n ): Promise<Contract | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<Contract>[],\n >(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<Contract>[],\n >(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<Contract, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<Contract[]>;\n override async list(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<Contract[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<Contract>, 'select'> & { select?: undefined })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<Contract> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<Contract> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find contracts by customer\n *\n * @param customerId - Customer ID\n * @returns Array of contracts\n * @deprecated Use SalesContractCollection.findByCustomer.\n */\n async findByCustomer(customerId: string): Promise<Contract[]> {\n const sales = await SalesContractCollection.create({\n ...this.options,\n db: this.db,\n });\n return sales.findByCustomer(customerId);\n }\n\n /**\n * Find contracts by vendor\n *\n * @param vendorId - Vendor ID\n * @returns Array of contracts\n * @deprecated Use PurchaseContractCollection.findByVendor.\n */\n async findByVendor(vendorId: string): Promise<Contract[]> {\n const purchases = await PurchaseContractCollection.create({\n ...this.options,\n db: this.db,\n });\n return purchases.findByVendor(vendorId);\n }\n\n /**\n * Hydrate a bounded tenant/date report candidate set once, retaining exact\n * STI descendants so callers can classify custom purchase types safely.\n */\n async listSnapshotReportContracts(options: {\n tenantId: string;\n from: Date;\n to: Date;\n }): Promise<Contract[]> {\n const contracts = await this.list({\n where: {\n tenantId: options.tenantId,\n 'issueDate >=': options.from.toISOString(),\n 'issueDate <=': options.to.toISOString(),\n },\n orderBy: 'issueDate ASC',\n });\n return contracts.filter(isContractSnapshotReportEligible);\n }\n\n /**\n * Find contracts by type (STI)\n *\n * @param contractType - Contract type\n * @returns Array of contracts\n */\n async findByType(contractType: ContractType): Promise<Contract[]> {\n return await this.list({\n where: { contractType },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find contracts by status\n *\n * @param status - Contract status\n * @returns Array of contracts\n */\n async findByStatus(status: ContractStatus): Promise<Contract[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all draft contracts\n *\n * @returns Array of draft contracts\n */\n async findDrafts(): Promise<Contract[]> {\n return await this.findByStatus(ContractStatus.DRAFT);\n }\n\n /**\n * Find all accepted contracts\n *\n * @returns Array of accepted contracts\n */\n async findAccepted(): Promise<Contract[]> {\n return await this.findByStatus(ContractStatus.ACCEPTED);\n }\n\n /**\n * Find overdue contracts\n *\n * @returns Array of overdue contracts\n */\n async findOverdue(): Promise<Contract[]> {\n const now = new Date().toISOString();\n // Get all contracts past due date that aren't completed or cancelled\n const all = await this.list({\n where: {\n 'dueDate <': now,\n },\n orderBy: 'dueDate ASC',\n });\n return all.filter(\n (c) =>\n c.status !== ContractStatus.COMPLETED &&\n c.status !== ContractStatus.CANCELLED,\n );\n }\n\n /**\n * Find expired estimates/quotes\n *\n * @returns Array of expired estimates\n */\n async findExpired(): Promise<Contract[]> {\n const now = new Date().toISOString();\n // Get estimates past expiry date that aren't accepted, declined, or cancelled\n const estimates = await this.list({\n where: {\n contractType: ContractType.ESTIMATE,\n 'expiryDate <': now,\n },\n orderBy: 'expiryDate ASC',\n });\n return estimates.filter(\n (c) =>\n c.status !== ContractStatus.ACCEPTED &&\n c.status !== ContractStatus.DECLINED &&\n c.status !== ContractStatus.CANCELLED,\n );\n }\n\n /**\n * Find contracts in date range\n *\n * @param startDate - Start date\n * @param endDate - End date\n * @returns Array of contracts\n */\n async findByDateRange(startDate: Date, endDate: Date): Promise<Contract[]> {\n return await this.list({\n where: {\n 'issueDate >=': startDate.toISOString(),\n 'issueDate <=': endDate.toISOString(),\n },\n orderBy: 'issueDate DESC',\n });\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all contracts belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of contracts for the tenant\n */\n async findByTenant(tenantId: string): Promise<Contract[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global contracts (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global contracts\n */\n async findGlobal(): Promise<Contract[]> {\n return queryGlobal<Contract>(this);\n }\n\n /**\n * Find contracts for a tenant including global contracts.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global contracts\n */\n async findWithGlobals(tenantId: string): Promise<Contract[]> {\n return queryWithGlobals<Contract>(\n this,\n tenantId,\n 'Contract.findWithGlobals',\n );\n }\n}\n","/** Approved contract billing capacity; construction authorization belongs to the host. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { ContractCollection } from './collections/ContractCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n} from './document-money-internal.js';\nimport { Agreement, type Contract, Order } from './models/Contract.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { MoneyValidationError } from './money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { ContractStatus, InvoiceStatus } from './types/index.js';\n\n/** Exact billing entitlement in the schedule's explicit net or gross basis. */\nexport interface ContractBillingMilestone {\n key: string;\n label: string;\n amountMinor: number;\n}\n/** Immutable approved revision; ceiling is derived from original money plus amendments. */\nexport interface ContractBillingScheduleRevision {\n revision: number;\n requestId: string;\n approvalEvidenceRef: string;\n taxPolicyEvidenceRef: string;\n currency: string;\n basis: 'net' | 'gross';\n amendmentMinor: number;\n approvedTotalMinor: number;\n milestones: ContractBillingMilestone[];\n}\n/** Exact invoice amounts the host approved, independently of a net-only billing ceiling. */\nexport interface ContractMilestoneInvoiceMoney {\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n}\n/** Immutable issued claim; settlement, cancellation and credits never implicitly reopen it. */\nexport interface ContractMilestoneClaim {\n requestId: string;\n revision: number;\n milestoneKey: string;\n invoiceId: string;\n moneySnapshotId: string;\n approvedMoney: ContractMilestoneInvoiceMoney;\n invoiceApprovalEvidenceRef: string;\n}\n/** Persisted append-only schedule history and billing claims. */\nexport interface ContractBillingSchedule {\n version: 1;\n originalAmountMinor: number;\n capacityPolicy: 'issued-consumed';\n revisions: ContractBillingScheduleRevision[];\n claims: ContractMilestoneClaim[];\n}\ninterface ScheduleCommand {\n db: DatabaseInterface;\n tenantId: string;\n contractId: string;\n requestId: string;\n}\n/** The host must authorize approval and retain the referenced policy/evidence. */\nexport interface ApproveContractBillingScheduleInput extends ScheduleCommand {\n expectedRevision: number;\n approvalEvidenceRef: string;\n taxPolicyEvidenceRef: string;\n currency: string;\n basis: 'net' | 'gross';\n /** Zero for the original schedule; explicit signed approved value change thereafter. */\n amendmentMinor: number;\n milestones: ContractBillingMilestone[];\n}\n/** Issue an existing prepared draft under exact host-approved money and capacity. */\nexport interface IssueContractMilestoneInvoiceInput extends ScheduleCommand {\n revision: number;\n milestoneKey: string;\n invoiceId: string;\n approvedMoney: ContractMilestoneInvoiceMoney;\n invoiceApprovalEvidenceRef: string;\n}\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value || value.trim() !== value)\n invalid(`${label} must be nonempty trimmed text`);\n return value;\n}\nfunction integer(value: unknown, label: string, signed = false): number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n (!signed && value < 0)\n )\n invalid(`${label} must be a ${signed ? '' : 'nonnegative '}safe integer`);\n return value;\n}\nfunction safe(value: bigint): number {\n const result = Number(value);\n return integer(result, 'Computed amount');\n}\nfunction context(input: ScheduleCommand): void {\n text(input.tenantId, 'Tenant');\n text(input.contractId, 'Contract');\n text(input.requestId, 'Request');\n if (getTenantId() !== input.tenantId)\n invalid('Schedule command requires its active tenant context');\n}\nfunction milestones(\n value: ContractBillingMilestone[],\n): ContractBillingMilestone[] {\n if (!Array.isArray(value) || value.length === 0)\n invalid('A schedule requires milestones');\n const keys = new Set<string>();\n return value.map((entry) => {\n if (!entry || typeof entry !== 'object') invalid('Invalid milestone');\n const key = text(entry.key, 'Milestone key');\n if (keys.has(key)) invalid('Milestone keys must be unique');\n keys.add(key);\n return {\n key,\n label: text(entry.label, 'Milestone label'),\n amountMinor: integer(entry.amountMinor, 'Milestone amount'),\n };\n });\n}\nfunction money(\n value: ContractMilestoneInvoiceMoney,\n): ContractMilestoneInvoiceMoney {\n if (!value || typeof value !== 'object')\n invalid('Approved invoice money is required');\n const netMinor = integer(value.netMinor, 'Approved net');\n const taxMinor = integer(value.taxMinor, 'Approved tax');\n const grossMinor = integer(value.grossMinor, 'Approved gross');\n if (BigInt(netMinor) + BigInt(taxMinor) !== BigInt(grossMinor))\n invalid('Approved invoice money must reconcile');\n return { netMinor, taxMinor, grossMinor };\n}\n/** Allocate integer relative weights with the exact rounding remainder on the final milestone. */\nexport function allocateContractMilestones(\n totalMinor: number,\n weights: readonly number[],\n): number[] {\n integer(totalMinor, 'Total');\n if (!Array.isArray(weights) || !weights.length)\n invalid('Milestone weights are required');\n const values = weights.map((value) => {\n integer(value, 'Weight');\n if (!value) invalid('Weights must be positive');\n return BigInt(value);\n });\n const sum = values.reduce((a, b) => a + b, 0n);\n let remaining = BigInt(totalMinor);\n return values.map((value, index) => {\n const amount =\n index === values.length - 1\n ? remaining\n : (BigInt(totalMinor) * value) / sum;\n remaining -= amount;\n return safe(amount);\n });\n}\n/** Read immutable schedule evidence; a detached result cannot mutate its Contract. */\nexport function getContractBillingSchedule(\n contract: Contract,\n): ContractBillingSchedule | null {\n if (!contract.billingScheduleJson) return null;\n let parsed: ContractBillingSchedule;\n try {\n parsed = JSON.parse(contract.billingScheduleJson);\n } catch {\n invalid('Stored billing schedule is invalid');\n }\n if (\n parsed.version !== 1 ||\n parsed.capacityPolicy !== 'issued-consumed' ||\n !Array.isArray(parsed.revisions) ||\n !parsed.revisions.length ||\n !Array.isArray(parsed.claims)\n )\n invalid('Stored billing schedule is invalid');\n return parsed;\n}\nasync function loadContract(\n db: DatabaseInterface,\n tenantId: string,\n contractId: string,\n): Promise<Order | Agreement> {\n const collection = await ContractCollection.create({ db });\n await lockDocumentMoneyParents([{ id: contractId, tenantId, collection }]);\n const contract = await collection.get({ id: contractId }, { cache: false });\n if (\n !(contract instanceof Order || contract instanceof Agreement) ||\n contract.tenantId !== tenantId ||\n !contract.customerId ||\n contract.status !== ContractStatus.ACCEPTED ||\n !contract.moneySnapshotId\n )\n invalid(\n 'Schedule requires an accepted customer contract in the active tenant',\n );\n return contract;\n}\n/** Append an approved schedule; original frozen Contract money remains authoritative and unchanged. */\nexport async function approveContractBillingSchedule(\n input: ApproveContractBillingScheduleInput,\n): Promise<ContractBillingScheduleRevision> {\n context(input);\n const expectedRevision = integer(input.expectedRevision, 'Expected revision');\n const proposal = {\n requestId: input.requestId,\n approvalEvidenceRef: text(input.approvalEvidenceRef, 'Approval evidence'),\n taxPolicyEvidenceRef: text(\n input.taxPolicyEvidenceRef,\n 'Tax policy evidence',\n ),\n currency: text(input.currency, 'Currency'),\n basis: input.basis,\n amendmentMinor: integer(input.amendmentMinor, 'Amendment', true),\n milestones: milestones(input.milestones),\n };\n if (proposal.basis !== 'net' && proposal.basis !== 'gross')\n invalid('Schedule basis must explicitly be net or gross');\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const contract = await loadContract(db, input.tenantId, input.contractId);\n const stored = getContractBillingSchedule(contract);\n const replay = stored?.revisions.find(\n (entry) => entry.requestId === input.requestId,\n );\n if (replay) {\n const { revision, approvedTotalMinor: _total, ...old } = replay;\n if (\n revision !== expectedRevision + 1 ||\n JSON.stringify(old) !== JSON.stringify(proposal)\n )\n invalid('Schedule request changed');\n return replay;\n }\n if (stored?.claims.some((entry) => entry.requestId === input.requestId))\n invalid('Request identity already used');\n const previous = stored?.revisions.at(-1);\n if ((previous?.revision ?? 0) !== expectedRevision)\n invalid('Schedule revision changed');\n if (\n contract.currency !== proposal.currency ||\n (previous &&\n (previous.currency !== proposal.currency ||\n previous.basis !== proposal.basis))\n )\n invalid('Schedule currency and basis must match original approval');\n const originalAmountMinor =\n stored?.originalAmountMinor ??\n (proposal.basis === 'net' ? contract.subtotal : contract.totalAmount);\n integer(originalAmountMinor, 'Original contract amount');\n if (!stored) {\n if (proposal.amendmentMinor !== 0)\n invalid('Initial schedule cannot amend original contract value');\n const invoices = await (\n await InvoiceCollection.create({ db })\n ).findByContract(input.contractId);\n if (\n invoices.some(\n (invoice) => invoice.kind === 'invoice' && !!invoice.moneySnapshotId,\n )\n )\n invalid(\n 'Existing issued contract invoices prevent initial schedule approval',\n );\n }\n const approvedTotalMinor = safe(\n BigInt(previous?.approvedTotalMinor ?? originalAmountMinor) +\n BigInt(proposal.amendmentMinor),\n );\n if (\n proposal.milestones.reduce(\n (sum, entry) => sum + BigInt(entry.amountMinor),\n 0n,\n ) !== BigInt(approvedTotalMinor)\n )\n invalid(\n 'Milestone total must equal original contract plus approved amendments',\n );\n for (const claim of stored?.claims ?? []) {\n const prior = stored?.revisions\n .find((entry) => entry.revision === claim.revision)\n ?.milestones.find((entry) => entry.key === claim.milestoneKey);\n const next = proposal.milestones.find(\n (entry) => entry.key === claim.milestoneKey,\n );\n if (!prior || !next || JSON.stringify(prior) !== JSON.stringify(next))\n invalid('An issued milestone cannot be removed or changed');\n }\n const revision: ContractBillingScheduleRevision = {\n revision: expectedRevision + 1,\n ...proposal,\n approvedTotalMinor,\n };\n const state: ContractBillingSchedule = stored ?? {\n version: 1,\n originalAmountMinor,\n capacityPolicy: 'issued-consumed',\n revisions: [],\n claims: [],\n };\n state.revisions.push(revision);\n contract.billingScheduleJson = JSON.stringify(state);\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return revision;\n });\n}\n\n// An executor-bound, one-invoice capability. Never exported from the package.\nconst issuePermissions = new WeakMap<\n object,\n Map<\n string,\n {\n contractId: string;\n amountMinor: number;\n basis: 'net' | 'gross';\n approvedMoney: ContractMilestoneInvoiceMoney;\n }\n >\n>();\n/** @internal Called by the ordinary money aggregate before any new invoice freezes. */\nexport async function assertContractScheduleInvoiceFreeze(\n db: DatabaseInterface,\n invoice: Invoice,\n): Promise<void> {\n if (invoice.kind !== 'invoice' || !invoice.contractId) return;\n const contract = await (await ContractCollection.create({ db })).get(\n { id: invoice.contractId },\n { cache: false },\n );\n if (!contract) return;\n if (contract.tenantId !== invoice.tenantId)\n invalid('Invoice contract must belong to its active tenant');\n const state = getContractBillingSchedule(contract);\n if (!state) return;\n // Abandoning an unissued draft creates no billing entitlement.\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n !invoice.moneySnapshotId &&\n !invoice.arJournalId\n )\n return;\n if (!(contract instanceof Order || contract instanceof Agreement))\n invalid('Scheduled contract must be a customer contract');\n const permission = invoice.id\n ? issuePermissions.get(db as object)?.get(invoice.id)\n : undefined;\n if (!permission || permission.contractId !== invoice.contractId)\n invalid(\n 'Scheduled contract invoices must use issueContractMilestoneInvoice',\n );\n if (\n invoice.customerId !== contract.customerId ||\n invoice.currency !== contract.currency\n )\n invalid('Milestone invoice must match contract customer and currency');\n const actual = {\n netMinor: invoice.subtotal,\n taxMinor: invoice.taxAmount,\n grossMinor: invoice.totalAmount,\n };\n if (\n JSON.stringify(actual) !== JSON.stringify(permission.approvedMoney) ||\n (permission.basis === 'net' ? invoice.subtotal : invoice.totalAmount) !==\n permission.amountMinor\n )\n invalid('Milestone invoice money differs from approved amounts');\n}\n/** Atomically issue/freeze one prepared draft and consume exactly one approved milestone. */\nexport async function issueContractMilestoneInvoice(\n input: IssueContractMilestoneInvoiceInput,\n): Promise<ContractMilestoneClaim> {\n context(input);\n const request = {\n requestId: input.requestId,\n revision: integer(input.revision, 'Revision'),\n milestoneKey: text(input.milestoneKey, 'Milestone key'),\n invoiceId: text(input.invoiceId, 'Invoice'),\n approvedMoney: money(input.approvedMoney),\n invoiceApprovalEvidenceRef: text(\n input.invoiceApprovalEvidenceRef,\n 'Invoice approval evidence',\n ),\n };\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const contract = await loadContract(db, input.tenantId, input.contractId);\n const state = getContractBillingSchedule(contract);\n if (!state) invalid('Contract has no approved billing schedule');\n const replay = state.claims.find(\n (entry) => entry.requestId === request.requestId,\n );\n if (replay) {\n const { moneySnapshotId: _snapshot, ...prior } = replay;\n if (JSON.stringify(prior) !== JSON.stringify(request))\n invalid('Milestone issue request changed');\n return replay;\n }\n if (state.revisions.some((entry) => entry.requestId === request.requestId))\n invalid('Request identity already used');\n const revision = state.revisions.at(-1);\n if (!revision || revision.revision !== request.revision)\n invalid('Schedule revision changed');\n const milestone = revision.milestones.find(\n (entry) => entry.key === request.milestoneKey,\n );\n if (!milestone) invalid('Milestone does not exist in approved revision');\n if (\n state.claims.some(\n (entry) =>\n entry.milestoneKey === request.milestoneKey ||\n entry.invoiceId === request.invoiceId,\n )\n )\n invalid('Milestone or invoice already consumed');\n const invoices = await InvoiceCollection.create({ db });\n await lockDocumentMoneyParents([\n { id: request.invoiceId, tenantId: input.tenantId, collection: invoices },\n ]);\n const invoice = await invoices.get(\n { id: request.invoiceId },\n { cache: false },\n );\n if (\n !invoice ||\n invoice.tenantId !== input.tenantId ||\n invoice.kind !== 'invoice' ||\n invoice.status !== InvoiceStatus.DRAFT ||\n invoice.moneySnapshotId ||\n invoice.contractId !== input.contractId ||\n invoice.customerId !== contract.customerId ||\n invoice.currency !== revision.currency\n )\n invalid(\n 'Milestone requires a matching unissued draft in the active tenant',\n );\n const permissions = issuePermissions.get(db as object) ?? new Map();\n permissions.set(request.invoiceId, {\n contractId: input.contractId,\n amountMinor: milestone.amountMinor,\n basis: revision.basis,\n approvedMoney: request.approvedMoney,\n });\n issuePermissions.set(db as object, permissions);\n try {\n invoice.markSent();\n await invoice.save();\n } finally {\n permissions.delete(request.invoiceId);\n if (!permissions.size) issuePermissions.delete(db as object);\n }\n if (!invoice.moneySnapshotId) invalid('Milestone invoice was not frozen');\n const claim: ContractMilestoneClaim = {\n ...request,\n moneySnapshotId: invoice.moneySnapshotId,\n };\n state.claims.push(claim);\n contract.billingScheduleJson = JSON.stringify(state);\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return claim;\n });\n}\n","import { assertContractScheduleInvoiceFreeze } from './contract-billing-schedule.js';\nimport {\n getHistoricalSalesMoney,\n readHistoricalSalesLines,\n} from './historical-sales-money.js';\nimport type { HistoricalSalesMoneySnapshot } from './historical-sales-types.js';\n/** Transactional Invoice money aggregate persistence. */\n\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport {\n DocumentTaxCollection,\n type DocumentTaxWriteInput,\n} from './collections/DocumentTaxCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { InvoiceLineItemCollection } from './collections/InvoiceLineItemCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport {\n allocateFrozenCredit,\n type FrozenCreditAllocation,\n type IssuedCreditConsumption,\n} from './credit-allocation.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n withDocumentMoneyObjectTransaction,\n withDocumentMoneyTransaction,\n} from './document-money-internal.js';\nimport type { DocumentTax } from './models/DocumentTax.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { InvoiceLineItem } from './models/InvoiceLineItem.js';\nimport type { TaxSettings } from './models/TaxSettings.js';\nimport {\n calculateMoneyDocument,\n type MoneyDiscountInput,\n MoneyValidationError,\n type ResolvableTaxCodeInput,\n resolveLineTaxCode,\n} from './money.js';\nimport {\n lockTenantMoneyRuntime,\n withTenantMoneyRuntime,\n} from './tenant-money-barrier.js';\nimport type { InvoiceTaxComponentSnapshot } from './types/index.js';\nimport { InvoiceStatus } from './types/index.js';\n\ntype ProductTaxDefaults = {\n tenantId: string | null;\n defaultSalesTaxCodeId: string;\n};\n\ntype DeleteOptions = { expectedUpdatedAt?: Date | string };\n\nexport interface PreviewInvoiceMoneyInput {\n db: DatabaseInterface;\n tenantId: string;\n invoiceId: string;\n draft?: {\n header?: Partial<\n Pick<\n Invoice,\n | 'currency'\n | 'lineAmountType'\n | 'taxRoundingScope'\n | 'providerTaxAmount'\n | 'customerId'\n >\n >;\n lines?: Array<\n Partial<\n Pick<\n InvoiceLineItem,\n | 'id'\n | 'description'\n | 'productId'\n | 'quantity'\n | 'unitPrice'\n | 'discountType'\n | 'discountRate'\n | 'discount'\n | 'taxMode'\n | 'taxCodeId'\n >\n >\n >;\n };\n}\n\nexport interface PreviewInvoiceMoneyResult {\n source: 'calculated';\n header: {\n currency: string;\n lineAmountType: Invoice['lineAmountType'];\n taxRoundingScope: Invoice['taxRoundingScope'];\n subtotalMinor: number;\n discountTotalMinor: number;\n taxAmountMinor: number;\n providerTaxAmountMinor: number;\n totalAmountMinor: number;\n };\n lines: Array<{\n id: string;\n grossMinor: number;\n discountMinor: number;\n amountMinor: number;\n taxMinor: number;\n taxCodeId: string | null;\n taxCodeCode: string | null;\n taxCodeName: string | null;\n taxComponents: InvoiceLineItem['taxComponents'];\n }>;\n taxes: DocumentTaxWriteInput[];\n}\n\nexport interface GetInvoiceMoneyFactsInput {\n db: DatabaseInterface;\n tenantId: string;\n invoiceId: string;\n}\n\nexport interface InvoiceMoneyFacts {\n historical?: {\n snapshot: HistoricalSalesMoneySnapshot;\n lines: Array<{ sourceKey: string; lineId: string }>;\n };\n source: 'stored';\n payable?: ReturnType<Invoice['getPayableFacts']>;\n invoiceId: string;\n moneySnapshotId: string;\n kind: Invoice['kind'];\n status: Invoice['status'];\n header: PreviewInvoiceMoneyResult['header'];\n lines: PreviewInvoiceMoneyResult['lines'];\n taxes: DocumentTaxWriteInput[];\n}\n\nconst FROZEN_INVOICE_FIELDS = [\n 'moneyAuthority',\n 'historicalSalesMoneyJson',\n 'historicalSourceKeyHash',\n 'kind',\n 'creditedInvoiceId',\n 'tenantId',\n 'customerId',\n 'contractId',\n 'invoiceNumber',\n 'reference',\n 'issueDate',\n 'dueDate',\n 'subtotal',\n 'discountTotal',\n 'taxAmount',\n 'providerTaxAmount',\n 'totalAmount',\n 'currency',\n 'lineAmountType',\n 'taxRoundingScope',\n 'sellerTaxRegistrationsJson',\n 'partyTaxId',\n 'moneySnapshotId',\n 'notes',\n 'customerNotes',\n 'terms',\n] as const;\n\nconst FROZEN_LINE_FIELDS = [\n 'tenantId',\n 'invoiceId',\n 'creditedLineId',\n 'creditCalculationBasisJson',\n 'description',\n 'sku',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discountType',\n 'discountRate',\n 'discount',\n 'taxMode',\n 'taxCodeId',\n 'taxCodeCode',\n 'taxCodeName',\n 'taxComponentsJson',\n 'taxAmount',\n 'taxRate',\n 'amount',\n 'sourceType',\n 'sourceId',\n 'periodStart',\n 'periodEnd',\n 'revenueAccountId',\n 'sortOrder',\n 'moneySnapshotId',\n] as const;\n\n/** Frozen-field identity: an absent optional reference (`''`) equals a stored NULL. */\nfunction comparable(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n return value === '' || value === undefined ? null : value;\n}\n\nfunction assertFieldsUnchanged<T extends object>(\n proposed: T,\n persisted: T,\n fields: readonly (keyof T)[],\n label: string,\n): void {\n for (const field of fields) {\n if (comparable(proposed[field]) !== comparable(persisted[field])) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n `${label} ${String(field)} is frozen`,\n );\n }\n }\n}\n\nfunction assertTenantId(value: string | null): asserts value is string {\n if (!value || value.trim() !== value)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money requires a tenant-owned invoice',\n );\n}\n\nfunction requireId(value: string | null | undefined, label: string): string {\n if (!value)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `${label} requires a persisted ID`,\n );\n return value;\n}\n\n/** Lock the tenant's settings row; every money document belongs to a tenant. */\nasync function lockRuntimeSettings(\n db: DatabaseInterface,\n tenantId: string | null,\n): Promise<TaxSettings> {\n if (!tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Commerce money documents require a tenant',\n );\n return lockTenantMoneyRuntime(db, tenantId);\n}\n\nfunction isFrozen(invoice: Invoice): boolean {\n return (\n invoice.status !== InvoiceStatus.DRAFT ||\n !!invoice.arJournalId ||\n !!invoice.moneySnapshotId\n );\n}\n\nfunction aggregateSignature(invoice: Invoice): string {\n return JSON.stringify([\n invoice.lineAmountType,\n invoice.taxRoundingScope,\n invoice.subtotal,\n invoice.discountTotal,\n invoice.taxAmount,\n invoice.totalAmount,\n ]);\n}\n\nasync function loadInvoice(\n db: DatabaseInterface,\n id: string,\n): Promise<{ collection: InvoiceCollection; invoice: Invoice }> {\n const collection = await InvoiceCollection.create({ db });\n const invoice = await collection.get({ id }, { cache: false });\n if (!invoice)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice ${id} was not found`,\n );\n return { collection, invoice };\n}\n\nasync function findInvoice(\n db: DatabaseInterface,\n id: string,\n): Promise<Invoice | null> {\n const collection = await InvoiceCollection.create({ db });\n return collection.get({ id }, { cache: false });\n}\n\n/** @internal Acquire the invoice money lock and reload persisted authority. */\nexport async function lockAndReloadInvoice(\n db: DatabaseInterface,\n invoiceId: string,\n tenantId: string,\n): Promise<{ collection: InvoiceCollection; invoice: Invoice }> {\n const first = await loadInvoice(db, invoiceId);\n await lockDocumentMoneyParents([\n { id: invoiceId, tenantId, collection: first.collection },\n ]);\n const invoice = await first.collection.get(\n { id: invoiceId },\n { cache: false },\n );\n if (!invoice || invoice.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant identity changed while acquiring its money lock',\n );\n return { collection: first.collection, invoice };\n}\n\nasync function lockAndReloadMoneyInvoice(\n db: DatabaseInterface,\n invoiceId: string,\n tenantId: string,\n creditedInvoiceId: string | null,\n): Promise<{\n collection: InvoiceCollection;\n invoice: Invoice;\n source: Invoice | null;\n}> {\n const collection = await InvoiceCollection.create({ db });\n const ids = [invoiceId, ...(creditedInvoiceId ? [creditedInvoiceId] : [])];\n const loaded = await Promise.all(\n ids.map((id) => collection.get({ id }, { cache: false })),\n );\n if (loaded.some((row) => !row || row.tenantId !== tenantId))\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money parents must exist in the active tenant',\n );\n await lockDocumentMoneyParents(\n ids.map((id) => ({ id, tenantId, collection })),\n );\n const invoice = await collection.get({ id: invoiceId }, { cache: false });\n const source = creditedInvoiceId\n ? await collection.get({ id: creditedInvoiceId }, { cache: false })\n : null;\n if (\n !invoice ||\n invoice.tenantId !== tenantId ||\n (source && source.tenantId !== tenantId)\n )\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money parent identity changed while acquiring its lock',\n );\n return { collection, invoice, source };\n}\n\nfunction discountInput(line: InvoiceLineItem): MoneyDiscountInput {\n if (line.discountType === 'percent')\n return { kind: 'percent', rate: String(line.discountRate) };\n if (line.discountType === 'amount' || line.discount !== 0)\n return { kind: 'amount', minor: line.discount };\n if (line.discountType !== 'none')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Unknown discount type: ${line.discountType}`,\n );\n return { kind: 'none' };\n}\n\ntype CreditPreparation = {\n allocationByLineId: Map<string, FrozenCreditAllocation>;\n sourceByLineId: Map<string, InvoiceLineItem>;\n issuedLines: InvoiceLineItem[];\n issuedParentById: Map<string, Invoice>;\n sourceInvoice: Invoice;\n sourceTaxes: DocumentTax[];\n exhaustsDocument: boolean;\n};\n\nfunction issuedCredit(invoice: Invoice): boolean {\n return (\n invoice.kind === 'credit_note' &&\n invoice.status !== InvoiceStatus.DRAFT &&\n invoice.status !== InvoiceStatus.CANCELLED\n );\n}\n\n/** @internal Refresh one economic credit effect, including historical issued credits. */\nexport async function refreshIssuedCreditBalance(\n db: DatabaseInterface,\n source: Invoice,\n): Promise<void> {\n const sourceId = requireId(source.id, 'Credited invoice');\n const credits = await (await InvoiceCollection.create({ db })).list({\n where: { tenantId: source.tenantId, creditedInvoiceId: sourceId },\n limit: 100001,\n });\n if (credits.length > 100000)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Issued credit scope exceeds its bounded source limit',\n );\n const issued = credits.filter(issuedCredit).sort((left, right) => {\n const date = left.issueDate.getTime() - right.issueDate.getTime();\n if (date) return date;\n return String(left.id) < String(right.id)\n ? -1\n : String(left.id) > String(right.id)\n ? 1\n : 0;\n });\n const total = issued.reduce((sum, credit) => sum + credit.totalAmount, 0);\n if (!Number.isSafeInteger(total) || total < 0)\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n 'Issued credit total is not a nonnegative safe integer',\n );\n let remainingSource = Math.max(0, source.totalAmount - source.amountPaid);\n const managed = new Map<string, number>();\n if (\n source.retentionAccountingStateJson ||\n source.ordinaryAccountingStateJson\n ) {\n const providerState = JSON.parse(\n source.retentionAccountingStateJson || source.ordinaryAccountingStateJson,\n );\n for (const entry of providerState.credits) {\n const credit = issued.find(\n (candidate) => candidate.id === entry.creditId,\n );\n const retainedMinor = source.retentionAccountingStateJson\n ? entry.retainedMinor\n : 0;\n const frozen = retainedMinor + entry.appliedMinor;\n if (\n !credit ||\n managed.has(entry.creditId) ||\n !Number.isSafeInteger(retainedMinor) ||\n retainedMinor < 0 ||\n !Number.isSafeInteger(entry.appliedMinor) ||\n entry.appliedMinor < 0 ||\n !Number.isSafeInteger(frozen) ||\n frozen > credit.totalAmount ||\n frozen !== credit.creditedAmount ||\n frozen > remainingSource\n )\n throw new MoneyValidationError(\n 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED',\n 'Provider-managed credit allocation cannot change without an explicit reversal contract',\n );\n managed.set(entry.creditId, frozen);\n remainingSource -= frozen;\n }\n }\n // Provider applications are immutable authority, not a fresh allocation choice.\n // Reserve them before assigning residual capacity; neither database order nor\n // a later same-day credit's UUID may take an already committed application.\n for (const credit of [\n ...issued,\n ...credits.filter((entry) => !issued.includes(entry)),\n ]) {\n const included = issued.includes(credit);\n const frozen = managed.get(requireId(credit.id, 'Credit invoice'));\n const applied =\n frozen ?? (included ? Math.min(credit.totalAmount, remainingSource) : 0);\n if (included && frozen === undefined) remainingSource -= applied;\n if (credit.creditedAmount !== applied) {\n credit.creditedAmount = applied;\n credit.updatePaymentStatus(credit.amountPaid);\n // A zero application is not an issuance reversal. SENT can be recorded\n // without delivery timestamps, so payment status alone cannot restore it.\n if (included && credit.status === InvoiceStatus.DRAFT)\n credit.status = InvoiceStatus.SENT;\n await credit.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n }\n if (\n (source.retentionAccountingStateJson ||\n source.ordinaryAccountingStateJson) &&\n total !== source.creditedAmount\n ) {\n const state = JSON.parse(\n source.retentionAccountingStateJson || source.ordinaryAccountingStateJson,\n );\n if (\n state.status !== 'ready' ||\n state.steps.some(\n (step: { status: string }) => step.status !== 'confirmed',\n )\n )\n throw new MoneyValidationError(\n 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED',\n 'Provider retention operation must reconcile before changing source credits',\n );\n }\n source.creditedAmount = total;\n source.updatePaymentStatus(source.amountPaid);\n await source.saveDerived(DOCUMENT_MONEY_WRITE);\n}\n\nfunction lineNet(line: InvoiceLineItem, parent: Invoice): number {\n return parent.lineAmountType === 'inclusive'\n ? line.amount - line.taxAmount\n : line.amount;\n}\n\nasync function prepareCreditLines(\n db: DatabaseInterface,\n invoice: Invoice,\n lines: InvoiceLineItem[],\n): Promise<CreditPreparation> {\n if (!invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'A credit note requires a credited invoice',\n );\n const sourceInvoice = await findInvoice(db, invoice.creditedInvoiceId);\n if (\n sourceInvoice?.kind !== 'invoice' ||\n sourceInvoice.tenantId !== invoice.tenantId ||\n sourceInvoice.status === InvoiceStatus.DRAFT ||\n sourceInvoice.status === InvoiceStatus.CANCELLED ||\n !sourceInvoice.moneySnapshotId\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must be an issued, non-cancelled invoice in the same tenant',\n );\n if (sourceInvoice.moneyAuthority === 'historical')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Historical source credits require exact original monetary facts and concrete historical source line lineage, not calculated quantity or inferred tax',\n );\n if (sourceInvoice.currency !== invoice.currency)\n throw new MoneyValidationError(\n 'CURRENCY_MISMATCH',\n 'Credit note currency must match its credited invoice',\n );\n if (sourceInvoice.customerId !== invoice.customerId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credit note customer must match its credited invoice',\n );\n invoice.lineAmountType = sourceInvoice.lineAmountType;\n invoice.taxRoundingScope = sourceInvoice.taxRoundingScope;\n const lineCollection = await InvoiceLineItemCollection.create({ db });\n const sourceLines = await lineCollection.findByInvoice(\n requireId(sourceInvoice.id, 'Credited invoice'),\n );\n const sourceTaxes = await (\n await DocumentTaxCollection.create({ db })\n ).findByDocument(\n requireId(sourceInvoice.tenantId, 'Credited invoice tenant'),\n 'invoice',\n requireId(sourceInvoice.id, 'Credited invoice'),\n );\n const sourceByLineId = new Map(\n sourceLines.map((line) => [requireId(line.id, 'Credited line'), line]),\n );\n const invoices = await InvoiceCollection.create({ db });\n const priorCredits = (\n await invoices.list({\n where: {\n tenantId: invoice.tenantId,\n creditedInvoiceId: invoice.creditedInvoiceId,\n },\n })\n ).filter((row) => row.id !== invoice.id && issuedCredit(row));\n const issuedLines: InvoiceLineItem[] = [];\n const issuedParentById = new Map(\n priorCredits.map((row) => [requireId(row.id, 'Issued credit note'), row]),\n );\n const consumptions: IssuedCreditConsumption[] = [];\n for (const credit of priorCredits) {\n for (const line of await lineCollection.findByInvoice(\n requireId(credit.id, 'Issued credit note'),\n )) {\n if (!line.creditedLineId) continue;\n issuedLines.push(line);\n const basis = line.creditCalculationBasis;\n consumptions.push({\n creditedLineId: line.creditedLineId,\n quantity: basis?.kind === 'quantity' ? basis.quantity : '0',\n netMinor: lineNet(line, credit),\n discountMinor: line.discount,\n });\n }\n }\n const targeted = lines.filter((line) => line.creditedLineId);\n const allocation = targeted.length\n ? allocateFrozenCredit(\n sourceLines.map((line) => ({\n id: requireId(line.id, 'Credited line'),\n quantity: String(line.quantity),\n netMinor: lineNet(line, sourceInvoice),\n discountMinor: line.discount,\n unitPrice: line.unitPrice,\n discountType: line.discountType,\n discountRate: line.discountRate,\n })),\n consumptions,\n targeted.map((line) => {\n const basis = line.creditCalculationBasis;\n return basis?.kind === 'net_amount'\n ? {\n creditedLineId: requireId(line.creditedLineId, 'Credited line'),\n netMinor: basis.netMinor,\n }\n : {\n creditedLineId: requireId(line.creditedLineId, 'Credited line'),\n quantity:\n basis?.kind === 'quantity'\n ? basis.quantity\n : String(line.quantity),\n };\n }),\n )\n : { allocations: [], exhaustsDocument: false };\n const allocationByLineId = new Map<string, FrozenCreditAllocation>();\n const targetBySource = new Map(\n targeted.map((line) => [\n requireId(line.creditedLineId, 'Credited line'),\n line,\n ]),\n );\n for (const row of allocation.allocations) {\n const line = targetBySource.get(row.creditedLineId);\n if (!line)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credit allocation lost its target line',\n );\n line.creditCalculationBasis = row.basis;\n allocationByLineId.set(requireId(line.id, 'Credit line'), row);\n }\n return {\n allocationByLineId,\n sourceByLineId,\n issuedLines,\n issuedParentById,\n sourceInvoice,\n sourceTaxes,\n exhaustsDocument: allocation.exhaustsDocument,\n };\n}\n\nasync function recomputeInvoiceAggregate(\n db: DatabaseInterface,\n invoice: Invoice,\n settings: TaxSettings,\n freezeSnapshotId = '',\n persist = true,\n proposedLines?: InvoiceLineItem[],\n): Promise<{ lines: InvoiceLineItem[]; taxRows: DocumentTaxWriteInput[] }> {\n assertTenantId(invoice.tenantId);\n const tenantId = invoice.tenantId;\n const linesCollection = await InvoiceLineItemCollection.create({ db });\n const codesCollection = await TaxCodeCollection.create({ db });\n const componentsCollection = await TaxComponentCollection.create({ db });\n const invoiceId = requireId(invoice.id, 'Invoice calculation');\n const lines =\n proposedLines ?? (await linesCollection.findByInvoice(invoiceId));\n const credit =\n invoice.kind === 'credit_note'\n ? await prepareCreditLines(db, invoice, lines)\n : null;\n const codes = await codesCollection.list({ where: { tenantId } });\n const components = await componentsCollection.list({ where: { tenantId } });\n const componentById = new Map(\n components.map((row) => [requireId(row.id, 'Tax component'), row]),\n );\n const codeById = new Map(\n codes.map((row) => [requireId(row.id, 'Tax code'), row]),\n );\n const codeInputs: Record<string, ResolvableTaxCodeInput> = {};\n for (const code of codes) {\n const codeId = requireId(code.id, 'Tax code');\n codeInputs[codeId] = {\n id: codeId,\n kind: code.kind,\n active: code.active,\n appliesTo: code.appliesTo,\n components: code.components.map((part) => {\n const component = componentById.get(part.taxComponentId);\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax component ${part.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: requireId(component.id, 'Tax component'),\n percent: component.percent,\n compound: part.compound,\n };\n }),\n };\n }\n if (credit) {\n for (const source of credit.sourceByLineId.values()) {\n if (!source.taxCodeId) continue;\n const frozenKind = credit.sourceTaxes.find(\n (row) => row.taxCodeId === source.taxCodeId,\n )?.kind;\n codeInputs[source.taxCodeId] = {\n id: source.taxCodeId,\n kind:\n frozenKind ??\n (source.taxComponents.length ? 'taxable' : 'zero-rated'),\n active: true,\n appliesTo: 'sales',\n components: source.taxComponents.map((component) => ({\n taxComponentId: component.taxComponentId,\n percent: component.percent,\n compound: component.compound ?? false,\n })),\n };\n }\n }\n const exempt = await codesCollection.findByCode('exempt', tenantId);\n const outOfScope = await codesCollection.findByCode('out-of-scope', tenantId);\n const customers = await CustomerCollection.create({ db });\n const customer = invoice.customerId\n ? await customers.get({ id: invoice.customerId }, { cache: false })\n : null;\n if (customer && customer.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice customer must belong to its tenant',\n );\n\n // Products owns catalog reads. Load it lazily, on the aggregate transaction,\n // so commerce keeps the same runtime-only package edge used for ledgers.\n const productIds = [\n ...new Set(\n lines\n .filter((line) => !line.creditedLineId)\n .map((line) => line.productId)\n .filter((productId): productId is string => !!productId),\n ),\n ];\n const productById = new Map<string, ProductTaxDefaults>();\n if (productIds.length > 0) {\n const { ProductCollection } = await import(\n '@happyvertical/smrt-products/collections'\n );\n const products = await ProductCollection.create({ db });\n for (const productId of productIds) {\n const product = await products.get({ id: productId }, { cache: false });\n if (!product)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice product ${productId} was not found`,\n );\n if (product.tenantId !== null && product.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice product ${productId} must be global or belong to its tenant`,\n );\n productById.set(productId, product);\n }\n }\n\n type ResolvedMetadata = {\n id: string;\n code: string | null;\n name: string | null;\n kind: 'taxable' | 'zero-rated' | 'exempt' | 'out-of-scope';\n components: InvoiceTaxComponentSnapshot[];\n };\n const resolvedCodes = new Map<string, ResolvedMetadata | null>();\n const calculated = calculateMoneyDocument({\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n roundingScope: invoice.taxRoundingScope,\n lines: lines.map((line) => {\n if (line.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice line ${line.id} must belong to its parent tenant`,\n );\n const lineId = requireId(line.id, 'Invoice line');\n if (line.creditedLineId) {\n if (!credit)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Only a credit note may reference a credited line',\n );\n const source = credit.sourceByLineId.get(line.creditedLineId);\n const allocation = credit.allocationByLineId.get(lineId);\n if (!source || !allocation)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credited line is not part of the frozen source invoice',\n );\n const taxCode = source.taxCodeId\n ? (codeInputs[source.taxCodeId] ?? null)\n : null;\n resolvedCodes.set(\n lineId,\n source.taxCodeId\n ? {\n id: source.taxCodeId,\n code: source.taxCodeCode,\n name: source.taxCodeName,\n kind: taxCode?.kind ?? 'zero-rated',\n components: structuredClone(source.taxComponents),\n }\n : null,\n );\n line.description ||= source.description;\n line.sku ||= source.sku;\n line.productId = source.productId;\n line.revenueAccountId = source.revenueAccountId;\n if (allocation.basis.kind === 'quantity') {\n line.quantity = Number(allocation.basis.quantity);\n line.unitPrice = allocation.basis.sourceUnitPrice;\n line.discountType = allocation.discountMinor ? 'amount' : 'none';\n line.discountRate = '0';\n } else {\n line.quantity = 1;\n line.unitPrice = allocation.netMinor ?? allocation.basis.netMinor;\n line.discountType = 'none';\n line.discountRate = '0';\n }\n line.discount = allocation.discountMinor;\n return {\n id: lineId,\n quantity: line.quantity,\n unitPrice: line.unitPrice,\n netAmountMinor:\n allocation.basis.kind === 'net_amount'\n ? (allocation.netMinor ?? allocation.basis.netMinor)\n : undefined,\n discount: allocation.discountMinor\n ? ({ kind: 'amount', minor: allocation.discountMinor } as const)\n : ({ kind: 'none' } as const),\n taxCode,\n };\n }\n if (invoice.kind === 'invoice' && line.creditCalculationBasis)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Ordinary invoice lines cannot carry a credit calculation basis',\n );\n if (invoice.kind === 'credit_note' && line.taxMode !== 'override')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Free-form credit lines require an explicit tax-code override',\n );\n const resolved = resolveLineTaxCode(\n {\n lineAmountType: invoice.lineAmountType,\n lineOverride: line.taxMode === 'override' ? line.taxCodeId : null,\n },\n {\n direction: 'sales',\n codes: codeInputs,\n customerTaxExempt: customer?.taxExempt ?? false,\n exemptCodeId: exempt?.id,\n productCodeId: line.productId\n ? productById.get(line.productId)?.defaultSalesTaxCodeId || null\n : null,\n partyCodeId: customer?.defaultTaxCodeId,\n appDefaultCodeId: settings.defaultSalesTaxCodeId,\n outOfScopeCodeId: outOfScope?.id,\n },\n );\n resolvedCodes.set(\n lineId,\n resolved.taxCode\n ? (() => {\n const code = codeById.get(resolved.taxCode.id);\n if (!code)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax code ${resolved.taxCode.id} was not loaded`,\n );\n return {\n id: requireId(code.id, 'Tax code'),\n code: code.code,\n name: code.name,\n kind: code.kind,\n components: code.components.map((part) => {\n const component = componentById.get(part.taxComponentId);\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax component ${part.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: part.taxComponentId,\n name: component.name,\n percent: component.percent,\n ...(part.compound ? { compound: true } : {}),\n taxMinor: 0,\n };\n }),\n };\n })()\n : null,\n );\n return {\n id: requireId(line.id, 'Invoice line'),\n quantity: line.quantity,\n unitPrice: line.unitPrice,\n discount: discountInput(line),\n taxCode: resolved.taxCode,\n };\n }),\n });\n\n // When every original line is exhausted, consume the exact remaining frozen\n // component and taxable residual. This preserves document-rounding cents\n // without consulting today's rates; free-form goodwill lines remain separate.\n if (credit?.exhaustsDocument) {\n const resultById = new Map(calculated.lines.map((row) => [row.id, row]));\n const targeted = lines.filter((line) => !!line.creditedLineId);\n for (const line of targeted) {\n const source = credit.sourceByLineId.get(\n requireId(line.creditedLineId, 'Credited line'),\n );\n const result = resultById.get(requireId(line.id, 'Credit line'));\n if (!source || !result) continue;\n const prior = credit.issuedLines.filter(\n (candidate) => candidate.creditedLineId === source.id,\n );\n const priorNet = prior.reduce((sum, candidate) => {\n const parent = credit.issuedParentById.get(candidate.invoiceId);\n return sum + (parent ? lineNet(candidate, parent) : 0);\n }, 0);\n const desiredNet = lineNet(source, credit.sourceInvoice) - priorNet;\n const netDelta = desiredNet - result.netMinor;\n result.netMinor = desiredNet;\n result.amountMinor += netDelta;\n for (const sourceComponent of source.taxComponents) {\n const component = result.components.find(\n (candidate) =>\n candidate.taxComponentId === sourceComponent.taxComponentId,\n );\n if (!component) continue;\n const priorTax = prior.reduce(\n (sum, candidate) =>\n sum +\n (candidate.taxComponents.find(\n (part) => part.taxComponentId === sourceComponent.taxComponentId,\n )?.taxMinor ?? 0),\n 0,\n );\n const desiredTax = sourceComponent.taxMinor - priorTax;\n const taxDelta = desiredTax - component.taxMinor;\n component.taxMinor = desiredTax;\n if (sourceComponent.compound) {\n component.compound = true;\n component.taxableMinor =\n (sourceComponent.taxableMinor ?? 0) -\n prior.reduce(\n (sum, candidate) =>\n sum +\n (candidate.taxComponents.find(\n (part) =>\n part.taxComponentId === sourceComponent.taxComponentId,\n )?.taxableMinor ?? 0),\n 0,\n );\n }\n result.taxMinor += taxDelta;\n if (invoice.lineAmountType === 'inclusive')\n result.amountMinor += taxDelta;\n }\n }\n const rebuilt = new Map<\n string,\n {\n taxCodeId: string | null;\n taxComponentId: string | null;\n taxableMinor: number;\n netMinor?: number;\n taxMinor: number;\n }\n >();\n for (const result of calculated.lines) {\n const metadata = resolvedCodes.get(result.id) ?? null;\n const parts = result.components.length\n ? result.components\n : [\n {\n taxComponentId: null,\n taxMinor: 0,\n compound: false,\n taxableMinor: undefined,\n },\n ];\n for (const part of parts) {\n const key = `${metadata?.id ?? ''}\\u0000${part.taxComponentId ?? ''}`;\n const row = rebuilt.get(key) ?? {\n taxCodeId: metadata?.id ?? null,\n taxComponentId: part.taxComponentId,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor += part.taxableMinor ?? result.netMinor;\n if (part.compound) row.netMinor = (row.netMinor ?? 0) + result.netMinor;\n row.taxMinor += part.taxMinor;\n rebuilt.set(key, row);\n }\n }\n calculated.taxes = [...rebuilt.values()].sort((left, right) => {\n const a = `${left.taxCodeId ?? ''}\\u0000${left.taxComponentId ?? ''}`;\n const b = `${right.taxCodeId ?? ''}\\u0000${right.taxComponentId ?? ''}`;\n return a < b ? -1 : a > b ? 1 : 0;\n });\n calculated.subtotalMinor = calculated.lines.reduce(\n (sum, row) => sum + row.netMinor,\n 0,\n );\n calculated.taxMinor = calculated.lines.reduce(\n (sum, row) => sum + row.taxMinor,\n 0,\n );\n calculated.totalMinor = calculated.subtotalMinor + calculated.taxMinor;\n }\n\n if (credit) {\n const resultById = new Map(calculated.lines.map((row) => [row.id, row]));\n for (const [lineId, allocation] of credit.allocationByLineId) {\n if (allocation.basis.kind !== 'quantity') continue;\n const result = resultById.get(lineId);\n const hasAmountBasisConsumption = credit.issuedLines.some(\n (line) =>\n line.creditedLineId === allocation.creditedLineId &&\n line.creditCalculationBasis?.kind === 'net_amount',\n );\n if (\n result &&\n Math.abs(result.netMinor) > Math.abs(allocation.remainingNetMinor) &&\n (!allocation.exhaustsLine || hasAmountBasisConsumption)\n )\n throw new MoneyValidationError(\n 'CREDIT_EXCEEDS_LINE',\n 'Credit quantity exceeds the remaining frozen net amount',\n );\n }\n }\n\n const lineById = new Map(\n lines.map((line) => [requireId(line.id, 'Invoice line'), line]),\n );\n for (const result of calculated.lines) {\n const line = lineById.get(result.id);\n if (!line)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Calculated line ${result.id} was not loaded`,\n );\n const code = resolvedCodes.get(requireId(line.id, 'Invoice line')) ?? null;\n line.discount = result.discountMinor;\n line.amount = result.amountMinor;\n line.taxAmount = result.taxMinor;\n line.taxCodeId = code?.id ?? null;\n line.taxCodeCode = code?.code ?? null;\n line.taxCodeName = code?.name ?? null;\n line.taxComponents = result.components.map((entry) => {\n const component = code?.components.find(\n (candidate) => candidate.taxComponentId === entry.taxComponentId,\n );\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Calculated component ${entry.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: component.taxComponentId,\n name: component.name,\n percent: component.percent,\n taxMinor: entry.taxMinor,\n ...(entry.compound\n ? { compound: true, taxableMinor: entry.taxableMinor }\n : {}),\n };\n });\n line.taxRate = result.components.some((part) => part.compound)\n ? result.netMinor === 0\n ? 0\n : result.taxMinor / result.netMinor\n : code\n ? code.components.reduce(\n (sum, part) => sum + Number(part.percent) / 100,\n 0,\n )\n : 0;\n if (freezeSnapshotId) line.moneySnapshotId = freezeSnapshotId;\n if (persist) await line.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n\n const taxRows = calculated.taxes.map((tax): DocumentTaxWriteInput => {\n const code = tax.taxCodeId\n ? ([...resolvedCodes.values()].find(\n (candidate) => candidate?.id === tax.taxCodeId,\n ) ?? null)\n : null;\n const snapshotComponent = tax.taxComponentId\n ? code?.components.find(\n (candidate) => candidate.taxComponentId === tax.taxComponentId,\n )\n : null;\n const currentComponent = tax.taxComponentId\n ? componentById.get(tax.taxComponentId)\n : null;\n const sourceTax = credit?.sourceTaxes.find(\n (row) =>\n row.taxCodeId === tax.taxCodeId &&\n row.taxComponentId === tax.taxComponentId,\n );\n if (tax.taxCodeId && !code)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Document tax code ${tax.taxCodeId} was not loaded`,\n );\n if (tax.taxComponentId && !snapshotComponent)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Document tax component ${tax.taxComponentId} was not loaded`,\n );\n return {\n tenantId,\n documentType: invoice.kind,\n documentId: invoiceId,\n currency: invoice.currency,\n taxCodeId: code ? requireId(code.id, 'Tax code') : null,\n taxCodeCode: code?.code ?? null,\n kind: code?.kind ?? null,\n taxComponentId: snapshotComponent?.taxComponentId ?? null,\n taxComponentName: snapshotComponent?.name ?? null,\n percent: snapshotComponent?.percent ?? null,\n liabilityAccountId:\n sourceTax?.liabilityAccountId ||\n currentComponent?.liabilityAccountId ||\n null,\n taxableMinor: tax.taxableMinor,\n netMinor: tax.netMinor ?? null,\n taxMinor: tax.taxMinor,\n recoverableMinor: 0,\n };\n });\n if (persist) {\n const documentTaxes = await DocumentTaxCollection.create({ db });\n await documentTaxes.replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {\n tenantId,\n documentType: invoice.kind,\n documentId: invoiceId,\n rows: taxRows,\n });\n }\n invoice.subtotal = calculated.subtotalMinor;\n invoice.discountTotal = calculated.discountTotalMinor;\n invoice.taxAmount = calculated.taxMinor + invoice.providerTaxAmount;\n invoice.totalAmount = calculated.totalMinor + invoice.providerTaxAmount;\n return { lines, taxRows };\n}\n\nasync function previewInvoiceMoneyOnScope(\n input: PreviewInvoiceMoneyInput,\n settings: TaxSettings,\n): Promise<PreviewInvoiceMoneyResult> {\n if (!input.tenantId || getTenantId() !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview requires its active principal tenant',\n );\n const { invoice } = await loadInvoice(input.db, input.invoiceId);\n if (invoice.tenantId !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview cannot cross tenant boundaries',\n );\n if (invoice.status !== InvoiceStatus.DRAFT || invoice.moneySnapshotId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Frozen invoice money cannot be previewed as a proposed draft',\n );\n const proposedHeader = input.draft?.header;\n if (proposedHeader)\n for (const field of [\n 'currency',\n 'lineAmountType',\n 'taxRoundingScope',\n 'providerTaxAmount',\n 'customerId',\n ] as const)\n if (proposedHeader[field] !== undefined)\n invoice[field] = proposedHeader[field] as never;\n const storedLines = await (\n await InvoiceLineItemCollection.create({ db: input.db })\n ).findByInvoice(input.invoiceId);\n const storedById = new Map(storedLines.map((line) => [line.id, line]));\n const providedIds =\n input.draft?.lines\n ?.map((line) => line.id)\n .filter((id): id is string => !!id) ?? [];\n if (new Set(providedIds).size !== providedIds.length)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview line ids must be distinct',\n );\n const unknownId = providedIds.find((id) => !storedById.has(id));\n if (unknownId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice preview line ${unknownId} was not found on the invoice`,\n );\n const proposedLines = input.draft?.lines\n ? input.draft.lines.map((proposed) => {\n const line = proposed.id ? storedById.get(proposed.id) : undefined;\n const result = line ?? new InvoiceLineItem();\n for (const field of [\n 'description',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discountType',\n 'discountRate',\n 'discount',\n 'taxMode',\n 'taxCodeId',\n ] as const)\n if (proposed[field] !== undefined)\n result[field] = proposed[field] as never;\n result.id ||= crypto.randomUUID();\n result.invoiceId = input.invoiceId;\n result.tenantId = input.tenantId;\n return result;\n })\n : storedLines;\n const calculated = await recomputeInvoiceAggregate(\n input.db,\n invoice,\n settings,\n '',\n false,\n proposedLines,\n );\n return {\n source: 'calculated',\n header: {\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n taxRoundingScope: invoice.taxRoundingScope,\n subtotalMinor: invoice.subtotal,\n discountTotalMinor: invoice.discountTotal,\n taxAmountMinor: invoice.taxAmount,\n providerTaxAmountMinor: invoice.providerTaxAmount,\n totalAmountMinor: invoice.totalAmount,\n },\n lines: calculated.lines.map((line) => ({\n id: requireId(line.id, 'Preview line'),\n grossMinor: line.amount + line.discount,\n discountMinor: line.discount,\n amountMinor: line.amount,\n taxMinor: line.taxAmount,\n taxCodeId: line.taxCodeId,\n taxCodeCode: line.taxCodeCode,\n taxCodeName: line.taxCodeName,\n taxComponents: structuredClone(line.taxComponents),\n })),\n taxes: calculated.taxRows,\n };\n}\n\n/** Calculate a proposed draft invoice in memory through the owning resolver. */\nexport async function previewInvoiceMoney(\n input: PreviewInvoiceMoneyInput,\n): Promise<PreviewInvoiceMoneyResult> {\n return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) =>\n previewInvoiceMoneyOnScope({ ...input, db: scope.db }, scope.settings),\n );\n}\n\nasync function getInvoiceMoneyFactsOnScope(\n input: GetInvoiceMoneyFactsInput,\n): Promise<InvoiceMoneyFacts> {\n if (!input.tenantId || getTenantId() !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money facts require their active principal tenant',\n );\n const { invoice } = await loadInvoice(input.db, input.invoiceId);\n if (invoice.tenantId !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money facts cannot cross tenant boundaries',\n );\n const lines = await (\n await InvoiceLineItemCollection.create({ db: input.db })\n ).findByInvoice(input.invoiceId);\n const taxes = await (\n await DocumentTaxCollection.create({ db: input.db })\n ).findByDocument(input.tenantId, invoice.kind, input.invoiceId);\n const historical = getHistoricalSalesMoney(invoice);\n return {\n source: 'stored',\n ...(historical\n ? {\n historical: {\n snapshot: historical,\n lines: (await readHistoricalSalesLines(input.db, invoice)).map(\n (line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n }),\n ),\n },\n }\n : {}),\n ...(invoice.retentionStateJson\n ? { payable: invoice.getPayableFacts() }\n : {}),\n invoiceId: input.invoiceId,\n moneySnapshotId: invoice.moneySnapshotId,\n kind: invoice.kind,\n status: invoice.status,\n header: {\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n taxRoundingScope: invoice.taxRoundingScope,\n subtotalMinor: invoice.subtotal,\n discountTotalMinor: invoice.discountTotal,\n taxAmountMinor: invoice.taxAmount,\n providerTaxAmountMinor: invoice.providerTaxAmount,\n totalAmountMinor: invoice.totalAmount,\n },\n lines: lines.map((line) => ({\n id: requireId(line.id, 'Invoice line'),\n grossMinor: line.amount + line.discount,\n discountMinor: line.discount,\n amountMinor: line.amount,\n taxMinor: line.taxAmount,\n taxCodeId: line.taxCodeId,\n taxCodeCode: line.taxCodeCode,\n taxCodeName: line.taxCodeName,\n taxComponents: structuredClone(line.taxComponents),\n })),\n taxes: taxes.map((row) => ({\n tenantId: requireId(row.tenantId, 'Document tax tenant'),\n documentType: row.documentType,\n documentId: row.documentId,\n currency: row.currency,\n taxCodeId: row.taxCodeId,\n taxCodeCode: row.taxCodeCode,\n kind: row.kind,\n taxComponentId: row.taxComponentId,\n taxComponentName: row.taxComponentName,\n percent: row.percent,\n liabilityAccountId: row.liabilityAccountId,\n taxableMinor: row.taxableMinor,\n ...(row.netMinor !== null ? { netMinor: row.netMinor } : {}),\n taxMinor: row.taxMinor,\n recoverableMinor: row.recoverableMinor,\n })),\n };\n}\n\n/** Read authoritative persisted money facts without resolution or recalculation. */\nexport async function getInvoiceMoneyFacts(\n input: GetInvoiceMoneyFactsInput,\n): Promise<InvoiceMoneyFacts> {\n return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) =>\n getInvoiceMoneyFactsOnScope({ ...input, db: scope.db }),\n );\n}\n\n/** Persist an invoice and recompute its complete money aggregate. */\nexport async function saveInvoice(input: Invoice): Promise<Invoice> {\n const priorRevision = input.updated_at;\n try {\n return await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (invoice) => {\n if (invoice.kind !== 'invoice' && invoice.kind !== 'credit_note')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice kind must be invoice or credit_note',\n );\n if (invoice.kind === 'invoice' && invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Only a credit note may reference a credited invoice',\n );\n if (invoice.kind === 'credit_note' && !invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'A credit note requires a credited invoice',\n );\n const candidateTenantId = getTenantId() ?? invoice.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const existing = invoice.id ? await findInvoice(tx, invoice.id) : null;\n const tenantId = existing?.tenantId ?? candidateTenantId;\n if (\n invoice.retentionAccountingStateJson !==\n (existing?.retentionAccountingStateJson ?? '') ||\n invoice.ordinaryAccountingStateJson !==\n (existing?.ordinaryAccountingStateJson ?? '')\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Retention accounting state is managed by provider commands',\n );\n if (\n invoice.moneyAuthority !==\n (existing?.moneyAuthority ?? 'calculated') ||\n invoice.historicalSalesMoneyJson !==\n (existing?.historicalSalesMoneyJson ?? '') ||\n invoice.historicalSourceKeyHash !==\n (existing?.historicalSourceKeyHash ?? null)\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Historical source authority is managed only by historical sales commands',\n );\n if (existing?.moneyAuthority === 'historical')\n getHistoricalSalesMoney(existing);\n\n if (invoice.retentionStateJson !== (existing?.retentionStateJson ?? ''))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Retention state is managed by retention commands',\n );\n if (\n candidateTenantId &&\n existing?.tenantId &&\n existing.tenantId !== candidateTenantId\n )\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant does not match its active money barrier',\n );\n assertTenantId(tenantId);\n if (!existing) {\n invoice.tenantId = tenantId;\n invoice.creditedAmount = 0;\n let source: Invoice | null = null;\n if (invoice.kind === 'credit_note') {\n source = await findInvoice(\n tx,\n requireId(invoice.creditedInvoiceId, 'Credited invoice'),\n );\n if (!source || source.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must exist in the active tenant',\n );\n await lockDocumentMoneyParents([\n {\n id: requireId(source.id, 'Credited invoice'),\n tenantId,\n collection: await InvoiceCollection.create({ db: tx }),\n },\n ]);\n if (\n source.kind !== 'invoice' ||\n source.status === InvoiceStatus.DRAFT ||\n source.status === InvoiceStatus.CANCELLED ||\n !source.moneySnapshotId\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must be an issued, non-cancelled invoice',\n );\n if (\n invoice.currency !== source.currency ||\n invoice.customerId !== source.customerId\n )\n throw new MoneyValidationError(\n invoice.currency !== source.currency\n ? 'CURRENCY_MISMATCH'\n : 'INVALID_MONEY_INPUT',\n 'Credit note currency and customer must match its source invoice',\n );\n }\n invoice.lineAmountType =\n invoice.kind === 'credit_note' && source\n ? source.lineAmountType\n : settings.defaultLineAmountType;\n invoice.taxRoundingScope =\n invoice.kind === 'credit_note' && source\n ? source.taxRoundingScope\n : settings.taxRoundingScope;\n invoice.subtotal = 0;\n invoice.discountTotal = 0;\n invoice.taxAmount = invoice.providerTaxAmount;\n invoice.totalAmount = invoice.providerTaxAmount;\n if (invoice.status !== InvoiceStatus.DRAFT || invoice.arJournalId) {\n await assertContractScheduleInvoiceFreeze(tx, invoice);\n const customers = await CustomerCollection.create({ db: tx });\n const customer = invoice.customerId\n ? await customers.get(\n { id: invoice.customerId },\n { cache: false },\n )\n : null;\n invoice.moneySnapshotId = crypto.randomUUID();\n invoice.sellerTaxRegistrations = structuredClone(\n settings.taxRegistrations,\n );\n invoice.partyTaxId = customer?.taxId ?? '';\n }\n return invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n if (invoice.tenantId !== existing.tenantId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice tenant identity cannot change',\n );\n if (\n invoice.kind !== existing.kind ||\n invoice.creditedInvoiceId !== existing.creditedInvoiceId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice kind and credited invoice identity are immutable',\n );\n const existingId = requireId(existing.id, 'Invoice');\n const locked = await lockAndReloadMoneyInvoice(\n tx,\n existingId,\n tenantId,\n existing.creditedInvoiceId,\n );\n invoice.creditedAmount = locked.invoice.creditedAmount;\n if (isFrozen(locked.invoice)) {\n if (\n invoice.arReversalJournalId !== locked.invoice.arReversalJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice reversal journal identity is server-managed',\n );\n if (\n locked.invoice.arJournalId &&\n invoice.arJournalId !== locked.invoice.arJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice revenue journal identity is frozen once assigned',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.kind === 'invoice' &&\n locked.invoice.isPaid()\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A paid invoice cannot be cancelled',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.kind === 'credit_note' &&\n locked.invoice.amountPaid > 0\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A refunded credit note cannot be cancelled',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.arJournalId &&\n !locked.invoice.arReversalJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A posted invoice requires an atomic reversal before cancellation',\n );\n assertFieldsUnchanged(\n invoice,\n locked.invoice,\n FROZEN_INVOICE_FIELDS,\n 'Invoice',\n );\n const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (locked.source)\n await refreshIssuedCreditBalance(tx, locked.source);\n return saved;\n }\n const freezing =\n invoice.status !== InvoiceStatus.DRAFT || !!invoice.arJournalId;\n const snapshotId = freezing\n ? locked.invoice.moneySnapshotId || crypto.randomUUID()\n : '';\n await recomputeInvoiceAggregate(tx, invoice, settings, snapshotId);\n if (freezing) {\n await assertContractScheduleInvoiceFreeze(tx, invoice);\n const customers = await CustomerCollection.create({ db: tx });\n const customer = invoice.customerId\n ? await customers.get({ id: invoice.customerId }, { cache: false })\n : null;\n invoice.sellerTaxRegistrations = structuredClone(\n settings.taxRegistrations,\n );\n invoice.partyTaxId = customer?.taxId ?? '';\n invoice.moneySnapshotId = snapshotId;\n }\n const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (locked.source) await refreshIssuedCreditBalance(tx, locked.source);\n return saved;\n }),\n );\n } catch (error) {\n input.updated_at = priorRevision;\n throw error;\n }\n}\n\n/** Persist a line and recompute its complete invoice aggregate. */\nexport async function saveInvoiceLineItem(\n input: InvoiceLineItem,\n): Promise<InvoiceLineItem> {\n return withDocumentMoneyObjectTransaction(input, async (line, tx) => {\n const candidateTenantId = getTenantId() ?? line.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = line.id\n ? await (await InvoiceLineItemCollection.create({ db: tx })).get(\n { id: line.id },\n { cache: false },\n )\n : null;\n const parentId = persisted?.invoiceId ?? line.invoiceId;\n const first = await loadInvoice(tx, parentId);\n if (candidateTenantId && first.invoice.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice line tenant does not match its active money barrier',\n );\n assertTenantId(first.invoice.tenantId);\n const { invoice, source } = await lockAndReloadMoneyInvoice(\n tx,\n parentId,\n first.invoice.tenantId,\n first.invoice.creditedInvoiceId,\n );\n if (persisted && line.invoiceId !== persisted.invoiceId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice line cannot move between parents',\n );\n line.invoiceId = requireId(invoice.id, 'Invoice');\n line.tenantId = invoice.tenantId;\n if (invoice.kind === 'invoice' && line.creditedLineId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Ordinary invoice lines cannot reference credited lines',\n );\n if (\n invoice.kind === 'credit_note' &&\n line.creditedLineId &&\n (!source || source.id !== invoice.creditedInvoiceId)\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit source changed while saving its line',\n );\n if (isFrozen(invoice)) {\n if (!persisted)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot add a line to a frozen invoice',\n );\n assertFieldsUnchanged(\n line,\n persisted,\n FROZEN_LINE_FIELDS,\n 'Invoice line',\n );\n return line.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n await line.saveDerived(DOCUMENT_MONEY_WRITE);\n const priorAggregate = aggregateSignature(invoice);\n await recomputeInvoiceAggregate(tx, invoice, settings);\n if (aggregateSignature(invoice) !== priorAggregate) {\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n const refreshed = await (\n await InvoiceLineItemCollection.create({ db: tx })\n ).get({ id: requireId(line.id, 'Invoice line') }, { cache: false });\n if (refreshed) {\n for (const field of [\n 'discount',\n 'amount',\n 'taxAmount',\n 'taxRate',\n 'taxCodeId',\n 'taxCodeCode',\n 'taxCodeName',\n 'taxComponentsJson',\n 'moneySnapshotId',\n 'updated_at',\n ] as const) {\n line[field] = refreshed[field] as never;\n }\n }\n return line;\n });\n}\n\nexport async function deleteInvoiceLineItem(\n input: InvoiceLineItem,\n options: DeleteOptions,\n): Promise<void> {\n await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (line) => {\n const candidateTenantId = getTenantId() ?? line.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = line.id\n ? await (await InvoiceLineItemCollection.create({ db: tx })).get(\n { id: line.id },\n { cache: false },\n )\n : null;\n if (!persisted) return;\n const first = await loadInvoice(tx, persisted.invoiceId);\n if (candidateTenantId && first.invoice.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice line tenant does not match its active money barrier',\n );\n assertTenantId(first.invoice.tenantId);\n const { invoice } = await lockAndReloadInvoice(\n tx,\n persisted.invoiceId,\n first.invoice.tenantId,\n );\n if (isFrozen(invoice))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot delete a line from a frozen invoice',\n );\n await line.deleteDerived(DOCUMENT_MONEY_WRITE, options);\n const priorAggregate = aggregateSignature(invoice);\n await recomputeInvoiceAggregate(tx, invoice, settings);\n if (aggregateSignature(invoice) !== priorAggregate) {\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n }),\n );\n}\n\nexport async function deleteInvoice(\n input: Invoice,\n options: DeleteOptions,\n): Promise<void> {\n await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (invoice) => {\n const candidateTenantId = getTenantId() ?? invoice.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = invoice.id ? await findInvoice(tx, invoice.id) : null;\n if (!persisted) return;\n if (candidateTenantId && persisted.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant does not match its active money barrier',\n );\n if (isFrozen(persisted))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot delete a frozen invoice',\n );\n assertTenantId(persisted.tenantId);\n const persistedId = requireId(persisted.id, 'Invoice');\n await lockAndReloadInvoice(tx, persistedId, persisted.tenantId);\n const documentTaxes = await DocumentTaxCollection.create({ db: tx });\n await documentTaxes.replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {\n tenantId: persisted.tenantId,\n documentType: 'invoice',\n documentId: persistedId,\n rows: [],\n });\n await invoice.deleteDerived(DOCUMENT_MONEY_WRITE, options);\n }),\n );\n}\n","import { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport type {\n HistoricalSalesMoneyFacts,\n HistoricalSalesRetention,\n HistoricalSalesSource,\n} from './historical-sales-types.js';\nimport { MoneyValidationError } from './money.js';\n\nfunction invalid(): never {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Historical sales require exact supported source facts and explicit unknown values',\n );\n}\nexport function historicalText(value: unknown, max = 2000): string {\n if (\n typeof value !== 'string' ||\n !value.trim() ||\n value.trim() !== value ||\n value.length > max\n )\n invalid();\n return value;\n}\nexport function historicalCalendarDate(value: unknown): string {\n const date = historicalText(value);\n if (\n !/^\\d{4}-\\d{2}-\\d{2}$/.test(date) ||\n !Number.isFinite(Date.parse(date)) ||\n new Date(date).toISOString().slice(0, 10) !== date\n )\n invalid();\n return date;\n}\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) invalid();\n return value as Record<string, unknown>;\n}\nfunction fields(input: unknown, allowed: readonly string[]) {\n const value = record(input);\n if (Object.keys(value).some((key) => !allowed.includes(key))) invalid();\n return value;\n}\nfunction integer(value: unknown): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value)) invalid();\n return value;\n}\nfunction nullableInteger(value: unknown): number | null {\n return value === null ? null : integer(value);\n}\nfunction nullableText(value: unknown): string | null {\n return value === null ? null : historicalText(value);\n}\nfunction sum(values: number[]): number {\n const result = values.reduce((total, value) => total + BigInt(value), 0n);\n if (\n result > BigInt(Number.MAX_SAFE_INTEGER) ||\n result < BigInt(Number.MIN_SAFE_INTEGER)\n )\n invalid();\n return Number(result);\n}\nfunction sameAmount(net: number, tax: number, gross: number) {\n if (sum([net, tax]) !== gross) invalid();\n}\nexport function historicalSalesMagnitudes(facts: HistoricalSalesMoneyFacts) {\n const sign =\n facts.kind === 'credit_note' && facts.polarity === 'signed' ? -1 : 1;\n const result = {\n netMinor: facts.netMinor * sign,\n taxMinor: facts.taxMinor * sign,\n grossMinor: facts.grossMinor * sign,\n };\n if (Object.values(result).some((value) => value < 0)) invalid();\n return result;\n}\nexport function validateHistoricalSalesSource(\n input: HistoricalSalesSource,\n): HistoricalSalesSource {\n const value = fields(input, [\n 'namespace',\n 'key',\n 'version',\n 'issuedOn',\n 'dueOn',\n 'timeZone',\n 'approval',\n 'retention',\n ]);\n const retention =\n value.retention == null\n ? value.retention\n : (() => {\n const r = fields(value.retention, [\n 'retainedMinor',\n 'creditPolicy',\n 'policyRef',\n 'effectiveOn',\n 'evidenceRef',\n 'originalActorRef',\n 'releases',\n ]);\n if (\n r.creditPolicy !== 'retained-first' ||\n !Array.isArray(r.releases) ||\n r.releases.length > 10000\n )\n invalid();\n const retainedMinor = integer(r.retainedMinor);\n if (retainedMinor <= 0) invalid();\n const effectiveOn = historicalCalendarDate(r.effectiveOn);\n const keys = new Set<string>();\n const releases = r.releases.map(\n (input): HistoricalSalesRetention['releases'][number] => {\n const event = fields(input, [\n 'sourceKey',\n 'amountMinor',\n 'effectiveOn',\n 'evidenceRef',\n 'originalActorRef',\n 'sameDayCreditOrder',\n ]);\n const sourceKey = historicalText(event.sourceKey),\n amountMinor = integer(event.amountMinor),\n on = historicalCalendarDate(event.effectiveOn);\n if (keys.has(sourceKey) || amountMinor <= 0 || on < effectiveOn)\n invalid();\n keys.add(sourceKey);\n return {\n ...(event.sameDayCreditOrder === undefined\n ? {}\n : {\n sameDayCreditOrder:\n event.sameDayCreditOrder === null ||\n event.sameDayCreditOrder === 'credit-before-release' ||\n event.sameDayCreditOrder === 'release-before-credit'\n ? event.sameDayCreditOrder\n : invalid(),\n }),\n sourceKey,\n amountMinor,\n effectiveOn: on,\n evidenceRef: historicalText(event.evidenceRef),\n originalActorRef: nullableText(event.originalActorRef),\n };\n },\n );\n if (sum(releases.map((event) => event.amountMinor)) > retainedMinor)\n invalid();\n return {\n retainedMinor,\n creditPolicy: 'retained-first' as const,\n policyRef: historicalText(r.policyRef),\n effectiveOn,\n evidenceRef: historicalText(r.evidenceRef),\n originalActorRef: nullableText(r.originalActorRef),\n releases,\n };\n })();\n if (\n retention &&\n retention.effectiveOn !== historicalCalendarDate(value.issuedOn)\n )\n invalid();\n const timeZone = historicalText(value.timeZone);\n try {\n new Intl.DateTimeFormat('en', { timeZone }).format(0);\n } catch {\n invalid();\n }\n const approval =\n value.approval === null\n ? null\n : fields(value.approval, ['actorRef', 'approvedOn']);\n return {\n ...(retention === undefined ? {} : { retention }),\n namespace: historicalText(value.namespace),\n key: historicalText(value.key),\n version: historicalText(value.version),\n issuedOn: historicalCalendarDate(value.issuedOn),\n dueOn: value.dueOn === null ? null : historicalCalendarDate(value.dueOn),\n timeZone,\n approval:\n approval === null\n ? null\n : {\n actorRef: historicalText(approval.actorRef),\n approvedOn:\n approval.approvedOn === null\n ? null\n : historicalCalendarDate(approval.approvedOn),\n },\n };\n}\n/** Validate original facts without a tax calculator, source normalization, or implicit polarity. */\nexport function validateHistoricalSalesMoneyFacts(\n input: HistoricalSalesMoneyFacts,\n): HistoricalSalesMoneyFacts {\n const value = fields(input, [\n 'currency',\n 'kind',\n 'polarity',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'taxComponents',\n 'detail',\n ]);\n const currency = historicalText(value.currency);\n if (\n !ISO_4217_MINOR_UNITS.has(currency) ||\n ISO_4217_MINOR_UNITS.get(currency) === null ||\n !['invoice', 'credit_note'].includes(value.kind as string) ||\n !['signed', 'magnitudes'].includes(value.polarity as string)\n )\n invalid();\n const netMinor = integer(value.netMinor),\n taxMinor = integer(value.taxMinor),\n grossMinor = integer(value.grossMinor);\n sameAmount(netMinor, taxMinor, grossMinor);\n const seenComponents = new Set<string>();\n const taxComponents =\n value.taxComponents === null\n ? null\n : (() => {\n if (\n !Array.isArray(value.taxComponents) ||\n value.taxComponents.length > 1000\n )\n invalid();\n return value.taxComponents.map((inputComponent) => {\n const component = fields(inputComponent, [\n 'sourceKey',\n 'label',\n 'amountMinor',\n 'classification',\n 'taxCodeId',\n 'taxComponentId',\n 'taxableMinor',\n 'netMinor',\n 'liabilityAccountId',\n ]),\n sourceKey = historicalText(component.sourceKey);\n if (seenComponents.has(sourceKey)) invalid();\n seenComponents.add(sourceKey);\n if (\n component.classification !== null &&\n !['taxable', 'zero-rated', 'exempt', 'out-of-scope'].includes(\n component.classification as string,\n )\n )\n invalid();\n const classification = component.classification as\n | 'taxable'\n | 'zero-rated'\n | 'exempt'\n | 'out-of-scope'\n | null;\n const amountMinor = integer(component.amountMinor),\n taxableMinor = nullableInteger(component.taxableMinor);\n if (\n classification !== null &&\n classification !== 'taxable' &&\n amountMinor !== 0\n )\n invalid();\n return {\n sourceKey,\n label: historicalText(component.label),\n amountMinor,\n classification,\n taxCodeId: nullableText(component.taxCodeId),\n taxComponentId: nullableText(component.taxComponentId),\n taxableMinor,\n netMinor: nullableInteger(component.netMinor),\n liabilityAccountId: nullableText(component.liabilityAccountId),\n };\n });\n })();\n if (\n taxComponents !== null &&\n sum(taxComponents.map((component) => component.amountMinor)) !== taxMinor\n )\n invalid();\n const detailInput = fields(\n value.detail,\n record(value.detail).kind === 'header-only' ? ['kind'] : ['kind', 'lines'],\n );\n let detail: HistoricalSalesMoneyFacts['detail'];\n if (detailInput.kind === 'header-only') detail = { kind: 'header-only' };\n else if (detailInput.kind === 'lines') {\n if (\n !Array.isArray(detailInput.lines) ||\n !detailInput.lines.length ||\n detailInput.lines.length > 100000\n )\n invalid();\n const seen = new Set<string>();\n const lines = detailInput.lines.map((inputLine) => {\n const line = fields(inputLine, [\n 'sourceKey',\n 'creditedLineId',\n 'description',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'quantityText',\n 'unitRateText',\n 'sourceFields',\n ]),\n sourceKey = historicalText(line.sourceKey);\n if (seen.has(sourceKey)) invalid();\n seen.add(sourceKey);\n const sourceFields = record(line.sourceFields);\n if (\n Object.keys(sourceFields).length > 100 ||\n Object.entries(sourceFields).some(\n ([key, cell]) =>\n key.length > 200 || typeof cell !== 'string' || cell.length > 10000,\n )\n )\n invalid();\n const netMinor = integer(line.netMinor),\n taxMinor = nullableInteger(line.taxMinor),\n grossMinor = nullableInteger(line.grossMinor);\n if (taxMinor !== null && grossMinor !== null)\n sameAmount(netMinor, taxMinor, grossMinor);\n if (\n typeof line.description !== 'string' ||\n line.description.length > 10000\n )\n invalid();\n return {\n sourceKey,\n description: line.description,\n creditedLineId: nullableText(line.creditedLineId),\n netMinor,\n taxMinor,\n grossMinor,\n quantityText: nullableText(line.quantityText),\n unitRateText: nullableText(line.unitRateText),\n sourceFields: Object.fromEntries(\n Object.entries(sourceFields),\n ) as Record<string, string>,\n };\n });\n if (\n sum(lines.map((line) => line.netMinor)) !== netMinor ||\n (lines.every((line) => line.taxMinor !== null) &&\n sum(lines.map((line) => line.taxMinor as number)) !== taxMinor) ||\n (lines.every((line) => line.grossMinor !== null) &&\n sum(lines.map((line) => line.grossMinor as number)) !== grossMinor)\n )\n invalid();\n detail = { kind: 'lines', lines };\n } else invalid();\n const result: HistoricalSalesMoneyFacts = {\n currency,\n kind: value.kind as HistoricalSalesMoneyFacts['kind'],\n polarity: value.polarity as HistoricalSalesMoneyFacts['polarity'],\n netMinor,\n taxMinor,\n grossMinor,\n taxComponents,\n detail,\n };\n historicalSalesMagnitudes(result);\n return result;\n}\n","/** Exact original issued sales authority. Host review is distinct from original issue/approval. */\nimport { createHash } from 'node:crypto';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport { HistoricalSalesLineCollection } from './collections/HistoricalSalesLineCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { InvoiceLineItemCollection } from './collections/InvoiceLineItemCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport { assertContractScheduleInvoiceFreeze } from './contract-billing-schedule.js';\nimport {\n lockAndReloadInvoice,\n refreshIssuedCreditBalance,\n} from './document-money.js';\nimport { DOCUMENT_MONEY_WRITE } from './document-money-internal.js';\nimport { withHistoricalCommerceWrite } from './historical-commerce-internal.js';\nimport type {\n HistoricalSalesMoneySnapshot,\n RecordHistoricalSalesMoneyInput,\n} from './historical-sales-types.js';\nimport {\n historicalSalesMagnitudes,\n historicalText,\n validateHistoricalSalesMoneyFacts,\n validateHistoricalSalesSource,\n} from './historical-sales-validation.js';\nimport { HistoricalSalesLine } from './models/HistoricalSalesLine.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { MoneyValidationError } from './money.js';\nimport {\n type InvoiceRetentionState,\n parseInvoiceRetention,\n} from './retention-money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { InvoiceStatus } from './types/index.js';\n\nexport type * from './historical-sales-types.js';\nexport { validateHistoricalSalesMoneyFacts } from './historical-sales-validation.js';\n\nfunction hash(value: unknown): string {\n return createHash('sha256').update(JSON.stringify(value)).digest('hex');\n}\nfunction identity(value: unknown): string {\n const h = hash(value);\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-a${h.slice(17, 20)}-${h.slice(20, 32)}`;\n}\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nexport function historicalSalesSourceHash(\n source: HistoricalSalesMoneySnapshot['source'],\n): string {\n return hash([source.namespace, source.key]);\n}\nfunction snapshotIdentity(\n invoice: Invoice,\n snapshot: HistoricalSalesMoneySnapshot,\n) {\n return identity({\n tenantId: invoice.tenantId,\n invoiceId: invoice.id,\n customerId: invoice.customerId,\n invoiceNumber: invoice.invoiceNumber,\n snapshot,\n });\n}\nfunction originalRetentionState(\n snapshot: HistoricalSalesMoneySnapshot,\n): InvoiceRetentionState | null {\n const r = snapshot.source.retention;\n if (!r) return null;\n return {\n version: 1,\n currency: snapshot.facts.currency,\n creditPolicy: r.creditPolicy,\n retainedMinor: r.retainedMinor,\n requestId: `historical-retention:${snapshot.requestId}`,\n policyVersion: r.policyRef,\n evidenceRef: r.evidenceRef,\n actorId: snapshot.review.actorId,\n reason: 'Original source retention',\n recordedAt: snapshot.recordedAt,\n effectiveOn: r.effectiveOn,\n releases: r.releases.map((event) => ({\n requestId: `historical-release:${event.sourceKey}`,\n policyVersion: r.policyRef,\n evidenceRef: event.evidenceRef,\n actorId: snapshot.review.actorId,\n reason: 'Original source release',\n recordedAt: snapshot.recordedAt,\n effectiveOn: event.effectiveOn,\n ...(event.sameDayCreditOrder === undefined\n ? {}\n : { sameDayCreditOrder: event.sameDayCreditOrder }),\n amountMinor: event.amountMinor,\n })),\n };\n}\n/** Stored source header evidence; never recalculates tax or source line allocations. */\nexport function getHistoricalSalesMoney(\n invoice: Invoice,\n): HistoricalSalesMoneySnapshot | null {\n if (\n invoice.moneyAuthority === 'calculated' &&\n !invoice.historicalSalesMoneyJson &&\n invoice.historicalSourceKeyHash === null\n )\n return null;\n if (\n invoice.moneyAuthority !== 'historical' ||\n !invoice.historicalSalesMoneyJson\n )\n invalid('Historical invoice authority is incomplete');\n const value = JSON.parse(\n invoice.historicalSalesMoneyJson,\n ) as HistoricalSalesMoneySnapshot;\n if (value.version !== 1)\n invalid('Historical invoice snapshot version is unsupported');\n const snapshot: HistoricalSalesMoneySnapshot = {\n version: 1,\n requestId: historicalText(value.requestId),\n evidenceRef: historicalText(value.evidenceRef),\n review: {\n actorId: historicalText(value.review?.actorId),\n policyRef: historicalText(value.review?.policyRef),\n },\n recordedAt: historicalText(value.recordedAt),\n source: validateHistoricalSalesSource(value.source),\n facts: validateHistoricalSalesMoneyFacts(value.facts),\n creditedSource:\n value.creditedSource === null\n ? null\n : {\n invoiceId: historicalText(value.creditedSource?.invoiceId),\n moneySnapshotId: historicalText(\n value.creditedSource?.moneySnapshotId,\n ),\n },\n };\n const amounts = historicalSalesMagnitudes(snapshot.facts);\n if (\n invoice.currency !== snapshot.facts.currency ||\n invoice.kind !== snapshot.facts.kind ||\n invoice.subtotal !== amounts.netMinor ||\n invoice.taxAmount !== amounts.taxMinor ||\n invoice.totalAmount !== amounts.grossMinor ||\n invoice.discountTotal !== 0 ||\n invoice.providerTaxAmount !== 0 ||\n invoice.historicalSourceKeyHash !==\n historicalSalesSourceHash(snapshot.source) ||\n invoice.moneySnapshotId !== snapshotIdentity(invoice, snapshot)\n )\n invalid(\n 'Historical invoice no longer matches its immutable original monetary authority',\n );\n if (\n invoice.issueDate.toISOString().slice(0, 10) !== snapshot.source.issuedOn ||\n (invoice.dueDate?.toISOString().slice(0, 10) ?? null) !==\n snapshot.source.dueOn\n )\n invalid('Historical source calendar dates changed');\n if (\n snapshot.facts.kind === 'credit_note'\n ? invoice.creditedInvoiceId !== snapshot.creditedSource?.invoiceId\n : snapshot.creditedSource !== null\n )\n invalid('Historical credit source lineage changed');\n const expectedRetention = originalRetentionState(snapshot),\n retained = parseInvoiceRetention(invoice.retentionStateJson);\n if (expectedRetention) {\n if (!retained) invalid('Original retention authority is missing');\n for (const key of Object.keys(\n expectedRetention,\n ) as (keyof InvoiceRetentionState)[]) {\n if (key === 'releases') continue;\n if (retained[key] !== expectedRetention[key])\n invalid('Original retention source projection changed');\n }\n if (\n JSON.stringify(\n retained.releases.slice(0, expectedRetention.releases.length),\n ) !== JSON.stringify(expectedRetention.releases)\n )\n invalid('Original retention release projection changed');\n } else if (retained)\n invalid('Historical invoice has no original retention authority');\n return structuredClone(snapshot);\n}\nfunction lineIdentity(invoiceId: string, sourceKey: string) {\n return identity({ kind: 'historical-sales-line:v1', invoiceId, sourceKey });\n}\n/** Read actual immutable source children for typed consumer crosswalks. */\nexport async function readHistoricalSalesLines(\n db: DatabaseInterface,\n invoice: Invoice,\n) {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return [];\n const lines = await (await HistoricalSalesLineCollection.create({ db })).list(\n {\n where: { tenantId: invoice.tenantId, invoiceId: invoice.id },\n limit: 100001,\n },\n );\n const expected =\n snapshot.facts.detail.kind === 'lines' ? snapshot.facts.detail.lines : [];\n if (lines.length !== expected.length)\n invalid('Historical invoice source child identities are incomplete');\n const byKey = new Map(lines.map((line) => [line.sourceKey, line]));\n if (byKey.size !== lines.length)\n invalid('Historical source child identity is ambiguous');\n return expected.map((source) => {\n const line = byKey.get(source.sourceKey);\n if (\n !line ||\n line.id !== lineIdentity(String(invoice.id), source.sourceKey) ||\n line.sourceKeyHash !== hash(source.sourceKey) ||\n line.moneySnapshotId !== invoice.moneySnapshotId ||\n line.description !== source.description ||\n line.creditedLineId !== source.creditedLineId ||\n line.netMinor !== source.netMinor ||\n line.taxMinor !== source.taxMinor ||\n line.grossMinor !== source.grossMinor ||\n line.quantityText !== source.quantityText ||\n line.unitRateText !== source.unitRateText ||\n line.sourceFieldsJson !== JSON.stringify(source.sourceFields)\n )\n invalid(\n 'Historical invoice source child no longer matches its original facts',\n );\n return line;\n });\n}\nasync function assertSourceLineCapacity(\n db: DatabaseInterface,\n invoices: InvoiceCollection,\n source: Invoice | null,\n snapshot: HistoricalSalesMoneySnapshot,\n) {\n if (snapshot.facts.detail.kind !== 'lines') return;\n const linked = snapshot.facts.detail.lines.filter(\n (line) => line.creditedLineId !== null,\n );\n if (!linked.length) return;\n if (!source || snapshot.facts.kind !== 'credit_note')\n invalid(\n 'Only an exact historical credit may link original historical lines',\n );\n const sourceLines = new Map(\n (await readHistoricalSalesLines(db, source)).map((line) => [line.id, line]),\n );\n const collection = await HistoricalSalesLineCollection.create({ db });\n const requestSign = snapshot.facts.polarity === 'signed' ? -1 : 1;\n const pending = new Map<\n string,\n { netMinor: bigint; taxMinor: bigint; grossMinor: bigint }\n >();\n for (const request of linked) {\n const original = sourceLines.get(request.creditedLineId ?? '');\n if (!original)\n invalid(\n 'Historical credit line does not belong to its exact original source invoice',\n );\n const inRequest = pending.get(String(original.id)) ?? {\n netMinor: 0n,\n taxMinor: 0n,\n grossMinor: 0n,\n };\n const previous = await collection.list({\n where: { tenantId: source.tenantId, creditedLineId: original.id },\n limit: 100001,\n });\n if (previous.length > 100000)\n invalid(\n 'Historical source line capacity exceeds the bounded credit scope',\n );\n const consumed = { netMinor: 0n, taxMinor: 0n, grossMinor: 0n };\n for (const line of previous) {\n const parent = await invoices.get(\n { id: line.invoiceId, tenantId: source.tenantId },\n { cache: false },\n );\n if (\n !parent ||\n parent.kind !== 'credit_note' ||\n parent.creditedInvoiceId !== source.id\n )\n invalid('Historical source line has invalid credit lineage');\n if (\n parent.status === InvoiceStatus.DRAFT ||\n parent.status === InvoiceStatus.CANCELLED\n )\n continue;\n const prior = getHistoricalSalesMoney(parent);\n if (!prior)\n invalid('Historical source line has no original monetary authority');\n const sign = prior.facts.polarity === 'signed' ? -1 : 1;\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n if (line[field] !== null)\n consumed[field] += BigInt(line[field]) * BigInt(sign);\n }\n }\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n const originalAmount = original[field],\n requestedAmount = request[field];\n if (originalAmount === null || requestedAmount === null) continue;\n const magnitude = originalAmount < 0 ? -1n : 1n;\n const originalMagnitude = BigInt(originalAmount) * magnitude;\n const requestMagnitude =\n BigInt(requestedAmount) * BigInt(requestSign) * magnitude;\n if (\n requestMagnitude < 0n ||\n (consumed[field] + inRequest[field]) * magnitude + requestMagnitude >\n originalMagnitude\n )\n invalid(\n 'Historical credit exceeds an exact original source line monetary capacity',\n );\n }\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const)\n if (request[field] !== null)\n inRequest[field] += BigInt(request[field]) * BigInt(requestSign);\n pending.set(String(original.id), inRequest);\n }\n}\nfunction stableRequest(snapshot: HistoricalSalesMoneySnapshot) {\n return {\n source: snapshot.source,\n facts: snapshot.facts,\n evidenceRef: snapshot.evidenceRef,\n policyRef: snapshot.review.policyRef,\n creditedSource: snapshot.creditedSource,\n };\n}\n/** Host-authorized import only. Source issue is retained evidence, never a new send/post. */\nexport async function recordHistoricalSalesMoney(\n input: RecordHistoricalSalesMoneyInput,\n) {\n if (getTenantId() !== input.tenantId)\n invalid('Historical sales require the explicit active tenant');\n const facts = validateHistoricalSalesMoneyFacts(input.facts),\n source = validateHistoricalSalesSource(input.source);\n const snapshot: HistoricalSalesMoneySnapshot = {\n version: 1,\n requestId: historicalText(input.requestId),\n evidenceRef: historicalText(input.evidenceRef),\n review: {\n actorId: historicalText(input.review?.actorId),\n policyRef: historicalText(input.review?.policyRef),\n },\n recordedAt: new Date().toISOString(),\n source,\n facts,\n creditedSource: input.creditedSource\n ? {\n invoiceId: historicalText(input.creditedSource.invoiceId),\n moneySnapshotId: historicalText(input.creditedSource.moneySnapshotId),\n }\n : null,\n };\n if ((facts.kind === 'credit_note') !== Boolean(snapshot.creditedSource))\n invalid(\n 'Historical credits require the exact original issued invoice snapshot',\n );\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const { invoice } = await lockAndReloadInvoice(\n db,\n historicalText(input.invoiceId),\n input.tenantId,\n );\n if (invoice.tenantId !== input.tenantId)\n invalid('Historical invoice is not owned by the active tenant');\n const existing = getHistoricalSalesMoney(invoice);\n if (existing) {\n if (hash(stableRequest(existing)) !== hash(stableRequest(snapshot)))\n invalid(\n 'Historical invoice retry differs from its original facts or reviewed policy',\n );\n return {\n snapshot: existing,\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n lines: (await readHistoricalSalesLines(db, invoice)).map((line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n })),\n };\n }\n if (\n invoice.status !== InvoiceStatus.DRAFT ||\n invoice.moneySnapshotId ||\n invoice.arJournalId ||\n invoice.amountPaid ||\n invoice.creditedAmount ||\n invoice.retentionStateJson ||\n invoice.externalId ||\n invoice.externalProvider ||\n invoice.providerTaxAmount\n )\n invalid(\n 'Historical source money requires an empty unfrozen invoice without current financial effects',\n );\n if (invoice.kind !== facts.kind || invoice.currency !== facts.currency)\n invalid('Historical source kind/currency must match its draft invoice');\n const customer = invoice.customerId\n ? await (await CustomerCollection.create({ db })).get(\n { id: invoice.customerId, tenantId: input.tenantId },\n { cache: false },\n )\n : null;\n if (!customer)\n invalid('Historical sales require a customer owned by the active tenant');\n if (\n (\n await (\n await InvoiceLineItemCollection.create({ db })\n ).findByInvoice(String(invoice.id))\n ).length\n )\n invalid(\n 'Historical source money cannot mix with calculated invoice lines',\n );\n const invoices = await InvoiceCollection.create({ db });\n const duplicate = (\n await invoices.list({\n where: {\n tenantId: input.tenantId,\n historicalSourceKeyHash: historicalSalesSourceHash(source),\n },\n limit: 1,\n })\n )[0];\n if (duplicate && duplicate.id !== invoice.id)\n invalid(\n 'Historical source identity already belongs to another canonical invoice',\n );\n for (const component of facts.taxComponents ?? []) {\n const code = component.taxCodeId\n ? await (await TaxCodeCollection.create({ db })).get(\n { id: component.taxCodeId, tenantId: input.tenantId },\n { cache: false },\n )\n : null;\n if (\n component.taxCodeId &&\n (!code ||\n (component.classification !== null &&\n code.kind !== component.classification))\n )\n invalid(\n 'Historical source tax code is not owned by its tenant with the reviewed classification',\n );\n if (component.taxComponentId) {\n const tax = await (await TaxComponentCollection.create({ db })).get(\n { id: component.taxComponentId, tenantId: input.tenantId },\n { cache: false },\n );\n if (\n !tax ||\n (code &&\n !code.components.some((part) => part.taxComponentId === tax.id))\n )\n invalid(\n 'Historical source tax component is not owned by its declared tenant/code',\n );\n }\n if (component.liabilityAccountId) {\n const { AccountCollection } = await import(\n '@happyvertical/smrt-ledgers'\n );\n const account = await (await AccountCollection.create({ db })).get(\n { id: component.liabilityAccountId, tenantId: input.tenantId },\n { cache: false },\n );\n if (!account || account.type !== 'liability')\n invalid(\n 'Historical source tax liability account is not owned by its tenant with the required type',\n );\n }\n }\n let credited: Invoice | null = null;\n const amounts = historicalSalesMagnitudes(facts);\n if (snapshot.creditedSource) {\n credited = (\n await lockAndReloadInvoice(\n db,\n snapshot.creditedSource.invoiceId,\n input.tenantId,\n )\n ).invoice;\n if (\n credited.kind !== 'invoice' ||\n credited.tenantId !== input.tenantId ||\n credited.customerId !== invoice.customerId ||\n credited.currency !== invoice.currency ||\n !credited.moneySnapshotId ||\n credited.moneySnapshotId !== snapshot.creditedSource.moneySnapshotId ||\n credited.status === InvoiceStatus.DRAFT ||\n credited.status === InvoiceStatus.CANCELLED ||\n invoice.creditedInvoiceId !== credited.id\n )\n invalid(\n 'Historical credit original invoice/customer/currency/snapshot does not match',\n );\n const prior = (\n await invoices\n .list({\n where: { tenantId: input.tenantId, creditedInvoiceId: credited.id },\n limit: 100001,\n })\n .then((rows) => {\n if (rows.length > 100000)\n invalid(\n 'Historical credit scope exceeds its bounded source limit',\n );\n return rows;\n })\n ).filter(\n (row) =>\n row.id !== invoice.id &&\n row.status !== InvoiceStatus.DRAFT &&\n row.status !== InvoiceStatus.CANCELLED,\n );\n if (prior.length > 100000)\n invalid('Historical credit scope exceeds its bounded source limit');\n const retention = parseInvoiceRetention(credited.retentionStateJson);\n if (retention) {\n const credits = [\n ...prior.map((row) => ({\n on:\n getHistoricalSalesMoney(row)?.source.issuedOn ??\n row.issueDate.toISOString().slice(0, 10),\n amount: row.totalAmount,\n })),\n { on: source.issuedOn, amount: amounts.grossMinor },\n ];\n let remaining = retention.retainedMinor;\n const events = [\n ...credits.map((event) => ({\n ...event,\n kind: 'credit' as const,\n rank: 1,\n })),\n ...retention.releases.map((release) => {\n const on = release.effectiveOn ?? release.recordedAt.slice(0, 10);\n if (\n credits.some((event) => event.on === on) &&\n !release.sameDayCreditOrder\n )\n invalid(\n 'Same-day original retention release/credit requires explicit reviewed ordering',\n );\n return {\n on,\n amount: release.amountMinor,\n kind: 'release' as const,\n rank:\n release.sameDayCreditOrder === 'release-before-credit' ? 0 : 2,\n };\n }),\n ].sort(\n (left, right) =>\n left.on.localeCompare(right.on) || left.rank - right.rank,\n );\n for (const event of events) {\n if (event.kind === 'credit')\n remaining = Math.max(0, remaining - event.amount);\n else {\n if (event.amount > remaining)\n invalid(\n 'Original retention release exceeds retained-first capacity at its source date',\n );\n remaining -= event.amount;\n }\n }\n }\n for (const [field, value] of [\n ['subtotal', amounts.netMinor],\n ['taxAmount', amounts.taxMinor],\n ['totalAmount', amounts.grossMinor],\n ] as const) {\n const consumed = prior.reduce(\n (sum, row) => sum + BigInt(row[field]),\n 0n,\n );\n if (consumed + BigInt(value) > BigInt(credited[field]))\n invalid(\n 'Historical credit exceeds the remaining exact original net/tax/gross capacity',\n );\n }\n }\n await assertSourceLineCapacity(db, invoices, credited, snapshot);\n if (\n source.retention &&\n (facts.kind !== 'invoice' ||\n source.retention.retainedMinor > amounts.grossMinor)\n )\n invalid('Historical retention must match original invoice gross');\n const originalRetention = originalRetentionState(snapshot);\n invoice.retentionStateJson = originalRetention\n ? JSON.stringify(originalRetention)\n : '';\n invoice.moneyAuthority = 'historical';\n invoice.historicalSalesMoneyJson = JSON.stringify(snapshot);\n invoice.historicalSourceKeyHash = historicalSalesSourceHash(source);\n invoice.subtotal = amounts.netMinor;\n invoice.discountTotal = 0;\n invoice.taxAmount = amounts.taxMinor;\n invoice.providerTaxAmount = 0;\n invoice.totalAmount = amounts.grossMinor;\n invoice.issueDate = new Date(`${source.issuedOn}T00:00:00Z`);\n invoice.dueDate =\n source.dueOn === null ? null : new Date(`${source.dueOn}T00:00:00Z`);\n invoice.moneySnapshotId = snapshotIdentity(invoice, snapshot);\n invoice.status = InvoiceStatus.SENT;\n await assertContractScheduleInvoiceFreeze(db, invoice);\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (facts.detail.kind === 'lines')\n for (const line of facts.detail.lines) {\n const child = await new HistoricalSalesLine({\n db,\n id: lineIdentity(String(invoice.id), line.sourceKey),\n tenantId: input.tenantId,\n invoiceId: String(invoice.id),\n ...line,\n sourceKeyHash: hash(line.sourceKey),\n moneySnapshotId: invoice.moneySnapshotId,\n }).initialize();\n await withHistoricalCommerceWrite(child, () => child.save());\n }\n if (credited) await refreshIssuedCreditBalance(db, credited);\n return {\n snapshot: structuredClone(snapshot),\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n lines: (await readHistoricalSalesLines(db, invoice)).map((line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n })),\n };\n });\n}\n","/** Original header totals remain readable even when detailed tax classifications are unknown. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n DocumentTaxReportFact,\n DocumentTaxReportFactsOptions,\n} from './collections/DocumentTaxCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { getHistoricalSalesMoney } from './historical-sales-money.js';\nimport { historicalSalesMagnitudes } from './historical-sales-validation.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\n\nexport interface HistoricalSalesHeaderReportFact {\n invoiceId: string;\n moneySnapshotId: string;\n customerId: string;\n invoiceNumber: string;\n kind: Invoice['kind'];\n issueDate: string;\n currency: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n taxBreakdownKnown: boolean;\n}\nexport class HistoricalSalesTaxClassificationRequired extends Error {\n readonly code = 'HISTORICAL_SALES_TAX_CLASSIFICATION_REQUIRED';\n constructor(readonly invoiceId: string) {\n super(\n `Historical invoice ${invoiceId} retains exact header totals, but this tax breakdown requires explicit reviewed source classification, tax identity and taxable basis. Read the historical header facts or resolve the source assessment; never infer a rate or line allocation.`,\n );\n this.name = 'HistoricalSalesTaxClassificationRequired';\n }\n}\nfunction classified(invoice: Invoice) {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return false;\n const components = snapshot.facts.taxComponents;\n return Boolean(\n components?.length &&\n components.every(\n (component) =>\n component.classification !== null &&\n component.taxCodeId &&\n component.taxableMinor !== null &&\n component.netMinor !== null &&\n (component.classification !== 'taxable' || component.taxComponentId),\n ),\n );\n}\n/** @internal Project explicit source detail only; a known header is not a component classification. */\nexport function historicalSalesTaxReportFacts(\n invoice: Invoice,\n): DocumentTaxReportFact[] {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return [];\n if (snapshot.facts.netMinor === 0 && snapshot.facts.taxMinor === 0) return [];\n if (!classified(invoice))\n throw new HistoricalSalesTaxClassificationRequired(String(invoice.id));\n const sign =\n snapshot.facts.kind === 'credit_note' &&\n snapshot.facts.polarity === 'signed'\n ? -1\n : 1;\n return (snapshot.facts.taxComponents ?? []).map((component) => {\n if (\n component.classification === null ||\n !component.taxCodeId ||\n component.taxableMinor === null\n )\n throw new HistoricalSalesTaxClassificationRequired(String(invoice.id));\n return {\n tenantId: String(invoice.tenantId),\n documentType: invoice.kind,\n documentId: String(invoice.id),\n documentNumber: invoice.invoiceNumber,\n partyId: invoice.customerId,\n documentKind: invoice.kind,\n issueDate: invoice.issueDate.toISOString(),\n status: invoice.status,\n direction: 'sales',\n currency: invoice.currency,\n taxCodeId: component.taxCodeId,\n taxCodeKind: component.classification,\n taxableMinor: component.taxableMinor * sign,\n ...(component.netMinor === null\n ? {}\n : { netMinor: component.netMinor * sign }),\n taxMinor: component.amountMinor * sign,\n recoverableMinor: 0,\n taxComponentId: component.taxComponentId,\n componentName: component.label,\n liabilityAccountId: component.liabilityAccountId,\n commitmentId: null,\n commitmentLineId: null,\n };\n });\n}\n/** @internal Invoice source rows for the same public report scope; never silently truncate. */\nexport async function historicalSalesReportInvoices(\n db: DatabaseInterface,\n options: DocumentTaxReportFactsOptions,\n) {\n const rows = await (await InvoiceCollection.create({ db })).list({\n where: {\n tenantId: options.tenantId,\n moneyAuthority: 'historical',\n 'issueDate >=': options.from.toISOString(),\n 'issueDate <=': options.to.toISOString(),\n 'status not in': ['draft', 'cancelled'],\n ...(options.currency ? { currency: options.currency } : {}),\n },\n limit: 100001,\n });\n if (rows.length > 100000)\n throw new Error(\n 'Historical sales report scope exceeds the bounded document limit; select a smaller scope',\n );\n return rows;\n}\n/** Exact generic header reporting does not require a fabricated tax breakdown. */\nexport async function listHistoricalSalesHeaderFacts(\n input: DocumentTaxReportFactsOptions & { db: DatabaseInterface },\n): Promise<HistoricalSalesHeaderReportFact[]> {\n if (getTenantId() !== input.tenantId)\n throw new Error(\n 'Historical sales reporting requires the explicit active tenant',\n );\n if (\n !(input.from instanceof Date) ||\n !(input.to instanceof Date) ||\n !Number.isFinite(input.from.getTime()) ||\n !Number.isFinite(input.to.getTime()) ||\n input.from > input.to\n )\n throw new Error(\n 'Historical sales report requires an explicit valid period',\n );\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) =>\n (await historicalSalesReportInvoices(db, input)).map((invoice) => {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot)\n throw new Error('Historical source monetary authority is unavailable');\n return {\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n customerId: invoice.customerId,\n invoiceNumber: invoice.invoiceNumber,\n kind: invoice.kind,\n issueDate: invoice.issueDate.toISOString(),\n currency: invoice.currency,\n ...historicalSalesMagnitudes(snapshot.facts),\n taxBreakdownKnown: classified(invoice),\n };\n }),\n );\n}\n","/** Persisted per-code/component tax totals for a commerce document. */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError, type TaxCodeKind } from '../money.js';\n\nexport type CommerceDocumentType = 'invoice' | 'contract' | 'credit_note';\n\nexport interface DocumentTaxOptions extends SmrtObjectOptions {\n tenantId?: string;\n documentType?: CommerceDocumentType;\n documentId?: string;\n currency?: string;\n taxCodeId?: string | null;\n taxCodeCode?: string | null;\n kind?: TaxCodeKind | null;\n taxComponentId?: string | null;\n taxComponentName?: string | null;\n percent?: string | null;\n liabilityAccountId?: string | null;\n taxableMinor?: number;\n netMinor?: number | null;\n taxMinor?: number;\n recoverableMinor?: number;\n}\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'document_taxes',\n conflictColumns: [\n 'document_type',\n 'document_id',\n 'tax_code_id',\n 'tax_component_id',\n ],\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class DocumentTax extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @tenantId()\n tenantId = '';\n\n @field({ required: true })\n documentType: CommerceDocumentType = 'invoice';\n\n @field({ required: true })\n documentId = '';\n\n @field({ required: true })\n currency = 'USD';\n\n @field({ nullable: true })\n taxCodeId: string | null = null;\n\n @field({ nullable: true })\n taxCodeCode: string | null = null;\n\n @field({ nullable: true })\n kind: TaxCodeKind | null = null;\n\n @field({ nullable: true })\n taxComponentId: string | null = null;\n\n @field({ nullable: true })\n taxComponentName: string | null = null;\n\n @field({ type: 'decimal', nullable: true })\n percent: string | null = null;\n\n @field({ nullable: true })\n liabilityAccountId: string | null = null;\n\n @field({\n description:\n 'Actual component taxable basis, including prior compound taxes.',\n ui: { format: 'money' },\n })\n taxableMinor = 0;\n\n @field({\n type: 'integer',\n nullable: true,\n description: 'Net basis when different from the component taxable basis.',\n ui: { format: 'money' },\n })\n netMinor: number | null = null;\n\n @field({\n description: 'Tax total in integer minor units.',\n ui: { format: 'money' },\n })\n taxMinor = 0;\n\n @field({\n description: 'Recoverable purchase tax in integer minor units.',\n ui: { format: 'money' },\n })\n recoverableMinor = 0;\n\n constructor(options: DocumentTaxOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.documentType !== undefined)\n this.documentType = options.documentType;\n if (options.documentId !== undefined) this.documentId = options.documentId;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.taxCodeId !== undefined) this.taxCodeId = options.taxCodeId;\n if (options.taxCodeCode !== undefined)\n this.taxCodeCode = options.taxCodeCode;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.taxComponentId !== undefined)\n this.taxComponentId = options.taxComponentId;\n if (options.taxComponentName !== undefined)\n this.taxComponentName = options.taxComponentName;\n if (options.percent !== undefined) this.percent = options.percent;\n if (options.liabilityAccountId !== undefined)\n this.liabilityAccountId = options.liabilityAccountId;\n if (options.taxableMinor !== undefined)\n this.taxableMinor = options.taxableMinor;\n if (options.netMinor !== undefined) this.netMinor = options.netMinor;\n if (options.taxMinor !== undefined) this.taxMinor = options.taxMinor;\n if (options.recoverableMinor !== undefined)\n this.recoverableMinor = options.recoverableMinor;\n }\n\n private assertValidDerivedRow(): void {\n if (!['invoice', 'contract', 'credit_note'].includes(this.documentType)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Unknown document tax type: ${this.documentType}`,\n );\n }\n for (const [label, value] of [\n ['tenantId', this.tenantId],\n ['documentId', this.documentId],\n ['currency', this.currency],\n ] as const) {\n if (!value || value.trim() !== value) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `DocumentTax ${label} must be a nonempty value`,\n );\n }\n }\n for (const [label, value] of [\n ['taxableMinor', this.taxableMinor],\n ['netMinor', this.netMinor ?? this.taxableMinor],\n ['taxMinor', this.taxMinor],\n ['recoverableMinor', this.recoverableMinor],\n ] as const) {\n if (!Number.isSafeInteger(value)) {\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n `DocumentTax ${label} must be safe integer minor units`,\n );\n }\n }\n if (this.taxCodeId === null) {\n if (\n this.taxComponentId !== null ||\n this.taxCodeCode !== null ||\n this.kind !== null ||\n this.taxComponentName !== null ||\n this.percent !== null ||\n this.liabilityAccountId !== null ||\n this.taxMinor !== 0 ||\n this.recoverableMinor !== 0\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'An unassigned DocumentTax row cannot carry code/component snapshots or tax',\n );\n }\n return;\n }\n if (!this.taxCodeCode || !this.kind) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Assigned DocumentTax rows require code and kind snapshots',\n );\n }\n if (this.taxComponentId === null) {\n if (\n this.kind === 'taxable' ||\n this.taxComponentName !== null ||\n this.percent !== null ||\n this.liabilityAccountId !== null ||\n this.taxMinor !== 0 ||\n this.recoverableMinor !== 0\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Component-less DocumentTax rows must be non-taxable zero-tax snapshots',\n );\n }\n return;\n }\n if (this.kind !== 'taxable' || !this.taxComponentName || !this.percent) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Component DocumentTax rows require taxable component snapshots',\n );\n }\n if (\n this.recoverableMinor !== 0 &&\n this.recoverableMinor !== this.taxMinor\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax recoverableMinor must be zero or the component tax total',\n );\n }\n }\n\n override async save(): Promise<this> {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax rows are derived and cannot be saved directly',\n );\n }\n\n override async delete(\n _options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax rows are derived and cannot be deleted directly',\n );\n }\n\n /** @internal Aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n this.assertValidDerivedRow();\n return (await super.save()) as this;\n }\n\n /** @internal Aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n await super.delete(options);\n }\n}\n","/**\n * VendorCollection - Collection manager for Vendor objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Vendor } from '../models/Vendor.js';\nimport { VendorStatus } from '../types/index.js';\n\nexport class VendorCollection extends SmrtCollection<Vendor> {\n static readonly _itemClass = Vendor;\n\n /**\n * Find vendors by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of vendors linked to this profile\n */\n async findByProfile(profileId: string): Promise<Vendor[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active vendors\n *\n * @returns Array of active vendors\n */\n async findActive(): Promise<Vendor[]> {\n return await this.list({\n where: { status: VendorStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find vendors by status\n *\n * @param status - Vendor status\n * @returns Array of vendors\n */\n async findByStatus(status: VendorStatus): Promise<Vendor[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a vendor for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Vendor\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n leadTimeDays: number;\n minimumOrderAmount: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Vendor> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const vendor = await this.create({\n profileId,\n leadTimeDays: defaults.leadTimeDays ?? 0,\n minimumOrderAmount: defaults.minimumOrderAmount ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: VendorStatus.ACTIVE,\n });\n await vendor.save();\n return vendor;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all vendors belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of vendors for the tenant\n */\n async findByTenant(tenantId: string): Promise<Vendor[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global vendors (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global vendors\n */\n async findGlobal(): Promise<Vendor[]> {\n return queryGlobal<Vendor>(this);\n }\n\n /**\n * Find vendors for a tenant including global vendors.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global vendors\n */\n async findWithGlobals(tenantId: string): Promise<Vendor[]> {\n return queryWithGlobals<Vendor>(this, tenantId, 'Vendor.findWithGlobals');\n }\n}\n","/** Exact monetary evidence received from a supplier, independent of calculated pricing. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport { ContractCollection } from './collections/ContractCollection.js';\nimport { ContractLineItemCollection } from './collections/ContractLineItemCollection.js';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport { VendorCollection } from './collections/VendorCollection.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n} from './document-money-internal.js';\nimport {\n Agreement,\n type Contract,\n Order,\n PurchaseOrder,\n SupplierQuote,\n} from './models/Contract.js';\nimport { MoneyValidationError, type TaxCodeKind } from './money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { ContractStatus } from './types/index.js';\n\n/** A supplier tax component. Null explicitly retains an unknown fact. */\nexport interface ReceivedPurchaseTaxComponent {\n sourceKey: string;\n label: string;\n amountMinor: number;\n classification: TaxCodeKind | null;\n /** Explicit report identity/basis; omission retains unknown, never implies a rate. */\n taxCodeId?: string | null;\n taxComponentId?: string | null;\n taxableMinor?: number | null;\n /** Explicit net allocation when supplier taxable basis includes prior taxes. */\n netMinor?: number | null;\n recoverableMinor: number | null;\n}\n/** Complete source line money; optional source decimal text is evidence, not a calculator input. */\nexport interface ReceivedPurchaseMoneyLine {\n sourceKey: string;\n description: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n quantityText?: string;\n unitRateText?: string;\n}\n/** Monetary evidence without a fabricated rate, quantity, or line allocation. */\nexport interface ReceivedPurchaseMoneyFacts {\n currency: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n taxComponents: ReceivedPurchaseTaxComponent[] | null;\n detail:\n | { kind: 'header-only' }\n | { kind: 'lines'; lines: ReceivedPurchaseMoneyLine[] };\n}\n/** Immutable request and supplier evidence identity retained with the amounts. */\nexport interface ReceivedPurchaseMoneySnapshot {\n version: 1;\n requestId: string;\n evidenceRef: string;\n facts: ReceivedPurchaseMoneyFacts;\n sourceQuote: ReceivedPurchaseQuoteSource | null;\n}\nexport interface ReceivedPurchaseQuoteSource {\n contractId: string;\n relationship: 'copy' | 'negotiated';\n}\n/** Public command input. The host authorizes the human before calling this command. */\nexport interface RecordReceivedPurchaseMoneyInput {\n db: DatabaseInterface;\n tenantId: string;\n contractId: string;\n requestId: string;\n evidenceRef: string;\n facts: ReceivedPurchaseMoneyFacts;\n sourceQuote?: ReceivedPurchaseQuoteSource;\n}\n\n/** Complete received sales agreement evidence; recording is not revenue/tax recognition. */\nexport type ReceivedSalesContractMoneyFacts = ReceivedPurchaseMoneyFacts;\nexport type ReceivedSalesContractMoneySnapshot = ReceivedPurchaseMoneySnapshot;\nexport type RecordReceivedSalesContractMoneyInput = Omit<\n RecordReceivedPurchaseMoneyInput,\n 'sourceQuote'\n>;\n\n/** Record supplied complete facts on one empty draft Order/Agreement. */\nexport async function recordReceivedSalesContractMoney(\n input: RecordReceivedSalesContractMoneyInput,\n): Promise<ReceivedSalesContractMoneySnapshot> {\n if (Object.hasOwn(input, 'sourceQuote'))\n invalid('Sales agreement evidence cannot reference a supplier quote');\n if (\n input.facts.taxComponents?.some(\n (component) => component.recoverableMinor !== null,\n )\n )\n invalid(\n 'Purchase tax recovery is not applicable to sales agreement evidence; retain null',\n );\n return recordReceivedContractMoney(input, 'sales');\n}\n\n/** Read exact sales agreement evidence without calculating or recognizing an invoice. */\nexport function getReceivedSalesContractMoney(\n contract: Contract,\n): ReceivedSalesContractMoneySnapshot | null {\n if (!(contract instanceof Order || contract instanceof Agreement))\n return null;\n return getReceivedPurchaseMoney(contract);\n}\n\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nfunction object(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n invalid(`${label} must be an object`);\n return value as Record<string, unknown>;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value || value.trim() !== value)\n invalid(`${label} must be nonempty trimmed text`);\n return value;\n}\nfunction minor(value: unknown, label: string): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)\n invalid(`${label} must be a nonnegative safe integer`);\n return value;\n}\nfunction amounts(value: Record<string, unknown>, label: string) {\n const netMinor = minor(value.netMinor, `${label} net`);\n const taxMinor = minor(value.taxMinor, `${label} tax`);\n const grossMinor = minor(value.grossMinor, `${label} gross`);\n if (BigInt(netMinor) + BigInt(taxMinor) !== BigInt(grossMinor))\n invalid(`${label} net plus tax must equal gross`);\n return { netMinor, taxMinor, grossMinor };\n}\nfunction unique(keys: string[], label: string): void {\n if (new Set(keys).size !== keys.length)\n invalid(`${label} source keys must be unique`);\n}\n\n/** Validate and canonicalize exact received money, retaining unknowns as null. */\nexport function validateReceivedPurchaseMoneyFacts(\n value: unknown,\n): ReceivedPurchaseMoneyFacts {\n const input = object(value, 'Received purchase facts');\n const currency = text(input.currency, 'Currency');\n if (\n !/^[A-Z]{3}$/.test(currency) ||\n !ISO_4217_MINOR_UNITS.has(currency) ||\n ISO_4217_MINOR_UNITS.get(currency) === null\n )\n invalid('Currency must be a supported uppercase ISO 4217 code');\n const totals = amounts(input, 'Document');\n let taxComponents: ReceivedPurchaseTaxComponent[] | null = null;\n if (input.taxComponents !== null) {\n if (!Array.isArray(input.taxComponents))\n invalid('Tax components must be an array or explicit null');\n taxComponents = input.taxComponents.map((raw) => {\n const component = object(raw, 'Tax component');\n const amountMinor = minor(component.amountMinor, 'Component amount');\n const recoverableMinor =\n component.recoverableMinor === null\n ? null\n : minor(component.recoverableMinor, 'Recoverable amount');\n if (recoverableMinor !== null && recoverableMinor > amountMinor)\n invalid('Recoverable tax cannot exceed component tax');\n const classification = component.classification;\n if (\n classification !== null &&\n !['taxable', 'zero-rated', 'exempt', 'out-of-scope'].includes(\n String(classification),\n )\n )\n invalid('Unknown tax classification');\n const taxableMinor =\n component.taxableMinor == null\n ? null\n : minor(component.taxableMinor, 'Taxable basis');\n const netMinor =\n component.netMinor == null\n ? null\n : minor(component.netMinor, 'Component net basis');\n if (netMinor !== null && netMinor > totals.netMinor)\n invalid('Component net basis exceeds document net');\n if (\n classification !== null &&\n classification !== 'taxable' &&\n amountMinor !== 0\n )\n invalid('A non-taxable classification cannot contain tax');\n return {\n sourceKey: text(component.sourceKey, 'Component source key'),\n label: text(component.label, 'Component label'),\n amountMinor,\n classification: classification as TaxCodeKind | null,\n taxCodeId:\n component.taxCodeId == null\n ? null\n : text(component.taxCodeId, 'Tax code identity'),\n taxComponentId:\n component.taxComponentId == null\n ? null\n : text(component.taxComponentId, 'Tax component identity'),\n taxableMinor,\n ...(netMinor !== null ? { netMinor } : {}),\n recoverableMinor,\n };\n });\n unique(\n taxComponents.map((item) => item.sourceKey),\n 'Tax component',\n );\n if (\n taxComponents.reduce(\n (sum, item) => sum + BigInt(item.amountMinor),\n 0n,\n ) !== BigInt(totals.taxMinor)\n )\n invalid('Component tax sum must equal document tax');\n }\n const rawDetail = object(input.detail, 'Source detail');\n let detail: ReceivedPurchaseMoneyFacts['detail'];\n if (rawDetail.kind === 'header-only') {\n if ('lines' in rawDetail)\n invalid('Header-only evidence cannot contain monetary lines');\n detail = { kind: 'header-only' };\n } else if (rawDetail.kind === 'lines') {\n if (!Array.isArray(rawDetail.lines) || !rawDetail.lines.length)\n invalid('Complete source lines are required');\n const lines = rawDetail.lines.map((raw) => {\n const line = object(raw, 'Source line');\n const result: ReceivedPurchaseMoneyLine = {\n sourceKey: text(line.sourceKey, 'Line source key'),\n description: text(line.description, 'Line description'),\n ...amounts(line, 'Source line'),\n };\n for (const key of ['quantityText', 'unitRateText'] as const) {\n if (line[key] === undefined) continue;\n const decimal = text(line[key], key);\n if (!/^(?:0|[1-9]\\d*)(?:\\.\\d+)?$/.test(decimal))\n invalid(`${key} must be nonnegative decimal source text`);\n result[key] = decimal;\n }\n return result;\n });\n unique(\n lines.map((item) => item.sourceKey),\n 'Line',\n );\n for (const key of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n if (\n lines.reduce((sum, line) => sum + BigInt(line[key]), 0n) !==\n BigInt(totals[key])\n )\n invalid(`Source line ${key} sum must equal document amount`);\n }\n detail = { kind: 'lines', lines };\n } else invalid('Unknown received source detail kind');\n return { currency, ...totals, taxComponents, detail };\n}\n\nfunction quoteSource(value: unknown): ReceivedPurchaseQuoteSource | null {\n if (value == null) return null;\n const input = object(value, 'Source quote');\n if (input.relationship !== 'copy' && input.relationship !== 'negotiated')\n invalid('Unknown source quote relationship');\n return {\n contractId: text(input.contractId, 'Source quote identity'),\n relationship: input.relationship,\n };\n}\n\n/** Read validated received evidence; calculated contracts return null. */\nexport function getReceivedPurchaseMoney(\n contract: Pick<Contract, 'moneyAuthority' | 'receivedPurchaseMoneyJson'>,\n): ReceivedPurchaseMoneySnapshot | null {\n if (contract.moneyAuthority === 'calculated') {\n if (contract.receivedPurchaseMoneyJson)\n invalid('Calculated money cannot contain received evidence');\n return null;\n }\n if (contract.moneyAuthority !== 'received')\n invalid('Unknown contract money authority');\n let parsed: unknown;\n try {\n parsed = JSON.parse(contract.receivedPurchaseMoneyJson);\n } catch {\n invalid('Stored received money is invalid');\n }\n const input = object(parsed, 'Received snapshot');\n if (input.version !== 1) invalid('Unknown received money version');\n return {\n version: 1,\n requestId: text(input.requestId, 'Request identity'),\n evidenceRef: text(input.evidenceRef, 'Evidence reference'),\n facts: validateReceivedPurchaseMoneyFacts(input.facts),\n sourceQuote: quoteSource(input.sourceQuote),\n };\n}\n\n/** Record immutable source facts on one empty draft SupplierQuote or PurchaseOrder, retry safely. */\nexport async function recordReceivedPurchaseMoney(\n input: RecordReceivedPurchaseMoneyInput,\n): Promise<ReceivedPurchaseMoneySnapshot> {\n return recordReceivedContractMoney(input, 'purchase');\n}\n\nasync function recordReceivedContractMoney(\n input: RecordReceivedPurchaseMoneyInput,\n direction: 'purchase' | 'sales',\n): Promise<ReceivedPurchaseMoneySnapshot> {\n const tenantId = text(input.tenantId, 'Tenant');\n if (getTenantId() !== tenantId)\n invalid('Received contract money requires its active tenant context');\n const contractId = text(input.contractId, 'Contract');\n const snapshot: ReceivedPurchaseMoneySnapshot = {\n version: 1,\n requestId: text(input.requestId, 'Request identity'),\n evidenceRef: text(input.evidenceRef, 'Evidence reference'),\n facts: validateReceivedPurchaseMoneyFacts(input.facts),\n sourceQuote: quoteSource(input.sourceQuote),\n };\n const serialized = JSON.stringify(snapshot);\n return withTenantMoneyRuntime(input.db, tenantId, async ({ db }) => {\n const contracts = await ContractCollection.create({ db });\n await lockDocumentMoneyParents([\n { id: contractId, tenantId, collection: contracts },\n ...(snapshot.sourceQuote\n ? [\n {\n id: snapshot.sourceQuote.contractId,\n tenantId,\n collection: contracts,\n },\n ]\n : []),\n ]);\n const contract = await contracts.get({ id: contractId }, { cache: false });\n const validParty =\n direction === 'purchase'\n ? (contract instanceof SupplierQuote ||\n contract instanceof PurchaseOrder) &&\n contract.vendorId\n : (contract instanceof Order || contract instanceof Agreement) &&\n contract.customerId;\n if (!contract || contract.tenantId !== tenantId || !validParty)\n invalid(\n direction === 'purchase'\n ? 'Received money requires a supplier quote or purchase order in the active tenant'\n : 'Received money requires an Order or Agreement with a customer in the active tenant',\n );\n const stored = getReceivedPurchaseMoney(contract);\n if (stored) {\n if (JSON.stringify(stored) !== serialized)\n invalid(\n 'Received money request changed; create a separate contract revision',\n );\n return stored;\n }\n if (\n direction === 'purchase' &&\n (contract instanceof SupplierQuote || contract instanceof PurchaseOrder)\n ) {\n const vendor = await (await VendorCollection.create({ db })).get(\n { id: contract.vendorId },\n { cache: false },\n );\n if (!vendor || vendor.tenantId !== tenantId)\n invalid('Supplier must belong to the active tenant');\n } else if (contract instanceof Order || contract instanceof Agreement) {\n const customer = await (await CustomerCollection.create({ db })).get(\n { id: contract.customerId },\n { cache: false },\n );\n if (!customer || customer.tenantId !== tenantId)\n invalid('Customer must belong to the active tenant');\n }\n if (snapshot.sourceQuote) {\n if (!(contract instanceof PurchaseOrder))\n invalid('Only a purchase order can reference a source quote');\n const source = await contracts.get(\n { id: snapshot.sourceQuote.contractId },\n { cache: false },\n );\n if (\n !(source instanceof SupplierQuote) ||\n source.tenantId !== tenantId ||\n source.vendorId !== contract.vendorId ||\n source.currency !== contract.currency ||\n source.status !== ContractStatus.ACCEPTED ||\n !source.moneySnapshotId\n )\n invalid(\n 'Source quote must be accepted with matching tenant, vendor and currency',\n );\n const sourceMoney = getReceivedPurchaseMoney(source);\n if (!sourceMoney)\n invalid('Source quote must have received monetary evidence');\n if (\n snapshot.sourceQuote.relationship === 'copy' &&\n JSON.stringify(sourceMoney.facts) !== JSON.stringify(snapshot.facts)\n )\n invalid('Copied quote monetary facts must match exactly');\n if (\n snapshot.sourceQuote.relationship === 'negotiated' &&\n snapshot.evidenceRef === sourceMoney.evidenceRef\n )\n invalid(\n 'Negotiated award requires separate approved monetary evidence',\n );\n }\n for (const component of snapshot.facts.taxComponents ?? []) {\n if (component.taxCodeId) {\n const code = await (await TaxCodeCollection.create({ db })).get(\n { id: component.taxCodeId },\n { cache: false },\n );\n if (!code || code.tenantId !== tenantId)\n invalid('Tax report code must belong to the active tenant');\n if (\n component.classification !== null &&\n code.kind !== component.classification\n )\n invalid('Explicit tax classification must match its selected code');\n if (\n component.taxComponentId &&\n !code.components.some(\n (entry) => entry.taxComponentId === component.taxComponentId,\n )\n )\n invalid('Tax component must belong to its selected tax code');\n }\n if (component.taxComponentId) {\n const tax = await (await TaxComponentCollection.create({ db })).get(\n { id: component.taxComponentId },\n { cache: false },\n );\n if (!tax || tax.tenantId !== tenantId)\n invalid('Tax report component must belong to the active tenant');\n }\n }\n if (contract.status !== ContractStatus.DRAFT || contract.moneySnapshotId)\n invalid('Received money requires an unfrozen draft');\n if (contract.currency !== snapshot.facts.currency)\n invalid('Received money currency must match the contract');\n const lines = await (\n await ContractLineItemCollection.create({ db })\n ).findByContract(contractId);\n if (lines.length)\n invalid('Received money cannot mix with calculated contract lines');\n contract.moneyAuthority = 'received';\n contract.receivedPurchaseMoneyJson = serialized;\n contract.subtotal = snapshot.facts.netMinor;\n contract.discountTotal = 0;\n contract.taxAmount = snapshot.facts.taxMinor;\n contract.totalAmount = snapshot.facts.grossMinor;\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return snapshot;\n });\n}\n\n/** A received order cannot silently disappear from tax reporting when facts are unknown. */\nexport class ReceivedPurchaseTaxClassificationRequired extends Error {\n readonly code = 'RECEIVED_PURCHASE_TAX_CLASSIFICATION_REQUIRED';\n constructor(readonly contractId: string) {\n super(\n `Purchase order ${contractId} needs explicit tax classification, tax-code/component identity, taxable basis and recoverability in its received evidence before tax reporting. Record a reviewed replacement revision; do not infer tax rates.`,\n );\n this.name = 'ReceivedPurchaseTaxClassificationRequired';\n }\n}\n\n/** @internal Project explicitly classified source facts without inventing DocumentTax rates. */\nexport function receivedPurchaseReportFacts(\n contract: Contract,\n): import('./collections/DocumentTaxCollection.js').DocumentTaxReportFact[] {\n const snapshot = getReceivedPurchaseMoney(contract);\n if (!snapshot || !(contract instanceof PurchaseOrder)) return [];\n const id = text(contract.id, 'Purchase order identity');\n const components = snapshot.facts.taxComponents;\n if (!components?.length)\n throw new ReceivedPurchaseTaxClassificationRequired(id);\n return components.map((component) => {\n if (\n component.classification === null ||\n !component.taxCodeId ||\n component.taxableMinor == null ||\n component.recoverableMinor === null ||\n (component.taxableMinor > snapshot.facts.netMinor &&\n component.netMinor == null) ||\n (component.classification === 'taxable' && !component.taxComponentId)\n )\n throw new ReceivedPurchaseTaxClassificationRequired(id);\n return {\n tenantId: text(contract.tenantId, 'Tenant'),\n documentType: 'contract',\n documentId: id,\n documentNumber: contract.reference.trim() || id,\n partyId: contract.vendorId,\n documentKind: 'contract',\n issueDate: contract.issueDate.toISOString(),\n status: contract.status,\n direction: 'purchase',\n currency: snapshot.facts.currency,\n taxCodeId: component.taxCodeId,\n taxCodeKind: component.classification,\n taxableMinor: component.taxableMinor,\n ...(component.netMinor != null ? { netMinor: component.netMinor } : {}),\n taxMinor: component.amountMinor,\n recoverableMinor: component.recoverableMinor,\n taxComponentId: component.taxComponentId ?? null,\n componentName: component.label,\n liabilityAccountId: null,\n commitmentId: id,\n commitmentLineId: null,\n };\n });\n}\n","/** Owning collection for derived document tax totals. */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { withTenant } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport {\n historicalSalesReportInvoices,\n historicalSalesTaxReportFacts,\n} from '../historical-sales-reports.js';\nimport { classifyContractPurchase } from '../models/Contract.js';\nimport {\n type CommerceDocumentType,\n DocumentTax,\n type DocumentTaxOptions,\n} from '../models/DocumentTax.js';\nimport { MoneyValidationError, type TaxCodeKind } from '../money.js';\nimport { receivedPurchaseReportFacts } from '../received-purchase-money.js';\nimport { ContractCollection } from './ContractCollection.js';\n\nexport type DocumentTaxWriteInput = Required<\n Pick<\n DocumentTaxOptions,\n | 'tenantId'\n | 'documentType'\n | 'documentId'\n | 'currency'\n | 'taxCodeId'\n | 'taxCodeCode'\n | 'kind'\n | 'taxComponentId'\n | 'taxComponentName'\n | 'percent'\n | 'liabilityAccountId'\n | 'taxableMinor'\n | 'taxMinor'\n | 'recoverableMinor'\n >\n> & { netMinor?: number | null };\n\n/** Normalized immutable document-tax snapshots for tax-summary materialization. */\nexport interface DocumentTaxReportFact {\n tenantId: string;\n documentType: CommerceDocumentType;\n documentId: string;\n /** A document number/reference supplied to drilldown consumers. */\n documentNumber: string;\n /** Tenant-scoped party identity for a host to resolve as its party display. */\n partyId: string | null;\n /** Positive credit snapshots are negated once by the pure report aggregation. */\n documentKind: CommerceDocumentType;\n issueDate: string;\n status: string;\n direction: 'sales' | 'purchase';\n currency: string;\n taxCodeId: string | null;\n /** Null is an unassigned/unknown snapshot and must remain visible as a warning. */\n taxCodeKind: TaxCodeKind | null;\n taxableMinor: number;\n netMinor?: number;\n taxMinor: number;\n recoverableMinor: number;\n taxComponentId: string | null;\n componentName: string | null;\n liabilityAccountId: string | null;\n /** Purchase Contracts are the expense commitment identity; other documents are unlinked. */\n commitmentId: string | null;\n /** Document-tax snapshots are contract-level, so they retain no line allocation. */\n commitmentLineId: string | null;\n}\n\n/** @deprecated Use DocumentTaxReportFact. Kept for report-adapter compatibility. */\nexport type InvoiceTaxReportFact = DocumentTaxReportFact;\n\nexport interface DocumentTaxReportFactsOptions {\n tenantId: string;\n from: Date;\n to: Date;\n currency?: string;\n}\n\n/** @deprecated Use DocumentTaxReportFactsOptions. */\nexport type InvoiceTaxReportFactsOptions = DocumentTaxReportFactsOptions;\n\nconst TAX_CODE_KINDS = new Set<TaxCodeKind>([\n 'taxable',\n 'zero-rated',\n 'exempt',\n 'out-of-scope',\n]);\n\nfunction requiredText(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value.trim())\n throw new Error(`Invoice tax report ${label} must be a nonempty string.`);\n return value;\n}\n\nfunction storedMinor(value: unknown, label: string): number {\n const parsed =\n typeof value === 'bigint'\n ? Number(value)\n : typeof value === 'number'\n ? value\n : typeof value === 'string' && /^-?\\d+$/.test(value)\n ? Number(value)\n : Number.NaN;\n if (!Number.isSafeInteger(parsed))\n throw new RangeError(\n `Invoice tax report ${label} must be a safe integer minor-unit value.`,\n );\n return parsed;\n}\n\nfunction reportDate(value: unknown, label: string): string {\n const date = new Date(String(value));\n if (Number.isNaN(date.getTime()))\n throw new Error(`Invoice tax report ${label} must be a valid date.`);\n return date.toISOString();\n}\n\nfunction invoiceDocumentType(value: unknown): 'invoice' | 'credit_note' {\n if (value === 'invoice' || value === 'credit_note') return value;\n throw new Error(\n 'Invoice tax report document type must be invoice or credit_note.',\n );\n}\n\nfunction invoiceKind(value: unknown): 'invoice' | 'credit_note' {\n if (value === 'invoice' || value === 'credit_note') return value;\n throw new Error('Invoice tax report kind must be invoice or credit_note.');\n}\n\nfunction contractDocumentType(value: unknown): 'contract' {\n if (value === 'contract') return value;\n throw new Error('Contract tax report document type must be contract.');\n}\n\nfunction taxCodeKind(value: unknown): TaxCodeKind | null {\n return typeof value === 'string' && TAX_CODE_KINDS.has(value as TaxCodeKind)\n ? (value as TaxCodeKind)\n : null;\n}\n\nfunction assertReportFactOptions(options: DocumentTaxReportFactsOptions): void {\n if (!options.tenantId?.trim())\n throw new Error('Invoice tax report facts require a tenant.');\n if (!(options.from instanceof Date) || Number.isNaN(options.from.getTime()))\n throw new Error('Invoice tax report facts require a valid start date.');\n if (!(options.to instanceof Date) || Number.isNaN(options.to.getTime()))\n throw new Error('Invoice tax report facts require a valid end date.');\n if (options.from > options.to)\n throw new Error('Invoice tax report facts require an ordered date range.');\n if (options.currency !== undefined && !options.currency.trim())\n throw new Error(\n 'Invoice tax report currency must be nonempty when supplied.',\n );\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction identity(\n row: Pick<DocumentTaxWriteInput, 'taxCodeId' | 'taxComponentId'>,\n): string {\n return `${row.taxCodeId === null ? '0:' : `1:${row.taxCodeId}`}\\u0000${\n row.taxComponentId === null ? '0:' : `1:${row.taxComponentId}`\n }`;\n}\n\nconst BUSINESS_FIELDS = [\n 'tenantId',\n 'documentType',\n 'documentId',\n 'currency',\n 'taxCodeId',\n 'taxCodeCode',\n 'kind',\n 'taxComponentId',\n 'taxComponentName',\n 'percent',\n 'liabilityAccountId',\n 'taxableMinor',\n 'netMinor',\n 'taxMinor',\n 'recoverableMinor',\n] as const;\n\nfunction unchanged(row: DocumentTax, input: DocumentTaxWriteInput): boolean {\n return BUSINESS_FIELDS.every((field) => {\n const persisted = row[field];\n const proposed = input[field];\n if (field === 'percent' && persisted !== null && proposed !== null) {\n return String(persisted) === String(proposed);\n }\n return (persisted ?? null) === (proposed ?? null);\n });\n}\n\nexport class DocumentTaxCollection extends SmrtCollection<DocumentTax> {\n static readonly _itemClass = DocumentTax;\n\n /**\n * Read immutable commerce document-tax snapshots for one tenant.\n *\n * Invoice/credit rows join their shared storage by identity and tenant.\n * Purchase Contract rows first use the Contract owner's bounded hydrated\n * candidate API so custom PurchaseContract descendants retain their STI\n * classification. The query then joins only those candidate ids by identity\n * and tenant. Stored snapshots remain authoritative; this never recalculates\n * money or resolves present-day tax configuration.\n */\n async listReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n assertReportFactOptions(options);\n const [invoiceFacts, purchaseFacts] = await Promise.all([\n this.listInvoiceReportFacts(options),\n this.listPurchaseContractReportFacts(options),\n ]);\n return [...invoiceFacts, ...purchaseFacts].sort(\n (left, right) =>\n left.issueDate.localeCompare(right.issueDate) ||\n left.documentId.localeCompare(right.documentId) ||\n String(left.taxCodeId).localeCompare(String(right.taxCodeId)) ||\n String(left.taxComponentId).localeCompare(String(right.taxComponentId)),\n );\n }\n\n private async listInvoiceReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n const currencyClause = options.currency ? ' AND d.currency = ?' : '';\n const result = await this.db.query(\n `SELECT d.tenant_id, d.document_type, d.document_id, d.currency, d.tax_code_id, d.kind,\n d.tax_component_id, d.tax_component_name, d.liability_account_id,\n d.taxable_minor, d.net_minor, d.tax_minor, d.recoverable_minor,\n i.kind AS invoice_kind, i.invoice_number, i.customer_id, i.issue_date, i.status\n FROM document_taxes d\n JOIN invoices i\n ON CAST(i.id AS TEXT) = CAST(d.document_id AS TEXT)\n AND i.tenant_id = d.tenant_id\n WHERE CAST(d.tenant_id AS TEXT) = ?\n AND CAST(i.tenant_id AS TEXT) = ?\n AND (\n (d.document_type = 'invoice' AND i.kind = 'invoice')\n OR (d.document_type = 'credit_note' AND i.kind = 'credit_note')\n )\n AND i.status NOT IN ('draft', 'cancelled')\n AND i.issue_date >= ?\n AND i.issue_date <= ?${currencyClause}\n ORDER BY i.issue_date ASC, i.id ASC, d.tax_code_id ASC, d.tax_component_id ASC`,\n options.tenantId,\n options.tenantId,\n options.from.toISOString(),\n options.to.toISOString(),\n ...(options.currency ? [options.currency] : []),\n );\n const ordinary = result.rows.map(\n (row): DocumentTaxReportFact => ({\n tenantId: requiredText(row.tenant_id, 'tenant id'),\n documentType: invoiceDocumentType(row.document_type),\n documentId: requiredText(row.document_id, 'document id'),\n documentNumber: requiredText(row.invoice_number, 'invoice number'),\n partyId:\n typeof row.customer_id === 'string' && row.customer_id.trim()\n ? row.customer_id\n : null,\n documentKind: invoiceKind(row.invoice_kind),\n issueDate: reportDate(row.issue_date, 'issue date'),\n status: requiredText(row.status, 'invoice status'),\n direction: 'sales' as const,\n currency: requiredText(row.currency, 'currency'),\n taxCodeId: row.tax_code_id == null ? null : String(row.tax_code_id),\n taxCodeKind: taxCodeKind(row.kind),\n taxableMinor: storedMinor(row.taxable_minor, 'taxable minor'),\n ...(row.net_minor != null\n ? { netMinor: storedMinor(row.net_minor, 'net minor') }\n : {}),\n taxMinor: storedMinor(row.tax_minor, 'tax minor'),\n recoverableMinor: storedMinor(\n row.recoverable_minor,\n 'recoverable minor',\n ),\n taxComponentId:\n row.tax_component_id == null ? null : String(row.tax_component_id),\n componentName:\n row.tax_component_name == null\n ? null\n : String(row.tax_component_name),\n liabilityAccountId:\n row.liability_account_id == null\n ? null\n : String(row.liability_account_id),\n commitmentId: null,\n commitmentLineId: null,\n }),\n );\n return [\n ...ordinary,\n ...(await historicalSalesReportInvoices(this.db, options)).flatMap(\n historicalSalesTaxReportFacts,\n ),\n ];\n }\n\n private async listPurchaseContractReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n const contracts = await withTenant({ tenantId: options.tenantId }, () =>\n ContractCollection.create({ db: this.db }).then((collection) =>\n collection.listSnapshotReportContracts({\n tenantId: options.tenantId,\n from: options.from,\n to: options.to,\n }),\n ),\n );\n const candidates = contracts.filter(\n (contract) =>\n classifyContractPurchase(contract) &&\n (!options.currency || contract.currency === options.currency),\n );\n const receivedFacts = candidates\n .filter((contract) => contract.moneyAuthority === 'received')\n .flatMap(receivedPurchaseReportFacts);\n const purchases = candidates.filter(\n (contract) => contract.moneyAuthority !== 'received',\n );\n const ids = purchases.flatMap((contract) =>\n contract.id ? [contract.id] : [],\n );\n if (ids.length === 0) return receivedFacts;\n const byId = new Map(\n purchases.flatMap((contract) =>\n contract.id ? ([[contract.id, contract]] as const) : [],\n ),\n );\n const placeholders = ids.map(() => '?').join(', ');\n const currencyClause = options.currency ? ' AND d.currency = ?' : '';\n const result = await this.db.query(\n `SELECT d.tenant_id, d.document_type, d.document_id, d.currency, d.tax_code_id, d.kind,\n d.tax_component_id, d.tax_component_name, d.liability_account_id,\n d.taxable_minor, d.net_minor, d.tax_minor, d.recoverable_minor\n FROM document_taxes d\n JOIN contracts c\n ON CAST(c.id AS TEXT) = CAST(d.document_id AS TEXT)\n AND c.tenant_id = d.tenant_id\n WHERE CAST(d.tenant_id AS TEXT) = ?\n AND CAST(c.tenant_id AS TEXT) = ?\n AND d.document_type = 'contract'\n AND c.status NOT IN ('draft', 'cancelled')\n AND CAST(d.document_id AS TEXT) IN (${placeholders})${currencyClause}\n ORDER BY c.issue_date ASC, c.id ASC, d.tax_code_id ASC, d.tax_component_id ASC`,\n options.tenantId,\n options.tenantId,\n ...ids,\n ...(options.currency ? [options.currency] : []),\n );\n const calculatedFacts = result.rows.flatMap(\n (row): DocumentTaxReportFact[] => {\n const documentId = requiredText(row.document_id, 'contract id');\n const contract = byId.get(documentId);\n if (!contract) return [];\n return [\n {\n tenantId: requiredText(row.tenant_id, 'tenant id'),\n documentType: contractDocumentType(row.document_type),\n documentId,\n documentNumber: contract.reference.trim() || documentId,\n partyId:\n 'vendorId' in contract &&\n typeof contract.vendorId === 'string' &&\n contract.vendorId.trim()\n ? contract.vendorId\n : null,\n documentKind: 'contract',\n issueDate: reportDate(contract.issueDate, 'contract issue date'),\n status: requiredText(contract.status, 'contract status'),\n direction: 'purchase',\n currency: requiredText(row.currency, 'currency'),\n taxCodeId: row.tax_code_id == null ? null : String(row.tax_code_id),\n taxCodeKind: taxCodeKind(row.kind),\n taxableMinor: storedMinor(row.taxable_minor, 'taxable minor'),\n ...(row.net_minor != null\n ? { netMinor: storedMinor(row.net_minor, 'net minor') }\n : {}),\n taxMinor: storedMinor(row.tax_minor, 'tax minor'),\n recoverableMinor: storedMinor(\n row.recoverable_minor,\n 'recoverable minor',\n ),\n taxComponentId:\n row.tax_component_id == null\n ? null\n : String(row.tax_component_id),\n componentName:\n row.tax_component_name == null\n ? null\n : String(row.tax_component_name),\n liabilityAccountId:\n row.liability_account_id == null\n ? null\n : String(row.liability_account_id),\n // Expenses reference their PurchaseContract id as commitmentId.\n commitmentId: documentId,\n commitmentLineId: null,\n },\n ];\n },\n );\n return [...calculatedFacts, ...receivedFacts];\n }\n\n async findByDocument(\n tenantId: string,\n documentType: CommerceDocumentType,\n documentId: string,\n ): Promise<DocumentTax[]> {\n return this.list({\n where: { tenantId, documentType, documentId },\n orderBy: ['taxCodeId ASC', 'taxComponentId ASC'],\n });\n }\n\n /**\n * Replace one draft document's derived rows on the caller's transaction.\n * Unchanged rows are not saved, preserving their exact persisted bytes.\n *\n * @internal Aggregate persistence only.\n */\n async replaceDerivedForDocument(\n capability: DocumentMoneyWriteCapability,\n input: {\n tenantId: string;\n documentType: CommerceDocumentType;\n documentId: string;\n rows: readonly DocumentTaxWriteInput[];\n },\n ): Promise<DocumentTax[]> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n const desired = new Map<string, DocumentTaxWriteInput>();\n for (const row of input.rows) {\n if (\n row.tenantId !== input.tenantId ||\n row.documentType !== input.documentType ||\n row.documentId !== input.documentId\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax replacement rows must share tenant and document identity',\n );\n }\n const key = identity(row);\n if (desired.has(key)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax replacement contains a duplicate code/component identity',\n );\n }\n desired.set(key, row);\n }\n\n const existing = await this.findByDocument(\n input.tenantId,\n input.documentType,\n input.documentId,\n );\n const byIdentity = new Map(existing.map((row) => [identity(row), row]));\n const result: DocumentTax[] = [];\n for (const [key, rowInput] of [...desired].sort(([left], [right]) =>\n compareCodeUnits(left, right),\n )) {\n const current = byIdentity.get(key);\n if (current) {\n byIdentity.delete(key);\n if (!unchanged(current, rowInput)) {\n Object.assign(current, rowInput);\n await current.saveDerived(capability);\n }\n result.push(current);\n continue;\n }\n const created = await this.createUnsaved(rowInput);\n await created.saveDerived(capability);\n result.push(created);\n }\n for (const stale of [...byIdentity.values()].sort((left, right) =>\n compareCodeUnits(String(left.id), String(right.id)),\n )) {\n await stale.deleteDerived(capability, {\n expectedUpdatedAt: stale.updated_at ?? undefined,\n });\n }\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocumentTaxCollection-D85ut-Fo.js","names":["field","revision","saved","input","netMinor","taxMinor","grossMinor"],"sources":["../../src/party-contacts.ts","../../src/models/Customer.ts","../../src/collections/CustomerCollection.ts","../../src/models/InvoiceLineItem.ts","../../src/collections/InvoiceLineItemCollection.ts","../../src/models/HistoricalSalesLine.ts","../../src/collections/HistoricalSalesLineCollection.ts","../../src/models/Vendor.ts","../../src/models/Contract.ts","../../src/collections/PurchaseContractCollection.ts","../../src/collections/SalesContractCollection.ts","../../src/collections/ContractCollection.ts","../../src/contract-billing-schedule.ts","../../src/document-money.ts","../../src/historical-sales-validation.ts","../../src/historical-sales-money.ts","../../src/historical-sales-reports.ts","../../src/models/DocumentTax.ts","../../src/collections/VendorCollection.ts","../../src/received-purchase-money.ts","../../src/collections/DocumentTaxCollection.ts"],"sourcesContent":["/**\n * Contact rows for customers and vendors (#3501).\n *\n * `CustomerForm` and `VendorForm` (`./svelte`) post contacts as repeated\n * field names in DOM order, one value per row for each of `contactId`,\n * `contactName`, `contactLabel`, `contactEmail`, `contactPhone`, and\n * `contactAddress` (all overridable through the forms' `fieldNames`). The\n * helpers here read that payload, apply the native add/remove intents, and\n * write the rows to `Customer.contacts` / `Vendor.contacts`.\n *\n * @packageDocumentation\n */\n\nimport type { CustomerCollection } from './collections/CustomerCollection.js';\nimport type { VendorCollection } from './collections/VendorCollection.js';\nimport type { Customer } from './models/Customer.js';\nimport type { Vendor } from './models/Vendor.js';\nimport type { PartyContact } from './types/index.js';\n\n/** One submitted contact row, exactly as posted (untrimmed strings). */\nexport type PartyContactInput = Partial<PartyContact>;\n\n/** The text fields of a contact, which are also its error keys. */\nexport type PartyContactField = Exclude<keyof PartyContact, 'id'>;\n\n/** HTML names of the repeated contact fields; defaults match the forms. */\nexport interface PartyContactFieldNames {\n contactId: string;\n contactName: string;\n contactLabel: string;\n contactEmail: string;\n contactPhone: string;\n contactAddress: string;\n /** Hidden presence marker: the number of contact rows the form rendered. */\n contactCount: string;\n}\n\n/** Default contact field names, matching `DEFAULT_PARTY_FIELD_NAMES` in `./svelte`. */\nexport const DEFAULT_PARTY_CONTACT_FIELD_NAMES: PartyContactFieldNames = {\n contactId: 'contactId',\n contactName: 'contactName',\n contactLabel: 'contactLabel',\n contactEmail: 'contactEmail',\n contactPhone: 'contactPhone',\n contactAddress: 'contactAddress',\n contactCount: 'contactCount',\n};\n\n/** Maximum lengths, matching the form controls' `maxlength`. */\nexport const PARTY_CONTACT_MAX_LENGTHS: Readonly<\n Record<PartyContactField, number>\n> = {\n name: 160,\n label: 80,\n email: 320,\n phone: 80,\n address: 500,\n};\n\n/**\n * Per-row validation error codes, keyed by field. `unknown_contact` (on\n * `id`) means the posted id is not one of the party's saved contacts — a\n * stale or altered form; reload the party and show its current rows.\n */\nexport type PartyContactErrorCode =\n | 'too_long'\n | 'invalid_email'\n | 'unknown_contact';\n\n/** Errors for one submitted row; indexes match the submitted rows. */\nexport type PartyContactRowErrors = Partial<\n Record<PartyContactField | 'id', PartyContactErrorCode>\n>;\n\nconst FIELDS: readonly PartyContactField[] = [\n 'name',\n 'label',\n 'email',\n 'phone',\n 'address',\n];\n\n/** Thrown by {@link savePartyContacts} when any row is invalid; nothing is written. */\nexport class PartyContactValidationError extends Error {\n /** Errors aligned with the submitted rows; `undefined` for a valid row. */\n readonly errors: Array<PartyContactRowErrors | undefined>;\n\n constructor(errors: Array<PartyContactRowErrors | undefined>) {\n super('One or more contact rows are invalid');\n this.name = 'PartyContactValidationError';\n this.errors = errors;\n }\n}\n\n/**\n * Thrown by {@link readPartyContactRows} (and so {@link savePartyContacts}\n * given a form) when the posted contact payload cannot be trusted:\n * `missing` — no `contactCount` marker, so the editable contact block did\n * not render or was posted under other field names (treating that as \"no\n * contacts\" would delete them all); `misaligned` — the repeated fields or\n * the marker disagree on the row count. Nothing is written.\n */\nexport class PartyContactPayloadError extends Error {\n readonly reason: 'missing' | 'misaligned';\n\n constructor(reason: 'missing' | 'misaligned', message: string) {\n super(message);\n this.name = 'PartyContactPayloadError';\n this.reason = reason;\n }\n}\n\n/** Thrown by {@link savePartyContacts} when the party is not visible in the current tenant. */\nexport class PartyContactPartyNotFoundError extends Error {\n constructor(partyId: string) {\n super(`Customer or vendor ${partyId} was not found`);\n this.name = 'PartyContactPartyNotFoundError';\n }\n}\n\nfunction text(value: unknown): string {\n return typeof value === 'string' ? value : '';\n}\n\n/**\n * Normalize stored contacts (an array, a JSON string, or nothing) into\n * well-formed {@link PartyContact} rows. Non-object entries and non-string\n * values are dropped; a row without an id is given one.\n */\nexport function normalizePartyContacts(value: unknown): PartyContact[] {\n let input = value;\n if (typeof input === 'string') {\n try {\n input = JSON.parse(input);\n } catch {\n return [];\n }\n }\n if (!Array.isArray(input)) return [];\n const contacts: PartyContact[] = [];\n for (const entry of input) {\n if (!entry || typeof entry !== 'object') continue;\n const row = entry as Record<string, unknown>;\n contacts.push({\n id: text(row.id) || globalThis.crypto.randomUUID(),\n name: text(row.name),\n label: text(row.label),\n email: text(row.email),\n phone: text(row.phone),\n address: text(row.address),\n });\n }\n return contacts;\n}\n\n/** Minimal form-data reader; `FormData` and `URLSearchParams` both satisfy it. */\nexport interface PartyContactFormSource {\n getAll(name: string): unknown[];\n}\n\n/**\n * Read the contact rows a party form posted, in DOM order. The editable\n * contact block always posts a `contactCount` marker with its row count, and\n * every row renders all six fields. A missing marker (the block did not\n * render, or `fieldNames` differ from the form's) or any disagreeing count\n * throws {@link PartyContactPayloadError}, so zero rows is only ever read\n * when the form really posted an empty contact list.\n */\nexport function readPartyContactRows(\n form: PartyContactFormSource,\n fieldNames: Partial<PartyContactFieldNames> = {},\n): PartyContactInput[] {\n const names = { ...DEFAULT_PARTY_CONTACT_FIELD_NAMES, ...fieldNames };\n const column = (name: string) => form.getAll(name).map(text);\n const columns = {\n id: column(names.contactId),\n name: column(names.contactName),\n label: column(names.contactLabel),\n email: column(names.contactEmail),\n phone: column(names.contactPhone),\n address: column(names.contactAddress),\n };\n const markers = column(names.contactCount);\n if (markers.length !== 1)\n throw new PartyContactPayloadError(\n markers.length === 0 ? 'missing' : 'misaligned',\n markers.length === 0\n ? `Contact payload has no ${names.contactCount} marker; the contact fields were not posted under these names`\n : `Contact payload has ${markers.length} ${names.contactCount} markers`,\n );\n const count = columns.id.length;\n if (markers[0] !== String(count))\n throw new PartyContactPayloadError(\n 'misaligned',\n `Contact payload is misaligned: ${names.contactCount} is ${markers[0]} but ${count} contact ids were posted`,\n );\n for (const [key, values] of Object.entries(columns)) {\n if (values.length !== count)\n throw new PartyContactPayloadError(\n 'misaligned',\n `Contact payload is misaligned: ${count} contact ids but ${values.length} ${key} values`,\n );\n }\n return columns.id.map((id, index) => ({\n id,\n name: columns.name[index],\n label: columns.label[index],\n email: columns.email[index],\n phone: columns.phone[index],\n address: columns.address[index],\n }));\n}\n\n/** Submitter values for the forms' native contact row actions. */\nexport interface PartyContactIntents {\n /** Defaults to the forms' `addContact`. */\n addIntent?: string;\n /** Parses a remove submitter into a row index; defaults to `removeContact:<index>`. */\n parseRemoveIntent?: (intent: string) => number | undefined;\n}\n\nfunction defaultParseRemoveIntent(intent: string): number | undefined {\n const match = /^removeContact:(\\d+)$/.exec(intent);\n return match ? Number(match[1]) : undefined;\n}\n\n/**\n * Apply an add or remove submitter to the posted rows and return the rows\n * to render back into the form. Nothing is persisted: a row action is a\n * round trip, and only the save intent writes. `handled` is `false` for any\n * other intent (including save), with the rows unchanged; when it is `true`,\n * render the returned rows and do not save.\n */\nexport function applyPartyContactIntent(\n rows: readonly PartyContactInput[],\n intent: string,\n intents: PartyContactIntents = {},\n): { contacts: PartyContactInput[]; handled: boolean } {\n if (intent === (intents.addIntent ?? 'addContact'))\n return { contacts: [...rows, {}], handled: true };\n const index = (intents.parseRemoveIntent ?? defaultParseRemoveIntent)(intent);\n // A stale index (the row is already gone) is still a remove: it must not\n // fall through to a save.\n if (index !== undefined)\n return {\n contacts: rows.filter((_, position) => position !== index),\n handled: true,\n };\n return { contacts: [...rows], handled: false };\n}\n\n// Deliberately permissive: one \"@\" with text on both sides and no spaces.\n// Deliverability is the caller's concern.\nconst EMAIL = /^[^\\s@]+@[^\\s@]+$/;\n\n/**\n * Validate posted rows without persisting them. Returns the trimmed rows\n * that would be written (blank rows dropped) and, when any row is invalid,\n * errors aligned with the submitted rows. Ids are checked against the\n * party's saved contacts only by {@link savePartyContacts}.\n */\nexport function validatePartyContactRows(rows: readonly PartyContactInput[]): {\n contacts: PartyContactInput[];\n errors?: Array<PartyContactRowErrors | undefined>;\n} {\n const contacts: PartyContactInput[] = [];\n const errors: Array<PartyContactRowErrors | undefined> = [];\n let invalid = false;\n rows.forEach((row, index) => {\n const trimmed: PartyContactInput = { id: text(row.id).trim() };\n let rowErrors: PartyContactRowErrors | undefined;\n for (const field of FIELDS) {\n const value = text(row[field]).trim();\n trimmed[field] = value;\n if (value.length > PARTY_CONTACT_MAX_LENGTHS[field])\n rowErrors = { ...rowErrors, [field]: 'too_long' };\n }\n if (trimmed.email && !rowErrors?.email && !EMAIL.test(trimmed.email))\n rowErrors = { ...rowErrors, email: 'invalid_email' };\n errors[index] = rowErrors;\n if (rowErrors) invalid = true;\n if (FIELDS.some((field) => trimmed[field])) contacts.push(trimmed);\n });\n return invalid ? { contacts, errors } : { contacts };\n}\n\n/** Options for {@link savePartyContacts}. */\nexport interface SavePartyContactsOptions {\n /** Field names used to read a posted form; must match the form's `fieldNames`. */\n fieldNames?: Partial<PartyContactFieldNames>;\n /**\n * When set, the party must belong to this tenant. Use it to bind a form's\n * posted tenant to the loaded row in addition to the active tenant\n * context, which already scopes the lookup.\n */\n expectedTenantId?: string | null;\n}\n\n/**\n * Replace a customer's or vendor's contacts with the rows its form posted.\n *\n * Pass the posted `FormData` (with `options.fieldNames` when the form\n * overrides them): it is read with {@link readPartyContactRows}, so a payload\n * without the contact block's presence marker throws\n * {@link PartyContactPayloadError} instead of removing every contact. An\n * array is taken as rows the caller already read through that function.\n *\n * The party is loaded through `collection.get()`, so the active tenant\n * context scopes it: a party in another tenant is not found. Rows are\n * validated ({@link validatePartyContactRows}), blank rows dropped, kept\n * rows matched to saved contacts by id (new rows get a fresh id), and rows\n * that were not posted are removed. A posted id the party does not have is\n * an `unknown_contact` error. On any error nothing is written and a\n * {@link PartyContactValidationError} is thrown.\n *\n * This is a read-modify-write of one row: concurrent saves of the same party\n * are last-writer-wins, like any other field edit.\n *\n * @returns The saved contacts, in submitted order.\n */\nexport async function savePartyContacts(\n collection: CustomerCollection | VendorCollection,\n partyId: string,\n posted: PartyContactFormSource | readonly PartyContactInput[],\n options: SavePartyContactsOptions = {},\n): Promise<PartyContact[]> {\n // Reading the form here (rather than trusting a caller's array) keeps the\n // presence-marker check on the write path.\n const rows = Array.isArray(posted)\n ? (posted as readonly PartyContactInput[])\n : readPartyContactRows(\n posted as PartyContactFormSource,\n options.fieldNames,\n );\n const party: Customer | Vendor | null = await collection.get({\n id: partyId,\n });\n if (\n !party ||\n (options.expectedTenantId !== undefined &&\n party.tenantId !== options.expectedTenantId)\n )\n throw new PartyContactPartyNotFoundError(partyId);\n\n const validation = validatePartyContactRows(rows);\n const { contacts } = validation;\n const errors = validation.errors ?? rows.map(() => undefined);\n const saved = new Set(\n normalizePartyContacts(party.contacts).map((c) => c.id),\n );\n let invalid = validation.errors !== undefined;\n rows.forEach((row, index) => {\n const id = text(row.id).trim();\n if (id && !saved.has(id)) {\n errors[index] = { ...errors[index], id: 'unknown_contact' };\n invalid = true;\n }\n });\n if (invalid) throw new PartyContactValidationError(errors);\n\n const seen = new Set<string>();\n party.contacts = contacts.map((row) => {\n // A duplicated posted id (two rows claiming one contact) keeps the id\n // on the first row only, so stored ids stay unique.\n const id =\n row.id && !seen.has(row.id) ? row.id : globalThis.crypto.randomUUID();\n seen.add(id);\n return {\n id,\n name: row.name ?? '',\n label: row.label ?? '',\n email: row.email ?? '',\n phone: row.phone ?? '',\n address: row.address ?? '',\n };\n });\n await party.save();\n return party.contacts;\n}\n","/**\n * Customer model - links to Profile with customer-specific data\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { normalizePartyContacts } from '../party-contacts.js';\nimport {\n type Address,\n type CustomerOptions,\n CustomerStatus,\n CustomerType,\n type PartyContact,\n} from '../types/index.js';\n\n/**\n * Customer represents the customer role for a Profile.\n *\n * One Profile can have multiple Customer records (e.g., different business contexts).\n * Customer stores customer-specific data like credit limits and payment terms.\n *\n * @example\n * ```typescript\n * const customer = await customers.create({\n * profileId: 'profile-uuid',\n * creditLimit: 10000,\n * paymentTerms: 'Net 30'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Customer extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global customers\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Reference to smrt-profiles Profile\n * Plain string for cross-package reference\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', {\n description:\n 'Links this customer to their profile record, where their name and contact details are kept.',\n })\n profileId: string = '';\n\n /**\n * Maximum credit extended to this customer, in **integer minor units**\n * (cents, satoshis).\n *\n * Converts with the rest of commerce because\n * {@link Customer.hasAvailableCredit} compares it directly against a money\n * amount; a dollars-vs-cents split there would approve every request off by\n * a factor of 100 (#2401).\n */\n @field({\n description:\n 'The most this customer may owe you at one time. Leave it at zero if you do not set limits.',\n ui: { format: 'money' },\n })\n creditLimit: number = 0;\n\n /**\n * Payment terms (e.g., \"Net 30\", \"Due on receipt\", \"2/10 Net 30\")\n */\n @field({\n description:\n 'How long the customer has to pay, written the way you would say it, for example \"Net 30\".',\n })\n paymentTerms: string = '';\n\n /**\n * Whether customer is exempt from tax\n */\n @field({\n description: 'Turn this on if you do not charge this customer sales tax.',\n })\n taxExempt: boolean = false;\n\n /**\n * Tax identification number\n *\n * Sensitive (#1540): PII excluded from generated API/MCP responses and\n * rejected as a `where` filter key.\n */\n @field({\n sensitive: true,\n description:\n 'The tax or VAT number of the customer, kept on file for tax-exempt sales.',\n })\n taxId: string = '';\n\n /**\n * Tax code normally used for this customer's sales.\n *\n * An exempt customer always resolves to the tenant's exempt code before\n * this preference is considered.\n */\n @foreignKey('TaxCode', {\n description: 'The tax code normally used when selling to this customer.',\n })\n defaultTaxCodeId: string = '';\n\n /**\n * Default shipping address\n */\n @field({\n description:\n 'Where you usually send goods to this customer, so you do not retype it on every order.',\n })\n defaultShippingAddress: Address = {};\n\n /**\n * Default billing address\n */\n @field({ description: 'Where you send invoices to this customer.' })\n defaultBillingAddress: Address = {};\n\n /**\n * Customer status\n */\n @field({\n description:\n 'Whether you are still dealing with this customer: active, inactive or suspended.',\n })\n status: CustomerStatus = CustomerStatus.ACTIVE;\n\n /**\n * Customer classification — DTC, wholesale, or retail.\n *\n * Drives channel access (wholesale portal vs. storefront vs. POS), default\n * price tier, and credit terms. Defaults to DTC for backwards compatibility.\n */\n @field({\n description:\n 'The kind of customer: a direct shopper, a wholesale buyer or a retail customer.',\n })\n customerType: CustomerType = CustomerType.DTC;\n\n /**\n * Internal notes about this customer\n */\n @field({\n description: 'Anything worth remembering about this customer.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * People to reach at this customer, stored as a JSON column (#3501). Write\n * form rows through `savePartyContacts()`; every save normalizes the shape.\n */\n @field({\n description:\n 'The people you deal with at this customer, with their role and how to reach them.',\n })\n contacts: PartyContact[] = [];\n\n constructor(options: CustomerOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.creditLimit !== undefined)\n this.creditLimit = options.creditLimit;\n if (options.paymentTerms !== undefined)\n this.paymentTerms = options.paymentTerms;\n if (options.taxExempt !== undefined) this.taxExempt = options.taxExempt;\n if (options.taxId !== undefined) this.taxId = options.taxId;\n if (options.defaultTaxCodeId !== undefined)\n this.defaultTaxCodeId = options.defaultTaxCodeId;\n if (options.defaultShippingAddress !== undefined)\n this.defaultShippingAddress = options.defaultShippingAddress;\n if (options.defaultBillingAddress !== undefined)\n this.defaultBillingAddress = options.defaultBillingAddress;\n if (options.status !== undefined) this.status = options.status;\n // Treat `null` the same as `undefined` here. Customers loaded from\n // rows written before the `customer_type` column existed will\n // hydrate with the field as SQL `NULL`; without this guard the\n // SmrtObject loader would overwrite the `CustomerType.DTC`\n // initializer with `null`, breaking the documented\n // backwards-compatible default. Explicit string values (including\n // any future custom flavour) still take precedence.\n if (options.customerType !== undefined && options.customerType !== null) {\n this.customerType = options.customerType;\n }\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.contacts !== undefined)\n this.contacts = normalizePartyContacts(options.contacts);\n }\n\n /**\n * Re-normalize contacts after the framework's option-override pass, which\n * re-applies raw option values (including a stored JSON string).\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n this.contacts = normalizePartyContacts(this.contacts);\n return this;\n }\n\n /** Save with a final contacts normalization against direct assignment. */\n override async save(): Promise<this> {\n this.contacts = normalizePartyContacts(this.contacts);\n return super.save() as Promise<this>;\n }\n\n /**\n * Convenience predicate: is this a wholesale customer?\n */\n isWholesale(): boolean {\n return this.customerType === CustomerType.WHOLESALE;\n }\n\n /**\n * Check if customer is active\n */\n isActive(): boolean {\n return this.status === CustomerStatus.ACTIVE;\n }\n\n /**\n * Check if customer has available credit\n */\n hasAvailableCredit(amount: number): boolean {\n // In a full implementation, this would check against outstanding balances\n return this.creditLimit >= amount;\n }\n\n /**\n * Get the profile ID for external lookup.\n *\n * To get the actual Profile object, use the ProfileCollection from smrt-profiles:\n * ```typescript\n * const profiles = await ProfileCollection.create(options);\n * const profile = await profiles.get({ id: customer.profileId });\n * ```\n *\n * @returns The profile ID or empty string if not set\n */\n getProfileId(): string {\n return this.profileId;\n }\n}\n\nexport default Customer;\n","/**\n * CustomerCollection - Collection manager for Customer objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Customer } from '../models/Customer.js';\nimport { CustomerStatus } from '../types/index.js';\n\nexport class CustomerCollection extends SmrtCollection<Customer> {\n static readonly _itemClass = Customer;\n\n /**\n * Find customers by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of customers linked to this profile\n */\n async findByProfile(profileId: string): Promise<Customer[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active customers\n *\n * @returns Array of active customers\n */\n async findActive(): Promise<Customer[]> {\n return await this.list({\n where: { status: CustomerStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find customers by status\n *\n * @param status - Customer status\n * @returns Array of customers\n */\n async findByStatus(status: CustomerStatus): Promise<Customer[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a customer for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Customer\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n creditLimit: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Customer> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const customer = await this.create({\n profileId,\n creditLimit: defaults.creditLimit ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: CustomerStatus.ACTIVE,\n });\n await customer.save();\n return customer;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all customers belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of customers for the tenant\n */\n async findByTenant(tenantId: string): Promise<Customer[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global customers (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global customers\n */\n async findGlobal(): Promise<Customer[]> {\n return queryGlobal<Customer>(this);\n }\n\n /**\n * Find customers for a tenant including global customers.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global customers\n */\n async findWithGlobals(tenantId: string): Promise<Customer[]> {\n return queryWithGlobals<Customer>(\n this,\n tenantId,\n 'Customer.findWithGlobals',\n );\n }\n}\n","/**\n * InvoiceLineItem model - individual items on an invoice\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_READ_REBIND,\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyReadRebindCapability,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError } from '../money.js';\nimport type {\n InvoiceCreditCalculationBasis,\n InvoiceLineItemOptions,\n InvoiceTaxComponentSnapshot,\n} from '../types/index.js';\n\n/**\n * InvoiceLineItem represents a single line item on an invoice.\n *\n * Line items contain details of what is being billed, including\n * quantity, pricing, and optional source tracking (e.g., from ad campaigns).\n *\n * @example\n * ```typescript\n * const lineItem = await lineItems.create({\n * invoiceId: invoice.id,\n * description: 'Display Advertising - Summer Campaign',\n * quantity: 50000, // impressions\n * unitPrice: 1, // 1 cent per impression (minor units)\n * taxRate: 0.05,\n * sourceType: 'campaign',\n * sourceId: 'campaign-uuid',\n * periodStart: new Date('2025-06-01'),\n * periodEnd: new Date('2025-06-30')\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n writable: [\n 'invoiceId',\n 'description',\n 'sku',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discount',\n 'discountType',\n 'discountRate',\n 'taxRate',\n 'taxMode',\n 'taxCodeId',\n 'sourceType',\n 'sourceId',\n 'periodStart',\n 'periodEnd',\n 'revenueAccountId',\n 'sortOrder',\n ],\n },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class InvoiceLineItem extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /** @internal Collection read guard returns this snapshot on its root DB. */\n rebindMoneyRead(\n capability: DocumentMoneyReadRebindCapability,\n db: DatabaseInterface,\n ): this {\n if (capability !== DOCUMENT_MONEY_READ_REBIND)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice line read rebinding requires the owning capability',\n );\n this._db = db;\n this.options.db = db;\n return this;\n }\n\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global invoice line items\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Parent invoice\n */\n @field({ description: 'The invoice this line belongs to.' })\n @foreignKey('Invoice', { role: 'items' })\n invoiceId: string = '';\n\n @foreignKey('InvoiceLineItem', { nullable: true })\n creditedLineId: string | null = null;\n\n @field({\n description:\n 'Frozen source basis used to cap and reproduce an issued credit line.',\n })\n creditCalculationBasisJson = '';\n\n get creditCalculationBasis(): InvoiceCreditCalculationBasis | null {\n try {\n const value: unknown = JSON.parse(this.creditCalculationBasisJson);\n if (!value || typeof value !== 'object' || !('kind' in value))\n return null;\n const basis = value as Record<string, unknown>;\n if (\n (basis.kind !== 'quantity' && basis.kind !== 'net_amount') ||\n typeof basis.sourceQuantity !== 'string' ||\n !Number.isSafeInteger(basis.sourceUnitPrice) ||\n (basis.sourceDiscountType !== 'none' &&\n basis.sourceDiscountType !== 'percent' &&\n basis.sourceDiscountType !== 'amount') ||\n typeof basis.sourceDiscountRate !== 'string' ||\n !Number.isSafeInteger(basis.sourceDiscountMinor) ||\n (basis.kind === 'quantity' && typeof basis.quantity !== 'string') ||\n (basis.kind === 'net_amount' && !Number.isSafeInteger(basis.netMinor))\n )\n return null;\n return basis as unknown as InvoiceCreditCalculationBasis;\n } catch {\n return null;\n }\n }\n\n set creditCalculationBasis(value: InvoiceCreditCalculationBasis | null) {\n this.creditCalculationBasisJson = value ? JSON.stringify(value) : '';\n }\n\n /**\n * Item description\n */\n @field({ description: 'What is being billed on this line.' })\n description: string = '';\n\n /**\n * SKU or item code\n */\n sku: string = '';\n\n @crossPackageRef('@happyvertical/smrt-products:Product', { nullable: true })\n productId: string | null = null;\n\n /** Nonnegative decimal quantity (hours, weight, units), up to six fractional digits. */\n @field({ description: 'How many.' })\n quantity: number = 1.0;\n\n /**\n * Unit price before discount, in **integer minor units** (cents, satoshis),\n * in the document's pricing mode: tax-inclusive when its `lineAmountType`\n * is `inclusive`.\n *\n * Money is exact, so it is stored as minor units and never as a float —\n * `$19.99` is `1999`. An integer literal is what maps this to an INTEGER\n * column (#2361).\n */\n @field({\n description:\n \"The price of one, before discount; includes tax when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n unitPrice: number = 0;\n\n /**\n * Discount amount (flat, not percentage), in integer minor units (#2361).\n */\n @field({ ui: { format: 'money' } })\n discount: number = 0;\n\n discountType: 'none' | 'percent' | 'amount' = 'none';\n\n @field({ type: 'decimal' })\n discountRate = '0.0';\n\n /**\n * Tax rate as a decimal fraction (e.g., 0.05 for 5%).\n *\n * A genuine rate, not money: it is inherently fractional, so the `0.0`\n * initializer is load-bearing and maps it to a DECIMAL column. INTEGER would\n * truncate every rate to 0 (#2361).\n */\n @field({\n description:\n 'The stored fractional tax rate for this line (0.05 means 5%).',\n })\n taxRate: number = 0.0;\n\n taxMode: 'inherit' | 'override' = 'inherit';\n\n @foreignKey('TaxCode', { nullable: true })\n taxCodeId: string | null = null;\n\n taxCodeCode: string | null = null;\n\n taxCodeName: string | null = null;\n\n taxComponentsJson: string | null = null;\n\n get taxComponents(): InvoiceTaxComponentSnapshot[] {\n if (this.taxComponentsJson === null) return [];\n try {\n const value: unknown = JSON.parse(this.taxComponentsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is InvoiceTaxComponentSnapshot =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as InvoiceTaxComponentSnapshot).taxComponentId ===\n 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).name === 'string' &&\n typeof (entry as InvoiceTaxComponentSnapshot).percent === 'string' &&\n Number.isSafeInteger((entry as InvoiceTaxComponentSnapshot).taxMinor),\n );\n } catch {\n return [];\n }\n }\n\n set taxComponents(value: InvoiceTaxComponentSnapshot[]) {\n this.taxComponentsJson = JSON.stringify(value);\n }\n\n /** Exact sum of frozen component taxes, in integer minor units. */\n @field({ ui: { format: 'money' } })\n taxAmount = 0;\n\n /** Stable document snapshot identity; ordinary lifecycle saves do not change it. */\n moneySnapshotId = '';\n\n /**\n * Calculated line amount, in integer minor units (#2361): net of discount\n * and before tax for `exclusive` / `none` documents, and tax-inclusive for\n * `inclusive` ones; {@link taxAmount} holds the tax.\n */\n @field({\n description:\n \"The line amount: net of discount, and including tax only when the document's prices include tax.\",\n ui: { format: 'money' },\n })\n amount: number = 0;\n\n // ============================================================================\n // Source Tracking\n // ============================================================================\n\n /**\n * Type of source ('campaign' | 'contract' | 'manual' | etc.)\n */\n sourceType: string = '';\n\n /**\n * ID of the source (e.g., campaign ID, contract ID)\n */\n sourceId: string = '';\n\n /**\n * Service period start (for time-based billing)\n */\n periodStart: Date | null = null;\n\n /**\n * Service period end (for time-based billing)\n */\n periodEnd: Date | null = null;\n\n // ============================================================================\n // Accounting\n // ============================================================================\n\n /**\n * Revenue account ID (cross-package ref to smrt-ledgers)\n * Used for revenue recognition to specific accounts\n */\n @crossPackageRef('@happyvertical/smrt-ledgers:Account', { nullable: true })\n revenueAccountId: string | null = null;\n\n /**\n * Sort order within the invoice\n */\n sortOrder: number = 0;\n\n constructor(options: InvoiceLineItemOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.invoiceId !== undefined) this.invoiceId = options.invoiceId;\n if (options.creditedLineId !== undefined)\n this.creditedLineId = options.creditedLineId;\n if (options.creditCalculationBasisJson !== undefined)\n this.creditCalculationBasisJson = options.creditCalculationBasisJson;\n if (options.creditCalculationBasis !== undefined)\n this.creditCalculationBasis = structuredClone(\n options.creditCalculationBasis,\n );\n if (options.description !== undefined)\n this.description = options.description;\n if (options.sku !== undefined) this.sku = options.sku;\n if (options.productId !== undefined) this.productId = options.productId;\n if (options.quantity !== undefined) this.quantity = options.quantity;\n if (options.unitPrice !== undefined) this.unitPrice = options.unitPrice;\n if (options.discount !== undefined) this.discount = options.discount;\n if (options.discountType !== undefined)\n this.discountType = options.discountType;\n if (options.discountRate !== undefined)\n this.discountRate = options.discountRate;\n if (options.taxRate !== undefined) this.taxRate = options.taxRate;\n if (options.taxMode !== undefined) this.taxMode = options.taxMode;\n if (options.taxCodeId !== undefined) this.taxCodeId = options.taxCodeId;\n if (options.taxCodeCode !== undefined)\n this.taxCodeCode = options.taxCodeCode;\n if (options.taxCodeName !== undefined)\n this.taxCodeName = options.taxCodeName;\n if (options.taxComponentsJson !== undefined)\n this.taxComponentsJson = options.taxComponentsJson;\n if (options.taxComponents !== undefined)\n this.taxComponents = structuredClone(options.taxComponents);\n if (options.taxAmount !== undefined) this.taxAmount = options.taxAmount;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.amount !== undefined) this.amount = options.amount;\n if (options.sourceType !== undefined) this.sourceType = options.sourceType;\n if (options.sourceId !== undefined) this.sourceId = options.sourceId;\n if (options.periodStart !== undefined)\n this.periodStart = options.periodStart;\n if (options.periodEnd !== undefined) this.periodEnd = options.periodEnd;\n if (options.revenueAccountId !== undefined)\n this.revenueAccountId = options.revenueAccountId;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n /** Refuse an old-format row read from the database. */\n override async initialize(): Promise<this> {\n await super.initialize();\n // A row read from the database must not be old-format money data.\n if (this.isPersisted) {\n const { assertHydratedMoneyRowCurrent } = await import(\n '../upgrade/detect.js'\n );\n await assertHydratedMoneyRowCurrent(this);\n }\n return this;\n }\n\n /** Persist through the invoice money aggregate. */\n override async save(): Promise<this> {\n const { saveInvoiceLineItem } = await import('../document-money.js');\n return (await saveInvoiceLineItem(this)) as this;\n }\n\n /** @internal Aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Invoice line money write capability is required');\n // Money is integer minor units: refuse a major-unit price before it can\n // reach the database (#2401), ahead of the aggregate recompute.\n for (const [field, value] of [\n ['unitPrice', this.unitPrice],\n ['discount', this.discount],\n ] as const)\n if (!Number.isSafeInteger(value))\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n `Invoice line ${field} ${value} must be a safe integer number of minor units`,\n );\n return (await super.save()) as this;\n }\n\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteInvoiceLineItem } = await import('../document-money.js');\n await deleteInvoiceLineItem(this, options);\n }\n\n /** @internal Aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Invoice line money write capability is required');\n await super.delete(options);\n }\n\n /**\n * Check if line item has source tracking\n */\n hasSource(): boolean {\n return !!this.sourceType && !!this.sourceId;\n }\n\n /**\n * Check if line item has a service period\n */\n hasPeriod(): boolean {\n return !!this.periodStart && !!this.periodEnd;\n }\n}\n\nexport default InvoiceLineItem;\n","/**\n * InvoiceLineItemCollection - Collection manager for InvoiceLineItem objects\n * @packageDocumentation\n */\n\nimport {\n SmrtCollection,\n type SmrtListOptions,\n type SmrtObject,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n type SmrtWhereClause,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n queryGlobal,\n queryWithGlobals,\n} from '@happyvertical/smrt-tenancy';\nimport { DOCUMENT_MONEY_READ_REBIND } from '../document-money-internal.js';\nimport { InvoiceLineItem } from '../models/InvoiceLineItem.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport { assertCommerceMoneySchemaCurrent } from '../upgrade/detect.js';\n\nexport class InvoiceLineItemCollection extends SmrtCollection<InvoiceLineItem> {\n static readonly _itemClass = InvoiceLineItem;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) {\n // Without a tenant, still refuse a database with old money storage.\n await assertCommerceMoneySchemaCurrent(rootDb);\n return operation();\n }\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof InvoiceLineItem)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof InvoiceLineItem)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<InvoiceLineItem>,\n options: Parameters<SmrtCollection<InvoiceLineItem>['get']>[1] = {},\n ): Promise<InvoiceLineItem | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<InvoiceLineItem>[],\n >(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<InvoiceLineItem, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<InvoiceLineItem[]>;\n override async list(\n options: Omit<SmrtListOptions<InvoiceLineItem>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<InvoiceLineItem[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<InvoiceLineItem>, 'select'> & {\n select?: undefined;\n })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<InvoiceLineItem> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find line items by invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Array of line items, sorted by sortOrder\n */\n async findByInvoice(invoiceId: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { invoiceId },\n orderBy: 'sortOrder ASC',\n });\n }\n\n /**\n * Find line items by source\n *\n * @param sourceType - Source type (e.g., 'campaign', 'contract')\n * @param sourceId - Source ID\n * @returns Array of line items\n */\n async findBySource(\n sourceType: string,\n sourceId: string,\n ): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType, sourceId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find line items by source type only\n *\n * @param sourceType - Source type (e.g., 'campaign')\n * @returns Array of line items\n */\n async findBySourceType(sourceType: string): Promise<InvoiceLineItem[]> {\n return await this.list({\n where: { sourceType },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Calculate total amount for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Total amount\n */\n async getTotalForInvoice(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n return lineItems.reduce((sum, item) => sum + item.amount, 0);\n }\n\n /**\n * Get the next sort order for an invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Next sort order number\n */\n async getNextSortOrder(invoiceId: string): Promise<number> {\n const lineItems = await this.findByInvoice(invoiceId);\n if (lineItems.length === 0) return 0;\n\n const maxSortOrder = Math.max(...lineItems.map((item) => item.sortOrder));\n return maxSortOrder + 1;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all invoice line items belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of invoice line items for the tenant\n */\n async findByTenant(tenantId: string): Promise<InvoiceLineItem[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global invoice line items (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global invoice line items\n */\n async findGlobal(): Promise<InvoiceLineItem[]> {\n return queryGlobal<InvoiceLineItem>(this);\n }\n\n /**\n * Find invoice line items for a tenant including global line items.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global invoice line items\n */\n async findWithGlobals(tenantId: string): Promise<InvoiceLineItem[]> {\n return queryWithGlobals<InvoiceLineItem>(\n this,\n tenantId,\n 'InvoiceLineItem.findWithGlobals',\n );\n }\n}\n","import {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n type SmrtSaveOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { assertHistoricalCommerceWrite } from '../historical-commerce-internal.js';\nimport type { HistoricalSalesLineInput } from '../historical-sales-types.js';\nexport interface HistoricalSalesLineOptions\n extends SmrtObjectOptions,\n Partial<HistoricalSalesLineInput> {\n tenantId?: string;\n invoiceId?: string;\n sourceKeyHash?: string;\n sourceFieldsJson?: string;\n moneySnapshotId?: string;\n}\n/** An immutable source line with explicit unknowns, never a calculated InvoiceLineItem. */\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'historical_sales_lines',\n indexes: [\n {\n name: 'historical_sales_line_source_key',\n columns: ['tenantId', 'invoiceId', 'sourceKeyHash'],\n unique: true,\n },\n ],\n api: { include: ['get', 'list'] },\n cli: { include: ['get', 'list'] },\n mcp: { include: ['get', 'list'] },\n})\nexport class HistoricalSalesLine extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @tenantId() tenantId = '';\n @foreignKey('Invoice') invoiceId = '';\n @foreignKey('HistoricalSalesLine', { nullable: true }) creditedLineId:\n | string\n | null = null;\n sourceKey = '';\n sourceKeyHash = '';\n description = '';\n @field({ ui: { format: 'money' } }) netMinor = 0;\n @field({ type: 'integer', nullable: true, ui: { format: 'money' } }) taxMinor:\n | number\n | null = null;\n @field({ type: 'integer', nullable: true, ui: { format: 'money' } })\n grossMinor: number | null = null;\n @field({ type: 'text', nullable: true }) quantityText: string | null = null;\n @field({ type: 'text', nullable: true }) unitRateText: string | null = null;\n sourceFieldsJson = '{}';\n moneySnapshotId = '';\n constructor(options: HistoricalSalesLineOptions = {}) {\n super(options);\n for (const key of [\n 'tenantId',\n 'invoiceId',\n 'creditedLineId',\n 'sourceKey',\n 'sourceKeyHash',\n 'description',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'quantityText',\n 'unitRateText',\n 'sourceFieldsJson',\n 'moneySnapshotId',\n ] as const)\n if (options[key] !== undefined)\n Object.assign(this, { [key]: options[key] });\n if (options.sourceFields !== undefined)\n this.sourceFieldsJson = JSON.stringify(options.sourceFields);\n }\n override async save(options?: SmrtSaveOptions): Promise<this> {\n assertHistoricalCommerceWrite(this);\n if (\n !this.tenantId ||\n !this.invoiceId ||\n !this.sourceKey ||\n !this.sourceKeyHash ||\n !this.moneySnapshotId\n )\n throw new Error('Historical source line identity is incomplete');\n if (this.id && (await this.db.get(this.tableName, { id: this.id })))\n throw new Error('Historical sales source lines are immutable');\n return super.save(options);\n }\n override async delete(): Promise<void> {\n throw new Error('Historical sales source lines cannot be deleted');\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { HistoricalSalesLine } from '../models/HistoricalSalesLine.js';\nexport class HistoricalSalesLineCollection extends SmrtCollection<HistoricalSalesLine> {\n static readonly _itemClass = HistoricalSalesLine;\n}\n","/**\n * Vendor model - links to Profile with vendor-specific data\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { normalizePartyContacts } from '../party-contacts.js';\nimport {\n type PartyContact,\n type VendorOptions,\n VendorStatus,\n} from '../types/index.js';\n\n/**\n * Vendor represents the vendor/supplier role for a Profile.\n *\n * One Profile can have both Customer and Vendor records - e.g., a company\n * you both buy from and sell to.\n *\n * @example\n * ```typescript\n * const vendor = await vendors.create({\n * profileId: 'profile-uuid',\n * leadTimeDays: 14,\n * minimumOrderAmount: 500,\n * paymentTerms: 'Net 60'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Vendor extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global vendors\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Reference to smrt-profiles Profile\n * Plain string for cross-package reference\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile', {\n description:\n 'Links this vendor to their profile record, where their name and contact details are kept.',\n })\n profileId: string = '';\n\n /**\n * Typical lead time in days for orders\n */\n @field({\n description:\n 'How many days the vendor usually takes between your order and delivery.',\n })\n leadTimeDays: number = 0;\n\n /**\n * Minimum order amount required, in **integer minor units** (cents,\n * satoshis). Compared against `Contract.totalAmount`, which is also minor\n * units (#2401).\n */\n @field({\n description: 'The smallest order the vendor will accept.',\n ui: { format: 'money' },\n })\n minimumOrderAmount: number = 0;\n\n /**\n * Payment terms for this vendor (e.g., \"Net 60\")\n */\n @field({\n description:\n 'How long you have to pay this vendor, written the way you would say it, for example \"Net 30\".',\n })\n paymentTerms: string = '';\n\n /**\n * Default currency for transactions with this vendor\n */\n @field({\n description: 'The currency this vendor bills you in.',\n ui: { widget: 'currency' },\n })\n currency: string = 'USD';\n\n /**\n * Supplier registration number.\n *\n * Sensitive for the same reason as a customer's tax ID: it is identifying\n * business information and must not enter generated list/search surfaces.\n */\n @field({\n sensitive: true,\n description: 'The vendor tax or VAT registration number kept on file.',\n })\n taxId: string = '';\n\n /** Tax code normally used for purchases from this vendor. */\n @foreignKey('TaxCode', {\n description: 'The tax code normally used when buying from this vendor.',\n })\n defaultTaxCodeId: string = '';\n\n /**\n * Default contact email for orders\n */\n @field({\n description: 'The email address you normally use to reach this vendor.',\n ui: { widget: 'email' },\n })\n defaultContactEmail: string = '';\n\n /**\n * Default contact phone for orders\n */\n @field({\n description: 'The phone number you normally use to reach this vendor.',\n ui: { widget: 'phone' },\n })\n defaultContactPhone: string = '';\n\n /**\n * Vendor status\n */\n @field({\n description:\n 'Whether you still buy from this vendor: active, inactive or suspended.',\n })\n status: VendorStatus = VendorStatus.ACTIVE;\n\n /**\n * Internal notes about this vendor\n */\n @field({\n description: 'Anything worth remembering about this vendor.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * Per-currency payout destinations for this vendor.\n *\n * Stored as a JSON column. Keys are payout-rail-qualified currency codes —\n * the code must encode both the asset and the rail (e.g. `USDC-base`,\n * `USDC-solana`, `BTC`, `USD-stripe`, `USD-wire`). Values are whatever the\n * receiving rail needs as a destination (EVM address, BTC address, Stripe\n * Connect account id, IBAN, etc.).\n *\n * MVP shape: a flat map on the vendor row. A vendor with no entry for a\n * given currency cannot be paid in that currency — filtering is the\n * consumer's responsibility (the upstream `PaymentIntent` builder filters\n * `paymentOptions` at quote time against this map).\n *\n * Use {@link getPayoutAddress} for a `Map.get`-style lookup that returns\n * `undefined` for missing entries; direct property access is also fine.\n *\n * Sensitive (#1540): payout destinations are excluded from generated API/MCP\n * responses and rejected as a `where` filter key.\n */\n @field({\n sensitive: true,\n description: 'Where payments to this vendor should be sent.',\n })\n payoutAddresses: Record<string, string> = {};\n\n /**\n * People to reach at this vendor, stored as a JSON column (#3501). Write\n * form rows through `savePartyContacts()`; every save normalizes the shape.\n */\n @field({\n description:\n 'The people you deal with at this vendor, with their role and how to reach them.',\n })\n contacts: PartyContact[] = [];\n\n constructor(options: VendorOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.leadTimeDays !== undefined)\n this.leadTimeDays = options.leadTimeDays;\n if (options.minimumOrderAmount !== undefined)\n this.minimumOrderAmount = options.minimumOrderAmount;\n if (options.paymentTerms !== undefined)\n this.paymentTerms = options.paymentTerms;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.taxId !== undefined) this.taxId = options.taxId;\n if (options.defaultTaxCodeId !== undefined)\n this.defaultTaxCodeId = options.defaultTaxCodeId;\n if (options.defaultContactEmail !== undefined)\n this.defaultContactEmail = options.defaultContactEmail;\n if (options.defaultContactPhone !== undefined)\n this.defaultContactPhone = options.defaultContactPhone;\n if (options.status !== undefined) this.status = options.status;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.payoutAddresses !== undefined) {\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n options.payoutAddresses,\n );\n }\n if (options.contacts !== undefined)\n this.contacts = normalizePartyContacts(options.contacts);\n }\n\n /**\n * The framework's {@link SmrtObject.initialize} re-applies `options` keys on\n * top of constructor-set values so option data always wins over field\n * initializers. That means our constructor's normalization runs *before*\n * `initializePropertiesFromOptions` overwrites `payoutAddresses` with the\n * raw cloned value. Re-normalize once super has finished so consumers\n * who pass a string, a partially-typed map, or `null` end up with a\n * clean `Record<string, string>` before any save / read happens.\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n this.payoutAddresses as unknown,\n );\n this.contacts = normalizePartyContacts(this.contacts);\n return this;\n }\n\n /**\n * Save with a final normalization pass so direct field assignments\n * (`vendor.payoutAddresses = somethingFunny`) can't smuggle non-string\n * values into the persisted row.\n */\n override async save(): Promise<this> {\n this.payoutAddresses = Vendor.normalizePayoutAddresses(\n this.payoutAddresses as unknown,\n );\n this.contacts = normalizePartyContacts(this.contacts);\n return super.save() as Promise<this>;\n }\n\n /**\n * Check if vendor is active\n */\n isActive(): boolean {\n return this.status === VendorStatus.ACTIVE;\n }\n\n /**\n * Check if order meets minimum requirements\n */\n meetsMinimumOrder(amount: number): boolean {\n return amount >= this.minimumOrderAmount;\n }\n\n /**\n * Get the profile ID for external lookup.\n *\n * To get the actual Profile object, use the ProfileCollection from smrt-profiles:\n * ```typescript\n * const profiles = await ProfileCollection.create(options);\n * const profile = await profiles.get({ id: vendor.profileId });\n * ```\n *\n * @returns The profile ID or empty string if not set\n */\n getProfileId(): string {\n return this.profileId;\n }\n\n /**\n * Look up the payout destination for a single currency. Returns\n * `undefined` if the vendor has no entry for that currency — caller's\n * job to decide whether that means \"skip the option\" or \"raise a\n * configuration error\". The lookup is case-sensitive; the contract is\n * that the currency code passed in matches exactly what was stored\n * (`USDC-base`, not `usdc-base`).\n */\n getPayoutAddress(currency: string): string | undefined {\n const map = this.payoutAddresses;\n if (!map || typeof map !== 'object') return undefined;\n const value = (map as Record<string, unknown>)[currency];\n return typeof value === 'string' ? value : undefined;\n }\n\n /**\n * Set the payout destination for a single currency. Mutates the live\n * map and returns `this` for chaining. Use {@link clearPayoutAddress}\n * to remove a single entry.\n */\n setPayoutAddress(currency: string, destination: string): this {\n this.payoutAddresses = {\n ...(this.payoutAddresses ?? {}),\n [currency]: destination,\n };\n return this;\n }\n\n /**\n * Remove a single currency entry from the payout map. No-op if the\n * currency was already absent.\n */\n clearPayoutAddress(currency: string): this {\n if (!this.payoutAddresses || !(currency in this.payoutAddresses)) {\n return this;\n }\n const next = { ...this.payoutAddresses };\n delete next[currency];\n this.payoutAddresses = next;\n return this;\n }\n\n /**\n * Normalize an input value (object, pre-serialized JSON string, or\n * `null`/`undefined`) into a plain `Record<string, string>`. Used by\n * the constructor so consumers can pass either shape into\n * `VendorCollection.create({ payoutAddresses: ... })`.\n *\n * Non-string values inside an input object are silently dropped — a\n * `Record<string, string>` invariant is what consumers downstream\n * (`PaymentIntent` builders, payout SDK adapters) rely on.\n */\n private static normalizePayoutAddresses(\n value: unknown,\n ): Record<string, string> {\n if (value == null) return {};\n let parsed: unknown = value;\n if (typeof value === 'string') {\n try {\n parsed = JSON.parse(value);\n } catch {\n return {};\n }\n }\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return {};\n }\n const out: Record<string, string> = {};\n for (const [key, v] of Object.entries(parsed as Record<string, unknown>)) {\n if (typeof v === 'string') out[key] = v;\n }\n return out;\n }\n}\n\nexport default Vendor;\n","/**\n * Contract model with STI for different contract types\n * @packageDocumentation\n */\n\nimport {\n field,\n foreignKey,\n type Meta,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_READ_REBIND,\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyReadRebindCapability,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { assertIntegerMinorUnits } from '../money.js';\nimport {\n type ContractOptions,\n ContractStatus,\n ContractType,\n type LicenseSaleOptions,\n type PurchaseContractOptions,\n type PurchaseOrderOptions,\n type SalesContractOptions,\n type TaxRegistrationOptions,\n} from '../types/index.js';\nimport { Customer } from './Customer.js';\nimport { Vendor } from './Vendor.js';\n\n/**\n * Legal status transitions for a Contract (and all its STI subtypes), keyed by\n * the prior persisted status. A status re-saved unchanged (no-op) and a\n * brand-new row are always permitted; this map governs *changes* only.\n *\n * Flow: DRAFT → SENT → (ACCEPTED | DECLINED); ACCEPTED → (COMPLETED |\n * CANCELLED). An estimate/order may also be cancelled directly from DRAFT/SENT.\n * DECLINED / COMPLETED / CANCELLED are terminal. This guards against raw\n * mass-assignment forcing, e.g., a DECLINED contract back to ACCEPTED or a\n * COMPLETED one back to DRAFT. See S5 audit #1390.\n */\nconst CONTRACT_STATUS_TRANSITIONS: Record<ContractStatus, ContractStatus[]> = {\n [ContractStatus.DRAFT]: [\n ContractStatus.SENT,\n ContractStatus.ACCEPTED,\n ContractStatus.DECLINED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.SENT]: [\n ContractStatus.ACCEPTED,\n ContractStatus.DECLINED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.ACCEPTED]: [\n ContractStatus.COMPLETED,\n ContractStatus.CANCELLED,\n ],\n [ContractStatus.DECLINED]: [],\n [ContractStatus.COMPLETED]: [],\n [ContractStatus.CANCELLED]: [],\n};\n\n/**\n * Module-scoped record of the status each Contract instance was loaded with,\n * for the save-time transition guard. WeakMap keeps it out of the schema and\n * GCs with the instance — same pattern as the other commerce models.\n */\nconst loadedContractStatus = new WeakMap<Contract, ContractStatus>();\n\n/** Whether a Contract belongs to the purchase STI branch, including descendants. */\nexport function classifyContractPurchase(contract: Contract): boolean {\n return 'vendorId' in contract;\n}\n\n/** Frozen snapshots are reportable except cancelled contracts and supplier quotes. */\nexport function isContractSnapshotReportEligible(contract: Contract): boolean {\n return (\n !(contract instanceof SupplierQuote) &&\n contract.status !== ContractStatus.DRAFT &&\n contract.status !== ContractStatus.CANCELLED\n );\n}\n\n/**\n * Contract is the base class for all commercial agreements.\n *\n * Uses Single Table Inheritance (STI) for ten leaf types. SalesContract owns\n * the customer link for Estimate, Order, WholesaleOrder, Cart, Lease,\n * Agreement, and LicenseSale. PurchaseContract owns the vendor link for\n * SupplierQuote, PurchaseOrder and ProductionOrder. Both branches share `contracts`.\n *\n * @example\n * ```typescript\n * // Create a customer order\n * const order = await contracts.create({\n * _meta_type: 'Order',\n * customerId: customer.id,\n * totalAmount: 150000, // $1,500.00 in cents\n * status: ContractStatus.DRAFT\n * });\n *\n * // Create a purchase order to vendor\n * const po = await contracts.create({\n * _meta_type: 'PurchaseOrder',\n * vendorId: vendor.id,\n * totalAmount: 500000, // $5,000.00 in cents\n * reference: 'PO-2024-001'\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class Contract extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n /** @internal Collection read guard returns this snapshot on its root DB. */\n rebindMoneyRead(\n capability: DocumentMoneyReadRebindCapability,\n db: DatabaseInterface,\n ): this {\n if (capability !== DOCUMENT_MONEY_READ_REBIND)\n throw new Error('Contract read rebinding requires the owning capability');\n this._db = db;\n this.options.db = db;\n return this;\n }\n\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support both tenant-scoped and global contracts\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Contract type discriminator (STI)\n */\n @field({\n description:\n 'The kind of contract: order, estimate, lease, agreement and so on.',\n })\n contractType: ContractType = ContractType.ORDER;\n\n /**\n * Current status of the contract\n */\n @field({\n description:\n 'Where the order or agreement stands, for example draft, sent, accepted or completed.',\n })\n status: ContractStatus = ContractStatus.DRAFT;\n\n /**\n * Subtotal before tax, in **integer minor units** (cents, satoshis).\n *\n * The `= 0` initializer is load-bearing: SMRT maps an integer literal to\n * INTEGER and a decimal literal to DECIMAL. Money is exact, so it is stored\n * as minor units and never as a float — `$19.99` is `1999`, not `19.99`\n * (#2401).\n */\n @field({ description: 'The amount before tax.', ui: { format: 'money' } })\n subtotal: number = 0;\n\n /** Informational sum of resolved line discounts, in integer minor units. */\n @field({ ui: { format: 'money' } })\n discountTotal: number = 0;\n\n /**\n * Tax amount, in integer minor units (#2401).\n */\n @field({ description: 'The tax charged.', ui: { format: 'money' } })\n taxAmount: number = 0;\n\n /**\n * Total amount including tax, in integer minor units (#2401).\n */\n @field({\n description: 'The full amount, tax included.',\n ui: { format: 'money' },\n })\n totalAmount: number = 0;\n\n /**\n * Currency code (ISO 4217)\n */\n @field({\n description: 'The currency of the amounts.',\n ui: { widget: 'currency' },\n })\n currency: string = 'USD';\n\n /** Calculated pricing or immutable source-declared purchase evidence. */\n @field({\n description:\n 'Whether amounts were calculated or recorded from reviewed original paperwork.',\n })\n moneyAuthority: 'calculated' | 'received' = 'calculated';\n\n /** Guarded received evidence; write through the public received purchase/sales contract commands only. */\n receivedPurchaseMoneyJson = '';\n\n /**\n * Append-only approved milestone schedule and issued claim evidence.\n * `''` means no schedule; the column defaults to it, and a NULL stored by an\n * earlier writer hydrates as `''` (#4155).\n */\n @field({ type: 'text', default: '' })\n billingScheduleJson = '';\n\n /** Pricing interpretation fixed before the Contract leaves draft. */\n lineAmountType: 'exclusive' | 'inclusive' | 'none' = 'exclusive';\n\n /** Component rounding scope fixed before the Contract leaves draft. */\n taxRoundingScope: 'line' | 'document' = 'line';\n\n /** Immutable seller registration snapshot once the Contract leaves draft. */\n sellerTaxRegistrationsJson = '[]';\n\n get sellerTaxRegistrations(): TaxRegistrationOptions[] {\n try {\n const value: unknown = JSON.parse(this.sellerTaxRegistrationsJson);\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is TaxRegistrationOptions =>\n !!entry &&\n typeof entry === 'object' &&\n typeof (entry as TaxRegistrationOptions).taxComponentId ===\n 'string' &&\n typeof (entry as TaxRegistrationOptions).number === 'string' &&\n typeof (entry as TaxRegistrationOptions).label === 'string',\n );\n } catch {\n return [];\n }\n }\n\n set sellerTaxRegistrations(value: TaxRegistrationOptions[]) {\n this.sellerTaxRegistrationsJson = JSON.stringify(value);\n }\n\n /** Immutable customer or vendor tax identifier snapshot after issue. */\n partyTaxId = '';\n\n /** Stable issue/freeze identity, independent of lifecycle updated_at. */\n moneySnapshotId = '';\n\n /**\n * Date contract was issued\n */\n @field({\n description: 'The date it was issued or placed.',\n // A business date: the natural time axis of contract reports (#4100).\n ui: { format: 'date' },\n })\n issueDate: Date = new Date();\n\n /**\n * Payment due date\n */\n @field({ description: 'The date payment or delivery is due.' })\n dueDate: Date | null = null;\n\n /**\n * Expiry date (for estimates/quotes)\n */\n @field({ description: 'The last day the price or offer is good for.' })\n expiryDate: Date | null = null;\n\n /**\n * External reference number (PO number, quote number, etc.)\n */\n @field({\n description:\n 'Your own number or note for finding this later, such as a purchase order or quote number.',\n })\n reference: string = '';\n\n /**\n * Internal notes\n */\n @field({\n description: 'Anything worth remembering about this.',\n ui: { widget: 'textarea' },\n })\n notes: string = '';\n\n /**\n * Terms and conditions\n */\n @field({\n description:\n 'The conditions agreed, such as deposits, payment or delivery conditions.',\n ui: { widget: 'textarea' },\n })\n terms: string = '';\n\n /**\n * Sales channel that owns this contract.\n *\n * Plain string so consumers can model their own channels without an enum\n * change (e.g. `dtc-web`, `wholesale-b2b`, `pos-store-1`, `marketplace-faire`).\n * Empty string means \"unattributed / legacy\".\n */\n @field({\n description:\n 'Where it came from, for example your shop, a marketplace or a phone call.',\n })\n channelId: string = '';\n\n /**\n * STI discriminator field\n */\n static readonly _stiField = 'contractType';\n\n constructor(options: ContractOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.contractType !== undefined)\n this.contractType = options.contractType;\n if (options.status !== undefined) this.status = options.status;\n if (options.billingScheduleJson !== undefined)\n this.billingScheduleJson = options.billingScheduleJson;\n if (options.moneyAuthority !== undefined)\n this.moneyAuthority = options.moneyAuthority;\n if (options.receivedPurchaseMoneyJson !== undefined)\n this.receivedPurchaseMoneyJson = options.receivedPurchaseMoneyJson;\n if (options.subtotal !== undefined) this.subtotal = options.subtotal;\n if (options.discountTotal !== undefined)\n this.discountTotal = options.discountTotal;\n if (options.taxAmount !== undefined) this.taxAmount = options.taxAmount;\n if (options.totalAmount !== undefined)\n this.totalAmount = options.totalAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.lineAmountType !== undefined)\n this.lineAmountType = options.lineAmountType;\n if (options.taxRoundingScope !== undefined)\n this.taxRoundingScope = options.taxRoundingScope;\n if (options.sellerTaxRegistrationsJson !== undefined)\n this.sellerTaxRegistrationsJson = options.sellerTaxRegistrationsJson;\n if (options.sellerTaxRegistrations !== undefined)\n this.sellerTaxRegistrations = structuredClone(\n options.sellerTaxRegistrations,\n );\n if (options.partyTaxId !== undefined) this.partyTaxId = options.partyTaxId;\n if (options.moneySnapshotId !== undefined)\n this.moneySnapshotId = options.moneySnapshotId;\n if (options.issueDate !== undefined) this.issueDate = options.issueDate;\n if (options.dueDate !== undefined) this.dueDate = options.dueDate;\n if (options.expiryDate !== undefined) this.expiryDate = options.expiryDate;\n if (options.reference !== undefined) this.reference = options.reference;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.terms !== undefined) this.terms = options.terms;\n if (options.channelId !== undefined) this.channelId = options.channelId;\n }\n\n /**\n * Check if contract is in draft state\n */\n isDraft(): boolean {\n return this.status === ContractStatus.DRAFT;\n }\n\n /**\n * Check if contract is accepted\n */\n isAccepted(): boolean {\n return this.status === ContractStatus.ACCEPTED;\n }\n\n /**\n * Check if contract is completed\n */\n isCompleted(): boolean {\n return this.status === ContractStatus.COMPLETED;\n }\n\n /**\n * Check if contract is expired (for estimates)\n */\n isExpired(): boolean {\n if (!this.expiryDate) return false;\n return new Date() > this.expiryDate;\n }\n\n /**\n * Check if contract is overdue\n */\n isOverdue(): boolean {\n if (!this.dueDate) return false;\n if (this.status === ContractStatus.COMPLETED) return false;\n return new Date() > this.dueDate;\n }\n\n /**\n * Calculate and update totals from line items\n */\n async recalculateTotals(): Promise<void> {\n const { recalculateContractTotals } = await import('../contract-money.js');\n await recalculateContractTotals(this);\n }\n\n /**\n * Capture the status the row was loaded with so the save-time transition\n * guard can reject illegal status flips made via raw field assignment\n * (mass-assignment on the generated update route, a stale caller, etc.).\n * Only persisted rows carry a prior status.\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n // No schedule is `''`; a row written before the column had a default\n // holds NULL, which means the same thing (#4155).\n this.billingScheduleJson ??= '';\n // A row read from the database must not be old-format money data.\n if (this.isPersisted) {\n const { assertHydratedMoneyRowCurrent } = await import(\n '../upgrade/detect.js'\n );\n await assertHydratedMoneyRowCurrent(this);\n }\n if (await this.isSaved()) {\n loadedContractStatus.set(this, this.status);\n }\n return this;\n }\n\n /**\n * Validate the amounts and the status transition before persisting, then\n * save. Inherited by every STI subtype (Estimate/Order/Lease/.../LicenseSale),\n * so a forged `status` on any of them is caught here. LicenseSale layers its\n * own rights-immutability guard on top via `super.save()`. See S5 audit\n * #1390.\n *\n * `subtotal` / `taxAmount` / `totalAmount` are mass-assignable on the\n * generated create/update routes, so the minor-units check runs on every\n * write surface (#2401).\n */\n override async save(): Promise<this> {\n const { saveContract } = await import('../contract-money.js');\n return (await saveContract(this)) as this;\n }\n\n /** Received purchase monetary history cannot be deleted. */\n override async delete(\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n const { deleteContract } = await import('../contract-money.js');\n await deleteContract(this, options);\n }\n\n /** @internal Contract aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract money write capability is required');\n await super.delete(options);\n }\n\n /** @internal Contract aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE)\n throw new Error('Contract money write capability is required');\n assertIntegerMinorUnits('Contract', this.reference || this.id || '<new>', [\n ['subtotal', this.subtotal],\n ['discountTotal', this.discountTotal],\n ['taxAmount', this.taxAmount],\n ['totalAmount', this.totalAmount],\n ]);\n const prior = await this.resolvePriorStatus();\n this.assertContractStatusTransition(prior);\n const result = (await super.save()) as this;\n loadedContractStatus.set(this, this.status);\n return result;\n }\n\n /**\n * Reject an illegal status flip done via raw assignment. No-op transitions\n * and brand-new rows are always allowed.\n */\n protected assertContractStatusTransition(\n prior: ContractStatus | undefined,\n ): void {\n if (prior === undefined) return; // new row — any starting status is fine\n if (prior === this.status) return; // no-op re-save\n const allowed = CONTRACT_STATUS_TRANSITIONS[prior] ?? [];\n if (!allowed.includes(this.status)) {\n throw new Error(\n `Contract ${this.reference || this.id}: illegal status transition ` +\n `'${prior}' → '${this.status}'.`,\n );\n }\n }\n\n /**\n * Resolve the AUTHORITATIVE prior status (S5 audit #1390 round 5, codex\n * MEDIUM#2). The WeakMap is only populated when {@link initialize} loaded the\n * row from the DB; it is empty for an instance built via\n * `collection.create({ id: <existing>, _skipLoad: true })` — the upsert path\n * that lets a caller write onto an existing row without hydrating it. Trusting\n * an empty WeakMap there would treat the write as a brand-new row and skip the\n * transition guard entirely (a poisonable prior-state). Mirrors the\n * authoritative-prior-load applied to Payment/PaymentIntent/Invoice/Payout.\n *\n * So when this instance carries an `id`, read the persisted row straight from\n * the database and treat its `status` as the prior — a create-onto-existing is\n * an update. Only when no row exists in the DB (truly new) do we fall back to\n * the WeakMap (which is also empty then), i.e. `undefined` = genuinely new.\n * The raw row's `status` column is single-word (no snake_case transform).\n */\n protected async resolvePriorStatus(): Promise<ContractStatus | undefined> {\n if (this.id) {\n try {\n const row = await this.db.get(this.tableName, { id: this.id });\n if (row && row.status != null) {\n return row.status as ContractStatus;\n }\n } catch {\n // DB not ready / table absent — fall through to the in-memory record.\n }\n }\n return loadedContractStatus.get(this);\n }\n}\n\n// Every STI child below MUST repeat the `@TenantScoped` decoration. The\n// tenancy registry keys off the concrete className passed by the\n// collection, not the inheritance chain — `OrderCollection.list()` sends\n// `'Order'` to the interceptor, which then misses the `'Contract'`\n// registration and skips tenant auto-filter/auto-populate. Without an\n// explicit `@TenantScoped` on each subclass, saves end up with\n// `tenantId: null` (the row becomes global / invisible to tenant-scoped\n// queries) and lists return rows across tenants.\n\n/** Customer-side contracts, including orders, estimates, and licenses. */\n@TenantScoped({ mode: 'optional' })\n@smrt({ abstract: true })\nexport abstract class SalesContract extends Contract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, {\n description: 'The customer a sales order or agreement is for.',\n })\n customerId: string | null = null;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/** Supplier-side contracts, including supplier quotes, purchase and production orders. */\n@TenantScoped({ mode: 'optional' })\n@smrt({ abstract: true })\nexport abstract class PurchaseContract extends Contract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, {\n description: 'The vendor supplying this quote or purchase contract.',\n })\n vendorId: string | null = null;\n\n constructor(options: PurchaseContractOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n }\n}\n\n/**\n * Estimate - Quote or proposal for a customer\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Estimate extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.ESTIMATE;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Order - Customer purchase order\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Order extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.ORDER;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Lease - Rental or lease agreement\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Lease extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.LEASE;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * Agreement - Service or maintenance agreement\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Agreement extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.AGREEMENT;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/** Supplier quotation received from a vendor; acceptance does not create an order. */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class SupplierQuote extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, { required: true })\n override vendorId: string | null = null;\n override contractType = ContractType.SUPPLIER_QUOTE;\n\n constructor(options: PurchaseContractOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n }\n}\n\n/**\n * PurchaseOrder - Order sent to vendor/supplier\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class PurchaseOrder extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Vendor, { required: true })\n override vendorId: string | null = null;\n override contractType = ContractType.PURCHASE_ORDER;\n\n /** Expected delivery calendar date (YYYY-MM-DD), or empty when unspecified. */\n @field({\n description:\n 'The date you expect the delivery, as YYYY-MM-DD. Leave blank if it is not known.',\n })\n expectedDate: Meta<string> = '';\n\n /** Delivery address/instructions snapshot, independent of the vendor address. */\n @field({\n description:\n 'Where this order should be delivered, including any delivery instructions.',\n })\n shipTo: Meta<string> = '';\n\n /** Construct a purchase order with its optional delivery header. */\n constructor(options: PurchaseOrderOptions = {}) {\n super(options);\n if (options.vendorId !== undefined) this.vendorId = options.vendorId;\n if (options.expectedDate !== undefined)\n this.expectedDate = options.expectedDate;\n if (options.shipTo !== undefined) this.shipTo = options.shipTo;\n }\n}\n\n/**\n * WholesaleOrder - B2B order placed by a wholesale customer.\n *\n * Behaves like an Order but is conventionally created against a customer with\n * `customerType: 'wholesale'`, uses NET-30/60 payment terms, and is delivered\n * via the wholesale-portal channel rather than retail checkout.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class WholesaleOrder extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @foreignKey(Customer, { required: true })\n override customerId: string | null = null;\n override contractType = ContractType.WHOLESALE_ORDER;\n\n constructor(options: SalesContractOptions = {}) {\n super(options);\n if (options.customerId !== undefined) this.customerId = options.customerId;\n }\n}\n\n/**\n * ProductionOrder - instruction to commission goods from an internal or\n * external factory.\n *\n * The manufacturing equivalent of a {@link PurchaseOrder} — but instead of\n * buying finished inventory, you're paying to *make* it. A ProductionOrder\n * consumes raw materials per a Bill of Materials (see\n * `@happyvertical/smrt-manufacturing`) and produces finished SKU stock when\n * posted (see `@happyvertical/smrt-inventory`).\n *\n * Carries two STI-meta fields that `ProductionService.consumeMaterials` /\n * `runProduction` read from the loaded row to resolve which BOM to walk:\n *\n * - `productId` — plain string ref to the upstream `Product` (or any\n * STI subtype, e.g. apparel `Style`). Used to look up the *active*\n * BOM via `BomService.findActiveForProduct` when no explicit\n * revision was pinned at the time the order was placed.\n * - `bomId` — optional pin to a specific BOM revision. When set, the\n * manufacturing service consumes against that exact revision even\n * if a newer BOM has become active in the meantime (keeps a\n * posted run from silently switching recipes mid-flight).\n *\n * Both fields are `Meta<string>` so the scanner routes them into the\n * shared `_meta_data` JSON column on the Contract STI table instead of\n * widening the base schema with manufacturing-specific columns.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class ProductionOrder extends PurchaseContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.PRODUCTION_ORDER;\n\n /**\n * Plain string reference to the upstream product the order is asked\n * to make. Cross-package id; never `@foreignKey()`. Required by\n * `ProductionService.consumeMaterials` unless `bomId` is supplied.\n */\n productId: Meta<string> = '';\n\n /**\n * Optional explicit BOM revision the order locked to at posting\n * time. When set, manufacturing uses this exact row even if the\n * product's active BOM has since changed. When empty, falls back\n * to the active BOM for `productId`.\n */\n bomId: Meta<string> = '';\n}\n\n/**\n * Cart - transient order-in-progress for a shopper.\n *\n * Persisted as a Contract so it can hold the same line items, totals, and\n * customer reference as a real Order, then convert in place (the application\n * promotes the row from `_meta_type: Cart` to `_meta_type: Order` at checkout\n * rather than copying data between tables).\n *\n * A Cart starts in {@link ContractStatus.DRAFT} via the base `Contract.status`\n * default — the subclass doesn't need its own override. Application code\n * is responsible for assigning the appropriate Order status at checkout;\n * the framework doesn't enforce a state machine on the cart → order transition.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class Cart extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.CART;\n}\n\n/**\n * Snapshot of the rights granted by a {@link LicenseSale}. The fields are\n * intentionally typed (not a generic JSON blob) so they survive schema\n * migrations and downstream consumers (PDF templating, hash-registry\n * publishers) can rely on the shape without re-parsing.\n *\n * Each field is opaque text — the values that make sense vary by\n * industry. A stock-media marketplace might use:\n *\n * - `medium`: `web,print,social`\n * - `distributionScope`: `worldwide` / `territorial`\n * - `exclusivity`: `exclusive` / `non-exclusive`\n * - `duration`: `perpetual` / `12-months` / `event-only`\n * - `territory`: ISO-3166 list or `worldwide`\n *\n * Booleans (`sublicensing`, `derivatives`) are typed as such; everything\n * else is a string so the model doesn't dictate vocabulary.\n */\nexport interface LicenseRightsSnapshot {\n medium: string;\n distributionScope: string;\n exclusivity: string;\n duration: string;\n territory: string;\n sublicensing: boolean;\n derivatives: boolean;\n}\n\n/**\n * Module-scoped WeakMap of \"rights snapshot the row was loaded with\".\n *\n * Used by {@link LicenseSale}'s immutability guard. We can't store the\n * captured snapshot as an instance field because the AST scanner would\n * pick it up as a persisted column; we can't store it as a `Meta<T>`\n * because then it'd round-trip with the row and the comparison would\n * always tautologically succeed. A WeakMap keyed by the instance is\n * the cleanest scope: no schema interaction, garbage-collected with\n * the instance.\n */\nconst issuedRightsSnapshot = new WeakMap<LicenseSale, string>();\n\n/**\n * LicenseSale — industry-neutral licensing primitive.\n *\n * Sits alongside the other Contract STI subtypes (Estimate, Order,\n * Lease, Agreement, PurchaseOrder, WholesaleOrder, ProductionOrder,\n * Cart) and represents a single sale of rights for a fee. A\n * stock-media marketplace selling a one-time license, a music-\n * licensing platform issuing a sync license, a code-asset marketplace\n * granting a redistribution right — all use the same primitive.\n *\n * Immutability invariant: once a `LicenseSale` is saved with\n * {@link ContractStatus.ACCEPTED}, its rights snapshot becomes\n * frozen. Re-saving with mutated rights throws. The only legal\n * transition out of ACCEPTED is `revoke()` (which moves status to\n * CANCELLED without changing the rights). If a different snapshot\n * is genuinely needed, the operator's contract is to issue a *new*\n * LicenseSale row and let the old one stand as historical record.\n *\n * All subtype-specific fields are declared as `Meta<T>` so the\n * scanner routes them into the shared `_meta_data` JSON column on\n * the `contracts` STI table — no migration of the base schema needed\n * to land this subtype.\n */\n@TenantScoped({ mode: 'optional' })\n@smrt()\nexport class LicenseSale extends SalesContract { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n override contractType = ContractType.LICENSE_SALE;\n\n /**\n * Plain string reference to the upstream `Sku` (from\n * `@happyvertical/smrt-products`) that this license was sold against.\n * Cross-package id; never `@foreignKey()`.\n */\n skuId: Meta<string> = '';\n\n /**\n * Plain string reference to the `Payment` that satisfied the\n * purchase. Cross-model reference matches the rest of the\n * package's convention.\n */\n paymentId: Meta<string> = '';\n\n /**\n * The licensee's email address — the primary identity carried\n * forward into PDF generation and any downstream hash-registry\n * publication. Required; without it, downstream rights cannot be\n * attributed.\n */\n licenseeEmail: Meta<string> = '';\n\n /**\n * Optional legal-entity name of the licensee for purchases that\n * warrant it (typically high-tier B2B licenses). Empty string for\n * individual-buyer licenses where the email *is* the legal identity.\n */\n licenseeLegalEntity: Meta<string> = '';\n\n /**\n * Optional ISO-3166 jurisdiction code of the licensee, captured for\n * tax / disclosure / governing-law purposes. Empty when not\n * required.\n */\n licenseeJurisdiction: Meta<string> = '';\n\n // -------- Rights snapshot (immutable once issued) --------\n\n /** Permitted media — `web,print,social`, `broadcast`, etc. */\n rightsMedium: Meta<string> = '';\n\n /** Distribution scope — `worldwide`, `territorial`, `private`, etc. */\n rightsDistributionScope: Meta<string> = '';\n\n /** Exclusivity — `exclusive` / `non-exclusive` / `co-exclusive`. */\n rightsExclusivity: Meta<string> = '';\n\n /** Duration — `perpetual` / `12-months` / `event-only`, etc. */\n rightsDuration: Meta<string> = '';\n\n /** Territory — ISO-3166 list, `worldwide`, region name, etc. */\n rightsTerritory: Meta<string> = '';\n\n /** Whether the licensee may sublicense the rights. */\n rightsSublicensing: Meta<boolean> = false;\n\n /** Whether the licensee may create derivative works. */\n rightsDerivatives: Meta<boolean> = false;\n\n // -------- Artefacts --------\n\n /** URL of the signed PDF (typically a cloud-storage public URL). */\n pdfUrl: Meta<string> = '';\n\n /**\n * SHA-256 of the signed PDF bytes (hex string, no `0x` prefix).\n * Lets downstream consumers verify the PDF the licensee holds is\n * the one this row was issued for, without re-fetching.\n */\n pdfHash: Meta<string> = '';\n\n /**\n * Optional reference to an on-chain hash-registry entry — set when\n * the LicenseSale's `pdfHash` has been anchored on a public chain\n * for tamper-evidence. Format is whatever the hash-registry\n * service emits (e.g. `chain:tx-hash:log-index`). Empty for\n * deployments that don't publish hashes on-chain.\n */\n onChainHashRegistryRef: Meta<string> = '';\n\n constructor(options: LicenseSaleOptions = {}) {\n super(options);\n if (options.skuId !== undefined) this.skuId = options.skuId;\n if (options.paymentId !== undefined) this.paymentId = options.paymentId;\n if (options.licenseeEmail !== undefined)\n this.licenseeEmail = options.licenseeEmail;\n if (options.licenseeLegalEntity !== undefined)\n this.licenseeLegalEntity = options.licenseeLegalEntity;\n if (options.licenseeJurisdiction !== undefined)\n this.licenseeJurisdiction = options.licenseeJurisdiction;\n if (options.rightsMedium !== undefined)\n this.rightsMedium = options.rightsMedium;\n if (options.rightsDistributionScope !== undefined)\n this.rightsDistributionScope = options.rightsDistributionScope;\n if (options.rightsExclusivity !== undefined)\n this.rightsExclusivity = options.rightsExclusivity;\n if (options.rightsDuration !== undefined)\n this.rightsDuration = options.rightsDuration;\n if (options.rightsTerritory !== undefined)\n this.rightsTerritory = options.rightsTerritory;\n if (options.rightsSublicensing !== undefined)\n this.rightsSublicensing = options.rightsSublicensing;\n if (options.rightsDerivatives !== undefined)\n this.rightsDerivatives = options.rightsDerivatives;\n if (options.pdfUrl !== undefined) this.pdfUrl = options.pdfUrl;\n if (options.pdfHash !== undefined) this.pdfHash = options.pdfHash;\n if (options.onChainHashRegistryRef !== undefined)\n this.onChainHashRegistryRef = options.onChainHashRegistryRef;\n }\n\n /**\n * Once `super.initialize()` has applied the framework's option-\n * override pass, capture the rights snapshot if (and only if) the\n * row arrived already issued. That's how the immutability guard\n * tells \"freshly drafting a license\" (snapshot still mutable) apart\n * from \"loaded an already-issued row\" (snapshot frozen).\n */\n override async initialize(): Promise<this> {\n await super.initialize();\n if (this.status === ContractStatus.ACCEPTED && (await this.isSaved())) {\n issuedRightsSnapshot.set(this, this.serializeRightsSnapshot());\n }\n return this;\n }\n\n /**\n * Return the current rights snapshot as a typed object. Read-only\n * for callers — mutation should go through assignment to the\n * individual `rights*` fields, gated by the issued-immutability\n * guard.\n */\n getRightsSnapshot(): LicenseRightsSnapshot {\n return {\n medium: this.rightsMedium,\n distributionScope: this.rightsDistributionScope,\n exclusivity: this.rightsExclusivity,\n duration: this.rightsDuration,\n territory: this.rightsTerritory,\n sublicensing: this.rightsSublicensing,\n derivatives: this.rightsDerivatives,\n };\n }\n\n /**\n * Revoke an issued license — moves status to `CANCELLED` without\n * touching the rights snapshot (which stays frozen). Throws if\n * called on a non-issued license; a draft license should be\n * deleted, not revoked.\n */\n revoke(): void {\n if (this.status !== ContractStatus.ACCEPTED) {\n throw new Error(\n `LicenseSale ${this.id ?? '<new>'}: cannot revoke from status '${this.status}' — only ACCEPTED licenses can be revoked`,\n );\n }\n this.status = ContractStatus.CANCELLED;\n }\n\n /**\n * Save with the immutability check: if the row was loaded with\n * `ACCEPTED` status, the rights snapshot at save time must match\n * the snapshot at load time. Anything else means an out-of-band\n * mutation crept in and we surface it instead of letting the row\n * drift silently.\n *\n * Newly-drafted licenses (where the row was constructed without\n * `ACCEPTED` status) capture their snapshot at the moment the\n * caller transitions to `ACCEPTED` and saves — `validateImmutable`\n * picks that up post-save on the next call.\n */\n override async save(): Promise<this> {\n this.validateImmutable();\n const result = (await super.save()) as this;\n // If this save transitioned the row to ACCEPTED, freeze the\n // snapshot for future saves.\n if (\n this.status === ContractStatus.ACCEPTED &&\n !issuedRightsSnapshot.has(this)\n ) {\n issuedRightsSnapshot.set(this, this.serializeRightsSnapshot());\n }\n return result;\n }\n\n /**\n * Compare the current rights against the captured snapshot\n * (populated either at load time by `initialize` or at first\n * issuance by `save`). Throws on mismatch.\n */\n private validateImmutable(): void {\n const captured = issuedRightsSnapshot.get(this);\n if (!captured) return;\n const current = this.serializeRightsSnapshot();\n if (captured !== current) {\n throw new Error(\n `LicenseSale ${this.id ?? '<new>'}: rights snapshot is immutable once issued (status=ACCEPTED). ` +\n 'Use revoke() to cancel the existing license and issue a new one with the updated rights.',\n );\n }\n }\n\n private serializeRightsSnapshot(): string {\n // Stable key ordering so a re-serialization after a no-op\n // assignment doesn't trip the equality check.\n return JSON.stringify({\n medium: this.rightsMedium,\n distributionScope: this.rightsDistributionScope,\n exclusivity: this.rightsExclusivity,\n duration: this.rightsDuration,\n territory: this.rightsTerritory,\n sublicensing: this.rightsSublicensing,\n derivatives: this.rightsDerivatives,\n });\n }\n}\n\nexport default Contract;\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { PurchaseContract } from '../models/Contract.js';\n\n/** Read supplier-side contracts across every purchase STI subtype. */\nexport class PurchaseContractCollection extends SmrtCollection<PurchaseContract> {\n static readonly _itemClass = PurchaseContract;\n\n async findByVendor(vendorId: string): Promise<PurchaseContract[]> {\n return this.list({\n where: { vendorId },\n orderBy: 'created_at DESC',\n });\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { SalesContract } from '../models/Contract.js';\n\n/** Read customer-side contracts across every sales STI subtype. */\nexport class SalesContractCollection extends SmrtCollection<SalesContract> {\n static readonly _itemClass = SalesContract;\n\n async findByCustomer(customerId: string): Promise<SalesContract[]> {\n return this.list({\n where: { customerId },\n orderBy: 'created_at DESC',\n });\n }\n}\n","/**\n * ContractCollection - Collection manager for Contract objects (STI)\n * @packageDocumentation\n */\n\nimport {\n SmrtCollection,\n type SmrtListOptions,\n type SmrtObject,\n type SmrtSelectedRow,\n type SmrtSelectField,\n type SmrtStiReadScope,\n type SmrtWhereClause,\n} from '@happyvertical/smrt-core';\nimport {\n getTenantId,\n queryGlobal,\n queryWithGlobals,\n} from '@happyvertical/smrt-tenancy';\nimport { DOCUMENT_MONEY_READ_REBIND } from '../document-money-internal.js';\nimport {\n Contract,\n isContractSnapshotReportEligible,\n} from '../models/Contract.js';\nimport { withTenantMoneyCollectionRead } from '../tenant-money-barrier.js';\nimport { ContractStatus, ContractType } from '../types/index.js';\nimport { assertCommerceMoneySchemaCurrent } from '../upgrade/detect.js';\nimport { PurchaseContractCollection } from './PurchaseContractCollection.js';\nimport { SalesContractCollection } from './SalesContractCollection.js';\n\nexport class ContractCollection extends SmrtCollection<Contract> {\n static readonly _itemClass = Contract;\n\n private async withMoneyRead<T>(operation: () => Promise<T>): Promise<T> {\n const rootDb = this.db;\n const tenantId = getTenantId();\n if (!tenantId) {\n // Without a tenant, still refuse a database with old money storage.\n await assertCommerceMoneySchemaCurrent(rootDb);\n return operation();\n }\n const result = await withTenantMoneyCollectionRead(\n rootDb,\n tenantId,\n (boundDb) => this.withDatabase(boundDb, operation),\n );\n if (result instanceof Contract)\n result.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n else if (Array.isArray(result))\n for (const item of result)\n if (item instanceof Contract)\n item.rebindMoneyRead(DOCUMENT_MONEY_READ_REBIND, rootDb);\n return result;\n }\n\n override async get(\n filter: string | SmrtWhereClause<Contract>,\n options: Parameters<SmrtCollection<Contract>['get']>[1] = {},\n ): Promise<Contract | null> {\n return this.withMoneyRead(() => super.get(filter, options));\n }\n\n override async list<\n const Select extends readonly SmrtSelectField<Contract>[],\n >(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<Record<string, unknown>[]>;\n override async list<\n const Select extends readonly SmrtSelectField<Contract>[],\n >(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select: Select;\n include?: never;\n stiScope?: undefined;\n },\n ): Promise<SmrtSelectedRow<Contract, Select>[]>;\n override async list(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope: SmrtStiReadScope;\n },\n ): Promise<SmrtObject[]>;\n override async list(options?: undefined): Promise<Contract[]>;\n override async list(\n options: Omit<SmrtListOptions<Contract>, 'select' | 'stiScope'> & {\n select?: undefined;\n stiScope?: undefined;\n },\n ): Promise<Contract[]>;\n override async list(\n options:\n | (Omit<SmrtListOptions<Contract>, 'select'> & { select?: undefined })\n | undefined,\n ): Promise<SmrtObject[]>;\n override async list(\n options: SmrtListOptions<Contract> | undefined,\n ): Promise<SmrtObject[] | Record<string, unknown>[]>;\n override async list(\n options: SmrtListOptions<Contract> = {},\n ): Promise<SmrtObject[] | Record<string, unknown>[]> {\n return this.withMoneyRead(() => super.list(options));\n }\n\n /**\n * Find contracts by customer\n *\n * @param customerId - Customer ID\n * @returns Array of contracts\n * @deprecated Use SalesContractCollection.findByCustomer.\n */\n async findByCustomer(customerId: string): Promise<Contract[]> {\n const sales = await SalesContractCollection.create({\n ...this.options,\n db: this.db,\n });\n return sales.findByCustomer(customerId);\n }\n\n /**\n * Find contracts by vendor\n *\n * @param vendorId - Vendor ID\n * @returns Array of contracts\n * @deprecated Use PurchaseContractCollection.findByVendor.\n */\n async findByVendor(vendorId: string): Promise<Contract[]> {\n const purchases = await PurchaseContractCollection.create({\n ...this.options,\n db: this.db,\n });\n return purchases.findByVendor(vendorId);\n }\n\n /**\n * Hydrate a bounded tenant/date report candidate set once, retaining exact\n * STI descendants so callers can classify custom purchase types safely.\n */\n async listSnapshotReportContracts(options: {\n tenantId: string;\n from: Date;\n to: Date;\n }): Promise<Contract[]> {\n const contracts = await this.list({\n where: {\n tenantId: options.tenantId,\n 'issueDate >=': options.from.toISOString(),\n 'issueDate <=': options.to.toISOString(),\n },\n orderBy: 'issueDate ASC',\n });\n return contracts.filter(isContractSnapshotReportEligible);\n }\n\n /**\n * Find contracts by type (STI)\n *\n * @param contractType - Contract type\n * @returns Array of contracts\n */\n async findByType(contractType: ContractType): Promise<Contract[]> {\n return await this.list({\n where: { contractType },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find contracts by status\n *\n * @param status - Contract status\n * @returns Array of contracts\n */\n async findByStatus(status: ContractStatus): Promise<Contract[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all draft contracts\n *\n * @returns Array of draft contracts\n */\n async findDrafts(): Promise<Contract[]> {\n return await this.findByStatus(ContractStatus.DRAFT);\n }\n\n /**\n * Find all accepted contracts\n *\n * @returns Array of accepted contracts\n */\n async findAccepted(): Promise<Contract[]> {\n return await this.findByStatus(ContractStatus.ACCEPTED);\n }\n\n /**\n * Find overdue contracts\n *\n * @returns Array of overdue contracts\n */\n async findOverdue(): Promise<Contract[]> {\n const now = new Date().toISOString();\n // Get all contracts past due date that aren't completed or cancelled\n const all = await this.list({\n where: {\n 'dueDate <': now,\n },\n orderBy: 'dueDate ASC',\n });\n return all.filter(\n (c) =>\n c.status !== ContractStatus.COMPLETED &&\n c.status !== ContractStatus.CANCELLED,\n );\n }\n\n /**\n * Find expired estimates/quotes\n *\n * @returns Array of expired estimates\n */\n async findExpired(): Promise<Contract[]> {\n const now = new Date().toISOString();\n // Get estimates past expiry date that aren't accepted, declined, or cancelled\n const estimates = await this.list({\n where: {\n contractType: ContractType.ESTIMATE,\n 'expiryDate <': now,\n },\n orderBy: 'expiryDate ASC',\n });\n return estimates.filter(\n (c) =>\n c.status !== ContractStatus.ACCEPTED &&\n c.status !== ContractStatus.DECLINED &&\n c.status !== ContractStatus.CANCELLED,\n );\n }\n\n /**\n * Find contracts in date range\n *\n * @param startDate - Start date\n * @param endDate - End date\n * @returns Array of contracts\n */\n async findByDateRange(startDate: Date, endDate: Date): Promise<Contract[]> {\n return await this.list({\n where: {\n 'issueDate >=': startDate.toISOString(),\n 'issueDate <=': endDate.toISOString(),\n },\n orderBy: 'issueDate DESC',\n });\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all contracts belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of contracts for the tenant\n */\n async findByTenant(tenantId: string): Promise<Contract[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global contracts (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global contracts\n */\n async findGlobal(): Promise<Contract[]> {\n return queryGlobal<Contract>(this);\n }\n\n /**\n * Find contracts for a tenant including global contracts.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global contracts\n */\n async findWithGlobals(tenantId: string): Promise<Contract[]> {\n return queryWithGlobals<Contract>(\n this,\n tenantId,\n 'Contract.findWithGlobals',\n );\n }\n}\n","/** Approved contract billing capacity; construction authorization belongs to the host. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { ContractCollection } from './collections/ContractCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n} from './document-money-internal.js';\nimport { Agreement, type Contract, Order } from './models/Contract.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { MoneyValidationError } from './money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { ContractStatus, InvoiceStatus } from './types/index.js';\n\n/** Exact billing entitlement in the schedule's explicit net or gross basis. */\nexport interface ContractBillingMilestone {\n key: string;\n label: string;\n amountMinor: number;\n}\n/** Immutable approved revision; ceiling is derived from original money plus amendments. */\nexport interface ContractBillingScheduleRevision {\n revision: number;\n requestId: string;\n approvalEvidenceRef: string;\n taxPolicyEvidenceRef: string;\n currency: string;\n basis: 'net' | 'gross';\n amendmentMinor: number;\n approvedTotalMinor: number;\n milestones: ContractBillingMilestone[];\n}\n/** Exact invoice amounts the host approved, independently of a net-only billing ceiling. */\nexport interface ContractMilestoneInvoiceMoney {\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n}\n/** Immutable issued claim; settlement, cancellation and credits never implicitly reopen it. */\nexport interface ContractMilestoneClaim {\n requestId: string;\n revision: number;\n milestoneKey: string;\n invoiceId: string;\n moneySnapshotId: string;\n approvedMoney: ContractMilestoneInvoiceMoney;\n invoiceApprovalEvidenceRef: string;\n}\n/** Persisted append-only schedule history and billing claims. */\nexport interface ContractBillingSchedule {\n version: 1;\n originalAmountMinor: number;\n capacityPolicy: 'issued-consumed';\n revisions: ContractBillingScheduleRevision[];\n claims: ContractMilestoneClaim[];\n}\ninterface ScheduleCommand {\n db: DatabaseInterface;\n tenantId: string;\n contractId: string;\n requestId: string;\n}\n/** The host must authorize approval and retain the referenced policy/evidence. */\nexport interface ApproveContractBillingScheduleInput extends ScheduleCommand {\n expectedRevision: number;\n approvalEvidenceRef: string;\n taxPolicyEvidenceRef: string;\n currency: string;\n basis: 'net' | 'gross';\n /** Zero for the original schedule; explicit signed approved value change thereafter. */\n amendmentMinor: number;\n milestones: ContractBillingMilestone[];\n}\n/** Issue an existing prepared draft under exact host-approved money and capacity. */\nexport interface IssueContractMilestoneInvoiceInput extends ScheduleCommand {\n revision: number;\n milestoneKey: string;\n invoiceId: string;\n approvedMoney: ContractMilestoneInvoiceMoney;\n invoiceApprovalEvidenceRef: string;\n}\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value || value.trim() !== value)\n invalid(`${label} must be nonempty trimmed text`);\n return value;\n}\nfunction integer(value: unknown, label: string, signed = false): number {\n if (\n typeof value !== 'number' ||\n !Number.isSafeInteger(value) ||\n (!signed && value < 0)\n )\n invalid(`${label} must be a ${signed ? '' : 'nonnegative '}safe integer`);\n return value;\n}\nfunction safe(value: bigint): number {\n const result = Number(value);\n return integer(result, 'Computed amount');\n}\nfunction context(input: ScheduleCommand): void {\n text(input.tenantId, 'Tenant');\n text(input.contractId, 'Contract');\n text(input.requestId, 'Request');\n if (getTenantId() !== input.tenantId)\n invalid('Schedule command requires its active tenant context');\n}\nfunction milestones(\n value: ContractBillingMilestone[],\n): ContractBillingMilestone[] {\n if (!Array.isArray(value) || value.length === 0)\n invalid('A schedule requires milestones');\n const keys = new Set<string>();\n return value.map((entry) => {\n if (!entry || typeof entry !== 'object') invalid('Invalid milestone');\n const key = text(entry.key, 'Milestone key');\n if (keys.has(key)) invalid('Milestone keys must be unique');\n keys.add(key);\n return {\n key,\n label: text(entry.label, 'Milestone label'),\n amountMinor: integer(entry.amountMinor, 'Milestone amount'),\n };\n });\n}\nfunction money(\n value: ContractMilestoneInvoiceMoney,\n): ContractMilestoneInvoiceMoney {\n if (!value || typeof value !== 'object')\n invalid('Approved invoice money is required');\n const netMinor = integer(value.netMinor, 'Approved net');\n const taxMinor = integer(value.taxMinor, 'Approved tax');\n const grossMinor = integer(value.grossMinor, 'Approved gross');\n if (BigInt(netMinor) + BigInt(taxMinor) !== BigInt(grossMinor))\n invalid('Approved invoice money must reconcile');\n return { netMinor, taxMinor, grossMinor };\n}\n/** Allocate integer relative weights with the exact rounding remainder on the final milestone. */\nexport function allocateContractMilestones(\n totalMinor: number,\n weights: readonly number[],\n): number[] {\n integer(totalMinor, 'Total');\n if (!Array.isArray(weights) || !weights.length)\n invalid('Milestone weights are required');\n const values = weights.map((value) => {\n integer(value, 'Weight');\n if (!value) invalid('Weights must be positive');\n return BigInt(value);\n });\n const sum = values.reduce((a, b) => a + b, 0n);\n let remaining = BigInt(totalMinor);\n return values.map((value, index) => {\n const amount =\n index === values.length - 1\n ? remaining\n : (BigInt(totalMinor) * value) / sum;\n remaining -= amount;\n return safe(amount);\n });\n}\n/** Read immutable schedule evidence; a detached result cannot mutate its Contract. */\nexport function getContractBillingSchedule(\n contract: Contract,\n): ContractBillingSchedule | null {\n if (!contract.billingScheduleJson) return null;\n let parsed: ContractBillingSchedule;\n try {\n parsed = JSON.parse(contract.billingScheduleJson);\n } catch {\n invalid('Stored billing schedule is invalid');\n }\n if (\n parsed.version !== 1 ||\n parsed.capacityPolicy !== 'issued-consumed' ||\n !Array.isArray(parsed.revisions) ||\n !parsed.revisions.length ||\n !Array.isArray(parsed.claims)\n )\n invalid('Stored billing schedule is invalid');\n return parsed;\n}\nasync function loadContract(\n db: DatabaseInterface,\n tenantId: string,\n contractId: string,\n): Promise<Order | Agreement> {\n const collection = await ContractCollection.create({ db });\n await lockDocumentMoneyParents([{ id: contractId, tenantId, collection }]);\n const contract = await collection.get({ id: contractId }, { cache: false });\n if (\n !(contract instanceof Order || contract instanceof Agreement) ||\n contract.tenantId !== tenantId ||\n !contract.customerId ||\n contract.status !== ContractStatus.ACCEPTED ||\n !contract.moneySnapshotId\n )\n invalid(\n 'Schedule requires an accepted customer contract in the active tenant',\n );\n return contract;\n}\n/** Append an approved schedule; original frozen Contract money remains authoritative and unchanged. */\nexport async function approveContractBillingSchedule(\n input: ApproveContractBillingScheduleInput,\n): Promise<ContractBillingScheduleRevision> {\n context(input);\n const expectedRevision = integer(input.expectedRevision, 'Expected revision');\n const proposal = {\n requestId: input.requestId,\n approvalEvidenceRef: text(input.approvalEvidenceRef, 'Approval evidence'),\n taxPolicyEvidenceRef: text(\n input.taxPolicyEvidenceRef,\n 'Tax policy evidence',\n ),\n currency: text(input.currency, 'Currency'),\n basis: input.basis,\n amendmentMinor: integer(input.amendmentMinor, 'Amendment', true),\n milestones: milestones(input.milestones),\n };\n if (proposal.basis !== 'net' && proposal.basis !== 'gross')\n invalid('Schedule basis must explicitly be net or gross');\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const contract = await loadContract(db, input.tenantId, input.contractId);\n const stored = getContractBillingSchedule(contract);\n const replay = stored?.revisions.find(\n (entry) => entry.requestId === input.requestId,\n );\n if (replay) {\n const { revision, approvedTotalMinor: _total, ...old } = replay;\n if (\n revision !== expectedRevision + 1 ||\n JSON.stringify(old) !== JSON.stringify(proposal)\n )\n invalid('Schedule request changed');\n return replay;\n }\n if (stored?.claims.some((entry) => entry.requestId === input.requestId))\n invalid('Request identity already used');\n const previous = stored?.revisions.at(-1);\n if ((previous?.revision ?? 0) !== expectedRevision)\n invalid('Schedule revision changed');\n if (\n contract.currency !== proposal.currency ||\n (previous &&\n (previous.currency !== proposal.currency ||\n previous.basis !== proposal.basis))\n )\n invalid('Schedule currency and basis must match original approval');\n const originalAmountMinor =\n stored?.originalAmountMinor ??\n (proposal.basis === 'net' ? contract.subtotal : contract.totalAmount);\n integer(originalAmountMinor, 'Original contract amount');\n if (!stored) {\n if (proposal.amendmentMinor !== 0)\n invalid('Initial schedule cannot amend original contract value');\n const invoices = await (\n await InvoiceCollection.create({ db })\n ).findByContract(input.contractId);\n if (\n invoices.some(\n (invoice) => invoice.kind === 'invoice' && !!invoice.moneySnapshotId,\n )\n )\n invalid(\n 'Existing issued contract invoices prevent initial schedule approval',\n );\n }\n const approvedTotalMinor = safe(\n BigInt(previous?.approvedTotalMinor ?? originalAmountMinor) +\n BigInt(proposal.amendmentMinor),\n );\n if (\n proposal.milestones.reduce(\n (sum, entry) => sum + BigInt(entry.amountMinor),\n 0n,\n ) !== BigInt(approvedTotalMinor)\n )\n invalid(\n 'Milestone total must equal original contract plus approved amendments',\n );\n for (const claim of stored?.claims ?? []) {\n const prior = stored?.revisions\n .find((entry) => entry.revision === claim.revision)\n ?.milestones.find((entry) => entry.key === claim.milestoneKey);\n const next = proposal.milestones.find(\n (entry) => entry.key === claim.milestoneKey,\n );\n if (!prior || !next || JSON.stringify(prior) !== JSON.stringify(next))\n invalid('An issued milestone cannot be removed or changed');\n }\n const revision: ContractBillingScheduleRevision = {\n revision: expectedRevision + 1,\n ...proposal,\n approvedTotalMinor,\n };\n const state: ContractBillingSchedule = stored ?? {\n version: 1,\n originalAmountMinor,\n capacityPolicy: 'issued-consumed',\n revisions: [],\n claims: [],\n };\n state.revisions.push(revision);\n contract.billingScheduleJson = JSON.stringify(state);\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return revision;\n });\n}\n\n// An executor-bound, one-invoice capability. Never exported from the package.\nconst issuePermissions = new WeakMap<\n object,\n Map<\n string,\n {\n contractId: string;\n amountMinor: number;\n basis: 'net' | 'gross';\n approvedMoney: ContractMilestoneInvoiceMoney;\n }\n >\n>();\n/** @internal Called by the ordinary money aggregate before any new invoice freezes. */\nexport async function assertContractScheduleInvoiceFreeze(\n db: DatabaseInterface,\n invoice: Invoice,\n): Promise<void> {\n if (invoice.kind !== 'invoice' || !invoice.contractId) return;\n const contract = await (await ContractCollection.create({ db })).get(\n { id: invoice.contractId },\n { cache: false },\n );\n if (!contract) return;\n if (contract.tenantId !== invoice.tenantId)\n invalid('Invoice contract must belong to its active tenant');\n const state = getContractBillingSchedule(contract);\n if (!state) return;\n // Abandoning an unissued draft creates no billing entitlement.\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n !invoice.moneySnapshotId &&\n !invoice.arJournalId\n )\n return;\n if (!(contract instanceof Order || contract instanceof Agreement))\n invalid('Scheduled contract must be a customer contract');\n const permission = invoice.id\n ? issuePermissions.get(db as object)?.get(invoice.id)\n : undefined;\n if (!permission || permission.contractId !== invoice.contractId)\n invalid(\n 'Scheduled contract invoices must use issueContractMilestoneInvoice',\n );\n if (\n invoice.customerId !== contract.customerId ||\n invoice.currency !== contract.currency\n )\n invalid('Milestone invoice must match contract customer and currency');\n const actual = {\n netMinor: invoice.subtotal,\n taxMinor: invoice.taxAmount,\n grossMinor: invoice.totalAmount,\n };\n if (\n JSON.stringify(actual) !== JSON.stringify(permission.approvedMoney) ||\n (permission.basis === 'net' ? invoice.subtotal : invoice.totalAmount) !==\n permission.amountMinor\n )\n invalid('Milestone invoice money differs from approved amounts');\n}\n/** Atomically issue/freeze one prepared draft and consume exactly one approved milestone. */\nexport async function issueContractMilestoneInvoice(\n input: IssueContractMilestoneInvoiceInput,\n): Promise<ContractMilestoneClaim> {\n context(input);\n const request = {\n requestId: input.requestId,\n revision: integer(input.revision, 'Revision'),\n milestoneKey: text(input.milestoneKey, 'Milestone key'),\n invoiceId: text(input.invoiceId, 'Invoice'),\n approvedMoney: money(input.approvedMoney),\n invoiceApprovalEvidenceRef: text(\n input.invoiceApprovalEvidenceRef,\n 'Invoice approval evidence',\n ),\n };\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const contract = await loadContract(db, input.tenantId, input.contractId);\n const state = getContractBillingSchedule(contract);\n if (!state) invalid('Contract has no approved billing schedule');\n const replay = state.claims.find(\n (entry) => entry.requestId === request.requestId,\n );\n if (replay) {\n const { moneySnapshotId: _snapshot, ...prior } = replay;\n if (JSON.stringify(prior) !== JSON.stringify(request))\n invalid('Milestone issue request changed');\n return replay;\n }\n if (state.revisions.some((entry) => entry.requestId === request.requestId))\n invalid('Request identity already used');\n const revision = state.revisions.at(-1);\n if (!revision || revision.revision !== request.revision)\n invalid('Schedule revision changed');\n const milestone = revision.milestones.find(\n (entry) => entry.key === request.milestoneKey,\n );\n if (!milestone) invalid('Milestone does not exist in approved revision');\n if (\n state.claims.some(\n (entry) =>\n entry.milestoneKey === request.milestoneKey ||\n entry.invoiceId === request.invoiceId,\n )\n )\n invalid('Milestone or invoice already consumed');\n const invoices = await InvoiceCollection.create({ db });\n await lockDocumentMoneyParents([\n { id: request.invoiceId, tenantId: input.tenantId, collection: invoices },\n ]);\n const invoice = await invoices.get(\n { id: request.invoiceId },\n { cache: false },\n );\n if (\n !invoice ||\n invoice.tenantId !== input.tenantId ||\n invoice.kind !== 'invoice' ||\n invoice.status !== InvoiceStatus.DRAFT ||\n invoice.moneySnapshotId ||\n invoice.contractId !== input.contractId ||\n invoice.customerId !== contract.customerId ||\n invoice.currency !== revision.currency\n )\n invalid(\n 'Milestone requires a matching unissued draft in the active tenant',\n );\n const permissions = issuePermissions.get(db as object) ?? new Map();\n permissions.set(request.invoiceId, {\n contractId: input.contractId,\n amountMinor: milestone.amountMinor,\n basis: revision.basis,\n approvedMoney: request.approvedMoney,\n });\n issuePermissions.set(db as object, permissions);\n try {\n invoice.markSent();\n await invoice.save();\n } finally {\n permissions.delete(request.invoiceId);\n if (!permissions.size) issuePermissions.delete(db as object);\n }\n if (!invoice.moneySnapshotId) invalid('Milestone invoice was not frozen');\n const claim: ContractMilestoneClaim = {\n ...request,\n moneySnapshotId: invoice.moneySnapshotId,\n };\n state.claims.push(claim);\n contract.billingScheduleJson = JSON.stringify(state);\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return claim;\n });\n}\n","import { assertContractScheduleInvoiceFreeze } from './contract-billing-schedule.js';\nimport {\n getHistoricalSalesMoney,\n readHistoricalSalesLines,\n} from './historical-sales-money.js';\nimport type { HistoricalSalesMoneySnapshot } from './historical-sales-types.js';\n/** Transactional Invoice money aggregate persistence. */\n\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport {\n DocumentTaxCollection,\n type DocumentTaxWriteInput,\n} from './collections/DocumentTaxCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { InvoiceLineItemCollection } from './collections/InvoiceLineItemCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport {\n allocateFrozenCredit,\n type FrozenCreditAllocation,\n type IssuedCreditConsumption,\n} from './credit-allocation.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n withDocumentMoneyObjectTransaction,\n withDocumentMoneyTransaction,\n} from './document-money-internal.js';\nimport type { DocumentTax } from './models/DocumentTax.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { InvoiceLineItem } from './models/InvoiceLineItem.js';\nimport type { TaxSettings } from './models/TaxSettings.js';\nimport {\n calculateMoneyDocument,\n type MoneyDiscountInput,\n MoneyValidationError,\n type ResolvableTaxCodeInput,\n resolveLineTaxCode,\n} from './money.js';\nimport {\n lockTenantMoneyRuntime,\n withTenantMoneyRuntime,\n} from './tenant-money-barrier.js';\nimport type { InvoiceTaxComponentSnapshot } from './types/index.js';\nimport { InvoiceStatus } from './types/index.js';\n\ntype ProductTaxDefaults = {\n tenantId: string | null;\n defaultSalesTaxCodeId: string;\n};\n\ntype DeleteOptions = { expectedUpdatedAt?: Date | string };\n\nexport interface PreviewInvoiceMoneyInput {\n db: DatabaseInterface;\n tenantId: string;\n invoiceId: string;\n draft?: {\n header?: Partial<\n Pick<\n Invoice,\n | 'currency'\n | 'lineAmountType'\n | 'taxRoundingScope'\n | 'providerTaxAmount'\n | 'customerId'\n >\n >;\n lines?: Array<\n Partial<\n Pick<\n InvoiceLineItem,\n | 'id'\n | 'description'\n | 'productId'\n | 'quantity'\n | 'unitPrice'\n | 'discountType'\n | 'discountRate'\n | 'discount'\n | 'taxMode'\n | 'taxCodeId'\n >\n >\n >;\n };\n}\n\nexport interface PreviewInvoiceMoneyResult {\n source: 'calculated';\n header: {\n currency: string;\n lineAmountType: Invoice['lineAmountType'];\n taxRoundingScope: Invoice['taxRoundingScope'];\n subtotalMinor: number;\n discountTotalMinor: number;\n taxAmountMinor: number;\n providerTaxAmountMinor: number;\n totalAmountMinor: number;\n };\n lines: Array<{\n id: string;\n grossMinor: number;\n discountMinor: number;\n amountMinor: number;\n taxMinor: number;\n taxCodeId: string | null;\n taxCodeCode: string | null;\n taxCodeName: string | null;\n taxComponents: InvoiceLineItem['taxComponents'];\n }>;\n taxes: DocumentTaxWriteInput[];\n}\n\nexport interface GetInvoiceMoneyFactsInput {\n db: DatabaseInterface;\n tenantId: string;\n invoiceId: string;\n}\n\nexport interface InvoiceMoneyFacts {\n historical?: {\n snapshot: HistoricalSalesMoneySnapshot;\n lines: Array<{ sourceKey: string; lineId: string }>;\n };\n source: 'stored';\n payable?: ReturnType<Invoice['getPayableFacts']>;\n invoiceId: string;\n moneySnapshotId: string;\n kind: Invoice['kind'];\n status: Invoice['status'];\n header: PreviewInvoiceMoneyResult['header'];\n lines: PreviewInvoiceMoneyResult['lines'];\n taxes: DocumentTaxWriteInput[];\n}\n\nconst FROZEN_INVOICE_FIELDS = [\n 'moneyAuthority',\n 'historicalSalesMoneyJson',\n 'historicalSourceKeyHash',\n 'kind',\n 'creditedInvoiceId',\n 'tenantId',\n 'customerId',\n 'contractId',\n 'invoiceNumber',\n 'reference',\n 'issueDate',\n 'dueDate',\n 'subtotal',\n 'discountTotal',\n 'taxAmount',\n 'providerTaxAmount',\n 'totalAmount',\n 'currency',\n 'lineAmountType',\n 'taxRoundingScope',\n 'sellerTaxRegistrationsJson',\n 'partyTaxId',\n 'moneySnapshotId',\n 'notes',\n 'customerNotes',\n 'terms',\n] as const;\n\nconst FROZEN_LINE_FIELDS = [\n 'tenantId',\n 'invoiceId',\n 'creditedLineId',\n 'creditCalculationBasisJson',\n 'description',\n 'sku',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discountType',\n 'discountRate',\n 'discount',\n 'taxMode',\n 'taxCodeId',\n 'taxCodeCode',\n 'taxCodeName',\n 'taxComponentsJson',\n 'taxAmount',\n 'taxRate',\n 'amount',\n 'sourceType',\n 'sourceId',\n 'periodStart',\n 'periodEnd',\n 'revenueAccountId',\n 'sortOrder',\n 'moneySnapshotId',\n] as const;\n\n/** Frozen-field identity: an absent optional reference (`''`) equals a stored NULL. */\nfunction comparable(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString();\n return value === '' || value === undefined ? null : value;\n}\n\nfunction assertFieldsUnchanged<T extends object>(\n proposed: T,\n persisted: T,\n fields: readonly (keyof T)[],\n label: string,\n): void {\n for (const field of fields) {\n if (comparable(proposed[field]) !== comparable(persisted[field])) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n `${label} ${String(field)} is frozen`,\n );\n }\n }\n}\n\nfunction assertTenantId(value: string | null): asserts value is string {\n if (!value || value.trim() !== value)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money requires a tenant-owned invoice',\n );\n}\n\nfunction requireId(value: string | null | undefined, label: string): string {\n if (!value)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `${label} requires a persisted ID`,\n );\n return value;\n}\n\n/** Lock the tenant's settings row; every money document belongs to a tenant. */\nasync function lockRuntimeSettings(\n db: DatabaseInterface,\n tenantId: string | null,\n): Promise<TaxSettings> {\n if (!tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Commerce money documents require a tenant',\n );\n return lockTenantMoneyRuntime(db, tenantId);\n}\n\nfunction isFrozen(invoice: Invoice): boolean {\n return (\n invoice.status !== InvoiceStatus.DRAFT ||\n !!invoice.arJournalId ||\n !!invoice.moneySnapshotId\n );\n}\n\nfunction aggregateSignature(invoice: Invoice): string {\n return JSON.stringify([\n invoice.lineAmountType,\n invoice.taxRoundingScope,\n invoice.subtotal,\n invoice.discountTotal,\n invoice.taxAmount,\n invoice.totalAmount,\n ]);\n}\n\nasync function loadInvoice(\n db: DatabaseInterface,\n id: string,\n): Promise<{ collection: InvoiceCollection; invoice: Invoice }> {\n const collection = await InvoiceCollection.create({ db });\n const invoice = await collection.get({ id }, { cache: false });\n if (!invoice)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice ${id} was not found`,\n );\n return { collection, invoice };\n}\n\nasync function findInvoice(\n db: DatabaseInterface,\n id: string,\n): Promise<Invoice | null> {\n const collection = await InvoiceCollection.create({ db });\n return collection.get({ id }, { cache: false });\n}\n\n/** @internal Acquire the invoice money lock and reload persisted authority. */\nexport async function lockAndReloadInvoice(\n db: DatabaseInterface,\n invoiceId: string,\n tenantId: string,\n): Promise<{ collection: InvoiceCollection; invoice: Invoice }> {\n const first = await loadInvoice(db, invoiceId);\n await lockDocumentMoneyParents([\n { id: invoiceId, tenantId, collection: first.collection },\n ]);\n const invoice = await first.collection.get(\n { id: invoiceId },\n { cache: false },\n );\n if (!invoice || invoice.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant identity changed while acquiring its money lock',\n );\n return { collection: first.collection, invoice };\n}\n\nasync function lockAndReloadMoneyInvoice(\n db: DatabaseInterface,\n invoiceId: string,\n tenantId: string,\n creditedInvoiceId: string | null,\n): Promise<{\n collection: InvoiceCollection;\n invoice: Invoice;\n source: Invoice | null;\n}> {\n const collection = await InvoiceCollection.create({ db });\n const ids = [invoiceId, ...(creditedInvoiceId ? [creditedInvoiceId] : [])];\n const loaded = await Promise.all(\n ids.map((id) => collection.get({ id }, { cache: false })),\n );\n if (loaded.some((row) => !row || row.tenantId !== tenantId))\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money parents must exist in the active tenant',\n );\n await lockDocumentMoneyParents(\n ids.map((id) => ({ id, tenantId, collection })),\n );\n const invoice = await collection.get({ id: invoiceId }, { cache: false });\n const source = creditedInvoiceId\n ? await collection.get({ id: creditedInvoiceId }, { cache: false })\n : null;\n if (\n !invoice ||\n invoice.tenantId !== tenantId ||\n (source && source.tenantId !== tenantId)\n )\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money parent identity changed while acquiring its lock',\n );\n return { collection, invoice, source };\n}\n\nfunction discountInput(line: InvoiceLineItem): MoneyDiscountInput {\n if (line.discountType === 'percent')\n return { kind: 'percent', rate: String(line.discountRate) };\n if (line.discountType === 'amount' || line.discount !== 0)\n return { kind: 'amount', minor: line.discount };\n if (line.discountType !== 'none')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Unknown discount type: ${line.discountType}`,\n );\n return { kind: 'none' };\n}\n\ntype CreditPreparation = {\n allocationByLineId: Map<string, FrozenCreditAllocation>;\n sourceByLineId: Map<string, InvoiceLineItem>;\n issuedLines: InvoiceLineItem[];\n issuedParentById: Map<string, Invoice>;\n sourceInvoice: Invoice;\n sourceTaxes: DocumentTax[];\n exhaustsDocument: boolean;\n};\n\nfunction issuedCredit(invoice: Invoice): boolean {\n return (\n invoice.kind === 'credit_note' &&\n invoice.status !== InvoiceStatus.DRAFT &&\n invoice.status !== InvoiceStatus.CANCELLED\n );\n}\n\n/** @internal Refresh one economic credit effect, including historical issued credits. */\nexport async function refreshIssuedCreditBalance(\n db: DatabaseInterface,\n source: Invoice,\n): Promise<void> {\n const sourceId = requireId(source.id, 'Credited invoice');\n const credits = await (await InvoiceCollection.create({ db })).list({\n where: { tenantId: source.tenantId, creditedInvoiceId: sourceId },\n limit: 100001,\n });\n if (credits.length > 100000)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Issued credit scope exceeds its bounded source limit',\n );\n const issued = credits.filter(issuedCredit).sort((left, right) => {\n const date = left.issueDate.getTime() - right.issueDate.getTime();\n if (date) return date;\n return String(left.id) < String(right.id)\n ? -1\n : String(left.id) > String(right.id)\n ? 1\n : 0;\n });\n const total = issued.reduce((sum, credit) => sum + credit.totalAmount, 0);\n if (!Number.isSafeInteger(total) || total < 0)\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n 'Issued credit total is not a nonnegative safe integer',\n );\n let remainingSource = Math.max(0, source.totalAmount - source.amountPaid);\n const managed = new Map<string, number>();\n if (\n source.retentionAccountingStateJson ||\n source.ordinaryAccountingStateJson\n ) {\n const providerState = JSON.parse(\n source.retentionAccountingStateJson || source.ordinaryAccountingStateJson,\n );\n for (const entry of providerState.credits) {\n const credit = issued.find(\n (candidate) => candidate.id === entry.creditId,\n );\n const retainedMinor = source.retentionAccountingStateJson\n ? entry.retainedMinor\n : 0;\n const frozen = retainedMinor + entry.appliedMinor;\n if (\n !credit ||\n managed.has(entry.creditId) ||\n !Number.isSafeInteger(retainedMinor) ||\n retainedMinor < 0 ||\n !Number.isSafeInteger(entry.appliedMinor) ||\n entry.appliedMinor < 0 ||\n !Number.isSafeInteger(frozen) ||\n frozen > credit.totalAmount ||\n frozen !== credit.creditedAmount ||\n frozen > remainingSource\n )\n throw new MoneyValidationError(\n 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED',\n 'Provider-managed credit allocation cannot change without an explicit reversal contract',\n );\n managed.set(entry.creditId, frozen);\n remainingSource -= frozen;\n }\n }\n // Provider applications are immutable authority, not a fresh allocation choice.\n // Reserve them before assigning residual capacity; neither database order nor\n // a later same-day credit's UUID may take an already committed application.\n for (const credit of [\n ...issued,\n ...credits.filter((entry) => !issued.includes(entry)),\n ]) {\n const included = issued.includes(credit);\n const frozen = managed.get(requireId(credit.id, 'Credit invoice'));\n const applied =\n frozen ?? (included ? Math.min(credit.totalAmount, remainingSource) : 0);\n if (included && frozen === undefined) remainingSource -= applied;\n if (credit.creditedAmount !== applied) {\n credit.creditedAmount = applied;\n credit.updatePaymentStatus(credit.amountPaid);\n // A zero application is not an issuance reversal. SENT can be recorded\n // without delivery timestamps, so payment status alone cannot restore it.\n if (included && credit.status === InvoiceStatus.DRAFT)\n credit.status = InvoiceStatus.SENT;\n await credit.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n }\n if (\n (source.retentionAccountingStateJson ||\n source.ordinaryAccountingStateJson) &&\n total !== source.creditedAmount\n ) {\n const state = JSON.parse(\n source.retentionAccountingStateJson || source.ordinaryAccountingStateJson,\n );\n if (\n state.status !== 'ready' ||\n state.steps.some(\n (step: { status: string }) => step.status !== 'confirmed',\n )\n )\n throw new MoneyValidationError(\n 'ACCOUNTING_SYNC_RECONCILIATION_REQUIRED',\n 'Provider retention operation must reconcile before changing source credits',\n );\n }\n source.creditedAmount = total;\n source.updatePaymentStatus(source.amountPaid);\n await source.saveDerived(DOCUMENT_MONEY_WRITE);\n}\n\nfunction lineNet(line: InvoiceLineItem, parent: Invoice): number {\n return parent.lineAmountType === 'inclusive'\n ? line.amount - line.taxAmount\n : line.amount;\n}\n\nasync function prepareCreditLines(\n db: DatabaseInterface,\n invoice: Invoice,\n lines: InvoiceLineItem[],\n): Promise<CreditPreparation> {\n if (!invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'A credit note requires a credited invoice',\n );\n const sourceInvoice = await findInvoice(db, invoice.creditedInvoiceId);\n if (\n sourceInvoice?.kind !== 'invoice' ||\n sourceInvoice.tenantId !== invoice.tenantId ||\n sourceInvoice.status === InvoiceStatus.DRAFT ||\n sourceInvoice.status === InvoiceStatus.CANCELLED ||\n !sourceInvoice.moneySnapshotId\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must be an issued, non-cancelled invoice in the same tenant',\n );\n if (sourceInvoice.moneyAuthority === 'historical')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Historical source credits require exact original monetary facts and concrete historical source line lineage, not calculated quantity or inferred tax',\n );\n if (sourceInvoice.currency !== invoice.currency)\n throw new MoneyValidationError(\n 'CURRENCY_MISMATCH',\n 'Credit note currency must match its credited invoice',\n );\n if (sourceInvoice.customerId !== invoice.customerId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credit note customer must match its credited invoice',\n );\n invoice.lineAmountType = sourceInvoice.lineAmountType;\n invoice.taxRoundingScope = sourceInvoice.taxRoundingScope;\n const lineCollection = await InvoiceLineItemCollection.create({ db });\n const sourceLines = await lineCollection.findByInvoice(\n requireId(sourceInvoice.id, 'Credited invoice'),\n );\n const sourceTaxes = await (\n await DocumentTaxCollection.create({ db })\n ).findByDocument(\n requireId(sourceInvoice.tenantId, 'Credited invoice tenant'),\n 'invoice',\n requireId(sourceInvoice.id, 'Credited invoice'),\n );\n const sourceByLineId = new Map(\n sourceLines.map((line) => [requireId(line.id, 'Credited line'), line]),\n );\n const invoices = await InvoiceCollection.create({ db });\n const priorCredits = (\n await invoices.list({\n where: {\n tenantId: invoice.tenantId,\n creditedInvoiceId: invoice.creditedInvoiceId,\n },\n })\n ).filter((row) => row.id !== invoice.id && issuedCredit(row));\n const issuedLines: InvoiceLineItem[] = [];\n const issuedParentById = new Map(\n priorCredits.map((row) => [requireId(row.id, 'Issued credit note'), row]),\n );\n const consumptions: IssuedCreditConsumption[] = [];\n for (const credit of priorCredits) {\n for (const line of await lineCollection.findByInvoice(\n requireId(credit.id, 'Issued credit note'),\n )) {\n if (!line.creditedLineId) continue;\n issuedLines.push(line);\n const basis = line.creditCalculationBasis;\n consumptions.push({\n creditedLineId: line.creditedLineId,\n quantity: basis?.kind === 'quantity' ? basis.quantity : '0',\n netMinor: lineNet(line, credit),\n discountMinor: line.discount,\n });\n }\n }\n const targeted = lines.filter((line) => line.creditedLineId);\n const allocation = targeted.length\n ? allocateFrozenCredit(\n sourceLines.map((line) => ({\n id: requireId(line.id, 'Credited line'),\n quantity: String(line.quantity),\n netMinor: lineNet(line, sourceInvoice),\n discountMinor: line.discount,\n unitPrice: line.unitPrice,\n discountType: line.discountType,\n discountRate: line.discountRate,\n })),\n consumptions,\n targeted.map((line) => {\n const basis = line.creditCalculationBasis;\n return basis?.kind === 'net_amount'\n ? {\n creditedLineId: requireId(line.creditedLineId, 'Credited line'),\n netMinor: basis.netMinor,\n }\n : {\n creditedLineId: requireId(line.creditedLineId, 'Credited line'),\n quantity:\n basis?.kind === 'quantity'\n ? basis.quantity\n : String(line.quantity),\n };\n }),\n )\n : { allocations: [], exhaustsDocument: false };\n const allocationByLineId = new Map<string, FrozenCreditAllocation>();\n const targetBySource = new Map(\n targeted.map((line) => [\n requireId(line.creditedLineId, 'Credited line'),\n line,\n ]),\n );\n for (const row of allocation.allocations) {\n const line = targetBySource.get(row.creditedLineId);\n if (!line)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credit allocation lost its target line',\n );\n line.creditCalculationBasis = row.basis;\n allocationByLineId.set(requireId(line.id, 'Credit line'), row);\n }\n return {\n allocationByLineId,\n sourceByLineId,\n issuedLines,\n issuedParentById,\n sourceInvoice,\n sourceTaxes,\n exhaustsDocument: allocation.exhaustsDocument,\n };\n}\n\nasync function recomputeInvoiceAggregate(\n db: DatabaseInterface,\n invoice: Invoice,\n settings: TaxSettings,\n freezeSnapshotId = '',\n persist = true,\n proposedLines?: InvoiceLineItem[],\n): Promise<{ lines: InvoiceLineItem[]; taxRows: DocumentTaxWriteInput[] }> {\n assertTenantId(invoice.tenantId);\n const tenantId = invoice.tenantId;\n const linesCollection = await InvoiceLineItemCollection.create({ db });\n const codesCollection = await TaxCodeCollection.create({ db });\n const componentsCollection = await TaxComponentCollection.create({ db });\n const invoiceId = requireId(invoice.id, 'Invoice calculation');\n const lines =\n proposedLines ?? (await linesCollection.findByInvoice(invoiceId));\n const credit =\n invoice.kind === 'credit_note'\n ? await prepareCreditLines(db, invoice, lines)\n : null;\n const codes = await codesCollection.list({ where: { tenantId } });\n const components = await componentsCollection.list({ where: { tenantId } });\n const componentById = new Map(\n components.map((row) => [requireId(row.id, 'Tax component'), row]),\n );\n const codeById = new Map(\n codes.map((row) => [requireId(row.id, 'Tax code'), row]),\n );\n const codeInputs: Record<string, ResolvableTaxCodeInput> = {};\n for (const code of codes) {\n const codeId = requireId(code.id, 'Tax code');\n codeInputs[codeId] = {\n id: codeId,\n kind: code.kind,\n active: code.active,\n appliesTo: code.appliesTo,\n components: code.components.map((part) => {\n const component = componentById.get(part.taxComponentId);\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax component ${part.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: requireId(component.id, 'Tax component'),\n percent: component.percent,\n compound: part.compound,\n };\n }),\n };\n }\n if (credit) {\n for (const source of credit.sourceByLineId.values()) {\n if (!source.taxCodeId) continue;\n const frozenKind = credit.sourceTaxes.find(\n (row) => row.taxCodeId === source.taxCodeId,\n )?.kind;\n codeInputs[source.taxCodeId] = {\n id: source.taxCodeId,\n kind:\n frozenKind ??\n (source.taxComponents.length ? 'taxable' : 'zero-rated'),\n active: true,\n appliesTo: 'sales',\n components: source.taxComponents.map((component) => ({\n taxComponentId: component.taxComponentId,\n percent: component.percent,\n compound: component.compound ?? false,\n })),\n };\n }\n }\n const exempt = await codesCollection.findByCode('exempt', tenantId);\n const outOfScope = await codesCollection.findByCode('out-of-scope', tenantId);\n const customers = await CustomerCollection.create({ db });\n const customer = invoice.customerId\n ? await customers.get({ id: invoice.customerId }, { cache: false })\n : null;\n if (customer && customer.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice customer must belong to its tenant',\n );\n\n // Products owns catalog reads. Load it lazily, on the aggregate transaction,\n // so commerce keeps the same runtime-only package edge used for ledgers.\n const productIds = [\n ...new Set(\n lines\n .filter((line) => !line.creditedLineId)\n .map((line) => line.productId)\n .filter((productId): productId is string => !!productId),\n ),\n ];\n const productById = new Map<string, ProductTaxDefaults>();\n if (productIds.length > 0) {\n const { ProductCollection } = await import(\n '@happyvertical/smrt-products/collections'\n );\n const products = await ProductCollection.create({ db });\n for (const productId of productIds) {\n const product = await products.get({ id: productId }, { cache: false });\n if (!product)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice product ${productId} was not found`,\n );\n if (product.tenantId !== null && product.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice product ${productId} must be global or belong to its tenant`,\n );\n productById.set(productId, product);\n }\n }\n\n type ResolvedMetadata = {\n id: string;\n code: string | null;\n name: string | null;\n kind: 'taxable' | 'zero-rated' | 'exempt' | 'out-of-scope';\n components: InvoiceTaxComponentSnapshot[];\n };\n const resolvedCodes = new Map<string, ResolvedMetadata | null>();\n const calculated = calculateMoneyDocument({\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n roundingScope: invoice.taxRoundingScope,\n lines: lines.map((line) => {\n if (line.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice line ${line.id} must belong to its parent tenant`,\n );\n const lineId = requireId(line.id, 'Invoice line');\n if (line.creditedLineId) {\n if (!credit)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Only a credit note may reference a credited line',\n );\n const source = credit.sourceByLineId.get(line.creditedLineId);\n const allocation = credit.allocationByLineId.get(lineId);\n if (!source || !allocation)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Credited line is not part of the frozen source invoice',\n );\n const taxCode = source.taxCodeId\n ? (codeInputs[source.taxCodeId] ?? null)\n : null;\n resolvedCodes.set(\n lineId,\n source.taxCodeId\n ? {\n id: source.taxCodeId,\n code: source.taxCodeCode,\n name: source.taxCodeName,\n kind: taxCode?.kind ?? 'zero-rated',\n components: structuredClone(source.taxComponents),\n }\n : null,\n );\n line.description ||= source.description;\n line.sku ||= source.sku;\n line.productId = source.productId;\n line.revenueAccountId = source.revenueAccountId;\n if (allocation.basis.kind === 'quantity') {\n line.quantity = Number(allocation.basis.quantity);\n line.unitPrice = allocation.basis.sourceUnitPrice;\n line.discountType = allocation.discountMinor ? 'amount' : 'none';\n line.discountRate = '0';\n } else {\n line.quantity = 1;\n line.unitPrice = allocation.netMinor ?? allocation.basis.netMinor;\n line.discountType = 'none';\n line.discountRate = '0';\n }\n line.discount = allocation.discountMinor;\n return {\n id: lineId,\n quantity: line.quantity,\n unitPrice: line.unitPrice,\n netAmountMinor:\n allocation.basis.kind === 'net_amount'\n ? (allocation.netMinor ?? allocation.basis.netMinor)\n : undefined,\n discount: allocation.discountMinor\n ? ({ kind: 'amount', minor: allocation.discountMinor } as const)\n : ({ kind: 'none' } as const),\n taxCode,\n };\n }\n if (invoice.kind === 'invoice' && line.creditCalculationBasis)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Ordinary invoice lines cannot carry a credit calculation basis',\n );\n if (invoice.kind === 'credit_note' && line.taxMode !== 'override')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Free-form credit lines require an explicit tax-code override',\n );\n const resolved = resolveLineTaxCode(\n {\n lineAmountType: invoice.lineAmountType,\n lineOverride: line.taxMode === 'override' ? line.taxCodeId : null,\n },\n {\n direction: 'sales',\n codes: codeInputs,\n customerTaxExempt: customer?.taxExempt ?? false,\n exemptCodeId: exempt?.id,\n productCodeId: line.productId\n ? productById.get(line.productId)?.defaultSalesTaxCodeId || null\n : null,\n partyCodeId: customer?.defaultTaxCodeId,\n appDefaultCodeId: settings.defaultSalesTaxCodeId,\n outOfScopeCodeId: outOfScope?.id,\n },\n );\n resolvedCodes.set(\n lineId,\n resolved.taxCode\n ? (() => {\n const code = codeById.get(resolved.taxCode.id);\n if (!code)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax code ${resolved.taxCode.id} was not loaded`,\n );\n return {\n id: requireId(code.id, 'Tax code'),\n code: code.code,\n name: code.name,\n kind: code.kind,\n components: code.components.map((part) => {\n const component = componentById.get(part.taxComponentId);\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Tax component ${part.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: part.taxComponentId,\n name: component.name,\n percent: component.percent,\n ...(part.compound ? { compound: true } : {}),\n taxMinor: 0,\n };\n }),\n };\n })()\n : null,\n );\n return {\n id: requireId(line.id, 'Invoice line'),\n quantity: line.quantity,\n unitPrice: line.unitPrice,\n discount: discountInput(line),\n taxCode: resolved.taxCode,\n };\n }),\n });\n\n // When every original line is exhausted, consume the exact remaining frozen\n // component and taxable residual. This preserves document-rounding cents\n // without consulting today's rates; free-form goodwill lines remain separate.\n if (credit?.exhaustsDocument) {\n const resultById = new Map(calculated.lines.map((row) => [row.id, row]));\n const targeted = lines.filter((line) => !!line.creditedLineId);\n for (const line of targeted) {\n const source = credit.sourceByLineId.get(\n requireId(line.creditedLineId, 'Credited line'),\n );\n const result = resultById.get(requireId(line.id, 'Credit line'));\n if (!source || !result) continue;\n const prior = credit.issuedLines.filter(\n (candidate) => candidate.creditedLineId === source.id,\n );\n const priorNet = prior.reduce((sum, candidate) => {\n const parent = credit.issuedParentById.get(candidate.invoiceId);\n return sum + (parent ? lineNet(candidate, parent) : 0);\n }, 0);\n const desiredNet = lineNet(source, credit.sourceInvoice) - priorNet;\n const netDelta = desiredNet - result.netMinor;\n result.netMinor = desiredNet;\n result.amountMinor += netDelta;\n for (const sourceComponent of source.taxComponents) {\n const component = result.components.find(\n (candidate) =>\n candidate.taxComponentId === sourceComponent.taxComponentId,\n );\n if (!component) continue;\n const priorTax = prior.reduce(\n (sum, candidate) =>\n sum +\n (candidate.taxComponents.find(\n (part) => part.taxComponentId === sourceComponent.taxComponentId,\n )?.taxMinor ?? 0),\n 0,\n );\n const desiredTax = sourceComponent.taxMinor - priorTax;\n const taxDelta = desiredTax - component.taxMinor;\n component.taxMinor = desiredTax;\n if (sourceComponent.compound) {\n component.compound = true;\n component.taxableMinor =\n (sourceComponent.taxableMinor ?? 0) -\n prior.reduce(\n (sum, candidate) =>\n sum +\n (candidate.taxComponents.find(\n (part) =>\n part.taxComponentId === sourceComponent.taxComponentId,\n )?.taxableMinor ?? 0),\n 0,\n );\n }\n result.taxMinor += taxDelta;\n if (invoice.lineAmountType === 'inclusive')\n result.amountMinor += taxDelta;\n }\n }\n const rebuilt = new Map<\n string,\n {\n taxCodeId: string | null;\n taxComponentId: string | null;\n taxableMinor: number;\n netMinor?: number;\n taxMinor: number;\n }\n >();\n for (const result of calculated.lines) {\n const metadata = resolvedCodes.get(result.id) ?? null;\n const parts = result.components.length\n ? result.components\n : [\n {\n taxComponentId: null,\n taxMinor: 0,\n compound: false,\n taxableMinor: undefined,\n },\n ];\n for (const part of parts) {\n const key = `${metadata?.id ?? ''}\\u0000${part.taxComponentId ?? ''}`;\n const row = rebuilt.get(key) ?? {\n taxCodeId: metadata?.id ?? null,\n taxComponentId: part.taxComponentId,\n taxableMinor: 0,\n taxMinor: 0,\n };\n row.taxableMinor += part.taxableMinor ?? result.netMinor;\n if (part.compound) row.netMinor = (row.netMinor ?? 0) + result.netMinor;\n row.taxMinor += part.taxMinor;\n rebuilt.set(key, row);\n }\n }\n calculated.taxes = [...rebuilt.values()].sort((left, right) => {\n const a = `${left.taxCodeId ?? ''}\\u0000${left.taxComponentId ?? ''}`;\n const b = `${right.taxCodeId ?? ''}\\u0000${right.taxComponentId ?? ''}`;\n return a < b ? -1 : a > b ? 1 : 0;\n });\n calculated.subtotalMinor = calculated.lines.reduce(\n (sum, row) => sum + row.netMinor,\n 0,\n );\n calculated.taxMinor = calculated.lines.reduce(\n (sum, row) => sum + row.taxMinor,\n 0,\n );\n calculated.totalMinor = calculated.subtotalMinor + calculated.taxMinor;\n }\n\n if (credit) {\n const resultById = new Map(calculated.lines.map((row) => [row.id, row]));\n for (const [lineId, allocation] of credit.allocationByLineId) {\n if (allocation.basis.kind !== 'quantity') continue;\n const result = resultById.get(lineId);\n const hasAmountBasisConsumption = credit.issuedLines.some(\n (line) =>\n line.creditedLineId === allocation.creditedLineId &&\n line.creditCalculationBasis?.kind === 'net_amount',\n );\n if (\n result &&\n Math.abs(result.netMinor) > Math.abs(allocation.remainingNetMinor) &&\n (!allocation.exhaustsLine || hasAmountBasisConsumption)\n )\n throw new MoneyValidationError(\n 'CREDIT_EXCEEDS_LINE',\n 'Credit quantity exceeds the remaining frozen net amount',\n );\n }\n }\n\n const lineById = new Map(\n lines.map((line) => [requireId(line.id, 'Invoice line'), line]),\n );\n for (const result of calculated.lines) {\n const line = lineById.get(result.id);\n if (!line)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Calculated line ${result.id} was not loaded`,\n );\n const code = resolvedCodes.get(requireId(line.id, 'Invoice line')) ?? null;\n line.discount = result.discountMinor;\n line.amount = result.amountMinor;\n line.taxAmount = result.taxMinor;\n line.taxCodeId = code?.id ?? null;\n line.taxCodeCode = code?.code ?? null;\n line.taxCodeName = code?.name ?? null;\n line.taxComponents = result.components.map((entry) => {\n const component = code?.components.find(\n (candidate) => candidate.taxComponentId === entry.taxComponentId,\n );\n if (!component)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Calculated component ${entry.taxComponentId} was not loaded`,\n );\n return {\n taxComponentId: component.taxComponentId,\n name: component.name,\n percent: component.percent,\n taxMinor: entry.taxMinor,\n ...(entry.compound\n ? { compound: true, taxableMinor: entry.taxableMinor }\n : {}),\n };\n });\n line.taxRate = result.components.some((part) => part.compound)\n ? result.netMinor === 0\n ? 0\n : result.taxMinor / result.netMinor\n : code\n ? code.components.reduce(\n (sum, part) => sum + Number(part.percent) / 100,\n 0,\n )\n : 0;\n if (freezeSnapshotId) line.moneySnapshotId = freezeSnapshotId;\n if (persist) await line.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n\n const taxRows = calculated.taxes.map((tax): DocumentTaxWriteInput => {\n const code = tax.taxCodeId\n ? ([...resolvedCodes.values()].find(\n (candidate) => candidate?.id === tax.taxCodeId,\n ) ?? null)\n : null;\n const snapshotComponent = tax.taxComponentId\n ? code?.components.find(\n (candidate) => candidate.taxComponentId === tax.taxComponentId,\n )\n : null;\n const currentComponent = tax.taxComponentId\n ? componentById.get(tax.taxComponentId)\n : null;\n const sourceTax = credit?.sourceTaxes.find(\n (row) =>\n row.taxCodeId === tax.taxCodeId &&\n row.taxComponentId === tax.taxComponentId,\n );\n if (tax.taxCodeId && !code)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Document tax code ${tax.taxCodeId} was not loaded`,\n );\n if (tax.taxComponentId && !snapshotComponent)\n throw new MoneyValidationError(\n 'TAX_CODE_NOT_FOUND',\n `Document tax component ${tax.taxComponentId} was not loaded`,\n );\n return {\n tenantId,\n documentType: invoice.kind,\n documentId: invoiceId,\n currency: invoice.currency,\n taxCodeId: code ? requireId(code.id, 'Tax code') : null,\n taxCodeCode: code?.code ?? null,\n kind: code?.kind ?? null,\n taxComponentId: snapshotComponent?.taxComponentId ?? null,\n taxComponentName: snapshotComponent?.name ?? null,\n percent: snapshotComponent?.percent ?? null,\n liabilityAccountId:\n sourceTax?.liabilityAccountId ||\n currentComponent?.liabilityAccountId ||\n null,\n taxableMinor: tax.taxableMinor,\n netMinor: tax.netMinor ?? null,\n taxMinor: tax.taxMinor,\n recoverableMinor: 0,\n };\n });\n if (persist) {\n const documentTaxes = await DocumentTaxCollection.create({ db });\n await documentTaxes.replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {\n tenantId,\n documentType: invoice.kind,\n documentId: invoiceId,\n rows: taxRows,\n });\n }\n invoice.subtotal = calculated.subtotalMinor;\n invoice.discountTotal = calculated.discountTotalMinor;\n invoice.taxAmount = calculated.taxMinor + invoice.providerTaxAmount;\n invoice.totalAmount = calculated.totalMinor + invoice.providerTaxAmount;\n return { lines, taxRows };\n}\n\nasync function previewInvoiceMoneyOnScope(\n input: PreviewInvoiceMoneyInput,\n settings: TaxSettings,\n): Promise<PreviewInvoiceMoneyResult> {\n if (!input.tenantId || getTenantId() !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview requires its active principal tenant',\n );\n const { invoice } = await loadInvoice(input.db, input.invoiceId);\n if (invoice.tenantId !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview cannot cross tenant boundaries',\n );\n if (invoice.status !== InvoiceStatus.DRAFT || invoice.moneySnapshotId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Frozen invoice money cannot be previewed as a proposed draft',\n );\n const proposedHeader = input.draft?.header;\n if (proposedHeader)\n for (const field of [\n 'currency',\n 'lineAmountType',\n 'taxRoundingScope',\n 'providerTaxAmount',\n 'customerId',\n ] as const)\n if (proposedHeader[field] !== undefined)\n invoice[field] = proposedHeader[field] as never;\n const storedLines = await (\n await InvoiceLineItemCollection.create({ db: input.db })\n ).findByInvoice(input.invoiceId);\n const storedById = new Map(storedLines.map((line) => [line.id, line]));\n const providedIds =\n input.draft?.lines\n ?.map((line) => line.id)\n .filter((id): id is string => !!id) ?? [];\n if (new Set(providedIds).size !== providedIds.length)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice preview line ids must be distinct',\n );\n const unknownId = providedIds.find((id) => !storedById.has(id));\n if (unknownId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Invoice preview line ${unknownId} was not found on the invoice`,\n );\n const proposedLines = input.draft?.lines\n ? input.draft.lines.map((proposed) => {\n const line = proposed.id ? storedById.get(proposed.id) : undefined;\n const result = line ?? new InvoiceLineItem();\n for (const field of [\n 'description',\n 'productId',\n 'quantity',\n 'unitPrice',\n 'discountType',\n 'discountRate',\n 'discount',\n 'taxMode',\n 'taxCodeId',\n ] as const)\n if (proposed[field] !== undefined)\n result[field] = proposed[field] as never;\n result.id ||= crypto.randomUUID();\n result.invoiceId = input.invoiceId;\n result.tenantId = input.tenantId;\n return result;\n })\n : storedLines;\n const calculated = await recomputeInvoiceAggregate(\n input.db,\n invoice,\n settings,\n '',\n false,\n proposedLines,\n );\n return {\n source: 'calculated',\n header: {\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n taxRoundingScope: invoice.taxRoundingScope,\n subtotalMinor: invoice.subtotal,\n discountTotalMinor: invoice.discountTotal,\n taxAmountMinor: invoice.taxAmount,\n providerTaxAmountMinor: invoice.providerTaxAmount,\n totalAmountMinor: invoice.totalAmount,\n },\n lines: calculated.lines.map((line) => ({\n id: requireId(line.id, 'Preview line'),\n grossMinor: line.amount + line.discount,\n discountMinor: line.discount,\n amountMinor: line.amount,\n taxMinor: line.taxAmount,\n taxCodeId: line.taxCodeId,\n taxCodeCode: line.taxCodeCode,\n taxCodeName: line.taxCodeName,\n taxComponents: structuredClone(line.taxComponents),\n })),\n taxes: calculated.taxRows,\n };\n}\n\n/** Calculate a proposed draft invoice in memory through the owning resolver. */\nexport async function previewInvoiceMoney(\n input: PreviewInvoiceMoneyInput,\n): Promise<PreviewInvoiceMoneyResult> {\n return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) =>\n previewInvoiceMoneyOnScope({ ...input, db: scope.db }, scope.settings),\n );\n}\n\nasync function getInvoiceMoneyFactsOnScope(\n input: GetInvoiceMoneyFactsInput,\n): Promise<InvoiceMoneyFacts> {\n if (!input.tenantId || getTenantId() !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money facts require their active principal tenant',\n );\n const { invoice } = await loadInvoice(input.db, input.invoiceId);\n if (invoice.tenantId !== input.tenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice money facts cannot cross tenant boundaries',\n );\n const lines = await (\n await InvoiceLineItemCollection.create({ db: input.db })\n ).findByInvoice(input.invoiceId);\n const taxes = await (\n await DocumentTaxCollection.create({ db: input.db })\n ).findByDocument(input.tenantId, invoice.kind, input.invoiceId);\n const historical = getHistoricalSalesMoney(invoice);\n return {\n source: 'stored',\n ...(historical\n ? {\n historical: {\n snapshot: historical,\n lines: (await readHistoricalSalesLines(input.db, invoice)).map(\n (line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n }),\n ),\n },\n }\n : {}),\n ...(invoice.retentionStateJson\n ? { payable: invoice.getPayableFacts() }\n : {}),\n invoiceId: input.invoiceId,\n moneySnapshotId: invoice.moneySnapshotId,\n kind: invoice.kind,\n status: invoice.status,\n header: {\n currency: invoice.currency,\n lineAmountType: invoice.lineAmountType,\n taxRoundingScope: invoice.taxRoundingScope,\n subtotalMinor: invoice.subtotal,\n discountTotalMinor: invoice.discountTotal,\n taxAmountMinor: invoice.taxAmount,\n providerTaxAmountMinor: invoice.providerTaxAmount,\n totalAmountMinor: invoice.totalAmount,\n },\n lines: lines.map((line) => ({\n id: requireId(line.id, 'Invoice line'),\n grossMinor: line.amount + line.discount,\n discountMinor: line.discount,\n amountMinor: line.amount,\n taxMinor: line.taxAmount,\n taxCodeId: line.taxCodeId,\n taxCodeCode: line.taxCodeCode,\n taxCodeName: line.taxCodeName,\n taxComponents: structuredClone(line.taxComponents),\n })),\n taxes: taxes.map((row) => ({\n tenantId: requireId(row.tenantId, 'Document tax tenant'),\n documentType: row.documentType,\n documentId: row.documentId,\n currency: row.currency,\n taxCodeId: row.taxCodeId,\n taxCodeCode: row.taxCodeCode,\n kind: row.kind,\n taxComponentId: row.taxComponentId,\n taxComponentName: row.taxComponentName,\n percent: row.percent,\n liabilityAccountId: row.liabilityAccountId,\n taxableMinor: row.taxableMinor,\n ...(row.netMinor !== null ? { netMinor: row.netMinor } : {}),\n taxMinor: row.taxMinor,\n recoverableMinor: row.recoverableMinor,\n })),\n };\n}\n\n/** Read authoritative persisted money facts without resolution or recalculation. */\nexport async function getInvoiceMoneyFacts(\n input: GetInvoiceMoneyFactsInput,\n): Promise<InvoiceMoneyFacts> {\n return withTenantMoneyRuntime(input.db, input.tenantId, async (scope) =>\n getInvoiceMoneyFactsOnScope({ ...input, db: scope.db }),\n );\n}\n\n/** Persist an invoice and recompute its complete money aggregate. */\nexport async function saveInvoice(input: Invoice): Promise<Invoice> {\n const priorRevision = input.updated_at;\n try {\n return await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (invoice) => {\n if (invoice.kind !== 'invoice' && invoice.kind !== 'credit_note')\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice kind must be invoice or credit_note',\n );\n if (invoice.kind === 'invoice' && invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Only a credit note may reference a credited invoice',\n );\n if (invoice.kind === 'credit_note' && !invoice.creditedInvoiceId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'A credit note requires a credited invoice',\n );\n const candidateTenantId = getTenantId() ?? invoice.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const existing = invoice.id ? await findInvoice(tx, invoice.id) : null;\n const tenantId = existing?.tenantId ?? candidateTenantId;\n if (\n invoice.retentionAccountingStateJson !==\n (existing?.retentionAccountingStateJson ?? '') ||\n invoice.ordinaryAccountingStateJson !==\n (existing?.ordinaryAccountingStateJson ?? '')\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Retention accounting state is managed by provider commands',\n );\n if (\n invoice.moneyAuthority !==\n (existing?.moneyAuthority ?? 'calculated') ||\n invoice.historicalSalesMoneyJson !==\n (existing?.historicalSalesMoneyJson ?? '') ||\n invoice.historicalSourceKeyHash !==\n (existing?.historicalSourceKeyHash ?? null)\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Historical source authority is managed only by historical sales commands',\n );\n if (existing?.moneyAuthority === 'historical')\n getHistoricalSalesMoney(existing);\n\n if (invoice.retentionStateJson !== (existing?.retentionStateJson ?? ''))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Retention state is managed by retention commands',\n );\n if (\n candidateTenantId &&\n existing?.tenantId &&\n existing.tenantId !== candidateTenantId\n )\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant does not match its active money barrier',\n );\n assertTenantId(tenantId);\n if (!existing) {\n invoice.tenantId = tenantId;\n invoice.creditedAmount = 0;\n let source: Invoice | null = null;\n if (invoice.kind === 'credit_note') {\n source = await findInvoice(\n tx,\n requireId(invoice.creditedInvoiceId, 'Credited invoice'),\n );\n if (!source || source.tenantId !== tenantId)\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must exist in the active tenant',\n );\n await lockDocumentMoneyParents([\n {\n id: requireId(source.id, 'Credited invoice'),\n tenantId,\n collection: await InvoiceCollection.create({ db: tx }),\n },\n ]);\n if (\n source.kind !== 'invoice' ||\n source.status === InvoiceStatus.DRAFT ||\n source.status === InvoiceStatus.CANCELLED ||\n !source.moneySnapshotId\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit target must be an issued, non-cancelled invoice',\n );\n if (\n invoice.currency !== source.currency ||\n invoice.customerId !== source.customerId\n )\n throw new MoneyValidationError(\n invoice.currency !== source.currency\n ? 'CURRENCY_MISMATCH'\n : 'INVALID_MONEY_INPUT',\n 'Credit note currency and customer must match its source invoice',\n );\n }\n invoice.lineAmountType =\n invoice.kind === 'credit_note' && source\n ? source.lineAmountType\n : settings.defaultLineAmountType;\n invoice.taxRoundingScope =\n invoice.kind === 'credit_note' && source\n ? source.taxRoundingScope\n : settings.taxRoundingScope;\n invoice.subtotal = 0;\n invoice.discountTotal = 0;\n invoice.taxAmount = invoice.providerTaxAmount;\n invoice.totalAmount = invoice.providerTaxAmount;\n if (invoice.status !== InvoiceStatus.DRAFT || invoice.arJournalId) {\n await assertContractScheduleInvoiceFreeze(tx, invoice);\n const customers = await CustomerCollection.create({ db: tx });\n const customer = invoice.customerId\n ? await customers.get(\n { id: invoice.customerId },\n { cache: false },\n )\n : null;\n invoice.moneySnapshotId = crypto.randomUUID();\n invoice.sellerTaxRegistrations = structuredClone(\n settings.taxRegistrations,\n );\n invoice.partyTaxId = customer?.taxId ?? '';\n }\n return invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n if (invoice.tenantId !== existing.tenantId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice tenant identity cannot change',\n );\n if (\n invoice.kind !== existing.kind ||\n invoice.creditedInvoiceId !== existing.creditedInvoiceId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice kind and credited invoice identity are immutable',\n );\n const existingId = requireId(existing.id, 'Invoice');\n const locked = await lockAndReloadMoneyInvoice(\n tx,\n existingId,\n tenantId,\n existing.creditedInvoiceId,\n );\n invoice.creditedAmount = locked.invoice.creditedAmount;\n if (isFrozen(locked.invoice)) {\n if (\n invoice.arReversalJournalId !== locked.invoice.arReversalJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice reversal journal identity is server-managed',\n );\n if (\n locked.invoice.arJournalId &&\n invoice.arJournalId !== locked.invoice.arJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice revenue journal identity is frozen once assigned',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.kind === 'invoice' &&\n locked.invoice.isPaid()\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A paid invoice cannot be cancelled',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.kind === 'credit_note' &&\n locked.invoice.amountPaid > 0\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A refunded credit note cannot be cancelled',\n );\n if (\n invoice.status === InvoiceStatus.CANCELLED &&\n locked.invoice.status !== InvoiceStatus.CANCELLED &&\n locked.invoice.arJournalId &&\n !locked.invoice.arReversalJournalId\n )\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'A posted invoice requires an atomic reversal before cancellation',\n );\n assertFieldsUnchanged(\n invoice,\n locked.invoice,\n FROZEN_INVOICE_FIELDS,\n 'Invoice',\n );\n const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (locked.source)\n await refreshIssuedCreditBalance(tx, locked.source);\n return saved;\n }\n const freezing =\n invoice.status !== InvoiceStatus.DRAFT || !!invoice.arJournalId;\n const snapshotId = freezing\n ? locked.invoice.moneySnapshotId || crypto.randomUUID()\n : '';\n await recomputeInvoiceAggregate(tx, invoice, settings, snapshotId);\n if (freezing) {\n await assertContractScheduleInvoiceFreeze(tx, invoice);\n const customers = await CustomerCollection.create({ db: tx });\n const customer = invoice.customerId\n ? await customers.get({ id: invoice.customerId }, { cache: false })\n : null;\n invoice.sellerTaxRegistrations = structuredClone(\n settings.taxRegistrations,\n );\n invoice.partyTaxId = customer?.taxId ?? '';\n invoice.moneySnapshotId = snapshotId;\n }\n const saved = await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (locked.source) await refreshIssuedCreditBalance(tx, locked.source);\n return saved;\n }),\n );\n } catch (error) {\n input.updated_at = priorRevision;\n throw error;\n }\n}\n\n/** Persist a line and recompute its complete invoice aggregate. */\nexport async function saveInvoiceLineItem(\n input: InvoiceLineItem,\n): Promise<InvoiceLineItem> {\n return withDocumentMoneyObjectTransaction(input, async (line, tx) => {\n const candidateTenantId = getTenantId() ?? line.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = line.id\n ? await (await InvoiceLineItemCollection.create({ db: tx })).get(\n { id: line.id },\n { cache: false },\n )\n : null;\n const parentId = persisted?.invoiceId ?? line.invoiceId;\n const first = await loadInvoice(tx, parentId);\n if (candidateTenantId && first.invoice.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice line tenant does not match its active money barrier',\n );\n assertTenantId(first.invoice.tenantId);\n const { invoice, source } = await lockAndReloadMoneyInvoice(\n tx,\n parentId,\n first.invoice.tenantId,\n first.invoice.creditedInvoiceId,\n );\n if (persisted && line.invoiceId !== persisted.invoiceId)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Invoice line cannot move between parents',\n );\n line.invoiceId = requireId(invoice.id, 'Invoice');\n line.tenantId = invoice.tenantId;\n if (invoice.kind === 'invoice' && line.creditedLineId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Ordinary invoice lines cannot reference credited lines',\n );\n if (\n invoice.kind === 'credit_note' &&\n line.creditedLineId &&\n (!source || source.id !== invoice.creditedInvoiceId)\n )\n throw new MoneyValidationError(\n 'CREDIT_TARGET_NOT_ISSUED',\n 'Credit source changed while saving its line',\n );\n if (isFrozen(invoice)) {\n if (!persisted)\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot add a line to a frozen invoice',\n );\n assertFieldsUnchanged(\n line,\n persisted,\n FROZEN_LINE_FIELDS,\n 'Invoice line',\n );\n return line.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n await line.saveDerived(DOCUMENT_MONEY_WRITE);\n const priorAggregate = aggregateSignature(invoice);\n await recomputeInvoiceAggregate(tx, invoice, settings);\n if (aggregateSignature(invoice) !== priorAggregate) {\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n const refreshed = await (\n await InvoiceLineItemCollection.create({ db: tx })\n ).get({ id: requireId(line.id, 'Invoice line') }, { cache: false });\n if (refreshed) {\n for (const field of [\n 'discount',\n 'amount',\n 'taxAmount',\n 'taxRate',\n 'taxCodeId',\n 'taxCodeCode',\n 'taxCodeName',\n 'taxComponentsJson',\n 'moneySnapshotId',\n 'updated_at',\n ] as const) {\n line[field] = refreshed[field] as never;\n }\n }\n return line;\n });\n}\n\nexport async function deleteInvoiceLineItem(\n input: InvoiceLineItem,\n options: DeleteOptions,\n): Promise<void> {\n await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (line) => {\n const candidateTenantId = getTenantId() ?? line.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = line.id\n ? await (await InvoiceLineItemCollection.create({ db: tx })).get(\n { id: line.id },\n { cache: false },\n )\n : null;\n if (!persisted) return;\n const first = await loadInvoice(tx, persisted.invoiceId);\n if (candidateTenantId && first.invoice.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice line tenant does not match its active money barrier',\n );\n assertTenantId(first.invoice.tenantId);\n const { invoice } = await lockAndReloadInvoice(\n tx,\n persisted.invoiceId,\n first.invoice.tenantId,\n );\n if (isFrozen(invoice))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot delete a line from a frozen invoice',\n );\n await line.deleteDerived(DOCUMENT_MONEY_WRITE, options);\n const priorAggregate = aggregateSignature(invoice);\n await recomputeInvoiceAggregate(tx, invoice, settings);\n if (aggregateSignature(invoice) !== priorAggregate) {\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n }\n }),\n );\n}\n\nexport async function deleteInvoice(\n input: Invoice,\n options: DeleteOptions,\n): Promise<void> {\n await withDocumentMoneyTransaction(input.db, async (tx) =>\n input.withDatabase(tx, async (invoice) => {\n const candidateTenantId = getTenantId() ?? invoice.tenantId ?? null;\n const settings = await lockRuntimeSettings(tx, candidateTenantId);\n const persisted = invoice.id ? await findInvoice(tx, invoice.id) : null;\n if (!persisted) return;\n if (candidateTenantId && persisted.tenantId !== candidateTenantId)\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Invoice tenant does not match its active money barrier',\n );\n if (isFrozen(persisted))\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'Cannot delete a frozen invoice',\n );\n assertTenantId(persisted.tenantId);\n const persistedId = requireId(persisted.id, 'Invoice');\n await lockAndReloadInvoice(tx, persistedId, persisted.tenantId);\n const documentTaxes = await DocumentTaxCollection.create({ db: tx });\n await documentTaxes.replaceDerivedForDocument(DOCUMENT_MONEY_WRITE, {\n tenantId: persisted.tenantId,\n documentType: 'invoice',\n documentId: persistedId,\n rows: [],\n });\n await invoice.deleteDerived(DOCUMENT_MONEY_WRITE, options);\n }),\n );\n}\n","import { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport type {\n HistoricalSalesMoneyFacts,\n HistoricalSalesRetention,\n HistoricalSalesSource,\n} from './historical-sales-types.js';\nimport { MoneyValidationError } from './money.js';\n\nfunction invalid(): never {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Historical sales require exact supported source facts and explicit unknown values',\n );\n}\nexport function historicalText(value: unknown, max = 2000): string {\n if (\n typeof value !== 'string' ||\n !value.trim() ||\n value.trim() !== value ||\n value.length > max\n )\n invalid();\n return value;\n}\nexport function historicalCalendarDate(value: unknown): string {\n const date = historicalText(value);\n if (\n !/^\\d{4}-\\d{2}-\\d{2}$/.test(date) ||\n !Number.isFinite(Date.parse(date)) ||\n new Date(date).toISOString().slice(0, 10) !== date\n )\n invalid();\n return date;\n}\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) invalid();\n return value as Record<string, unknown>;\n}\nfunction fields(input: unknown, allowed: readonly string[]) {\n const value = record(input);\n if (Object.keys(value).some((key) => !allowed.includes(key))) invalid();\n return value;\n}\nfunction integer(value: unknown): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value)) invalid();\n return value;\n}\nfunction nullableInteger(value: unknown): number | null {\n return value === null ? null : integer(value);\n}\nfunction nullableText(value: unknown): string | null {\n return value === null ? null : historicalText(value);\n}\nfunction sum(values: number[]): number {\n const result = values.reduce((total, value) => total + BigInt(value), 0n);\n if (\n result > BigInt(Number.MAX_SAFE_INTEGER) ||\n result < BigInt(Number.MIN_SAFE_INTEGER)\n )\n invalid();\n return Number(result);\n}\nfunction sameAmount(net: number, tax: number, gross: number) {\n if (sum([net, tax]) !== gross) invalid();\n}\nexport function historicalSalesMagnitudes(facts: HistoricalSalesMoneyFacts) {\n const sign =\n facts.kind === 'credit_note' && facts.polarity === 'signed' ? -1 : 1;\n const result = {\n netMinor: facts.netMinor * sign,\n taxMinor: facts.taxMinor * sign,\n grossMinor: facts.grossMinor * sign,\n };\n if (Object.values(result).some((value) => value < 0)) invalid();\n return result;\n}\nexport function validateHistoricalSalesSource(\n input: HistoricalSalesSource,\n): HistoricalSalesSource {\n const value = fields(input, [\n 'namespace',\n 'key',\n 'version',\n 'issuedOn',\n 'dueOn',\n 'timeZone',\n 'approval',\n 'retention',\n ]);\n const retention =\n value.retention == null\n ? value.retention\n : (() => {\n const r = fields(value.retention, [\n 'retainedMinor',\n 'creditPolicy',\n 'policyRef',\n 'effectiveOn',\n 'evidenceRef',\n 'originalActorRef',\n 'releases',\n ]);\n if (\n r.creditPolicy !== 'retained-first' ||\n !Array.isArray(r.releases) ||\n r.releases.length > 10000\n )\n invalid();\n const retainedMinor = integer(r.retainedMinor);\n if (retainedMinor <= 0) invalid();\n const effectiveOn = historicalCalendarDate(r.effectiveOn);\n const keys = new Set<string>();\n const releases = r.releases.map(\n (input): HistoricalSalesRetention['releases'][number] => {\n const event = fields(input, [\n 'sourceKey',\n 'amountMinor',\n 'effectiveOn',\n 'evidenceRef',\n 'originalActorRef',\n 'sameDayCreditOrder',\n ]);\n const sourceKey = historicalText(event.sourceKey),\n amountMinor = integer(event.amountMinor),\n on = historicalCalendarDate(event.effectiveOn);\n if (keys.has(sourceKey) || amountMinor <= 0 || on < effectiveOn)\n invalid();\n keys.add(sourceKey);\n return {\n ...(event.sameDayCreditOrder === undefined\n ? {}\n : {\n sameDayCreditOrder:\n event.sameDayCreditOrder === null ||\n event.sameDayCreditOrder === 'credit-before-release' ||\n event.sameDayCreditOrder === 'release-before-credit'\n ? event.sameDayCreditOrder\n : invalid(),\n }),\n sourceKey,\n amountMinor,\n effectiveOn: on,\n evidenceRef: historicalText(event.evidenceRef),\n originalActorRef: nullableText(event.originalActorRef),\n };\n },\n );\n if (sum(releases.map((event) => event.amountMinor)) > retainedMinor)\n invalid();\n return {\n retainedMinor,\n creditPolicy: 'retained-first' as const,\n policyRef: historicalText(r.policyRef),\n effectiveOn,\n evidenceRef: historicalText(r.evidenceRef),\n originalActorRef: nullableText(r.originalActorRef),\n releases,\n };\n })();\n if (\n retention &&\n retention.effectiveOn !== historicalCalendarDate(value.issuedOn)\n )\n invalid();\n const timeZone = historicalText(value.timeZone);\n try {\n new Intl.DateTimeFormat('en', { timeZone }).format(0);\n } catch {\n invalid();\n }\n const approval =\n value.approval === null\n ? null\n : fields(value.approval, ['actorRef', 'approvedOn']);\n return {\n ...(retention === undefined ? {} : { retention }),\n namespace: historicalText(value.namespace),\n key: historicalText(value.key),\n version: historicalText(value.version),\n issuedOn: historicalCalendarDate(value.issuedOn),\n dueOn: value.dueOn === null ? null : historicalCalendarDate(value.dueOn),\n timeZone,\n approval:\n approval === null\n ? null\n : {\n actorRef: historicalText(approval.actorRef),\n approvedOn:\n approval.approvedOn === null\n ? null\n : historicalCalendarDate(approval.approvedOn),\n },\n };\n}\n/** Validate original facts without a tax calculator, source normalization, or implicit polarity. */\nexport function validateHistoricalSalesMoneyFacts(\n input: HistoricalSalesMoneyFacts,\n): HistoricalSalesMoneyFacts {\n const value = fields(input, [\n 'currency',\n 'kind',\n 'polarity',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'taxComponents',\n 'detail',\n ]);\n const currency = historicalText(value.currency);\n if (\n !ISO_4217_MINOR_UNITS.has(currency) ||\n ISO_4217_MINOR_UNITS.get(currency) === null ||\n !['invoice', 'credit_note'].includes(value.kind as string) ||\n !['signed', 'magnitudes'].includes(value.polarity as string)\n )\n invalid();\n const netMinor = integer(value.netMinor),\n taxMinor = integer(value.taxMinor),\n grossMinor = integer(value.grossMinor);\n sameAmount(netMinor, taxMinor, grossMinor);\n const seenComponents = new Set<string>();\n const taxComponents =\n value.taxComponents === null\n ? null\n : (() => {\n if (\n !Array.isArray(value.taxComponents) ||\n value.taxComponents.length > 1000\n )\n invalid();\n return value.taxComponents.map((inputComponent) => {\n const component = fields(inputComponent, [\n 'sourceKey',\n 'label',\n 'amountMinor',\n 'classification',\n 'taxCodeId',\n 'taxComponentId',\n 'taxableMinor',\n 'netMinor',\n 'liabilityAccountId',\n ]),\n sourceKey = historicalText(component.sourceKey);\n if (seenComponents.has(sourceKey)) invalid();\n seenComponents.add(sourceKey);\n if (\n component.classification !== null &&\n !['taxable', 'zero-rated', 'exempt', 'out-of-scope'].includes(\n component.classification as string,\n )\n )\n invalid();\n const classification = component.classification as\n | 'taxable'\n | 'zero-rated'\n | 'exempt'\n | 'out-of-scope'\n | null;\n const amountMinor = integer(component.amountMinor),\n taxableMinor = nullableInteger(component.taxableMinor);\n if (\n classification !== null &&\n classification !== 'taxable' &&\n amountMinor !== 0\n )\n invalid();\n return {\n sourceKey,\n label: historicalText(component.label),\n amountMinor,\n classification,\n taxCodeId: nullableText(component.taxCodeId),\n taxComponentId: nullableText(component.taxComponentId),\n taxableMinor,\n netMinor: nullableInteger(component.netMinor),\n liabilityAccountId: nullableText(component.liabilityAccountId),\n };\n });\n })();\n if (\n taxComponents !== null &&\n sum(taxComponents.map((component) => component.amountMinor)) !== taxMinor\n )\n invalid();\n const detailInput = fields(\n value.detail,\n record(value.detail).kind === 'header-only' ? ['kind'] : ['kind', 'lines'],\n );\n let detail: HistoricalSalesMoneyFacts['detail'];\n if (detailInput.kind === 'header-only') detail = { kind: 'header-only' };\n else if (detailInput.kind === 'lines') {\n if (\n !Array.isArray(detailInput.lines) ||\n !detailInput.lines.length ||\n detailInput.lines.length > 100000\n )\n invalid();\n const seen = new Set<string>();\n const lines = detailInput.lines.map((inputLine) => {\n const line = fields(inputLine, [\n 'sourceKey',\n 'creditedLineId',\n 'description',\n 'netMinor',\n 'taxMinor',\n 'grossMinor',\n 'quantityText',\n 'unitRateText',\n 'sourceFields',\n ]),\n sourceKey = historicalText(line.sourceKey);\n if (seen.has(sourceKey)) invalid();\n seen.add(sourceKey);\n const sourceFields = record(line.sourceFields);\n if (\n Object.keys(sourceFields).length > 100 ||\n Object.entries(sourceFields).some(\n ([key, cell]) =>\n key.length > 200 || typeof cell !== 'string' || cell.length > 10000,\n )\n )\n invalid();\n const netMinor = integer(line.netMinor),\n taxMinor = nullableInteger(line.taxMinor),\n grossMinor = nullableInteger(line.grossMinor);\n if (taxMinor !== null && grossMinor !== null)\n sameAmount(netMinor, taxMinor, grossMinor);\n if (\n typeof line.description !== 'string' ||\n line.description.length > 10000\n )\n invalid();\n return {\n sourceKey,\n description: line.description,\n creditedLineId: nullableText(line.creditedLineId),\n netMinor,\n taxMinor,\n grossMinor,\n quantityText: nullableText(line.quantityText),\n unitRateText: nullableText(line.unitRateText),\n sourceFields: Object.fromEntries(\n Object.entries(sourceFields),\n ) as Record<string, string>,\n };\n });\n if (\n sum(lines.map((line) => line.netMinor)) !== netMinor ||\n (lines.every((line) => line.taxMinor !== null) &&\n sum(lines.map((line) => line.taxMinor as number)) !== taxMinor) ||\n (lines.every((line) => line.grossMinor !== null) &&\n sum(lines.map((line) => line.grossMinor as number)) !== grossMinor)\n )\n invalid();\n detail = { kind: 'lines', lines };\n } else invalid();\n const result: HistoricalSalesMoneyFacts = {\n currency,\n kind: value.kind as HistoricalSalesMoneyFacts['kind'],\n polarity: value.polarity as HistoricalSalesMoneyFacts['polarity'],\n netMinor,\n taxMinor,\n grossMinor,\n taxComponents,\n detail,\n };\n historicalSalesMagnitudes(result);\n return result;\n}\n","/** Exact original issued sales authority. Host review is distinct from original issue/approval. */\nimport { createHash } from 'node:crypto';\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport { HistoricalSalesLineCollection } from './collections/HistoricalSalesLineCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { InvoiceLineItemCollection } from './collections/InvoiceLineItemCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport { assertContractScheduleInvoiceFreeze } from './contract-billing-schedule.js';\nimport {\n lockAndReloadInvoice,\n refreshIssuedCreditBalance,\n} from './document-money.js';\nimport { DOCUMENT_MONEY_WRITE } from './document-money-internal.js';\nimport { withHistoricalCommerceWrite } from './historical-commerce-internal.js';\nimport type {\n HistoricalSalesMoneySnapshot,\n RecordHistoricalSalesMoneyInput,\n} from './historical-sales-types.js';\nimport {\n historicalSalesMagnitudes,\n historicalText,\n validateHistoricalSalesMoneyFacts,\n validateHistoricalSalesSource,\n} from './historical-sales-validation.js';\nimport { HistoricalSalesLine } from './models/HistoricalSalesLine.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { MoneyValidationError } from './money.js';\nimport {\n type InvoiceRetentionState,\n parseInvoiceRetention,\n} from './retention-money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { InvoiceStatus } from './types/index.js';\n\nexport type * from './historical-sales-types.js';\nexport { validateHistoricalSalesMoneyFacts } from './historical-sales-validation.js';\n\nfunction hash(value: unknown): string {\n return createHash('sha256').update(JSON.stringify(value)).digest('hex');\n}\nfunction identity(value: unknown): string {\n const h = hash(value);\n return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-a${h.slice(17, 20)}-${h.slice(20, 32)}`;\n}\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nexport function historicalSalesSourceHash(\n source: HistoricalSalesMoneySnapshot['source'],\n): string {\n return hash([source.namespace, source.key]);\n}\nfunction snapshotIdentity(\n invoice: Invoice,\n snapshot: HistoricalSalesMoneySnapshot,\n) {\n return identity({\n tenantId: invoice.tenantId,\n invoiceId: invoice.id,\n customerId: invoice.customerId,\n invoiceNumber: invoice.invoiceNumber,\n snapshot,\n });\n}\nfunction originalRetentionState(\n snapshot: HistoricalSalesMoneySnapshot,\n): InvoiceRetentionState | null {\n const r = snapshot.source.retention;\n if (!r) return null;\n return {\n version: 1,\n currency: snapshot.facts.currency,\n creditPolicy: r.creditPolicy,\n retainedMinor: r.retainedMinor,\n requestId: `historical-retention:${snapshot.requestId}`,\n policyVersion: r.policyRef,\n evidenceRef: r.evidenceRef,\n actorId: snapshot.review.actorId,\n reason: 'Original source retention',\n recordedAt: snapshot.recordedAt,\n effectiveOn: r.effectiveOn,\n releases: r.releases.map((event) => ({\n requestId: `historical-release:${event.sourceKey}`,\n policyVersion: r.policyRef,\n evidenceRef: event.evidenceRef,\n actorId: snapshot.review.actorId,\n reason: 'Original source release',\n recordedAt: snapshot.recordedAt,\n effectiveOn: event.effectiveOn,\n ...(event.sameDayCreditOrder === undefined\n ? {}\n : { sameDayCreditOrder: event.sameDayCreditOrder }),\n amountMinor: event.amountMinor,\n })),\n };\n}\n/** Stored source header evidence; never recalculates tax or source line allocations. */\nexport function getHistoricalSalesMoney(\n invoice: Invoice,\n): HistoricalSalesMoneySnapshot | null {\n if (\n invoice.moneyAuthority === 'calculated' &&\n !invoice.historicalSalesMoneyJson &&\n invoice.historicalSourceKeyHash === null\n )\n return null;\n if (\n invoice.moneyAuthority !== 'historical' ||\n !invoice.historicalSalesMoneyJson\n )\n invalid('Historical invoice authority is incomplete');\n const value = JSON.parse(\n invoice.historicalSalesMoneyJson,\n ) as HistoricalSalesMoneySnapshot;\n if (value.version !== 1)\n invalid('Historical invoice snapshot version is unsupported');\n const snapshot: HistoricalSalesMoneySnapshot = {\n version: 1,\n requestId: historicalText(value.requestId),\n evidenceRef: historicalText(value.evidenceRef),\n review: {\n actorId: historicalText(value.review?.actorId),\n policyRef: historicalText(value.review?.policyRef),\n },\n recordedAt: historicalText(value.recordedAt),\n source: validateHistoricalSalesSource(value.source),\n facts: validateHistoricalSalesMoneyFacts(value.facts),\n creditedSource:\n value.creditedSource === null\n ? null\n : {\n invoiceId: historicalText(value.creditedSource?.invoiceId),\n moneySnapshotId: historicalText(\n value.creditedSource?.moneySnapshotId,\n ),\n },\n };\n const amounts = historicalSalesMagnitudes(snapshot.facts);\n if (\n invoice.currency !== snapshot.facts.currency ||\n invoice.kind !== snapshot.facts.kind ||\n invoice.subtotal !== amounts.netMinor ||\n invoice.taxAmount !== amounts.taxMinor ||\n invoice.totalAmount !== amounts.grossMinor ||\n invoice.discountTotal !== 0 ||\n invoice.providerTaxAmount !== 0 ||\n invoice.historicalSourceKeyHash !==\n historicalSalesSourceHash(snapshot.source) ||\n invoice.moneySnapshotId !== snapshotIdentity(invoice, snapshot)\n )\n invalid(\n 'Historical invoice no longer matches its immutable original monetary authority',\n );\n if (\n invoice.issueDate.toISOString().slice(0, 10) !== snapshot.source.issuedOn ||\n (invoice.dueDate?.toISOString().slice(0, 10) ?? null) !==\n snapshot.source.dueOn\n )\n invalid('Historical source calendar dates changed');\n if (\n snapshot.facts.kind === 'credit_note'\n ? invoice.creditedInvoiceId !== snapshot.creditedSource?.invoiceId\n : snapshot.creditedSource !== null\n )\n invalid('Historical credit source lineage changed');\n const expectedRetention = originalRetentionState(snapshot),\n retained = parseInvoiceRetention(invoice.retentionStateJson);\n if (expectedRetention) {\n if (!retained) invalid('Original retention authority is missing');\n for (const key of Object.keys(\n expectedRetention,\n ) as (keyof InvoiceRetentionState)[]) {\n if (key === 'releases') continue;\n if (retained[key] !== expectedRetention[key])\n invalid('Original retention source projection changed');\n }\n if (\n JSON.stringify(\n retained.releases.slice(0, expectedRetention.releases.length),\n ) !== JSON.stringify(expectedRetention.releases)\n )\n invalid('Original retention release projection changed');\n } else if (retained)\n invalid('Historical invoice has no original retention authority');\n return structuredClone(snapshot);\n}\nfunction lineIdentity(invoiceId: string, sourceKey: string) {\n return identity({ kind: 'historical-sales-line:v1', invoiceId, sourceKey });\n}\n/** Read actual immutable source children for typed consumer crosswalks. */\nexport async function readHistoricalSalesLines(\n db: DatabaseInterface,\n invoice: Invoice,\n) {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return [];\n const lines = await (await HistoricalSalesLineCollection.create({ db })).list(\n {\n where: { tenantId: invoice.tenantId, invoiceId: invoice.id },\n limit: 100001,\n },\n );\n const expected =\n snapshot.facts.detail.kind === 'lines' ? snapshot.facts.detail.lines : [];\n if (lines.length !== expected.length)\n invalid('Historical invoice source child identities are incomplete');\n const byKey = new Map(lines.map((line) => [line.sourceKey, line]));\n if (byKey.size !== lines.length)\n invalid('Historical source child identity is ambiguous');\n return expected.map((source) => {\n const line = byKey.get(source.sourceKey);\n if (\n !line ||\n line.id !== lineIdentity(String(invoice.id), source.sourceKey) ||\n line.sourceKeyHash !== hash(source.sourceKey) ||\n line.moneySnapshotId !== invoice.moneySnapshotId ||\n line.description !== source.description ||\n line.creditedLineId !== source.creditedLineId ||\n line.netMinor !== source.netMinor ||\n line.taxMinor !== source.taxMinor ||\n line.grossMinor !== source.grossMinor ||\n line.quantityText !== source.quantityText ||\n line.unitRateText !== source.unitRateText ||\n line.sourceFieldsJson !== JSON.stringify(source.sourceFields)\n )\n invalid(\n 'Historical invoice source child no longer matches its original facts',\n );\n return line;\n });\n}\nasync function assertSourceLineCapacity(\n db: DatabaseInterface,\n invoices: InvoiceCollection,\n source: Invoice | null,\n snapshot: HistoricalSalesMoneySnapshot,\n) {\n if (snapshot.facts.detail.kind !== 'lines') return;\n const linked = snapshot.facts.detail.lines.filter(\n (line) => line.creditedLineId !== null,\n );\n if (!linked.length) return;\n if (!source || snapshot.facts.kind !== 'credit_note')\n invalid(\n 'Only an exact historical credit may link original historical lines',\n );\n const sourceLines = new Map(\n (await readHistoricalSalesLines(db, source)).map((line) => [line.id, line]),\n );\n const collection = await HistoricalSalesLineCollection.create({ db });\n const requestSign = snapshot.facts.polarity === 'signed' ? -1 : 1;\n const pending = new Map<\n string,\n { netMinor: bigint; taxMinor: bigint; grossMinor: bigint }\n >();\n for (const request of linked) {\n const original = sourceLines.get(request.creditedLineId ?? '');\n if (!original)\n invalid(\n 'Historical credit line does not belong to its exact original source invoice',\n );\n const inRequest = pending.get(String(original.id)) ?? {\n netMinor: 0n,\n taxMinor: 0n,\n grossMinor: 0n,\n };\n const previous = await collection.list({\n where: { tenantId: source.tenantId, creditedLineId: original.id },\n limit: 100001,\n });\n if (previous.length > 100000)\n invalid(\n 'Historical source line capacity exceeds the bounded credit scope',\n );\n const consumed = { netMinor: 0n, taxMinor: 0n, grossMinor: 0n };\n for (const line of previous) {\n const parent = await invoices.get(\n { id: line.invoiceId, tenantId: source.tenantId },\n { cache: false },\n );\n if (\n !parent ||\n parent.kind !== 'credit_note' ||\n parent.creditedInvoiceId !== source.id\n )\n invalid('Historical source line has invalid credit lineage');\n if (\n parent.status === InvoiceStatus.DRAFT ||\n parent.status === InvoiceStatus.CANCELLED\n )\n continue;\n const prior = getHistoricalSalesMoney(parent);\n if (!prior)\n invalid('Historical source line has no original monetary authority');\n const sign = prior.facts.polarity === 'signed' ? -1 : 1;\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n if (line[field] !== null)\n consumed[field] += BigInt(line[field]) * BigInt(sign);\n }\n }\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n const originalAmount = original[field],\n requestedAmount = request[field];\n if (originalAmount === null || requestedAmount === null) continue;\n const magnitude = originalAmount < 0 ? -1n : 1n;\n const originalMagnitude = BigInt(originalAmount) * magnitude;\n const requestMagnitude =\n BigInt(requestedAmount) * BigInt(requestSign) * magnitude;\n if (\n requestMagnitude < 0n ||\n (consumed[field] + inRequest[field]) * magnitude + requestMagnitude >\n originalMagnitude\n )\n invalid(\n 'Historical credit exceeds an exact original source line monetary capacity',\n );\n }\n for (const field of ['netMinor', 'taxMinor', 'grossMinor'] as const)\n if (request[field] !== null)\n inRequest[field] += BigInt(request[field]) * BigInt(requestSign);\n pending.set(String(original.id), inRequest);\n }\n}\nfunction stableRequest(snapshot: HistoricalSalesMoneySnapshot) {\n return {\n source: snapshot.source,\n facts: snapshot.facts,\n evidenceRef: snapshot.evidenceRef,\n policyRef: snapshot.review.policyRef,\n creditedSource: snapshot.creditedSource,\n };\n}\n/** Host-authorized import only. Source issue is retained evidence, never a new send/post. */\nexport async function recordHistoricalSalesMoney(\n input: RecordHistoricalSalesMoneyInput,\n) {\n if (getTenantId() !== input.tenantId)\n invalid('Historical sales require the explicit active tenant');\n const facts = validateHistoricalSalesMoneyFacts(input.facts),\n source = validateHistoricalSalesSource(input.source);\n const snapshot: HistoricalSalesMoneySnapshot = {\n version: 1,\n requestId: historicalText(input.requestId),\n evidenceRef: historicalText(input.evidenceRef),\n review: {\n actorId: historicalText(input.review?.actorId),\n policyRef: historicalText(input.review?.policyRef),\n },\n recordedAt: new Date().toISOString(),\n source,\n facts,\n creditedSource: input.creditedSource\n ? {\n invoiceId: historicalText(input.creditedSource.invoiceId),\n moneySnapshotId: historicalText(input.creditedSource.moneySnapshotId),\n }\n : null,\n };\n if ((facts.kind === 'credit_note') !== Boolean(snapshot.creditedSource))\n invalid(\n 'Historical credits require the exact original issued invoice snapshot',\n );\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) => {\n const { invoice } = await lockAndReloadInvoice(\n db,\n historicalText(input.invoiceId),\n input.tenantId,\n );\n if (invoice.tenantId !== input.tenantId)\n invalid('Historical invoice is not owned by the active tenant');\n const existing = getHistoricalSalesMoney(invoice);\n if (existing) {\n if (hash(stableRequest(existing)) !== hash(stableRequest(snapshot)))\n invalid(\n 'Historical invoice retry differs from its original facts or reviewed policy',\n );\n return {\n snapshot: existing,\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n lines: (await readHistoricalSalesLines(db, invoice)).map((line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n })),\n };\n }\n if (\n invoice.status !== InvoiceStatus.DRAFT ||\n invoice.moneySnapshotId ||\n invoice.arJournalId ||\n invoice.amountPaid ||\n invoice.creditedAmount ||\n invoice.retentionStateJson ||\n invoice.externalId ||\n invoice.externalProvider ||\n invoice.providerTaxAmount\n )\n invalid(\n 'Historical source money requires an empty unfrozen invoice without current financial effects',\n );\n if (invoice.kind !== facts.kind || invoice.currency !== facts.currency)\n invalid('Historical source kind/currency must match its draft invoice');\n const customer = invoice.customerId\n ? await (await CustomerCollection.create({ db })).get(\n { id: invoice.customerId, tenantId: input.tenantId },\n { cache: false },\n )\n : null;\n if (!customer)\n invalid('Historical sales require a customer owned by the active tenant');\n if (\n (\n await (\n await InvoiceLineItemCollection.create({ db })\n ).findByInvoice(String(invoice.id))\n ).length\n )\n invalid(\n 'Historical source money cannot mix with calculated invoice lines',\n );\n const invoices = await InvoiceCollection.create({ db });\n const duplicate = (\n await invoices.list({\n where: {\n tenantId: input.tenantId,\n historicalSourceKeyHash: historicalSalesSourceHash(source),\n },\n limit: 1,\n })\n )[0];\n if (duplicate && duplicate.id !== invoice.id)\n invalid(\n 'Historical source identity already belongs to another canonical invoice',\n );\n for (const component of facts.taxComponents ?? []) {\n const code = component.taxCodeId\n ? await (await TaxCodeCollection.create({ db })).get(\n { id: component.taxCodeId, tenantId: input.tenantId },\n { cache: false },\n )\n : null;\n if (\n component.taxCodeId &&\n (!code ||\n (component.classification !== null &&\n code.kind !== component.classification))\n )\n invalid(\n 'Historical source tax code is not owned by its tenant with the reviewed classification',\n );\n if (component.taxComponentId) {\n const tax = await (await TaxComponentCollection.create({ db })).get(\n { id: component.taxComponentId, tenantId: input.tenantId },\n { cache: false },\n );\n if (\n !tax ||\n (code &&\n !code.components.some((part) => part.taxComponentId === tax.id))\n )\n invalid(\n 'Historical source tax component is not owned by its declared tenant/code',\n );\n }\n if (component.liabilityAccountId) {\n const { AccountCollection } = await import(\n '@happyvertical/smrt-ledgers'\n );\n const account = await (await AccountCollection.create({ db })).get(\n { id: component.liabilityAccountId, tenantId: input.tenantId },\n { cache: false },\n );\n if (!account || account.type !== 'liability')\n invalid(\n 'Historical source tax liability account is not owned by its tenant with the required type',\n );\n }\n }\n let credited: Invoice | null = null;\n const amounts = historicalSalesMagnitudes(facts);\n if (snapshot.creditedSource) {\n credited = (\n await lockAndReloadInvoice(\n db,\n snapshot.creditedSource.invoiceId,\n input.tenantId,\n )\n ).invoice;\n if (\n credited.kind !== 'invoice' ||\n credited.tenantId !== input.tenantId ||\n credited.customerId !== invoice.customerId ||\n credited.currency !== invoice.currency ||\n !credited.moneySnapshotId ||\n credited.moneySnapshotId !== snapshot.creditedSource.moneySnapshotId ||\n credited.status === InvoiceStatus.DRAFT ||\n credited.status === InvoiceStatus.CANCELLED ||\n invoice.creditedInvoiceId !== credited.id\n )\n invalid(\n 'Historical credit original invoice/customer/currency/snapshot does not match',\n );\n const prior = (\n await invoices\n .list({\n where: { tenantId: input.tenantId, creditedInvoiceId: credited.id },\n limit: 100001,\n })\n .then((rows) => {\n if (rows.length > 100000)\n invalid(\n 'Historical credit scope exceeds its bounded source limit',\n );\n return rows;\n })\n ).filter(\n (row) =>\n row.id !== invoice.id &&\n row.status !== InvoiceStatus.DRAFT &&\n row.status !== InvoiceStatus.CANCELLED,\n );\n if (prior.length > 100000)\n invalid('Historical credit scope exceeds its bounded source limit');\n const retention = parseInvoiceRetention(credited.retentionStateJson);\n if (retention) {\n const credits = [\n ...prior.map((row) => ({\n on:\n getHistoricalSalesMoney(row)?.source.issuedOn ??\n row.issueDate.toISOString().slice(0, 10),\n amount: row.totalAmount,\n })),\n { on: source.issuedOn, amount: amounts.grossMinor },\n ];\n let remaining = retention.retainedMinor;\n const events = [\n ...credits.map((event) => ({\n ...event,\n kind: 'credit' as const,\n rank: 1,\n })),\n ...retention.releases.map((release) => {\n const on = release.effectiveOn ?? release.recordedAt.slice(0, 10);\n if (\n credits.some((event) => event.on === on) &&\n !release.sameDayCreditOrder\n )\n invalid(\n 'Same-day original retention release/credit requires explicit reviewed ordering',\n );\n return {\n on,\n amount: release.amountMinor,\n kind: 'release' as const,\n rank:\n release.sameDayCreditOrder === 'release-before-credit' ? 0 : 2,\n };\n }),\n ].sort(\n (left, right) =>\n left.on.localeCompare(right.on) || left.rank - right.rank,\n );\n for (const event of events) {\n if (event.kind === 'credit')\n remaining = Math.max(0, remaining - event.amount);\n else {\n if (event.amount > remaining)\n invalid(\n 'Original retention release exceeds retained-first capacity at its source date',\n );\n remaining -= event.amount;\n }\n }\n }\n for (const [field, value] of [\n ['subtotal', amounts.netMinor],\n ['taxAmount', amounts.taxMinor],\n ['totalAmount', amounts.grossMinor],\n ] as const) {\n const consumed = prior.reduce(\n (sum, row) => sum + BigInt(row[field]),\n 0n,\n );\n if (consumed + BigInt(value) > BigInt(credited[field]))\n invalid(\n 'Historical credit exceeds the remaining exact original net/tax/gross capacity',\n );\n }\n }\n await assertSourceLineCapacity(db, invoices, credited, snapshot);\n if (\n source.retention &&\n (facts.kind !== 'invoice' ||\n source.retention.retainedMinor > amounts.grossMinor)\n )\n invalid('Historical retention must match original invoice gross');\n const originalRetention = originalRetentionState(snapshot);\n invoice.retentionStateJson = originalRetention\n ? JSON.stringify(originalRetention)\n : '';\n invoice.moneyAuthority = 'historical';\n invoice.historicalSalesMoneyJson = JSON.stringify(snapshot);\n invoice.historicalSourceKeyHash = historicalSalesSourceHash(source);\n invoice.subtotal = amounts.netMinor;\n invoice.discountTotal = 0;\n invoice.taxAmount = amounts.taxMinor;\n invoice.providerTaxAmount = 0;\n invoice.totalAmount = amounts.grossMinor;\n invoice.issueDate = new Date(`${source.issuedOn}T00:00:00Z`);\n invoice.dueDate =\n source.dueOn === null ? null : new Date(`${source.dueOn}T00:00:00Z`);\n invoice.moneySnapshotId = snapshotIdentity(invoice, snapshot);\n invoice.status = InvoiceStatus.SENT;\n await assertContractScheduleInvoiceFreeze(db, invoice);\n await invoice.saveDerived(DOCUMENT_MONEY_WRITE);\n if (facts.detail.kind === 'lines')\n for (const line of facts.detail.lines) {\n const child = await new HistoricalSalesLine({\n db,\n id: lineIdentity(String(invoice.id), line.sourceKey),\n tenantId: input.tenantId,\n invoiceId: String(invoice.id),\n ...line,\n sourceKeyHash: hash(line.sourceKey),\n moneySnapshotId: invoice.moneySnapshotId,\n }).initialize();\n await withHistoricalCommerceWrite(child, () => child.save());\n }\n if (credited) await refreshIssuedCreditBalance(db, credited);\n return {\n snapshot: structuredClone(snapshot),\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n lines: (await readHistoricalSalesLines(db, invoice)).map((line) => ({\n sourceKey: line.sourceKey,\n lineId: String(line.id),\n })),\n };\n });\n}\n","/** Original header totals remain readable even when detailed tax classifications are unknown. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport type {\n DocumentTaxReportFact,\n DocumentTaxReportFactsOptions,\n} from './collections/DocumentTaxCollection.js';\nimport { InvoiceCollection } from './collections/InvoiceCollection.js';\nimport { getHistoricalSalesMoney } from './historical-sales-money.js';\nimport { historicalSalesMagnitudes } from './historical-sales-validation.js';\nimport type { Invoice } from './models/Invoice.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\n\nexport interface HistoricalSalesHeaderReportFact {\n invoiceId: string;\n moneySnapshotId: string;\n customerId: string;\n invoiceNumber: string;\n kind: Invoice['kind'];\n issueDate: string;\n currency: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n taxBreakdownKnown: boolean;\n}\nexport class HistoricalSalesTaxClassificationRequired extends Error {\n readonly code = 'HISTORICAL_SALES_TAX_CLASSIFICATION_REQUIRED';\n constructor(readonly invoiceId: string) {\n super(\n `Historical invoice ${invoiceId} retains exact header totals, but this tax breakdown requires explicit reviewed source classification, tax identity and taxable basis. Read the historical header facts or resolve the source assessment; never infer a rate or line allocation.`,\n );\n this.name = 'HistoricalSalesTaxClassificationRequired';\n }\n}\nfunction classified(invoice: Invoice) {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return false;\n const components = snapshot.facts.taxComponents;\n return Boolean(\n components?.length &&\n components.every(\n (component) =>\n component.classification !== null &&\n component.taxCodeId &&\n component.taxableMinor !== null &&\n component.netMinor !== null &&\n (component.classification !== 'taxable' || component.taxComponentId),\n ),\n );\n}\n/** @internal Project explicit source detail only; a known header is not a component classification. */\nexport function historicalSalesTaxReportFacts(\n invoice: Invoice,\n): DocumentTaxReportFact[] {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot) return [];\n if (snapshot.facts.netMinor === 0 && snapshot.facts.taxMinor === 0) return [];\n if (!classified(invoice))\n throw new HistoricalSalesTaxClassificationRequired(String(invoice.id));\n const sign =\n snapshot.facts.kind === 'credit_note' &&\n snapshot.facts.polarity === 'signed'\n ? -1\n : 1;\n return (snapshot.facts.taxComponents ?? []).map((component) => {\n if (\n component.classification === null ||\n !component.taxCodeId ||\n component.taxableMinor === null\n )\n throw new HistoricalSalesTaxClassificationRequired(String(invoice.id));\n return {\n tenantId: String(invoice.tenantId),\n documentType: invoice.kind,\n documentId: String(invoice.id),\n documentNumber: invoice.invoiceNumber,\n partyId: invoice.customerId,\n documentKind: invoice.kind,\n issueDate: invoice.issueDate.toISOString(),\n status: invoice.status,\n direction: 'sales',\n currency: invoice.currency,\n taxCodeId: component.taxCodeId,\n taxCodeKind: component.classification,\n taxableMinor: component.taxableMinor * sign,\n ...(component.netMinor === null\n ? {}\n : { netMinor: component.netMinor * sign }),\n taxMinor: component.amountMinor * sign,\n recoverableMinor: 0,\n taxComponentId: component.taxComponentId,\n componentName: component.label,\n liabilityAccountId: component.liabilityAccountId,\n commitmentId: null,\n commitmentLineId: null,\n };\n });\n}\n/** @internal Invoice source rows for the same public report scope; never silently truncate. */\nexport async function historicalSalesReportInvoices(\n db: DatabaseInterface,\n options: DocumentTaxReportFactsOptions,\n) {\n const rows = await (await InvoiceCollection.create({ db })).list({\n where: {\n tenantId: options.tenantId,\n moneyAuthority: 'historical',\n 'issueDate >=': options.from.toISOString(),\n 'issueDate <=': options.to.toISOString(),\n 'status not in': ['draft', 'cancelled'],\n ...(options.currency ? { currency: options.currency } : {}),\n },\n limit: 100001,\n });\n if (rows.length > 100000)\n throw new Error(\n 'Historical sales report scope exceeds the bounded document limit; select a smaller scope',\n );\n return rows;\n}\n/** Exact generic header reporting does not require a fabricated tax breakdown. */\nexport async function listHistoricalSalesHeaderFacts(\n input: DocumentTaxReportFactsOptions & { db: DatabaseInterface },\n): Promise<HistoricalSalesHeaderReportFact[]> {\n if (getTenantId() !== input.tenantId)\n throw new Error(\n 'Historical sales reporting requires the explicit active tenant',\n );\n if (\n !(input.from instanceof Date) ||\n !(input.to instanceof Date) ||\n !Number.isFinite(input.from.getTime()) ||\n !Number.isFinite(input.to.getTime()) ||\n input.from > input.to\n )\n throw new Error(\n 'Historical sales report requires an explicit valid period',\n );\n return withTenantMoneyRuntime(input.db, input.tenantId, async ({ db }) =>\n (await historicalSalesReportInvoices(db, input)).map((invoice) => {\n const snapshot = getHistoricalSalesMoney(invoice);\n if (!snapshot)\n throw new Error('Historical source monetary authority is unavailable');\n return {\n invoiceId: String(invoice.id),\n moneySnapshotId: invoice.moneySnapshotId,\n customerId: invoice.customerId,\n invoiceNumber: invoice.invoiceNumber,\n kind: invoice.kind,\n issueDate: invoice.issueDate.toISOString(),\n currency: invoice.currency,\n ...historicalSalesMagnitudes(snapshot.facts),\n taxBreakdownKnown: classified(invoice),\n };\n }),\n );\n}\n","/** Persisted per-code/component tax totals for a commerce document. */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport { MoneyValidationError, type TaxCodeKind } from '../money.js';\n\nexport type CommerceDocumentType = 'invoice' | 'contract' | 'credit_note';\n\nexport interface DocumentTaxOptions extends SmrtObjectOptions {\n tenantId?: string;\n documentType?: CommerceDocumentType;\n documentId?: string;\n currency?: string;\n taxCodeId?: string | null;\n taxCodeCode?: string | null;\n kind?: TaxCodeKind | null;\n taxComponentId?: string | null;\n taxComponentName?: string | null;\n percent?: string | null;\n liabilityAccountId?: string | null;\n taxableMinor?: number;\n netMinor?: number | null;\n taxMinor?: number;\n recoverableMinor?: number;\n}\n@TenantScoped({ mode: 'required' })\n@smrt({\n tableName: 'document_taxes',\n conflictColumns: [\n 'document_type',\n 'document_id',\n 'tax_code_id',\n 'tax_component_id',\n ],\n api: { include: ['list', 'get'] },\n mcp: { include: ['list', 'get'] },\n cli: { include: ['list', 'get'] },\n})\nexport class DocumentTax extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-commerce\";\n @tenantId()\n tenantId = '';\n\n @field({ required: true })\n documentType: CommerceDocumentType = 'invoice';\n\n @field({ required: true })\n documentId = '';\n\n @field({ required: true })\n currency = 'USD';\n\n @field({ nullable: true })\n taxCodeId: string | null = null;\n\n @field({ nullable: true })\n taxCodeCode: string | null = null;\n\n @field({ nullable: true })\n kind: TaxCodeKind | null = null;\n\n @field({ nullable: true })\n taxComponentId: string | null = null;\n\n @field({ nullable: true })\n taxComponentName: string | null = null;\n\n @field({ type: 'decimal', nullable: true })\n percent: string | null = null;\n\n @field({ nullable: true })\n liabilityAccountId: string | null = null;\n\n @field({\n description:\n 'Actual component taxable basis, including prior compound taxes.',\n ui: { format: 'money' },\n })\n taxableMinor = 0;\n\n @field({\n type: 'integer',\n nullable: true,\n description: 'Net basis when different from the component taxable basis.',\n ui: { format: 'money' },\n })\n netMinor: number | null = null;\n\n @field({\n description: 'Tax total in integer minor units.',\n ui: { format: 'money' },\n })\n taxMinor = 0;\n\n @field({\n description: 'Recoverable purchase tax in integer minor units.',\n ui: { format: 'money' },\n })\n recoverableMinor = 0;\n\n constructor(options: DocumentTaxOptions = {}) {\n super(options);\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.documentType !== undefined)\n this.documentType = options.documentType;\n if (options.documentId !== undefined) this.documentId = options.documentId;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.taxCodeId !== undefined) this.taxCodeId = options.taxCodeId;\n if (options.taxCodeCode !== undefined)\n this.taxCodeCode = options.taxCodeCode;\n if (options.kind !== undefined) this.kind = options.kind;\n if (options.taxComponentId !== undefined)\n this.taxComponentId = options.taxComponentId;\n if (options.taxComponentName !== undefined)\n this.taxComponentName = options.taxComponentName;\n if (options.percent !== undefined) this.percent = options.percent;\n if (options.liabilityAccountId !== undefined)\n this.liabilityAccountId = options.liabilityAccountId;\n if (options.taxableMinor !== undefined)\n this.taxableMinor = options.taxableMinor;\n if (options.netMinor !== undefined) this.netMinor = options.netMinor;\n if (options.taxMinor !== undefined) this.taxMinor = options.taxMinor;\n if (options.recoverableMinor !== undefined)\n this.recoverableMinor = options.recoverableMinor;\n }\n\n private assertValidDerivedRow(): void {\n if (!['invoice', 'contract', 'credit_note'].includes(this.documentType)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `Unknown document tax type: ${this.documentType}`,\n );\n }\n for (const [label, value] of [\n ['tenantId', this.tenantId],\n ['documentId', this.documentId],\n ['currency', this.currency],\n ] as const) {\n if (!value || value.trim() !== value) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n `DocumentTax ${label} must be a nonempty value`,\n );\n }\n }\n for (const [label, value] of [\n ['taxableMinor', this.taxableMinor],\n ['netMinor', this.netMinor ?? this.taxableMinor],\n ['taxMinor', this.taxMinor],\n ['recoverableMinor', this.recoverableMinor],\n ] as const) {\n if (!Number.isSafeInteger(value)) {\n throw new MoneyValidationError(\n 'UNSAFE_MONEY',\n `DocumentTax ${label} must be safe integer minor units`,\n );\n }\n }\n if (this.taxCodeId === null) {\n if (\n this.taxComponentId !== null ||\n this.taxCodeCode !== null ||\n this.kind !== null ||\n this.taxComponentName !== null ||\n this.percent !== null ||\n this.liabilityAccountId !== null ||\n this.taxMinor !== 0 ||\n this.recoverableMinor !== 0\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'An unassigned DocumentTax row cannot carry code/component snapshots or tax',\n );\n }\n return;\n }\n if (!this.taxCodeCode || !this.kind) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Assigned DocumentTax rows require code and kind snapshots',\n );\n }\n if (this.taxComponentId === null) {\n if (\n this.kind === 'taxable' ||\n this.taxComponentName !== null ||\n this.percent !== null ||\n this.liabilityAccountId !== null ||\n this.taxMinor !== 0 ||\n this.recoverableMinor !== 0\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Component-less DocumentTax rows must be non-taxable zero-tax snapshots',\n );\n }\n return;\n }\n if (this.kind !== 'taxable' || !this.taxComponentName || !this.percent) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'Component DocumentTax rows require taxable component snapshots',\n );\n }\n if (\n this.recoverableMinor !== 0 &&\n this.recoverableMinor !== this.taxMinor\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax recoverableMinor must be zero or the component tax total',\n );\n }\n }\n\n override async save(): Promise<this> {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax rows are derived and cannot be saved directly',\n );\n }\n\n override async delete(\n _options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax rows are derived and cannot be deleted directly',\n );\n }\n\n /** @internal Aggregate persistence only. */\n async saveDerived(capability: DocumentMoneyWriteCapability): Promise<this> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n this.assertValidDerivedRow();\n return (await super.save()) as this;\n }\n\n /** @internal Aggregate persistence only. */\n async deleteDerived(\n capability: DocumentMoneyWriteCapability,\n options: { expectedUpdatedAt?: Date | string } = {},\n ): Promise<void> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n await super.delete(options);\n }\n}\n","/**\n * VendorCollection - Collection manager for Vendor objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Vendor } from '../models/Vendor.js';\nimport { VendorStatus } from '../types/index.js';\n\nexport class VendorCollection extends SmrtCollection<Vendor> {\n static readonly _itemClass = Vendor;\n\n /**\n * Find vendors by profile ID\n *\n * @param profileId - Profile ID from smrt-profiles\n * @returns Array of vendors linked to this profile\n */\n async findByProfile(profileId: string): Promise<Vendor[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active vendors\n *\n * @returns Array of active vendors\n */\n async findActive(): Promise<Vendor[]> {\n return await this.list({\n where: { status: VendorStatus.ACTIVE },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find vendors by status\n *\n * @param status - Vendor status\n * @returns Array of vendors\n */\n async findByStatus(status: VendorStatus): Promise<Vendor[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Get or create a vendor for a profile\n *\n * @param profileId - Profile ID\n * @param defaults - Default values if creating\n * @returns Vendor\n */\n async getOrCreateForProfile(\n profileId: string,\n defaults: Partial<{\n leadTimeDays: number;\n minimumOrderAmount: number;\n paymentTerms: string;\n }> = {},\n ): Promise<Vendor> {\n const existing = await this.findByProfile(profileId);\n if (existing.length > 0) {\n return existing[0];\n }\n\n const vendor = await this.create({\n profileId,\n leadTimeDays: defaults.leadTimeDays ?? 0,\n minimumOrderAmount: defaults.minimumOrderAmount ?? 0,\n paymentTerms: defaults.paymentTerms ?? '',\n status: VendorStatus.ACTIVE,\n });\n await vendor.save();\n return vendor;\n }\n\n // ============================================================================\n // Tenant Helper Methods\n // ============================================================================\n\n /**\n * Find all vendors belonging to a specific tenant\n *\n * @param tenantId - Tenant ID\n * @returns Array of vendors for the tenant\n */\n async findByTenant(tenantId: string): Promise<Vendor[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global vendors (not associated with any tenant).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of global vendors\n */\n async findGlobal(): Promise<Vendor[]> {\n return queryGlobal<Vendor>(this);\n }\n\n /**\n * Find vendors for a tenant including global vendors.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - Tenant ID\n * @returns Array of tenant-specific and global vendors\n */\n async findWithGlobals(tenantId: string): Promise<Vendor[]> {\n return queryWithGlobals<Vendor>(this, tenantId, 'Vendor.findWithGlobals');\n }\n}\n","/** Exact monetary evidence received from a supplier, independent of calculated pricing. */\nimport type { DatabaseInterface } from '@happyvertical/smrt-core/migrations';\nimport { getTenantId } from '@happyvertical/smrt-tenancy';\nimport { ISO_4217_MINOR_UNITS } from '@happyvertical/smrt-ui/currency';\nimport { ContractCollection } from './collections/ContractCollection.js';\nimport { ContractLineItemCollection } from './collections/ContractLineItemCollection.js';\nimport { CustomerCollection } from './collections/CustomerCollection.js';\nimport { TaxCodeCollection } from './collections/TaxCodeCollection.js';\nimport { TaxComponentCollection } from './collections/TaxComponentCollection.js';\nimport { VendorCollection } from './collections/VendorCollection.js';\nimport {\n DOCUMENT_MONEY_WRITE,\n lockDocumentMoneyParents,\n} from './document-money-internal.js';\nimport {\n Agreement,\n type Contract,\n Order,\n PurchaseOrder,\n SupplierQuote,\n} from './models/Contract.js';\nimport { MoneyValidationError, type TaxCodeKind } from './money.js';\nimport { withTenantMoneyRuntime } from './tenant-money-barrier.js';\nimport { ContractStatus } from './types/index.js';\n\n/** A supplier tax component. Null explicitly retains an unknown fact. */\nexport interface ReceivedPurchaseTaxComponent {\n sourceKey: string;\n label: string;\n amountMinor: number;\n classification: TaxCodeKind | null;\n /** Explicit report identity/basis; omission retains unknown, never implies a rate. */\n taxCodeId?: string | null;\n taxComponentId?: string | null;\n taxableMinor?: number | null;\n /** Explicit net allocation when supplier taxable basis includes prior taxes. */\n netMinor?: number | null;\n recoverableMinor: number | null;\n}\n/** Complete source line money; optional source decimal text is evidence, not a calculator input. */\nexport interface ReceivedPurchaseMoneyLine {\n sourceKey: string;\n description: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n quantityText?: string;\n unitRateText?: string;\n}\n/** Monetary evidence without a fabricated rate, quantity, or line allocation. */\nexport interface ReceivedPurchaseMoneyFacts {\n currency: string;\n netMinor: number;\n taxMinor: number;\n grossMinor: number;\n taxComponents: ReceivedPurchaseTaxComponent[] | null;\n detail:\n | { kind: 'header-only' }\n | { kind: 'lines'; lines: ReceivedPurchaseMoneyLine[] };\n}\n/** Immutable request and supplier evidence identity retained with the amounts. */\nexport interface ReceivedPurchaseMoneySnapshot {\n version: 1;\n requestId: string;\n evidenceRef: string;\n facts: ReceivedPurchaseMoneyFacts;\n sourceQuote: ReceivedPurchaseQuoteSource | null;\n}\nexport interface ReceivedPurchaseQuoteSource {\n contractId: string;\n relationship: 'copy' | 'negotiated';\n}\n/** Public command input. The host authorizes the human before calling this command. */\nexport interface RecordReceivedPurchaseMoneyInput {\n db: DatabaseInterface;\n tenantId: string;\n contractId: string;\n requestId: string;\n evidenceRef: string;\n facts: ReceivedPurchaseMoneyFacts;\n sourceQuote?: ReceivedPurchaseQuoteSource;\n}\n\n/** Complete received sales agreement evidence; recording is not revenue/tax recognition. */\nexport type ReceivedSalesContractMoneyFacts = ReceivedPurchaseMoneyFacts;\nexport type ReceivedSalesContractMoneySnapshot = ReceivedPurchaseMoneySnapshot;\nexport type RecordReceivedSalesContractMoneyInput = Omit<\n RecordReceivedPurchaseMoneyInput,\n 'sourceQuote'\n>;\n\n/** Record supplied complete facts on one empty draft Order/Agreement. */\nexport async function recordReceivedSalesContractMoney(\n input: RecordReceivedSalesContractMoneyInput,\n): Promise<ReceivedSalesContractMoneySnapshot> {\n if (Object.hasOwn(input, 'sourceQuote'))\n invalid('Sales agreement evidence cannot reference a supplier quote');\n if (\n input.facts.taxComponents?.some(\n (component) => component.recoverableMinor !== null,\n )\n )\n invalid(\n 'Purchase tax recovery is not applicable to sales agreement evidence; retain null',\n );\n return recordReceivedContractMoney(input, 'sales');\n}\n\n/** Read exact sales agreement evidence without calculating or recognizing an invoice. */\nexport function getReceivedSalesContractMoney(\n contract: Contract,\n): ReceivedSalesContractMoneySnapshot | null {\n if (!(contract instanceof Order || contract instanceof Agreement))\n return null;\n return getReceivedPurchaseMoney(contract);\n}\n\nfunction invalid(message: string): never {\n throw new MoneyValidationError('INVALID_MONEY_INPUT', message);\n}\nfunction object(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value))\n invalid(`${label} must be an object`);\n return value as Record<string, unknown>;\n}\nfunction text(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value || value.trim() !== value)\n invalid(`${label} must be nonempty trimmed text`);\n return value;\n}\nfunction minor(value: unknown, label: string): number {\n if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0)\n invalid(`${label} must be a nonnegative safe integer`);\n return value;\n}\nfunction amounts(value: Record<string, unknown>, label: string) {\n const netMinor = minor(value.netMinor, `${label} net`);\n const taxMinor = minor(value.taxMinor, `${label} tax`);\n const grossMinor = minor(value.grossMinor, `${label} gross`);\n if (BigInt(netMinor) + BigInt(taxMinor) !== BigInt(grossMinor))\n invalid(`${label} net plus tax must equal gross`);\n return { netMinor, taxMinor, grossMinor };\n}\nfunction unique(keys: string[], label: string): void {\n if (new Set(keys).size !== keys.length)\n invalid(`${label} source keys must be unique`);\n}\n\n/** Validate and canonicalize exact received money, retaining unknowns as null. */\nexport function validateReceivedPurchaseMoneyFacts(\n value: unknown,\n): ReceivedPurchaseMoneyFacts {\n const input = object(value, 'Received purchase facts');\n const currency = text(input.currency, 'Currency');\n if (\n !/^[A-Z]{3}$/.test(currency) ||\n !ISO_4217_MINOR_UNITS.has(currency) ||\n ISO_4217_MINOR_UNITS.get(currency) === null\n )\n invalid('Currency must be a supported uppercase ISO 4217 code');\n const totals = amounts(input, 'Document');\n let taxComponents: ReceivedPurchaseTaxComponent[] | null = null;\n if (input.taxComponents !== null) {\n if (!Array.isArray(input.taxComponents))\n invalid('Tax components must be an array or explicit null');\n taxComponents = input.taxComponents.map((raw) => {\n const component = object(raw, 'Tax component');\n const amountMinor = minor(component.amountMinor, 'Component amount');\n const recoverableMinor =\n component.recoverableMinor === null\n ? null\n : minor(component.recoverableMinor, 'Recoverable amount');\n if (recoverableMinor !== null && recoverableMinor > amountMinor)\n invalid('Recoverable tax cannot exceed component tax');\n const classification = component.classification;\n if (\n classification !== null &&\n !['taxable', 'zero-rated', 'exempt', 'out-of-scope'].includes(\n String(classification),\n )\n )\n invalid('Unknown tax classification');\n const taxableMinor =\n component.taxableMinor == null\n ? null\n : minor(component.taxableMinor, 'Taxable basis');\n const netMinor =\n component.netMinor == null\n ? null\n : minor(component.netMinor, 'Component net basis');\n if (netMinor !== null && netMinor > totals.netMinor)\n invalid('Component net basis exceeds document net');\n if (\n classification !== null &&\n classification !== 'taxable' &&\n amountMinor !== 0\n )\n invalid('A non-taxable classification cannot contain tax');\n return {\n sourceKey: text(component.sourceKey, 'Component source key'),\n label: text(component.label, 'Component label'),\n amountMinor,\n classification: classification as TaxCodeKind | null,\n taxCodeId:\n component.taxCodeId == null\n ? null\n : text(component.taxCodeId, 'Tax code identity'),\n taxComponentId:\n component.taxComponentId == null\n ? null\n : text(component.taxComponentId, 'Tax component identity'),\n taxableMinor,\n ...(netMinor !== null ? { netMinor } : {}),\n recoverableMinor,\n };\n });\n unique(\n taxComponents.map((item) => item.sourceKey),\n 'Tax component',\n );\n if (\n taxComponents.reduce(\n (sum, item) => sum + BigInt(item.amountMinor),\n 0n,\n ) !== BigInt(totals.taxMinor)\n )\n invalid('Component tax sum must equal document tax');\n }\n const rawDetail = object(input.detail, 'Source detail');\n let detail: ReceivedPurchaseMoneyFacts['detail'];\n if (rawDetail.kind === 'header-only') {\n if ('lines' in rawDetail)\n invalid('Header-only evidence cannot contain monetary lines');\n detail = { kind: 'header-only' };\n } else if (rawDetail.kind === 'lines') {\n if (!Array.isArray(rawDetail.lines) || !rawDetail.lines.length)\n invalid('Complete source lines are required');\n const lines = rawDetail.lines.map((raw) => {\n const line = object(raw, 'Source line');\n const result: ReceivedPurchaseMoneyLine = {\n sourceKey: text(line.sourceKey, 'Line source key'),\n description: text(line.description, 'Line description'),\n ...amounts(line, 'Source line'),\n };\n for (const key of ['quantityText', 'unitRateText'] as const) {\n if (line[key] === undefined) continue;\n const decimal = text(line[key], key);\n if (!/^(?:0|[1-9]\\d*)(?:\\.\\d+)?$/.test(decimal))\n invalid(`${key} must be nonnegative decimal source text`);\n result[key] = decimal;\n }\n return result;\n });\n unique(\n lines.map((item) => item.sourceKey),\n 'Line',\n );\n for (const key of ['netMinor', 'taxMinor', 'grossMinor'] as const) {\n if (\n lines.reduce((sum, line) => sum + BigInt(line[key]), 0n) !==\n BigInt(totals[key])\n )\n invalid(`Source line ${key} sum must equal document amount`);\n }\n detail = { kind: 'lines', lines };\n } else invalid('Unknown received source detail kind');\n return { currency, ...totals, taxComponents, detail };\n}\n\nfunction quoteSource(value: unknown): ReceivedPurchaseQuoteSource | null {\n if (value == null) return null;\n const input = object(value, 'Source quote');\n if (input.relationship !== 'copy' && input.relationship !== 'negotiated')\n invalid('Unknown source quote relationship');\n return {\n contractId: text(input.contractId, 'Source quote identity'),\n relationship: input.relationship,\n };\n}\n\n/** Read validated received evidence; calculated contracts return null. */\nexport function getReceivedPurchaseMoney(\n contract: Pick<Contract, 'moneyAuthority' | 'receivedPurchaseMoneyJson'>,\n): ReceivedPurchaseMoneySnapshot | null {\n if (contract.moneyAuthority === 'calculated') {\n if (contract.receivedPurchaseMoneyJson)\n invalid('Calculated money cannot contain received evidence');\n return null;\n }\n if (contract.moneyAuthority !== 'received')\n invalid('Unknown contract money authority');\n let parsed: unknown;\n try {\n parsed = JSON.parse(contract.receivedPurchaseMoneyJson);\n } catch {\n invalid('Stored received money is invalid');\n }\n const input = object(parsed, 'Received snapshot');\n if (input.version !== 1) invalid('Unknown received money version');\n return {\n version: 1,\n requestId: text(input.requestId, 'Request identity'),\n evidenceRef: text(input.evidenceRef, 'Evidence reference'),\n facts: validateReceivedPurchaseMoneyFacts(input.facts),\n sourceQuote: quoteSource(input.sourceQuote),\n };\n}\n\n/** Record immutable source facts on one empty draft SupplierQuote or PurchaseOrder, retry safely. */\nexport async function recordReceivedPurchaseMoney(\n input: RecordReceivedPurchaseMoneyInput,\n): Promise<ReceivedPurchaseMoneySnapshot> {\n return recordReceivedContractMoney(input, 'purchase');\n}\n\nasync function recordReceivedContractMoney(\n input: RecordReceivedPurchaseMoneyInput,\n direction: 'purchase' | 'sales',\n): Promise<ReceivedPurchaseMoneySnapshot> {\n const tenantId = text(input.tenantId, 'Tenant');\n if (getTenantId() !== tenantId)\n invalid('Received contract money requires its active tenant context');\n const contractId = text(input.contractId, 'Contract');\n const snapshot: ReceivedPurchaseMoneySnapshot = {\n version: 1,\n requestId: text(input.requestId, 'Request identity'),\n evidenceRef: text(input.evidenceRef, 'Evidence reference'),\n facts: validateReceivedPurchaseMoneyFacts(input.facts),\n sourceQuote: quoteSource(input.sourceQuote),\n };\n const serialized = JSON.stringify(snapshot);\n return withTenantMoneyRuntime(input.db, tenantId, async ({ db }) => {\n const contracts = await ContractCollection.create({ db });\n await lockDocumentMoneyParents([\n { id: contractId, tenantId, collection: contracts },\n ...(snapshot.sourceQuote\n ? [\n {\n id: snapshot.sourceQuote.contractId,\n tenantId,\n collection: contracts,\n },\n ]\n : []),\n ]);\n const contract = await contracts.get({ id: contractId }, { cache: false });\n const validParty =\n direction === 'purchase'\n ? (contract instanceof SupplierQuote ||\n contract instanceof PurchaseOrder) &&\n contract.vendorId\n : (contract instanceof Order || contract instanceof Agreement) &&\n contract.customerId;\n if (!contract || contract.tenantId !== tenantId || !validParty)\n invalid(\n direction === 'purchase'\n ? 'Received money requires a supplier quote or purchase order in the active tenant'\n : 'Received money requires an Order or Agreement with a customer in the active tenant',\n );\n const stored = getReceivedPurchaseMoney(contract);\n if (stored) {\n if (JSON.stringify(stored) !== serialized)\n invalid(\n 'Received money request changed; create a separate contract revision',\n );\n return stored;\n }\n if (\n direction === 'purchase' &&\n (contract instanceof SupplierQuote || contract instanceof PurchaseOrder)\n ) {\n const vendor = await (await VendorCollection.create({ db })).get(\n { id: contract.vendorId },\n { cache: false },\n );\n if (!vendor || vendor.tenantId !== tenantId)\n invalid('Supplier must belong to the active tenant');\n } else if (contract instanceof Order || contract instanceof Agreement) {\n const customer = await (await CustomerCollection.create({ db })).get(\n { id: contract.customerId },\n { cache: false },\n );\n if (!customer || customer.tenantId !== tenantId)\n invalid('Customer must belong to the active tenant');\n }\n if (snapshot.sourceQuote) {\n if (!(contract instanceof PurchaseOrder))\n invalid('Only a purchase order can reference a source quote');\n const source = await contracts.get(\n { id: snapshot.sourceQuote.contractId },\n { cache: false },\n );\n if (\n !(source instanceof SupplierQuote) ||\n source.tenantId !== tenantId ||\n source.vendorId !== contract.vendorId ||\n source.currency !== contract.currency ||\n source.status !== ContractStatus.ACCEPTED ||\n !source.moneySnapshotId\n )\n invalid(\n 'Source quote must be accepted with matching tenant, vendor and currency',\n );\n const sourceMoney = getReceivedPurchaseMoney(source);\n if (!sourceMoney)\n invalid('Source quote must have received monetary evidence');\n if (\n snapshot.sourceQuote.relationship === 'copy' &&\n JSON.stringify(sourceMoney.facts) !== JSON.stringify(snapshot.facts)\n )\n invalid('Copied quote monetary facts must match exactly');\n if (\n snapshot.sourceQuote.relationship === 'negotiated' &&\n snapshot.evidenceRef === sourceMoney.evidenceRef\n )\n invalid(\n 'Negotiated award requires separate approved monetary evidence',\n );\n }\n for (const component of snapshot.facts.taxComponents ?? []) {\n if (component.taxCodeId) {\n const code = await (await TaxCodeCollection.create({ db })).get(\n { id: component.taxCodeId },\n { cache: false },\n );\n if (!code || code.tenantId !== tenantId)\n invalid('Tax report code must belong to the active tenant');\n if (\n component.classification !== null &&\n code.kind !== component.classification\n )\n invalid('Explicit tax classification must match its selected code');\n if (\n component.taxComponentId &&\n !code.components.some(\n (entry) => entry.taxComponentId === component.taxComponentId,\n )\n )\n invalid('Tax component must belong to its selected tax code');\n }\n if (component.taxComponentId) {\n const tax = await (await TaxComponentCollection.create({ db })).get(\n { id: component.taxComponentId },\n { cache: false },\n );\n if (!tax || tax.tenantId !== tenantId)\n invalid('Tax report component must belong to the active tenant');\n }\n }\n if (contract.status !== ContractStatus.DRAFT || contract.moneySnapshotId)\n invalid('Received money requires an unfrozen draft');\n if (contract.currency !== snapshot.facts.currency)\n invalid('Received money currency must match the contract');\n const lines = await (\n await ContractLineItemCollection.create({ db })\n ).findByContract(contractId);\n if (lines.length)\n invalid('Received money cannot mix with calculated contract lines');\n contract.moneyAuthority = 'received';\n contract.receivedPurchaseMoneyJson = serialized;\n contract.subtotal = snapshot.facts.netMinor;\n contract.discountTotal = 0;\n contract.taxAmount = snapshot.facts.taxMinor;\n contract.totalAmount = snapshot.facts.grossMinor;\n await contract.saveDerived(DOCUMENT_MONEY_WRITE);\n return snapshot;\n });\n}\n\n/** A received order cannot silently disappear from tax reporting when facts are unknown. */\nexport class ReceivedPurchaseTaxClassificationRequired extends Error {\n readonly code = 'RECEIVED_PURCHASE_TAX_CLASSIFICATION_REQUIRED';\n constructor(readonly contractId: string) {\n super(\n `Purchase order ${contractId} needs explicit tax classification, tax-code/component identity, taxable basis and recoverability in its received evidence before tax reporting. Record a reviewed replacement revision; do not infer tax rates.`,\n );\n this.name = 'ReceivedPurchaseTaxClassificationRequired';\n }\n}\n\n/** @internal Project explicitly classified source facts without inventing DocumentTax rates. */\nexport function receivedPurchaseReportFacts(\n contract: Contract,\n): import('./collections/DocumentTaxCollection.js').DocumentTaxReportFact[] {\n const snapshot = getReceivedPurchaseMoney(contract);\n if (!snapshot || !(contract instanceof PurchaseOrder)) return [];\n const id = text(contract.id, 'Purchase order identity');\n const components = snapshot.facts.taxComponents;\n if (!components?.length)\n throw new ReceivedPurchaseTaxClassificationRequired(id);\n return components.map((component) => {\n if (\n component.classification === null ||\n !component.taxCodeId ||\n component.taxableMinor == null ||\n component.recoverableMinor === null ||\n (component.taxableMinor > snapshot.facts.netMinor &&\n component.netMinor == null) ||\n (component.classification === 'taxable' && !component.taxComponentId)\n )\n throw new ReceivedPurchaseTaxClassificationRequired(id);\n return {\n tenantId: text(contract.tenantId, 'Tenant'),\n documentType: 'contract',\n documentId: id,\n documentNumber: contract.reference.trim() || id,\n partyId: contract.vendorId,\n documentKind: 'contract',\n issueDate: contract.issueDate.toISOString(),\n status: contract.status,\n direction: 'purchase',\n currency: snapshot.facts.currency,\n taxCodeId: component.taxCodeId,\n taxCodeKind: component.classification,\n taxableMinor: component.taxableMinor,\n ...(component.netMinor != null ? { netMinor: component.netMinor } : {}),\n taxMinor: component.amountMinor,\n recoverableMinor: component.recoverableMinor,\n taxComponentId: component.taxComponentId ?? null,\n componentName: component.label,\n liabilityAccountId: null,\n commitmentId: id,\n commitmentLineId: null,\n };\n });\n}\n","/** Owning collection for derived document tax totals. */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { withTenant } from '@happyvertical/smrt-tenancy';\nimport {\n DOCUMENT_MONEY_WRITE,\n type DocumentMoneyWriteCapability,\n} from '../document-money-internal.js';\nimport {\n historicalSalesReportInvoices,\n historicalSalesTaxReportFacts,\n} from '../historical-sales-reports.js';\nimport { classifyContractPurchase } from '../models/Contract.js';\nimport {\n type CommerceDocumentType,\n DocumentTax,\n type DocumentTaxOptions,\n} from '../models/DocumentTax.js';\nimport { MoneyValidationError, type TaxCodeKind } from '../money.js';\nimport { receivedPurchaseReportFacts } from '../received-purchase-money.js';\nimport { ContractCollection } from './ContractCollection.js';\n\nexport type DocumentTaxWriteInput = Required<\n Pick<\n DocumentTaxOptions,\n | 'tenantId'\n | 'documentType'\n | 'documentId'\n | 'currency'\n | 'taxCodeId'\n | 'taxCodeCode'\n | 'kind'\n | 'taxComponentId'\n | 'taxComponentName'\n | 'percent'\n | 'liabilityAccountId'\n | 'taxableMinor'\n | 'taxMinor'\n | 'recoverableMinor'\n >\n> & { netMinor?: number | null };\n\n/** Normalized immutable document-tax snapshots for tax-summary materialization. */\nexport interface DocumentTaxReportFact {\n tenantId: string;\n documentType: CommerceDocumentType;\n documentId: string;\n /** A document number/reference supplied to drilldown consumers. */\n documentNumber: string;\n /** Tenant-scoped party identity for a host to resolve as its party display. */\n partyId: string | null;\n /** Positive credit snapshots are negated once by the pure report aggregation. */\n documentKind: CommerceDocumentType;\n issueDate: string;\n status: string;\n direction: 'sales' | 'purchase';\n currency: string;\n taxCodeId: string | null;\n /** Null is an unassigned/unknown snapshot and must remain visible as a warning. */\n taxCodeKind: TaxCodeKind | null;\n taxableMinor: number;\n netMinor?: number;\n taxMinor: number;\n recoverableMinor: number;\n taxComponentId: string | null;\n componentName: string | null;\n liabilityAccountId: string | null;\n /** Purchase Contracts are the expense commitment identity; other documents are unlinked. */\n commitmentId: string | null;\n /** Document-tax snapshots are contract-level, so they retain no line allocation. */\n commitmentLineId: string | null;\n}\n\n/** @deprecated Use DocumentTaxReportFact. Kept for report-adapter compatibility. */\nexport type InvoiceTaxReportFact = DocumentTaxReportFact;\n\nexport interface DocumentTaxReportFactsOptions {\n tenantId: string;\n from: Date;\n to: Date;\n currency?: string;\n}\n\n/** @deprecated Use DocumentTaxReportFactsOptions. */\nexport type InvoiceTaxReportFactsOptions = DocumentTaxReportFactsOptions;\n\nconst TAX_CODE_KINDS = new Set<TaxCodeKind>([\n 'taxable',\n 'zero-rated',\n 'exempt',\n 'out-of-scope',\n]);\n\nfunction requiredText(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value.trim())\n throw new Error(`Invoice tax report ${label} must be a nonempty string.`);\n return value;\n}\n\nfunction storedMinor(value: unknown, label: string): number {\n const parsed =\n typeof value === 'bigint'\n ? Number(value)\n : typeof value === 'number'\n ? value\n : typeof value === 'string' && /^-?\\d+$/.test(value)\n ? Number(value)\n : Number.NaN;\n if (!Number.isSafeInteger(parsed))\n throw new RangeError(\n `Invoice tax report ${label} must be a safe integer minor-unit value.`,\n );\n return parsed;\n}\n\nfunction reportDate(value: unknown, label: string): string {\n const date = new Date(String(value));\n if (Number.isNaN(date.getTime()))\n throw new Error(`Invoice tax report ${label} must be a valid date.`);\n return date.toISOString();\n}\n\nfunction invoiceDocumentType(value: unknown): 'invoice' | 'credit_note' {\n if (value === 'invoice' || value === 'credit_note') return value;\n throw new Error(\n 'Invoice tax report document type must be invoice or credit_note.',\n );\n}\n\nfunction invoiceKind(value: unknown): 'invoice' | 'credit_note' {\n if (value === 'invoice' || value === 'credit_note') return value;\n throw new Error('Invoice tax report kind must be invoice or credit_note.');\n}\n\nfunction contractDocumentType(value: unknown): 'contract' {\n if (value === 'contract') return value;\n throw new Error('Contract tax report document type must be contract.');\n}\n\nfunction taxCodeKind(value: unknown): TaxCodeKind | null {\n return typeof value === 'string' && TAX_CODE_KINDS.has(value as TaxCodeKind)\n ? (value as TaxCodeKind)\n : null;\n}\n\nfunction assertReportFactOptions(options: DocumentTaxReportFactsOptions): void {\n if (!options.tenantId?.trim())\n throw new Error('Invoice tax report facts require a tenant.');\n if (!(options.from instanceof Date) || Number.isNaN(options.from.getTime()))\n throw new Error('Invoice tax report facts require a valid start date.');\n if (!(options.to instanceof Date) || Number.isNaN(options.to.getTime()))\n throw new Error('Invoice tax report facts require a valid end date.');\n if (options.from > options.to)\n throw new Error('Invoice tax report facts require an ordered date range.');\n if (options.currency !== undefined && !options.currency.trim())\n throw new Error(\n 'Invoice tax report currency must be nonempty when supplied.',\n );\n}\n\nfunction compareCodeUnits(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\nfunction identity(\n row: Pick<DocumentTaxWriteInput, 'taxCodeId' | 'taxComponentId'>,\n): string {\n return `${row.taxCodeId === null ? '0:' : `1:${row.taxCodeId}`}\\u0000${\n row.taxComponentId === null ? '0:' : `1:${row.taxComponentId}`\n }`;\n}\n\nconst BUSINESS_FIELDS = [\n 'tenantId',\n 'documentType',\n 'documentId',\n 'currency',\n 'taxCodeId',\n 'taxCodeCode',\n 'kind',\n 'taxComponentId',\n 'taxComponentName',\n 'percent',\n 'liabilityAccountId',\n 'taxableMinor',\n 'netMinor',\n 'taxMinor',\n 'recoverableMinor',\n] as const;\n\nfunction unchanged(row: DocumentTax, input: DocumentTaxWriteInput): boolean {\n return BUSINESS_FIELDS.every((field) => {\n const persisted = row[field];\n const proposed = input[field];\n if (field === 'percent' && persisted !== null && proposed !== null) {\n return String(persisted) === String(proposed);\n }\n return (persisted ?? null) === (proposed ?? null);\n });\n}\n\nexport class DocumentTaxCollection extends SmrtCollection<DocumentTax> {\n static readonly _itemClass = DocumentTax;\n\n /**\n * Read immutable commerce document-tax snapshots for one tenant.\n *\n * Invoice/credit rows join their shared storage by identity and tenant.\n * Purchase Contract rows first use the Contract owner's bounded hydrated\n * candidate API so custom PurchaseContract descendants retain their STI\n * classification. The query then joins only those candidate ids by identity\n * and tenant. Stored snapshots remain authoritative; this never recalculates\n * money or resolves present-day tax configuration.\n */\n async listReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n assertReportFactOptions(options);\n const [invoiceFacts, purchaseFacts] = await Promise.all([\n this.listInvoiceReportFacts(options),\n this.listPurchaseContractReportFacts(options),\n ]);\n return [...invoiceFacts, ...purchaseFacts].sort(\n (left, right) =>\n left.issueDate.localeCompare(right.issueDate) ||\n left.documentId.localeCompare(right.documentId) ||\n String(left.taxCodeId).localeCompare(String(right.taxCodeId)) ||\n String(left.taxComponentId).localeCompare(String(right.taxComponentId)),\n );\n }\n\n private async listInvoiceReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n const currencyClause = options.currency ? ' AND d.currency = ?' : '';\n const result = await this.db.query(\n `SELECT d.tenant_id, d.document_type, d.document_id, d.currency, d.tax_code_id, d.kind,\n d.tax_component_id, d.tax_component_name, d.liability_account_id,\n d.taxable_minor, d.net_minor, d.tax_minor, d.recoverable_minor,\n i.kind AS invoice_kind, i.invoice_number, i.customer_id, i.issue_date, i.status\n FROM document_taxes d\n JOIN invoices i\n ON CAST(i.id AS TEXT) = CAST(d.document_id AS TEXT)\n AND i.tenant_id = d.tenant_id\n WHERE CAST(d.tenant_id AS TEXT) = ?\n AND CAST(i.tenant_id AS TEXT) = ?\n AND (\n (d.document_type = 'invoice' AND i.kind = 'invoice')\n OR (d.document_type = 'credit_note' AND i.kind = 'credit_note')\n )\n AND i.status NOT IN ('draft', 'cancelled')\n AND i.issue_date >= ?\n AND i.issue_date <= ?${currencyClause}\n ORDER BY i.issue_date ASC, i.id ASC, d.tax_code_id ASC, d.tax_component_id ASC`,\n options.tenantId,\n options.tenantId,\n options.from.toISOString(),\n options.to.toISOString(),\n ...(options.currency ? [options.currency] : []),\n );\n const ordinary = result.rows.map(\n (row): DocumentTaxReportFact => ({\n tenantId: requiredText(row.tenant_id, 'tenant id'),\n documentType: invoiceDocumentType(row.document_type),\n documentId: requiredText(row.document_id, 'document id'),\n documentNumber: requiredText(row.invoice_number, 'invoice number'),\n partyId:\n typeof row.customer_id === 'string' && row.customer_id.trim()\n ? row.customer_id\n : null,\n documentKind: invoiceKind(row.invoice_kind),\n issueDate: reportDate(row.issue_date, 'issue date'),\n status: requiredText(row.status, 'invoice status'),\n direction: 'sales' as const,\n currency: requiredText(row.currency, 'currency'),\n taxCodeId: row.tax_code_id == null ? null : String(row.tax_code_id),\n taxCodeKind: taxCodeKind(row.kind),\n taxableMinor: storedMinor(row.taxable_minor, 'taxable minor'),\n ...(row.net_minor != null\n ? { netMinor: storedMinor(row.net_minor, 'net minor') }\n : {}),\n taxMinor: storedMinor(row.tax_minor, 'tax minor'),\n recoverableMinor: storedMinor(\n row.recoverable_minor,\n 'recoverable minor',\n ),\n taxComponentId:\n row.tax_component_id == null ? null : String(row.tax_component_id),\n componentName:\n row.tax_component_name == null\n ? null\n : String(row.tax_component_name),\n liabilityAccountId:\n row.liability_account_id == null\n ? null\n : String(row.liability_account_id),\n commitmentId: null,\n commitmentLineId: null,\n }),\n );\n return [\n ...ordinary,\n ...(await historicalSalesReportInvoices(this.db, options)).flatMap(\n historicalSalesTaxReportFacts,\n ),\n ];\n }\n\n private async listPurchaseContractReportFacts(\n options: DocumentTaxReportFactsOptions,\n ): Promise<DocumentTaxReportFact[]> {\n const contracts = await withTenant({ tenantId: options.tenantId }, () =>\n ContractCollection.create({ db: this.db }).then((collection) =>\n collection.listSnapshotReportContracts({\n tenantId: options.tenantId,\n from: options.from,\n to: options.to,\n }),\n ),\n );\n const candidates = contracts.filter(\n (contract) =>\n classifyContractPurchase(contract) &&\n (!options.currency || contract.currency === options.currency),\n );\n const receivedFacts = candidates\n .filter((contract) => contract.moneyAuthority === 'received')\n .flatMap(receivedPurchaseReportFacts);\n const purchases = candidates.filter(\n (contract) => contract.moneyAuthority !== 'received',\n );\n const ids = purchases.flatMap((contract) =>\n contract.id ? [contract.id] : [],\n );\n if (ids.length === 0) return receivedFacts;\n const byId = new Map(\n purchases.flatMap((contract) =>\n contract.id ? ([[contract.id, contract]] as const) : [],\n ),\n );\n const placeholders = ids.map(() => '?').join(', ');\n const currencyClause = options.currency ? ' AND d.currency = ?' : '';\n const result = await this.db.query(\n `SELECT d.tenant_id, d.document_type, d.document_id, d.currency, d.tax_code_id, d.kind,\n d.tax_component_id, d.tax_component_name, d.liability_account_id,\n d.taxable_minor, d.net_minor, d.tax_minor, d.recoverable_minor\n FROM document_taxes d\n JOIN contracts c\n ON CAST(c.id AS TEXT) = CAST(d.document_id AS TEXT)\n AND c.tenant_id = d.tenant_id\n WHERE CAST(d.tenant_id AS TEXT) = ?\n AND CAST(c.tenant_id AS TEXT) = ?\n AND d.document_type = 'contract'\n AND c.status NOT IN ('draft', 'cancelled')\n AND CAST(d.document_id AS TEXT) IN (${placeholders})${currencyClause}\n ORDER BY c.issue_date ASC, c.id ASC, d.tax_code_id ASC, d.tax_component_id ASC`,\n options.tenantId,\n options.tenantId,\n ...ids,\n ...(options.currency ? [options.currency] : []),\n );\n const calculatedFacts = result.rows.flatMap(\n (row): DocumentTaxReportFact[] => {\n const documentId = requiredText(row.document_id, 'contract id');\n const contract = byId.get(documentId);\n if (!contract) return [];\n return [\n {\n tenantId: requiredText(row.tenant_id, 'tenant id'),\n documentType: contractDocumentType(row.document_type),\n documentId,\n documentNumber: contract.reference.trim() || documentId,\n partyId:\n 'vendorId' in contract &&\n typeof contract.vendorId === 'string' &&\n contract.vendorId.trim()\n ? contract.vendorId\n : null,\n documentKind: 'contract',\n issueDate: reportDate(contract.issueDate, 'contract issue date'),\n status: requiredText(contract.status, 'contract status'),\n direction: 'purchase',\n currency: requiredText(row.currency, 'currency'),\n taxCodeId: row.tax_code_id == null ? null : String(row.tax_code_id),\n taxCodeKind: taxCodeKind(row.kind),\n taxableMinor: storedMinor(row.taxable_minor, 'taxable minor'),\n ...(row.net_minor != null\n ? { netMinor: storedMinor(row.net_minor, 'net minor') }\n : {}),\n taxMinor: storedMinor(row.tax_minor, 'tax minor'),\n recoverableMinor: storedMinor(\n row.recoverable_minor,\n 'recoverable minor',\n ),\n taxComponentId:\n row.tax_component_id == null\n ? null\n : String(row.tax_component_id),\n componentName:\n row.tax_component_name == null\n ? null\n : String(row.tax_component_name),\n liabilityAccountId:\n row.liability_account_id == null\n ? null\n : String(row.liability_account_id),\n // Expenses reference their PurchaseContract id as commitmentId.\n commitmentId: documentId,\n commitmentLineId: null,\n },\n ];\n },\n );\n return [...calculatedFacts, ...receivedFacts];\n }\n\n async findByDocument(\n tenantId: string,\n documentType: CommerceDocumentType,\n documentId: string,\n ): Promise<DocumentTax[]> {\n return this.list({\n where: { tenantId, documentType, documentId },\n orderBy: ['taxCodeId ASC', 'taxComponentId ASC'],\n });\n }\n\n /**\n * Replace one draft document's derived rows on the caller's transaction.\n * Unchanged rows are not saved, preserving their exact persisted bytes.\n *\n * @internal Aggregate persistence only.\n */\n async replaceDerivedForDocument(\n capability: DocumentMoneyWriteCapability,\n input: {\n tenantId: string;\n documentType: CommerceDocumentType;\n documentId: string;\n rows: readonly DocumentTaxWriteInput[];\n },\n ): Promise<DocumentTax[]> {\n if (capability !== DOCUMENT_MONEY_WRITE) {\n throw new MoneyValidationError(\n 'FROZEN_DOCUMENT',\n 'DocumentTax write capability is required',\n );\n }\n const desired = new Map<string, DocumentTaxWriteInput>();\n for (const row of input.rows) {\n if (\n row.tenantId !== input.tenantId ||\n row.documentType !== input.documentType ||\n row.documentId !== input.documentId\n ) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax replacement rows must share tenant and document identity',\n );\n }\n const key = identity(row);\n if (desired.has(key)) {\n throw new MoneyValidationError(\n 'INVALID_MONEY_INPUT',\n 'DocumentTax replacement contains a duplicate code/component identity',\n );\n }\n desired.set(key, row);\n }\n\n const existing = await this.findByDocument(\n input.tenantId,\n input.documentType,\n input.documentId,\n );\n const byIdentity = new Map(existing.map((row) => [identity(row), row]));\n const result: DocumentTax[] = [];\n for (const [key, rowInput] of [...desired].sort(([left], [right]) =>\n compareCodeUnits(left, right),\n )) {\n const current = byIdentity.get(key);\n if (current) {\n byIdentity.delete(key);\n if (!unchanged(current, rowInput)) {\n Object.assign(current, rowInput);\n await current.saveDerived(capability);\n }\n result.push(current);\n continue;\n }\n const created = await this.createUnsaved(rowInput);\n await created.saveDerived(capability);\n result.push(created);\n }\n for (const stale of [...byIdentity.values()].sort((left, right) =>\n compareCodeUnits(String(left.id), String(right.id)),\n )) {\n await stale.deleteDerived(capability, {\n expectedUpdatedAt: stale.updated_at ?? undefined,\n });\n }\n return result;\n }\n}\n"],"mappings":"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"}
|