@final-commerce/common 2.3.0 → 2.4.0-staging.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../enums/currency.enum.ts","../enums/core.enum.ts","../enums/stripe-currencies.enum.ts","../enums/product.enum.ts","../enums/payments.enum.ts","../utils/currency.util.ts","../units/system-units.ts","../units/convert.ts","../utils/order-totals.util.ts","../constants/pricing.constants.ts","../utils/pricing.util.ts","../utils/report-sign.util.ts","../utils/mongo.util.ts","../units/family-code.ts","../order-state-machine/types.ts","../order-state-machine/state-schema.ts","../order-state-machine/financial-invariants.ts","../order-state-machine/default-cross-axis-rules.ts","../order-state-machine/default-config.ts","../order-state-machine/pos-preset.ts","../order-state-machine/build-order-context.ts","../order-state-machine/display-state.ts","../order-state-machine/condition-eval.ts","../order-state-machine/engine.ts","../order-state-machine/validate-config.ts","../order-state-machine/set-order-state.ts","../order-state-machine/legacy-infer.ts","../order-state-machine/write-strategy.ts","../order-state-machine/resolve-template.ts","../order-state-machine/validate-fragment.ts","../order-state-machine/merge-fragment.ts","../order-state-machine/remove-fragment.ts","../order-state-machine/actions.ts","../order-state-machine/pubsub.ts","../constants/adyen.constants.ts"],"sourcesContent":["export * from './utils';\nexport * from './enums';\nexport * from './interfaces';\nexport * from './units';\nexport * from './order-state-machine';\nexport * from './constants/adyen.constants';\nexport * from './constants/pricing.constants';\n","/**\n * ISO 4217 Currency Code Enum\n * Contains all supported currency codes.\n */\nexport enum CurrencyCode {\n // Major currencies with 2 decimal places\n USD = 'USD',\n EUR = 'EUR',\n GBP = 'GBP',\n CAD = 'CAD',\n AUD = 'AUD',\n NZD = 'NZD',\n CHF = 'CHF',\n CNY = 'CNY',\n INR = 'INR',\n MXN = 'MXN',\n BRL = 'BRL',\n ZAR = 'ZAR',\n SGD = 'SGD',\n HKD = 'HKD',\n SEK = 'SEK',\n NOK = 'NOK',\n DKK = 'DKK',\n PLN = 'PLN',\n THB = 'THB',\n MYR = 'MYR',\n PHP = 'PHP',\n IDR = 'IDR',\n AED = 'AED',\n SAR = 'SAR',\n ILS = 'ILS',\n TRY = 'TRY',\n RUB = 'RUB',\n HTG = 'HTG',\n\n // New Currencies with 2 decimal places\n BND = 'BND', // Brunei Dollar\n CRC = 'CRC', // Costa Rican Colón\n BDT = 'BDT', // Bangladeshi Taka\n UAH = 'UAH', // Ukrainian Hryvnia\n NGN = 'NGN', // Nigerian Naira\n AFN = 'AFN', // Afghan Afghani\n ALL = 'ALL', // Albanian Lek\n AMD = 'AMD', // Armenian Dram\n ANG = 'ANG', // Netherlands Antillean Guilder\n AOA = 'AOA', // Angolan Kwanza\n ARS = 'ARS', // Argentine Peso\n AWG = 'AWG', // Aruban Florin\n AZN = 'AZN', // Azerbaijani Manat\n BAM = 'BAM', // Bosnia and Herzegovina Convertible Mark\n BBD = 'BBD', // Barbadian Dollar\n BGN = 'BGN', // Bulgarian Lev\n BMD = 'BMD', // Bermudian Dollar\n BOB = 'BOB', // Bolivian Boliviano\n BSD = 'BSD', // Bahamian Dollar\n BTN = 'BTN', // Bhutanese Ngultrum\n BWP = 'BWP', // Botswana Pula\n BYN = 'BYN', // Belarusian Ruble\n BZD = 'BZD', // Belize Dollar\n COP = 'COP', // Colombian Peso\n CZK = 'CZK', // Czech Koruna\n DOP = 'DOP', // Dominican Peso\n DZD = 'DZD', // Algerian Dinar\n EGP = 'EGP', // Egyptian Pound\n ETB = 'ETB', // Ethiopian Birr\n FJD = 'FJD', // Fijian Dollar\n GEL = 'GEL', // Georgian Lari\n GHS = 'GHS', // Ghanaian Cedi\n GTQ = 'GTQ', // Guatemalan Quetzal\n GYD = 'GYD', // Guyanese Dollar\n HNL = 'HNL', // Honduran Lempira\n IRR = 'IRR', // Iranian Rial\n JMD = 'JMD', // Jamaican Dollar\n KES = 'KES', // Kenyan Shilling\n KGS = 'KGS', // Kyrgyzstani Som\n KHR = 'KHR', // Cambodian Riel\n KYD = 'KYD', // Cayman Islands Dollar\n KZT = 'KZT', // Kazakhstani Tenge\n LAK = 'LAK', // Lao Kip\n LBP = 'LBP', // Lebanese Pound\n LKR = 'LKR', // Sri Lankan Rupee\n MAD = 'MAD', // Moroccan Dirham\n MDL = 'MDL', // Moldovan Leu\n MKD = 'MKD', // Macedonian Denar\n MMK = 'MMK', // Myanmar Kyat\n MNT = 'MNT', // Mongolian Tögrög\n MOP = 'MOP', // Macanese Pataca\n MUR = 'MUR', // Mauritian Rupee\n MVR = 'MVR', // Maldivian Rufiyaa\n MZN = 'MZN', // Mozambican Metical\n NAD = 'NAD', // Namibian Dollar\n NIO = 'NIO', // Nicaraguan Córdoba\n NPR = 'NPR', // Nepalese Rupee\n PAB = 'PAB', // Panamanian Balboa\n PEN = 'PEN', // Peruvian Sol\n PGK = 'PGK', // Papua New Guinean Kina\n PKR = 'PKR', // Pakistani Rupee\n QAR = 'QAR', // Qatari Riyal\n RON = 'RON', // Romanian Leu\n RSD = 'RSD', // Serbian Dinar\n SBD = 'SBD', // Solomon Islands Dollar\n SRD = 'SRD', // Surinamese Dollar\n SYP = 'SYP', // Syrian Pound\n TJS = 'TJS', // Tajikistani Somoni\n TMT = 'TMT', // Turkmenistani Manat\n TOP = 'TOP', // Tongan Paʻanga\n TTD = 'TTD', // Trinidad and Tobago Dollar\n TZS = 'TZS', // Tanzanian Shilling\n UYU = 'UYU', // Uruguayan Peso\n UZS = 'UZS', // Uzbekistani Som\n VES = 'VES', // Venezuelan Bolívar Soberano\n WST = 'WST', // Samoan Tala\n XCD = 'XCD', // East Caribbean Dollar\n YER = 'YER', // Yemeni Rial\n ZMW = 'ZMW', // Zambian Kwacha\n CDF = 'CDF', // Congolese Franc\n CUP = 'CUP', // Cuban Peso\n ERN = 'ERN', // Eritrean Nakfa\n FKP = 'FKP', // Falkland Islands Pound\n GIP = 'GIP', // Gibraltar Pound\n GMD = 'GMD', // Gambian Dalasi\n KPW = 'KPW', // North Korean Won\n LRD = 'LRD', // Liberian Dollar\n LSL = 'LSL', // Lesotho Loti\n MGA = 'MGA', // Malagasy Ariary\n MWK = 'MWK', // Malawian Kwacha\n SCR = 'SCR', // Seychellois Rupee\n SDG = 'SDG', // Sudanese Pound\n SHP = 'SHP', // Saint Helena Pound\n SLE = 'SLE', // Sierra Leonean Leone\n SOS = 'SOS', // Somali Shilling\n SSP = 'SSP', // South Sudanese Pound\n STN = 'STN', // São Tomé and Príncipe Dobra\n SZL = 'SZL', // Swazi Lilangeni\n VED = 'VED', // Venezuelan Bolívar Digital\n XCG = 'XCG', // Caribbean Guilder\n\n // Zero decimal currencies\n JPY = 'JPY',\n KRW = 'KRW',\n VND = 'VND',\n CLP = 'CLP',\n ISK = 'ISK',\n HUF = 'HUF',\n TWD = 'TWD',\n\n // New Currencies with 0 decimal places\n GNF = 'GNF', // Guinean Franc\n BIF = 'BIF', // Burundian Franc\n DJF = 'DJF', // Djiboutian Franc\n KMF = 'KMF', // Comoro Franc\n PYG = 'PYG', // Paraguayan Guaraní\n RWF = 'RWF', // Rwandan Franc\n UGX = 'UGX', // Ugandan Shilling\n VUV = 'VUV', // Vanuatu Vatu\n XAF = 'XAF', // Central African CFA Franc\n XOF = 'XOF', // West African CFA Franc\n XPF = 'XPF', // CFP Franc\n\n // Three decimal currencies\n KWD = 'KWD',\n BHD = 'BHD',\n OMR = 'OMR',\n JOD = 'JOD',\n TND = 'TND',\n LYD = 'LYD',\n IQD = 'IQD',\n}\n","// Dashboard\nexport enum TimePeriod {\n TODAY = 'today',\n THIS_WEEK = 'this week',\n THIS_MONTH = 'this month',\n THIS_YEAR = 'this year',\n All_TIME = 'all_time',\n}\n\nexport enum TopMetericsSort {\n TOTAL_PAYMENT_VOLUME = 'totalPaymentVolume',\n TOTAL_TRANSACTION = 'totalTransaction',\n}\n\nexport enum CompanyType {\n COMPANY = 'company',\n ROOT = 'root',\n ORGANIZATION = 'organization',\n}\n\nexport enum CustomTableAvailability {\n PUBLIC = 'public',\n ORGANIZATION = 'organization',\n}\n\nexport enum AttributeType {\n STRING = 'string',\n NUMBER = 'number',\n BOOLEAN = 'boolean',\n DATE = 'date',\n JSON_STRING = 'json-string',\n}\n\nexport enum Platform {\n WOO_COMMERCE = 'woo-commerce',\n SHOPIFY = 'shopify',\n OLIVER = 'oliver',\n STANDALONE = 'standalone',\n}\n\nexport enum OrderPlatform {\n POS = 'in-store',\n WOO_COMMERCE = 'woo-commerce',\n PUBLIC_API = 'public-api',\n}\n\nexport enum CustomerPlatform {\n POS = 'in-store',\n WOO_COMMERCE = 'woo-commerce',\n}\n\nexport enum StationStatus {\n IN_USE = 'IN_USE',\n AVAILABLE = 'AVAILABLE',\n}\n\n//Inventory\nexport enum InventoryBaseActionEnum {\n ADD = 'ADD',\n REMOVE = 'REMOVE',\n RECOUNT = 'RECOUNT',\n SKIP = 'SKIP',\n}\nexport type InventoryBaseActionType = `${InventoryBaseActionEnum}`;\n\nexport enum InventorySpecificActionType {\n STOCK_RECEIVED = 'STOCK_RECEIVED',\n INVENTORY_RECOUNT = 'INVENTORY_RECOUNT',\n DAMAGE = 'DAMAGE',\n THEFT = 'THEFT',\n LOSS = 'LOSS',\n RESTOCK_RETURN = 'RESTOCK_RETURN',\n // Only for Refund events\n REFUND_RESTOCK_RETURN = 'REFUND_RESTOCK_RETURN',\n REFUND_DAMAGE = 'REFUND_DAMAGE',\n // Only for Order events @see OrderCreated triger under mongoose trigger\n SALE = 'SALE',\n // Drawing a glass out of the bottle pool is a composition, not a loss. Without its own reason\n // code the bottle report reads as shrinkage every time a glass is poured.\n COMPOSED_FOR_SALE = 'COMPOSED_FOR_SALE',\n // The shelf was emptied because the variant left its unit family. A count in one family cannot\n // be reread in another — 500 g is not 500 ml — so the only honest number is zero. Recording it\n // as a recount would blame a stocktake nobody ran.\n UNIT_FAMILY_CHANGED = 'UNIT_FAMILY_CHANGED',\n // Stock transfer events\n TRANSFER = 'TRANSFER',\n BULK_RECOUNT = 'BULK_RECOUNT',\n // TODO(FI-6965): Move it to separate enum for woo-commerce specific actions\n APPLIED_FROM_WOO = 'APPLIED_FROM_WOO',\n PO_RECEIVED = 'PO_RECEIVED',\n // A stock movement that already happened on a connected provider (e.g. a Shopify sale recorded\n // by the sync lane). Must NEVER be rejected for insufficient stock — it lands even into negative\n // (Sarnia ruling #1: the provider sale is a completed fact; clamping at zero would erase it).\n // NOTE: an EXTERNAL_SALE against a pool-borrowing variant skips the COMPOSED_FOR_SALE relabel\n // at updateStock:2316, which is correct — Sarnia excludes pool-involved variants from mapped\n // cells in v1 (verdict: pooled). If that exclusion lifts, revisit viaVariantId stamping here.\n EXTERNAL_SALE = 'EXTERNAL_SALE',\n // A provider-originated restock (return, receipt, or manual correction from the provider side).\n EXTERNAL_RESTOCK = 'EXTERNAL_RESTOCK',\n}\n\nexport enum ExtensionCategory {\n SYNC = 'sync',\n PAYMENT = 'payment',\n HUB = 'hub',\n BUILDER = 'builder',\n}\n\nexport enum FeesCustomBillingStatus {\n UNPAID = 'unpaid',\n PAID = 'paid',\n OPEN = 'open',\n}\n\nexport enum PricingPlanEnum {\n DEFAULT = 'default',\n MINIMUM = 'minimum',\n ORGANIZATION = 'organization',\n PLAN = 'plan',\n COMPANY = 'company',\n}\n\nexport enum PricingLevel {\n ORG = 'org',\n PLAN = 'plan',\n DEFAULT = 'default',\n MINIMUM = 'minimum',\n}\n\nexport enum PricingRegionEnum {\n EUROPE = 'europe',\n OTHER = 'others',\n NORTH_AMERICA = 'northAmerica',\n}\n\nexport enum MenuProject {\n MANAGE = 'Manage',\n SCALE = 'Scale',\n BUILD = 'Build',\n PAY = 'Pay',\n RUN = 'Run',\n}\n\nexport enum UserTypes {\n COMPANY_OWNER = 'owner',\n ORG_USER = 'organization_user',\n ORG_OWNER = 'organization_owner',\n FINAL_USER = 'final_user',\n FINAL_OWNER = 'final_owner',\n EMPLOYEE = 'employee',\n SUPER_ADMIN = 'super_admin',\n MANAGER = 'manager',\n ADMIN = 'admin',\n ASSISTANT_MANAGER = 'assistant',\n CASHIER = 'cashier',\n RESELLER = 'reseller',\n}\n\nexport enum OwnerType {\n API_KEY = 'api-key',\n ORGANIZATION = 'organization',\n COMPANY = 'company',\n}\n\nexport enum PublicationAvailability {\n GLOBAL = 'global',\n PRIVATE = 'private',\n}\n\nexport enum PublicationStatus {\n APPROVED = 'approved',\n REJECTED = 'rejected',\n PENDING = 'pending',\n NOT_APPLICABLE = 'not_applicable',\n}\n\nexport interface PublicationConfig {\n availability: PublicationAvailability;\n status: PublicationStatus;\n}\n\nexport enum ResidualStatus {\n PAID = 'paid',\n DUE = 'due',\n ACCRUING = 'accruing',\n}\n\nexport enum PreviewImageMode {\n STATIC = 'static',\n DYNAMIC = 'dynamic',\n}\n\nexport enum LibraryItemType {\n FLOW = 'flow',\n PAGE = 'page',\n COMPOSITION = 'composition',\n LAYOUT = 'layout',\n}\n\nexport enum ResidualPaymentMethod {\n CHEQUE = 'cheque',\n}\n\nexport enum PaymentMethod {\n CUSTOM = 'Custom',\n CASH = 'Cash',\n TERMINAL = 'Terminal',\n CLOUD = 'Cloud',\n BLUETOOTH = 'Bluetooth',\n}\n\nexport enum NonRevenueItemType {\n GIFT_CARD = 'gift-card',\n}\n\nexport enum ReceiptSendChannel {\n EMAIL = 'email',\n TEXT = 'text',\n}\n\n// Discriminates a digital receipt as a sale receipt vs a refund receipt.\nexport enum ReceiptType {\n ORDER = 'order',\n REFUND = 'refund',\n}\n\nexport enum StripeStatus {\n ACTIVE = 'active', // When custom payment subscription is active\n INACTIVE = 'inactive', // When custom payment extension is uninstalled\n PAYMENT_METHOD_REQUIRED = 'payment_method_required', // Default status when a new customer is created\n PAYMENT_METHOD_ADDED = 'payment_method_added', // When Payment Method is added to the customer\n}\n\nexport enum InvoiceStatus {\n PAID = 'paid',\n PENDING = 'pending',\n EXPIRED = 'expired',\n}\n","/**\n * ISO 4217 Currency Code Enum\n * Contains all stripe supported currency codes.\n */\nexport enum StripeCurrencyCode {\n // Major currencies with 2 decimal places\n USD = 'USD',\n EUR = 'EUR',\n GBP = 'GBP',\n CAD = 'CAD',\n AUD = 'AUD',\n NZD = 'NZD',\n CHF = 'CHF',\n CNY = 'CNY',\n INR = 'INR',\n MXN = 'MXN',\n BRL = 'BRL',\n ZAR = 'ZAR',\n SGD = 'SGD',\n HKD = 'HKD',\n SEK = 'SEK',\n NOK = 'NOK',\n DKK = 'DKK',\n PLN = 'PLN',\n THB = 'THB',\n MYR = 'MYR',\n PHP = 'PHP',\n IDR = 'IDR',\n AED = 'AED',\n SAR = 'SAR',\n ILS = 'ILS',\n TRY = 'TRY',\n RUB = 'RUB',\n\n // Zero decimal currencies\n JPY = 'JPY',\n KRW = 'KRW',\n VND = 'VND',\n CLP = 'CLP',\n ISK = 'ISK',\n HUF = 'HUF',\n TWD = 'TWD',\n\n // Three decimal currencies\n KWD = 'KWD',\n BHD = 'BHD',\n OMR = 'OMR',\n JOD = 'JOD',\n TND = 'TND',\n LYD = 'LYD',\n IQD = 'IQD',\n}\n","/*\n Current supported Product Types, used in Product Schema & Most Front-End Types \n*/\nexport enum ProductType {\n SIMPLE = 'simple',\n VARIABLE = 'variable',\n}\n\n/*\n Current supported Product Status, used in Product Schema & Most Front-End Types \n*/\nexport enum ProductStatus {\n ACTIVE = 'active',\n INACTIVE = 'inactive',\n DRAFT = 'draft',\n}\n","// Acquiring processor a company's payments are routed through.\nexport enum PaymentProcessor {\n STRIPE = 'stripe',\n ADYEN = 'adyen',\n /**\n * Payment captured outside FinalPay entirely — set by third parties syncing\n * external order data in. Never written by the POS. Distinguishes \"synced\n * from elsewhere\" from an absent value (legacy FinalPay/Stripe record).\n */\n EXTERNAL = 'external',\n}\n","import { CurrencyCode } from '@/enums/index';\nimport { StripeCurrencyCode } from '@/enums/stripe-currencies.enum';\nimport { Amount, CurrencyConfig } from '@/interfaces/index';\n\n/**\n * Currency utility functions for handling monetary amounts in minor currency units.\n *\n * All monetary values are stored in the database as integers representing the smallest\n * currency unit (e.g., cents for USD, pence for GBP). This avoids floating-point\n * precision issues and ensures accurate financial calculations.\n *\n * @example\n * // Convert $10.50 to cents for storage\n * const cents = toMinorUnits(10.50, 'USD'); // Returns 1050\n *\n * // Convert cents back to dollars for display\n * const dollars = fromMinorUnits(1050, 'USD'); // Returns 10.50\n *\n * // Format for display\n * const formatted = formatCurrency(1050, 'USD'); // Returns '$10.50'\n */\n\n/**\n * Configuration for supported currencies.\n * Currencies are keyed by their ISO 4217 currency code.\n */\nexport const CURRENCY_CONFIG: Record<CurrencyCode | string, CurrencyConfig> = {\n // Major currencies with 2 decimal places\n [CurrencyCode.USD]: { minorUnits: 2, symbol: '$', symbolPosition: 'prefix' },\n [CurrencyCode.EUR]: { minorUnits: 2, symbol: '€', symbolPosition: 'prefix' },\n [CurrencyCode.GBP]: { minorUnits: 2, symbol: '£', symbolPosition: 'prefix' },\n [CurrencyCode.CAD]: { minorUnits: 2, symbol: 'CA$', symbolPosition: 'prefix' },\n [CurrencyCode.AUD]: { minorUnits: 2, symbol: 'A$', symbolPosition: 'prefix' },\n [CurrencyCode.NZD]: { minorUnits: 2, symbol: 'NZ$', symbolPosition: 'prefix' },\n [CurrencyCode.CHF]: { minorUnits: 2, symbol: 'CHF', symbolPosition: 'prefix' },\n [CurrencyCode.CNY]: { minorUnits: 2, symbol: '¥', symbolPosition: 'prefix' },\n [CurrencyCode.INR]: { minorUnits: 2, symbol: '₹', symbolPosition: 'prefix' },\n [CurrencyCode.MXN]: { minorUnits: 2, symbol: 'MX$', symbolPosition: 'prefix' },\n [CurrencyCode.BRL]: { minorUnits: 2, symbol: 'R$', symbolPosition: 'prefix' },\n [CurrencyCode.ZAR]: { minorUnits: 2, symbol: 'R', symbolPosition: 'prefix' },\n [CurrencyCode.SGD]: { minorUnits: 2, symbol: 'S$', symbolPosition: 'prefix' },\n [CurrencyCode.HKD]: { minorUnits: 2, symbol: 'HK$', symbolPosition: 'prefix' },\n [CurrencyCode.SEK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.NOK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.DKK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.PLN]: { minorUnits: 2, symbol: 'zł', symbolPosition: 'suffix' },\n [CurrencyCode.THB]: { minorUnits: 2, symbol: '฿', symbolPosition: 'prefix' },\n [CurrencyCode.MYR]: { minorUnits: 2, symbol: 'RM', symbolPosition: 'prefix' },\n [CurrencyCode.PHP]: { minorUnits: 2, symbol: '₱', symbolPosition: 'prefix' },\n [CurrencyCode.IDR]: { minorUnits: 2, symbol: 'Rp', symbolPosition: 'prefix' },\n [CurrencyCode.AED]: { minorUnits: 2, symbol: 'د.إ', symbolPosition: 'prefix' },\n [CurrencyCode.SAR]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.ILS]: { minorUnits: 2, symbol: '₪', symbolPosition: 'prefix' },\n [CurrencyCode.TRY]: { minorUnits: 2, symbol: '₺', symbolPosition: 'prefix' },\n [CurrencyCode.RUB]: { minorUnits: 2, symbol: '₽', symbolPosition: 'suffix' },\n [CurrencyCode.HTG]: { minorUnits: 2, symbol: 'HTG', symbolPosition: 'prefix' },\n\n // New Currencies with 2 decimal places\n [CurrencyCode.BND]: { minorUnits: 2, symbol: 'BND', symbolPosition: 'prefix' },\n [CurrencyCode.CRC]: { minorUnits: 2, symbol: 'CRC', symbolPosition: 'prefix' },\n [CurrencyCode.BDT]: { minorUnits: 2, symbol: 'BDT', symbolPosition: 'prefix' },\n [CurrencyCode.UAH]: { minorUnits: 2, symbol: 'UAH', symbolPosition: 'prefix' },\n [CurrencyCode.NGN]: { minorUnits: 2, symbol: '₦', symbolPosition: 'prefix' },\n [CurrencyCode.AFN]: { minorUnits: 2, symbol: '؋', symbolPosition: 'prefix' },\n [CurrencyCode.ALL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'suffix' },\n [CurrencyCode.AMD]: { minorUnits: 2, symbol: '֏', symbolPosition: 'suffix' },\n [CurrencyCode.ANG]: { minorUnits: 2, symbol: 'ƒ', symbolPosition: 'prefix' },\n [CurrencyCode.AOA]: { minorUnits: 2, symbol: 'Kz', symbolPosition: 'prefix' },\n [CurrencyCode.ARS]: { minorUnits: 2, symbol: 'AR$', symbolPosition: 'prefix' },\n [CurrencyCode.AWG]: { minorUnits: 2, symbol: 'Afl.', symbolPosition: 'prefix' },\n [CurrencyCode.AZN]: { minorUnits: 2, symbol: '₼', symbolPosition: 'prefix' },\n [CurrencyCode.BAM]: { minorUnits: 2, symbol: 'KM', symbolPosition: 'suffix' },\n [CurrencyCode.BBD]: { minorUnits: 2, symbol: 'Bds$', symbolPosition: 'prefix' },\n [CurrencyCode.BGN]: { minorUnits: 2, symbol: 'лв', symbolPosition: 'suffix' },\n [CurrencyCode.BMD]: { minorUnits: 2, symbol: 'BD$', symbolPosition: 'prefix' },\n [CurrencyCode.BOB]: { minorUnits: 2, symbol: 'Bs.', symbolPosition: 'prefix' },\n [CurrencyCode.BSD]: { minorUnits: 2, symbol: 'B$', symbolPosition: 'prefix' },\n [CurrencyCode.BTN]: { minorUnits: 2, symbol: 'Nu.', symbolPosition: 'prefix' },\n [CurrencyCode.BWP]: { minorUnits: 2, symbol: 'P', symbolPosition: 'prefix' },\n [CurrencyCode.BYN]: { minorUnits: 2, symbol: 'Br', symbolPosition: 'suffix' },\n [CurrencyCode.BZD]: { minorUnits: 2, symbol: 'BZ$', symbolPosition: 'prefix' },\n [CurrencyCode.COP]: { minorUnits: 2, symbol: 'COL$', symbolPosition: 'prefix' },\n [CurrencyCode.CZK]: { minorUnits: 2, symbol: 'Kč', symbolPosition: 'suffix' },\n [CurrencyCode.DOP]: { minorUnits: 2, symbol: 'RD$', symbolPosition: 'prefix' },\n [CurrencyCode.DZD]: { minorUnits: 2, symbol: 'DA', symbolPosition: 'prefix' },\n [CurrencyCode.EGP]: { minorUnits: 2, symbol: 'E£', symbolPosition: 'prefix' },\n [CurrencyCode.ETB]: { minorUnits: 2, symbol: 'Br', symbolPosition: 'prefix' },\n [CurrencyCode.FJD]: { minorUnits: 2, symbol: 'FJ$', symbolPosition: 'prefix' },\n [CurrencyCode.GEL]: { minorUnits: 2, symbol: '₾', symbolPosition: 'prefix' },\n [CurrencyCode.GHS]: { minorUnits: 2, symbol: '₵', symbolPosition: 'prefix' },\n [CurrencyCode.GTQ]: { minorUnits: 2, symbol: 'Q', symbolPosition: 'prefix' },\n [CurrencyCode.GYD]: { minorUnits: 2, symbol: 'G$', symbolPosition: 'prefix' },\n [CurrencyCode.HNL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'prefix' },\n [CurrencyCode.IRR]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.JMD]: { minorUnits: 2, symbol: 'J$', symbolPosition: 'prefix' },\n [CurrencyCode.KES]: { minorUnits: 2, symbol: 'KSh', symbolPosition: 'prefix' },\n [CurrencyCode.KGS]: { minorUnits: 2, symbol: 'с', symbolPosition: 'suffix' },\n [CurrencyCode.KHR]: { minorUnits: 2, symbol: '៛', symbolPosition: 'prefix' },\n [CurrencyCode.KYD]: { minorUnits: 2, symbol: 'CI$', symbolPosition: 'prefix' },\n [CurrencyCode.KZT]: { minorUnits: 2, symbol: '₸', symbolPosition: 'prefix' },\n [CurrencyCode.LAK]: { minorUnits: 2, symbol: '₭', symbolPosition: 'prefix' },\n [CurrencyCode.LBP]: { minorUnits: 2, symbol: 'L£', symbolPosition: 'prefix' },\n [CurrencyCode.LKR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.MAD]: { minorUnits: 2, symbol: 'DH', symbolPosition: 'prefix' },\n [CurrencyCode.MDL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'suffix' },\n [CurrencyCode.MKD]: { minorUnits: 2, symbol: 'ден', symbolPosition: 'suffix' },\n [CurrencyCode.MMK]: { minorUnits: 2, symbol: 'K', symbolPosition: 'prefix' },\n [CurrencyCode.MNT]: { minorUnits: 2, symbol: '₮', symbolPosition: 'prefix' },\n [CurrencyCode.MOP]: { minorUnits: 2, symbol: 'MOP$', symbolPosition: 'prefix' },\n [CurrencyCode.MUR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.MVR]: { minorUnits: 2, symbol: 'Rf', symbolPosition: 'prefix' },\n [CurrencyCode.MZN]: { minorUnits: 2, symbol: 'MT', symbolPosition: 'prefix' },\n [CurrencyCode.NAD]: { minorUnits: 2, symbol: 'N$', symbolPosition: 'prefix' },\n [CurrencyCode.NIO]: { minorUnits: 2, symbol: 'C$', symbolPosition: 'prefix' },\n [CurrencyCode.NPR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.PAB]: { minorUnits: 2, symbol: 'B/.', symbolPosition: 'prefix' },\n [CurrencyCode.PEN]: { minorUnits: 2, symbol: 'S/', symbolPosition: 'prefix' },\n [CurrencyCode.PGK]: { minorUnits: 2, symbol: 'K', symbolPosition: 'prefix' },\n [CurrencyCode.PKR]: { minorUnits: 2, symbol: '₨', symbolPosition: 'prefix' },\n [CurrencyCode.QAR]: { minorUnits: 2, symbol: 'QR', symbolPosition: 'prefix' },\n [CurrencyCode.RON]: { minorUnits: 2, symbol: 'lei', symbolPosition: 'suffix' },\n [CurrencyCode.RSD]: { minorUnits: 2, symbol: 'дин.', symbolPosition: 'suffix' },\n [CurrencyCode.SBD]: { minorUnits: 2, symbol: 'SI$', symbolPosition: 'prefix' },\n [CurrencyCode.SRD]: { minorUnits: 2, symbol: 'Sr$', symbolPosition: 'prefix' },\n [CurrencyCode.SYP]: { minorUnits: 2, symbol: '£S', symbolPosition: 'prefix' },\n [CurrencyCode.TJS]: { minorUnits: 2, symbol: 'SM', symbolPosition: 'prefix' },\n [CurrencyCode.TMT]: { minorUnits: 2, symbol: 'm.', symbolPosition: 'prefix' },\n [CurrencyCode.TOP]: { minorUnits: 2, symbol: 'T$', symbolPosition: 'prefix' },\n [CurrencyCode.TTD]: { minorUnits: 2, symbol: 'TT$', symbolPosition: 'prefix' },\n [CurrencyCode.TZS]: { minorUnits: 2, symbol: 'TSh', symbolPosition: 'prefix' },\n [CurrencyCode.UYU]: { minorUnits: 2, symbol: '$U', symbolPosition: 'prefix' },\n [CurrencyCode.UZS]: { minorUnits: 2, symbol: 'сўм', symbolPosition: 'suffix' },\n [CurrencyCode.VES]: { minorUnits: 2, symbol: 'Bs.', symbolPosition: 'prefix' },\n [CurrencyCode.WST]: { minorUnits: 2, symbol: 'WS$', symbolPosition: 'prefix' },\n [CurrencyCode.XCD]: { minorUnits: 2, symbol: 'EC$', symbolPosition: 'prefix' },\n [CurrencyCode.YER]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.ZMW]: { minorUnits: 2, symbol: 'ZK', symbolPosition: 'prefix' },\n [CurrencyCode.CDF]: { minorUnits: 2, symbol: 'FC', symbolPosition: 'prefix' },\n [CurrencyCode.CUP]: { minorUnits: 2, symbol: '$MN', symbolPosition: 'prefix' },\n [CurrencyCode.ERN]: { minorUnits: 2, symbol: 'Nfk', symbolPosition: 'prefix' },\n [CurrencyCode.FKP]: { minorUnits: 2, symbol: 'FK£', symbolPosition: 'prefix' },\n [CurrencyCode.GIP]: { minorUnits: 2, symbol: 'GI£', symbolPosition: 'prefix' },\n [CurrencyCode.GMD]: { minorUnits: 2, symbol: 'D', symbolPosition: 'prefix' },\n [CurrencyCode.KPW]: { minorUnits: 2, symbol: 'KPW', symbolPosition: 'prefix' },\n [CurrencyCode.LRD]: { minorUnits: 2, symbol: 'L$', symbolPosition: 'prefix' },\n [CurrencyCode.LSL]: { minorUnits: 2, symbol: 'M', symbolPosition: 'prefix' },\n [CurrencyCode.MGA]: { minorUnits: 2, symbol: 'Ar', symbolPosition: 'prefix' },\n [CurrencyCode.MWK]: { minorUnits: 2, symbol: 'MK', symbolPosition: 'prefix' },\n [CurrencyCode.SCR]: { minorUnits: 2, symbol: 'SR', symbolPosition: 'prefix' },\n [CurrencyCode.SDG]: { minorUnits: 2, symbol: 'SDG', symbolPosition: 'prefix' },\n [CurrencyCode.SHP]: { minorUnits: 2, symbol: 'SH£', symbolPosition: 'prefix' },\n [CurrencyCode.SLE]: { minorUnits: 2, symbol: 'Le', symbolPosition: 'prefix' },\n [CurrencyCode.SOS]: { minorUnits: 2, symbol: 'SSh', symbolPosition: 'prefix' },\n [CurrencyCode.SSP]: { minorUnits: 2, symbol: 'SSP', symbolPosition: 'prefix' },\n [CurrencyCode.STN]: { minorUnits: 2, symbol: 'Db', symbolPosition: 'prefix' },\n [CurrencyCode.SZL]: { minorUnits: 2, symbol: 'E', symbolPosition: 'prefix' },\n [CurrencyCode.VED]: { minorUnits: 2, symbol: 'Bs.D', symbolPosition: 'prefix' },\n [CurrencyCode.XCG]: { minorUnits: 2, symbol: 'Cg', symbolPosition: 'prefix' },\n\n // Zero decimal currencies\n [CurrencyCode.JPY]: { minorUnits: 0, symbol: '¥', symbolPosition: 'prefix' },\n [CurrencyCode.KRW]: { minorUnits: 0, symbol: '₩', symbolPosition: 'prefix' },\n [CurrencyCode.VND]: { minorUnits: 0, symbol: '₫', symbolPosition: 'suffix' },\n [CurrencyCode.CLP]: { minorUnits: 0, symbol: 'CLP$', symbolPosition: 'prefix' },\n [CurrencyCode.ISK]: { minorUnits: 0, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.HUF]: { minorUnits: 0, symbol: 'Ft', symbolPosition: 'suffix' },\n [CurrencyCode.TWD]: { minorUnits: 0, symbol: 'NT$', symbolPosition: 'prefix' },\n\n // New Currencies with 0 decimal places\n [CurrencyCode.GNF]: { minorUnits: 0, symbol: 'GNF', symbolPosition: 'prefix' },\n [CurrencyCode.BIF]: { minorUnits: 0, symbol: 'FBu', symbolPosition: 'prefix' },\n [CurrencyCode.DJF]: { minorUnits: 0, symbol: 'Fdj', symbolPosition: 'prefix' },\n [CurrencyCode.KMF]: { minorUnits: 0, symbol: 'CF', symbolPosition: 'prefix' },\n [CurrencyCode.PYG]: { minorUnits: 0, symbol: '₲', symbolPosition: 'prefix' },\n [CurrencyCode.RWF]: { minorUnits: 0, symbol: 'FRw', symbolPosition: 'prefix' },\n [CurrencyCode.UGX]: { minorUnits: 0, symbol: 'USh', symbolPosition: 'prefix' },\n [CurrencyCode.VUV]: { minorUnits: 0, symbol: 'VT', symbolPosition: 'prefix' },\n [CurrencyCode.XAF]: { minorUnits: 0, symbol: 'FCFA', symbolPosition: 'suffix' },\n [CurrencyCode.XOF]: { minorUnits: 0, symbol: 'CFA', symbolPosition: 'suffix' },\n [CurrencyCode.XPF]: { minorUnits: 0, symbol: '₣', symbolPosition: 'suffix' },\n\n // Three decimal currencies\n [CurrencyCode.KWD]: { minorUnits: 3, symbol: 'KD', symbolPosition: 'prefix' },\n [CurrencyCode.BHD]: { minorUnits: 3, symbol: 'BD', symbolPosition: 'prefix' },\n [CurrencyCode.OMR]: { minorUnits: 3, symbol: 'OMR', symbolPosition: 'prefix' },\n [CurrencyCode.JOD]: { minorUnits: 3, symbol: 'JD', symbolPosition: 'prefix' },\n [CurrencyCode.TND]: { minorUnits: 3, symbol: 'DT', symbolPosition: 'prefix' },\n [CurrencyCode.LYD]: { minorUnits: 3, symbol: 'LD', symbolPosition: 'prefix' },\n [CurrencyCode.IQD]: { minorUnits: 3, symbol: 'IQD', symbolPosition: 'prefix' },\n};\n\n/** Default configuration for unknown currencies (assumes 2 decimal places) */\nconst DEFAULT_CURRENCY_CONFIG: CurrencyConfig = {\n minorUnits: 2,\n symbol: '',\n symbolPosition: 'prefix',\n};\n\n/**\n * Gets the currency configuration for a given currency code.\n * Falls back to default configuration (2 decimal places) for unknown currencies.\n *\n * @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')\n * @returns Currency configuration\n */\nexport function getCurrencyConfig(currency: CurrencyCode): CurrencyConfig {\n const upperCurrency = currency.toUpperCase();\n return CURRENCY_CONFIG[upperCurrency] || DEFAULT_CURRENCY_CONFIG;\n}\n\n/**\n * Gets the multiplier for converting between major and minor currency units.\n *\n * @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')\n * @returns The multiplier (e.g., 100 for USD, 1 for JPY, 1000 for KWD)\n *\n * @example\n * getMinorUnitMultiplier('USD'); // Returns 100\n * getMinorUnitMultiplier('JPY'); // Returns 1\n * getMinorUnitMultiplier('KWD'); // Returns 1000\n */\nexport function getMinorUnitMultiplier(currency: CurrencyCode): number {\n const config = getCurrencyConfig(currency);\n return Math.pow(10, config.minorUnits);\n}\n\n/**\n * Converts a major currency amount to minor units (e.g., dollars to cents).\n * Uses Math.round to handle floating-point precision issues.\n *\n * @param amount - Amount in major currency units (e.g., 10.50 dollars)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @returns Amount in minor units as an integer (e.g., 1050 cents)\n *\n * @example\n * toMinorUnits(10.50, 'USD'); // Returns 1050\n * toMinorUnits(1000, 'JPY'); // Returns 1000 (JPY has no minor units)\n * toMinorUnits(10.500, 'KWD'); // Returns 10500 (KWD has 3 decimal places)\n */\nexport function toMinorUnits(amount: number, currency: CurrencyCode): number {\n const multiplier = getMinorUnitMultiplier(currency);\n // Use Math.round to handle floating-point precision issues\n return Math.round(amount * multiplier);\n}\n\n/**\n * Converts minor currency units to major units (e.g., cents to dollars).\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @returns Amount in major units (e.g., 10.50 dollars)\n *\n * @example\n * fromMinorUnits(1050, 'USD'); // Returns 10.50\n * fromMinorUnits(1000, 'JPY'); // Returns 1000\n * fromMinorUnits(10500, 'KWD'); // Returns 10.500\n */\nexport function fromMinorUnits(minorAmount: number, currency: CurrencyCode): number {\n const multiplier = getMinorUnitMultiplier(currency);\n return minorAmount / multiplier;\n}\n\n/**\n * Formats a minor currency amount for display with currency symbol.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @param options - Formatting options\n * @returns Formatted currency string (e.g., '$10.50')\n *\n * @example\n * formatCurrency(1050, 'USD'); // Returns '$10.50'\n * formatCurrency(1000, 'JPY'); // Returns '¥1000'\n * formatCurrency(10500, 'KWD'); // Returns 'KD10.500'\n */\nexport function formatCurrency(\n minorAmount: number,\n currency: CurrencyCode,\n options: {\n /** Whether to include the currency symbol (default: true) */\n includeSymbol?: boolean;\n /** Whether to use grouping separators for thousands (default: true) */\n useGrouping?: boolean;\n } = {},\n): string {\n const { includeSymbol = true, useGrouping = true } = options;\n const config = getCurrencyConfig(currency);\n const majorAmount = fromMinorUnits(minorAmount, currency);\n\n const formattedNumber = majorAmount.toLocaleString('en-US', {\n minimumFractionDigits: config.minorUnits,\n maximumFractionDigits: config.minorUnits,\n useGrouping,\n });\n\n if (!includeSymbol || !config.symbol) {\n return formattedNumber;\n }\n\n if (config.symbolPosition === 'suffix') {\n return `${formattedNumber}${config.symbol}`;\n }\n\n return `${config.symbol}${formattedNumber}`;\n}\n\n/**\n * Safely adds two amounts in minor units.\n * Both amounts should already be in minor units (integers).\n *\n * @param a - First amount in minor units\n * @param b - Second amount in minor units\n * @returns Sum in minor units\n *\n * @example\n * addAmounts(1050, 250); // Returns 1300\n */\nexport function addAmounts(a: number, b: number): number {\n return Math.round(a + b);\n}\n\n/**\n * Safely subtracts two amounts in minor units.\n * Both amounts should already be in minor units (integers).\n *\n * @param a - First amount in minor units\n * @param b - Second amount to subtract in minor units\n * @returns Difference in minor units\n *\n * @example\n * subtractAmounts(1050, 250); // Returns 800\n */\nexport function subtractAmounts(a: number, b: number): number {\n return Math.round(a - b);\n}\n\n/**\n * Safely multiplies an amount by a factor.\n * The amount should be in minor units, the multiplier can be a decimal.\n *\n * @param amount - Amount in minor units\n * @param multiplier - Factor to multiply by (e.g., quantity or percentage as decimal)\n * @returns Product in minor units, rounded to nearest integer\n *\n * @example\n * multiplyAmount(1050, 2); // Returns 2100 (doubling)\n * multiplyAmount(1050, 0.15); // Returns 158 (15% of amount)\n */\nexport function multiplyAmount(amount: number, multiplier: number): number {\n return Math.round(amount * multiplier);\n}\n\n/**\n * Safely divides an amount by a divisor.\n * The amount should be in minor units.\n *\n * @param amount - Amount in minor units\n * @param divisor - Value to divide by\n * @returns Quotient in minor units, rounded to nearest integer\n *\n * @example\n * divideAmount(1050, 2); // Returns 525 (halving)\n * divideAmount(1000, 3); // Returns 333 (rounded)\n */\nexport function divideAmount(amount: number, divisor: number): number {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return Math.round(amount / divisor);\n}\n\n/**\n * Calculates a percentage of an amount.\n *\n * @param amount - Base amount in minor units\n * @param percentage - Percentage as a number (e.g., 15 for 15%, not 0.15)\n * @returns The percentage amount in minor units\n *\n * @example\n * calculatePercentage(10000, 15); // Returns 1500 (15% of 10000)\n * calculatePercentage(1050, 8.25); // Returns 87 (8.25% of 1050, rounded)\n */\nexport function calculatePercentage(amount: number, percentage: number): number {\n return Math.round((amount * percentage) / 100);\n}\n\n/**\n * Converts a string amount (e.g., \"10.50\") to minor units.\n * Useful for parsing user input or legacy string amounts.\n *\n * @param amountString - Amount as a string (e.g., \"10.50\")\n * @param currency - ISO 4217 currency code\n * @returns Amount in minor units, or null if parsing fails\n *\n * @example\n * parseAmountToMinorUnits(\"10.50\", \"USD\"); // Returns 1050\n * parseAmountToMinorUnits(\"invalid\", \"USD\"); // Returns null\n */\nexport function parseAmountToMinorUnits(amountString: string, currency: CurrencyCode): number | null {\n const parsed = parseFloat(amountString);\n if (isNaN(parsed)) {\n return null;\n }\n return toMinorUnits(parsed, currency);\n}\n\n/**\n * Checks if a currency code is supported with known configuration.\n *\n * @param currency - ISO 4217 currency code\n * @returns True if the currency has explicit configuration\n */\nexport function isSupportedCurrency(currency: CurrencyCode): boolean {\n return currency.toUpperCase() in CURRENCY_CONFIG;\n}\n\n/**\n * Validates that a string is a supported {@link CurrencyCode} and returns it.\n * @param value - Raw currency string (e.g. from API or DTO)\n * @returns Valid CurrencyCode\n * @throws Error if value is not a supported CurrencyCode\n */\nexport function parseCurrencyCode(value: string): CurrencyCode {\n if (!value || typeof value !== 'string') {\n throw new Error(`Currency value is missing or invalid`);\n }\n const validCodes = Object.values(CurrencyCode) as string[];\n if (!validCodes.includes(value)) {\n throw new Error(`\"${value}\" is not a supported CurrencyCode. Supported codes: ${validCodes.join(', ')}`);\n }\n return value as CurrencyCode;\n}\n\nexport function parseStripeCurrencyCode(value: string): StripeCurrencyCode {\n if (!value || typeof value !== 'string') {\n throw new Error(`Currency value is missing or invalid`);\n }\n const validCodes = Object.values(StripeCurrencyCode) as string[];\n if (!validCodes.includes(value)) {\n throw new Error(`\"${value}\" is not a supported Stripe CurrencyCode. Supported codes: ${validCodes.join(', ')}`);\n }\n return value as StripeCurrencyCode;\n}\n\n/**\n * Converts minor currency units to major units as a number.\n * Uses the minorUnits count directly instead of looking up by currency code.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param minorUnits - Number of decimal places for the currency (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n * @returns Amount in major units as a number (e.g., 10.50 dollars)\n *\n * @example\n * stringifyMinorUnits(1050, 2); // Returns 10.50\n * stringifyMinorUnits(1000, 0); // Returns 1000\n * stringifyMinorUnits(10500, 3); // Returns 10.5\n */\nexport function stringifyMinorUnits(minorAmount: number, minorUnits: number): number {\n const multiplier = Math.pow(10, minorUnits);\n return minorAmount / multiplier;\n}\n\n/**\n * Converts minor currency units to a plain decimal string without symbol or grouping.\n * Useful for APIs like WooCommerce that expect plain numeric strings.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param minorUnits - Number of decimal places for the currency (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n * @returns Plain decimal string (e.g., '10.50')\n *\n * @example\n * formatMinorUnitsToString(1050, 2); // Returns '10.50'\n * formatMinorUnitsToString(1000, 0); // Returns '1000'\n * formatMinorUnitsToString(10500, 3); // Returns '10.5'\n */\nexport function formatMinorUnitsToString(minorAmount: number, minorUnits: number): string {\n const majorAmount = stringifyMinorUnits(minorAmount, minorUnits);\n return majorAmount.toString();\n}\n\n/**\n * Get the number of minor units for a currency.\n * Used in BuilderHub\n * @param currency - ISO 4217 currency code\n * @returns Number of minor unit digits (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n */\nexport function getMinorUnits(currency: CurrencyCode): number {\n return getCurrencyConfig(currency).minorUnits;\n}\n\n/**\n * Creates an Amount object from user input string.\n * Converts \"31.22\" + \"USD\" → { amount: 3122, currency: \"USD\", minorUnits: 2 }\n * Used in BuilderHub\n * @param value - User input value (string like \"31.22\" or number)\n * @param currency - ISO 4217 currency code from company.settings.currency\n * @returns Amount object or undefined if value is empty/invalid\n */\nexport function createAmount(value: string | number | null | undefined, currency: CurrencyCode): Amount | undefined {\n if (value === null || value === undefined || value === '') {\n return undefined;\n }\n\n const numericValue = typeof value === 'string' ? parseFloat(value) : value;\n\n if (isNaN(numericValue)) {\n return undefined;\n }\n\n const minorUnits = getMinorUnits(currency);\n const multiplier = Math.pow(10, minorUnits);\n\n return {\n amount: Math.round(numericValue * multiplier),\n currency,\n minorUnits,\n };\n}\n\n/**\n * Converts an Amount object to a display string for the UI.\n * { amount: 3122, currency: \"USD\", minorUnits: 2 } → \"31.22\"\n * Used in BuilderHub\n * @param amount - Amount object from API response\n * @returns Formatted string (e.g., \"31.22\") or empty string if undefined\n */\nexport function amountToString(amount: Amount | undefined | null): string {\n if (!amount) {\n return '';\n }\n\n const divisor = Math.pow(10, amount.minorUnits);\n const majorValue = amount.amount / divisor;\n return majorValue.toFixed(amount.minorUnits);\n}\n","import type { MeasurementUnit, MeasurementUnitFamily } from './types';\n\n/**\n * Seeded families and units — constants, not rows.\n *\n * Identified by their UN/CEFACT Rec 20 code, the trade standard providers already speak: an import\n * that says `KGM` needs no lookup table to become a kilogram here. Families have no counterpart in\n * Rec 20 — it lists units, not dimensions — so those carry our own readable code.\n *\n * These used to be ObjectIds from a reserved `00000000…` range, so that seeded and merchant units\n * could share one id space without colliding. A code cannot be mistaken for a 24-character hex\n * string, so the reservation is no longer needed: merchant units keep their own generated ids and\n * the two kinds separate themselves.\n *\n * A merchant may add units *inside* these families (a 500 g pack, a 150 ml glass) — those are rows\n * in `measurement-units`. Nothing downstream inspects which kind an id is.\n *\n * ## Why metric and imperial are separate families\n *\n * Conversion is defined only inside a family, and stock is a whole number of one base. For weight\n * and volume the split is arithmetic, not taste: an ounce is `28.349523125` g, and at any decimal\n * base the numerator stays odd — `1 600 000 = 2⁹ × 5⁵` — so a shared base would force\n * `precision 0` on the ounce forever, and half a pound could never be keyed. For length and area a\n * shared base *is* possible; they are split anyway, so that one rule explains all of them.\n *\n * The cost is deliberate: **there is no kg ↔ lb conversion.** A merchant who receives and sells in\n * pounds never needs one. A merchant who receives in kilograms and sells in pounds does, and that\n * case is not solved here.\n *\n * ## Why some bases are not units\n *\n * `weight-imperial` counts in hundred-thousandths of an ounce; nobody trades in those. The base\n * belongs to the family, not to the list a merchant picks from. For metric families it happens to\n * coincide with a real unit — a gram is both — and that unit stays in the list on its own merit.\n *\n * Those four bases still exist as **rows**, generated below as `BASE_UNITS` and marked\n * `sellable: false`. A stock movement records the unit its quantity is counted in, so without a row\n * an imperial family could move no stock at all — it answered `412` on every attempt, which is how\n * this was found. The flag keeps them out of merchant-facing lists while leaving them resolvable by\n * id, because history must still render months later.\n *\n * ### Why the imperial weight base is a hundred-thousandth and not a thousandth\n *\n * Square — the only provider that carries units at all — offers **five** decimals on\n * `IMPERIAL_POUND`, verified against a live sandbox catalogue. At a thousandth of an ounce the\n * pound is `16_000`, `10^5` does not divide it, and `maxPrecisionFor` caps it at three: importing\n * such an item would have to round silently. Scaled down twice more the pound is `1_600_000`, five\n * decimals hold, and `1.00001 lb` is exactly `1_600_016`.\n *\n * It was changed while the imperial families were still empty — they could hold no stock, so no\n * data meant anything yet. Doing the same later is a migration of every stored quantity.\n *\n * ### Why not simply make the ounce the base — read this before \"simplifying\" it\n *\n * Because `10^precision` must divide `ratioToBase`, and with the ounce at `1` the pound is `16`.\n * Ten does not divide sixteen, so both would be pinned to **precision 0**: no `1.5 oz`, no\n * `1.25 lb`, no half a pound, ever.\n *\n * What makes this a trap rather than an obvious error is that it half-works. Storing in ounces,\n * some inputs land on integers and some do not:\n *\n * ```\n * 1.25 lb = 20.00 oz fine 1.1 lb = 17.60 oz not storable\n * 1.5 lb = 24.00 oz fine 1.01 lb = 16.16 oz not storable\n * ```\n *\n * A scale reading `1.25 lb` would sail through and a scale reading `1.1 lb` would not, so the bug\n * arrives long after the change, on a value nobody tested. The invariant is deliberately about\n * *every* admissible input, not the lucky ones. Scaling the ounce down puts the tens into the\n * pound's ratio: at `16_000` a hundred divides it, two decimals hold, and `1.01 lb` is `16_160`.\n *\n * The number is therefore chosen by the finest input any source can hand us, not by what the\n * declared precisions below need — those would be satisfied by far less. Worth knowing before\n * anyone \"corrects\" it downwards.\n */\n\nexport const SYSTEM_FAMILY_IDS = {\n COUNT: 'count',\n WEIGHT: 'weight-metric',\n WEIGHT_IMPERIAL: 'weight-imperial',\n VOLUME: 'volume-metric',\n VOLUME_IMPERIAL: 'volume-imperial',\n LENGTH: 'length-metric',\n LENGTH_IMPERIAL: 'length-imperial',\n AREA: 'area-metric',\n AREA_IMPERIAL: 'area-imperial',\n} as const;\n\nexport const SYSTEM_UNIT_IDS = {\n EACH: 'EA',\n GRAM: 'GRM',\n KILOGRAM: 'KGM',\n /** 100 g is a hectogram; the merchant-facing name stays \"100 g\". */\n HECTOGRAM: 'HGM',\n MILLILITRE: 'MLT',\n LITRE: 'LTR',\n} as const;\n\n/**\n * A family's base is immutable from the moment the family holds its first stock.\n *\n * Every stored quantity — `inventory.quantity`, a stock movement, an order line's `stockQuantity` —\n * is a whole number of its family's base, and nothing stamps the scale on the row. Change a base\n * and every one of those numbers silently means something else: rescaling `weight-metric` by a\n * thousand would turn a stored `6799` from `6.799 kg` into `0.006799 kg`, with no error anywhere.\n *\n * Changing one is therefore a **migration of every stored quantity in that family**, not an edit to\n * a constant here. The imperial weight base was rescaled ×100 on 2026-08-16 precisely because those\n * four families could hold no stock at the time — they answered `412` on every movement — so there\n * was nothing to reinterpret. That window is closed the day the first product is saved.\n *\n * This is also what keeps the door open to storing decimals instead of integers later: with the\n * base declared here and the rule above held, the switch is one division per row. Break the rule and\n * it stops being mechanical, because no one can tell what a given number was divided by.\n */\nexport const SYSTEM_FAMILIES: readonly MeasurementUnitFamily[] = [\n {\n familyId: SYSTEM_FAMILY_IDS.COUNT,\n companyId: null,\n name: 'Count',\n base: { name: 'Piece', abbreviation: 'ea', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.WEIGHT,\n companyId: null,\n name: 'Weight',\n base: { name: 'Gram', abbreviation: 'g', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL,\n companyId: null,\n name: 'Weight (imperial)',\n base: { name: 'Hundred-thousandth of an ounce', abbreviation: '10⁻⁵ oz', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.VOLUME,\n companyId: null,\n name: 'Volume',\n base: { name: 'Millilitre', abbreviation: 'ml', ratioToBase: 1, precision: 0 },\n },\n {\n // Cubic inches, not fluid ounces: a US gallon is 231 in³ and 128 fl oz, and 231 = 3 × 7 × 11.\n // With an ounce base the board foot lands on 6144000/77 — and lumber is the reason this family\n // exists at all.\n familyId: SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL,\n companyId: null,\n name: 'Volume (imperial)',\n base: { name: '1/128000 cubic inch', abbreviation: 'µin³', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.LENGTH,\n companyId: null,\n name: 'Length',\n base: { name: 'Millimetre', abbreviation: 'mm', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL,\n companyId: null,\n name: 'Length (imperial)',\n base: { name: 'Millionth of an inch', abbreviation: 'µin', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.AREA,\n companyId: null,\n name: 'Area',\n base: { name: 'Square millimetre', abbreviation: 'mm²', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.AREA_IMPERIAL,\n companyId: null,\n name: 'Area (imperial)',\n base: { name: 'Thousandth of a square inch', abbreviation: 'm-sq in', ratioToBase: 1, precision: 0 },\n },\n];\n\n/**\n * Every seeded unit, by family.\n *\n * `precision` here is the sensible default, not the arithmetic ceiling — `maxPrecisionFor` gives\n * that. Where the two differ it is a judgement: `CEN` (a hundred nails) could arithmetically carry\n * two decimals, but a hundred-and-fifty nails is keyed as 150 pieces, not 1.5 hundreds.\n *\n * Four units were looked at and left out rather than bent into shape:\n *\n * - `MGM` milligram — `1/1000` of a gram, not a whole number of base units. Moving the metric\n * weight base to milligrams would multiply every stored gram by a thousand for a unit nobody\n * retails in.\n * - `GRN` grain — an ounce is `437.5` grains, so the ratio is fractional at its source. No base\n * fixes that without costing the ounce its decimals.\n * - `GLI` imperial gallon — a whole number of neither US fluid ounces nor cubic inches. UK liquid\n * measure is a tenth family, not a row in this one.\n * - `CMQ` cubic centimetre — identical to the millilitre. A second name for one quantity, not a\n * second unit.\n */\nconst unit = (\n unitId: string,\n familyId: string,\n name: string,\n abbreviation: string,\n ratioToBase: number,\n precision: number,\n): MeasurementUnit => ({ unitId, companyId: null, familyId, name, abbreviation, ratioToBase, precision });\n\nconst SELLABLE_UNITS: readonly MeasurementUnit[] = [\n // ── Count ────────────────────────────────────────────────────────────────\n unit('EA', SYSTEM_FAMILY_IDS.COUNT, 'Each', 'ea', 1, 0),\n unit('PR', SYSTEM_FAMILY_IDS.COUNT, 'Pair', 'pr', 2, 0),\n unit('DZN', SYSTEM_FAMILY_IDS.COUNT, 'Dozen', 'dz', 12, 0),\n unit('GRO', SYSTEM_FAMILY_IDS.COUNT, 'Gross', 'gro', 144, 0),\n unit('CEN', SYSTEM_FAMILY_IDS.COUNT, 'Hundred', 'C', 100, 0),\n unit('MIL', SYSTEM_FAMILY_IDS.COUNT, 'Thousand', 'M', 1_000, 0),\n\n // ── Weight, metric ───────────────────────────────────────────────────────\n unit('GRM', SYSTEM_FAMILY_IDS.WEIGHT, 'Gram', 'g', 1, 0),\n unit('HGM', SYSTEM_FAMILY_IDS.WEIGHT, '100 g', '100g', 100, 2),\n unit('KGM', SYSTEM_FAMILY_IDS.WEIGHT, 'Kilogram', 'kg', 1_000, 3),\n unit('TNE', SYSTEM_FAMILY_IDS.WEIGHT, 'Tonne', 't', 1_000_000, 3),\n\n // ── Weight, imperial ─────────────────────────────────────────────────────\n unit('ONZ', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Ounce', 'oz', 100_000, 2),\n unit('LBR', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Pound', 'lb', 1_600_000, 2),\n unit('STI', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Stone', 'st', 22_400_000, 2),\n // `(US)` is not decoration: Rec 20 also carries `CWI`, the UK hundredweight, at 112 lb — 12 % more.\n // The code here is the right one; an unqualified \"cwt\" on screen is what would be ambiguous.\n unit('CWA', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Hundredweight (US)', 'cwt (US)', 160_000_000, 2),\n unit('STN', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Ton (short)', 'tn', 3_200_000_000, 3),\n\n // ── Volume, metric ───────────────────────────────────────────────────────\n unit('MLT', SYSTEM_FAMILY_IDS.VOLUME, 'Millilitre', 'ml', 1, 0),\n unit('CLT', SYSTEM_FAMILY_IDS.VOLUME, 'Centilitre', 'cl', 10, 1),\n unit('LTR', SYSTEM_FAMILY_IDS.VOLUME, 'Litre', 'l', 1_000, 3),\n unit('HLT', SYSTEM_FAMILY_IDS.VOLUME, 'Hectolitre', 'hl', 100_000, 3),\n unit('MTQ', SYSTEM_FAMILY_IDS.VOLUME, 'Cubic metre', 'm³', 1_000_000, 3),\n\n // ── Volume, imperial ─────────────────────────────────────────────────────\n unit('OZA', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Fluid ounce', 'fl oz', 231_000, 2),\n unit('PTL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Pint', 'pt', 3_696_000, 2),\n unit('QTL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Quart', 'qt', 7_392_000, 2),\n unit('GLL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Gallon', 'gal', 29_568_000, 3),\n unit('INQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic inch', 'in³', 128_000, 2),\n unit('BFT', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Board foot', 'fbm', 18_432_000, 2),\n unit('FTQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic foot', 'ft³', 221_184_000, 3),\n unit('YDQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic yard', 'yd³', 5_971_968_000, 3),\n\n // ── Length, metric ───────────────────────────────────────────────────────\n unit('MMT', SYSTEM_FAMILY_IDS.LENGTH, 'Millimetre', 'mm', 1, 0),\n unit('CMT', SYSTEM_FAMILY_IDS.LENGTH, 'Centimetre', 'cm', 10, 1),\n unit('MTR', SYSTEM_FAMILY_IDS.LENGTH, 'Metre', 'm', 1_000, 3),\n unit('KMT', SYSTEM_FAMILY_IDS.LENGTH, 'Kilometre', 'km', 1_000_000, 3),\n\n // ── Length, imperial ─────────────────────────────────────────────────────\n // `INH` carries four decimals, not three: an eighth of an inch is 0.125 but a sixteenth is\n // 0.0625, and sixteenths are the everyday fraction on a tape measure. A thirty-second needs five,\n // which is the ceiling; a sixty-fourth has no decimal form at all and is a question about\n // fraction input, not about precision.\n unit('INH', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Inch', 'in', 1_000_000, 4),\n unit('FOT', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Foot', 'ft', 12_000_000, 3),\n unit('LF', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Linear foot', 'lin ft', 12_000_000, 2),\n unit('YRD', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Yard', 'yd', 36_000_000, 3),\n unit('SMI', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Mile', 'mi', 63_360_000_000, 3),\n\n // ── Area, metric ─────────────────────────────────────────────────────────\n unit('MMK', SYSTEM_FAMILY_IDS.AREA, 'Square millimetre', 'mm²', 1, 0),\n unit('CMK', SYSTEM_FAMILY_IDS.AREA, 'Square centimetre', 'cm²', 100, 2),\n unit('MTK', SYSTEM_FAMILY_IDS.AREA, 'Square metre', 'm²', 1_000_000, 3),\n unit('HAR', SYSTEM_FAMILY_IDS.AREA, 'Hectare', 'ha', 10_000_000_000, 3),\n\n // ── Area, imperial ───────────────────────────────────────────────────────\n unit('INK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square inch', 'sq in', 1_000, 2),\n unit('FTK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square foot', 'sq ft', 144_000, 2),\n unit('YDK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square yard', 'sq yd', 1_296_000, 2),\n // A roofing square is exactly 100 square feet — a trade unit with a precise definition, which is\n // why it is a real row and not a label.\n unit('SQR', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square (roofing)', 'sq', 14_400_000, 2),\n unit('ACR', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Acre', 'ac', 6_272_640_000, 2),\n];\n\n/**\n * The unit rows that exist only to give a family's base an identifier.\n *\n * A stock movement records the unit its quantity is counted in, and stock is counted in the family\n * base — so without a row the four imperial families could move no stock at all. Derived rather\n * than typed out, so a base's name can never drift from the family that defines it, and so a\n * family whose base IS a real unit (a gram, a millilitre, a piece) gets no duplicate.\n *\n * `sellable: false` keeps them out of every merchant-facing list. They still resolve by id, which\n * is the whole point: history has to render `−20 000 10⁻⁵ oz` long after the sale.\n */\nconst BASE_UNITS: readonly MeasurementUnit[] = SYSTEM_FAMILIES.filter(\n (family) => !SELLABLE_UNITS.some((u) => u.familyId === family.familyId && u.ratioToBase === 1),\n).map((family) => ({\n unitId: `${family.familyId}-base`,\n companyId: null,\n familyId: family.familyId,\n name: family.base.name,\n abbreviation: family.base.abbreviation,\n ratioToBase: 1,\n precision: 0,\n sellable: false as const,\n}));\n\nexport const SYSTEM_UNITS: readonly MeasurementUnit[] = [...SELLABLE_UNITS, ...BASE_UNITS];\n\n/** A variant with no `unitId` is sold by the piece. This is that unit. */\nexport const DEFAULT_UNIT_ID = SYSTEM_UNIT_IDS.EACH;\n","import type { Measurable, MeasurementBase, MeasurementUnit, MeasurementUnitFamily } from './types';\nimport { SYSTEM_FAMILIES, SYSTEM_UNITS } from './system-units';\n\n/**\n * The arithmetic of units, defined once.\n *\n * Stock is stored as a whole number of the family's **base** unit — grams, millilitres, pieces.\n * Everything a person types or reads is converted at the edge. That is what keeps a stored\n * quantity from ever being a float: `40 - 1.589` drifts, `40000 - 1589` cannot.\n */\n\nconst EPSILON = 1e-9;\n\n/**\n * Is `value` a whole number, allowing for binary dust?\n *\n * The tolerance has to scale with the value. Float error is proportional to magnitude, and a\n * family's base can be huge: a pound is 1 600 000 base units, an acre 6 272 640 000. Measured,\n * `8.03 * 1_600_000` is `12_847_999.999999998` — off by 1.9e-9, which a fixed 1e-9 threshold reads\n * as \"not whole\" and rejects, though the quantity is perfectly legal. Across the 46 seeded units\n * that rejected 4.6% of all admissible quantities, the hectare 11.8% of them.\n *\n * It cannot swallow a real violation: a quantity finer than the unit allows is off by at least\n * `ratioToBase / 10^(precision+1)`, and the divisibility invariant keeps that above the tolerance\n * at every magnitude — `1.5891` kg misses by 0.1 against a tolerance of 1.6e-6.\n */\nexport function isWhole(value: number): boolean {\n return Math.abs(value - Math.round(value)) <= EPSILON * Math.max(1, Math.abs(value));\n}\n\n/** Finest a unit may be. Bounded so a valid quantity is always whole at `10^MAX_PRECISION`. */\nexport const MAX_PRECISION = 5;\n\n/** Seeded units first, then the company's own. One id space, one lookup. */\nexport function resolveUnit(unitId: string, companyUnits: readonly MeasurementUnit[] = []): MeasurementUnit {\n const unit = SYSTEM_UNITS.find((u) => u.unitId === unitId) ?? companyUnits.find((u) => u.unitId === unitId);\n if (!unit) throw new Error(`Unknown measurement unit: ${unitId}`);\n return unit;\n}\n\nexport function resolveFamily(\n familyId: string,\n companyFamilies: readonly MeasurementUnitFamily[] = [],\n): MeasurementUnitFamily {\n const family =\n SYSTEM_FAMILIES.find((f) => f.familyId === familyId) ?? companyFamilies.find((f) => f.familyId === familyId);\n if (!family) throw new Error(`Unknown measurement unit family: ${familyId}`);\n return family;\n}\n\n/**\n * What stock in this family is counted in.\n *\n * Used to be found by searching the unit list for `ratioToBase === 1`, which made \"exactly one such\n * unit\" an unwritten rule: at zero the lookup threw, at two it silently took whichever came first.\n * The base now belongs to the family, so there is one by construction and nothing to get wrong.\n *\n * It is also not something anyone sells. A thousandth of an ounce exists so `1.25 lb` has an exact\n * integer form; it has no trade code and no place in a dropdown.\n */\nexport function baseOf(familyId: string, companyFamilies: readonly MeasurementUnitFamily[] = []): MeasurementBase {\n return resolveFamily(familyId, companyFamilies).base;\n}\n\n/** The base of whichever family this unit belongs to. */\nexport function baseFor(\n unit: MeasurementUnit,\n companyFamilies: readonly MeasurementUnitFamily[] = [],\n): MeasurementBase {\n return baseOf(unit.familyId, companyFamilies);\n}\n\n/** Two units convert only inside one family. Every caller that mixes units must check this first. */\nexport function sameFamily(a: MeasurementUnit, b: MeasurementUnit): boolean {\n return a.familyId === b.familyId;\n}\n\n/**\n * Rejects a unit whose `precision` could produce a fraction of a base unit.\n *\n * A quantity with at most `p` decimals is `k / 10 ** p`, so it converts to `k * ratio / 10 ** p`\n * base units. That is whole for every possible input exactly when `10 ** p` divides `ratio`.\n *\n * ```\n * Kilogram ratio 1000, precision 3 → 1000 / 1000 = 1 ok\n * Kilogram ratio 1000, precision 4 → 1000 / 10000 1.5891 kg would be 1589.1 g\n * ```\n *\n * Call this before saving a unit. Every function below assumes it passed.\n */\nexport function assertUnitSane(unit: Measurable): void {\n const { ratioToBase, precision, name } = unit;\n if (!Number.isInteger(ratioToBase) || ratioToBase < 1)\n throw new Error(`Unit \"${name}\": ratioToBase must be a positive integer, got ${ratioToBase}`);\n if (!Number.isInteger(precision) || precision < 0 || precision > MAX_PRECISION)\n throw new Error(`Unit \"${name}\": precision must be an integer 0–${MAX_PRECISION}, got ${precision}`);\n if (ratioToBase % 10 ** precision !== 0)\n throw new Error(\n `Unit \"${name}\": precision ${precision} is finer than a ratio of ${ratioToBase} allows — ` +\n `at most ${maxPrecisionFor(ratioToBase)}. For anything finer the family needs a smaller base unit.`,\n );\n}\n\n/**\n * The finest `precision` a unit with this ratio may declare.\n *\n * Not a policy — a consequence. A quantity with `p` decimals is `k / 10^p`, so it converts to\n * `k * ratio / 10^p` base units, and that is whole for every input exactly when `10^p` divides the\n * ratio. Allowing more would let a sale ask for a fraction of the base unit, which does not exist.\n *\n * ```\n * 1000 (kilogram, base gram) → 3 1.589 kg is 1589 g\n * 500 (500 g pack) → 2 0.05 of a pack is 25 g; 0.005 would be 2.5 g\n * 125 (125 g burger) → 0 there is no half burger\n * 1 (the base unit itself) → 0 nothing left to divide\n * ```\n *\n * Whether to divide at all stays the merchant's call — a bottle sells whole, a weight does not.\n * This only says how far that call may go. A merchant who needs finer does not need a bigger\n * number here; they need a smaller base unit in the family (a slice, a millilitre, a half),\n * which is a decision about the family and should be made once.\n *\n * When a merchant reports \"it won't take 1.1 lb\", the answer is here and not at the till: an\n * imperial pound only carries decimals because its family counts in thousandths of an ounce\n * (`16_000`). Move that base up to the ounce itself and the ratio becomes `16`, this returns `0`,\n * and every fractional weight is rejected — while `1.25 lb` keeps working, because `20 oz` happens\n * to be whole. See the header of `system-units.ts` before changing any family's base.\n */\nexport function maxPrecisionFor(ratioToBase: number): number {\n if (!Number.isInteger(ratioToBase) || ratioToBase < 1)\n throw new Error(`ratioToBase must be a positive integer, got ${ratioToBase}`);\n let precision = 0;\n while (precision < MAX_PRECISION && ratioToBase % 10 ** (precision + 1) === 0) precision++;\n return precision;\n}\n\n/** Does this quantity fit the unit's precision? `1.589` kg yes, `1.5891` kg no. */\nexport function isValidQuantity(quantity: number, unit: Measurable): boolean {\n if (!Number.isFinite(quantity) || quantity < 0) return false;\n return isWhole(quantity * 10 ** unit.precision);\n}\n\n/**\n * A quantity in `unit` → whole base units. `1.589` kg → `1589` g.\n *\n * The `Math.round` removes binary dust (`1.589 * 1000` is `1588.9999999999998`), it does not\n * round the value: `assertUnitSane` guarantees the true product is an integer, and the throw\n * below fires rather than letting a bad unit pass silently.\n */\nexport function toBase(quantity: number, unit: Measurable): number {\n const exact = quantity * unit.ratioToBase;\n const whole = Math.round(exact);\n if (!isWhole(exact))\n throw new Error(\n `${quantity} ${unit.abbreviation} is ${exact} base units — not whole. ` +\n `Check the quantity against precision ${unit.precision}.`,\n );\n return whole;\n}\n\n/** Base units → a quantity in `unit`. `38911` g → `38.911` kg. May be fractional; for display. */\nexport function fromBase(baseQuantity: number, unit: Measurable): number {\n return baseQuantity / unit.ratioToBase;\n}\n\n/**\n * How much of `unit` the pool can still serve, at that unit's own precision — NOT a whole count.\n * `38911` g of a 500 g pack at precision 2 is `77.82` packs, and 0.82 of a pack is sellable when\n * the unit says two decimals are. Only precision 0 makes the result an integer.\n */\nexport function availableIn(baseQuantity: number, unit: Measurable): number {\n const step = unit.ratioToBase / 10 ** unit.precision;\n return Math.floor(baseQuantity / step) / 10 ** unit.precision;\n}\n\n/** `38911` g in kilograms → `\"38.911\"`. Rounding happens here, on the way to a screen, never on write. */\nexport function formatQuantity(baseQuantity: number, unit: Measurable): string {\n return fromBase(baseQuantity, unit).toFixed(unit.precision);\n}\n\n/**\n * Format a quantity that is ALREADY on the unit's own scale — a typed amount, a live preview.\n *\n * `formatQuantity` takes base units and divides; this one does not divide. Use it for the number\n * a person is entering, before it becomes stock.\n */\nexport function formatInUnit(quantity: number, unit: Measurable): string {\n return quantity.toFixed(unit.precision);\n}\n\n/** Snap a typed quantity to what the unit accepts. `1.5891` at precision 3 → `1.589`. */\nexport function roundToPrecision(quantity: number, precision: number): number {\n const scale = 10 ** precision;\n return Math.round(quantity * scale) / scale;\n}\n\n/**\n * Line extension: unit price × quantity → minor currency units, with the PRODUCT rounded half-up\n * exactly once.\n *\n * `priceMinor` is normalised on the way in, not rounded a second time: money is integral\n * everywhere upstream, and `BigInt` refuses a fraction outright — without the coercion a stray\n * `1799.6` would throw a RangeError instead of billing 1800.\n *\n * `4.234` litres at `1800` per litre → `7621`, not `7200`.\n *\n * Money is integral everywhere in the platform, so a line total must never be reached by\n * multiplying two floats. But a measured quantity is not an integer, and the usual fix —\n * coercing it to one before the multiply — silently charges for a different amount than left\n * the shelf. Both directions are wrong: `4.6` rounded up overcharges, `0.456` rounded down\n * charges nothing at all for goods that are gone.\n *\n * The quantity is scaled into an integer, multiplied in `BigInt`, and divided back half-up.\n * Nothing is approximate between the inputs and that single final rounding. Fixed per-unit\n * discounts and fees extend the same way.\n *\n * No unit is needed: `assertUnitSane` caps precision at {@link MAX_PRECISION}, so scaling by\n * `10^MAX_PRECISION` makes *any* valid quantity whole. Which quantities are valid is a\n * different question, answered by `isValidQuantity` where the variant is known — see\n * {@link extendPriceFor} when you hold the unit and want both at once.\n */\nexport function extendPrice(priceMinor: number, quantity: number): number {\n const scale = 10 ** MAX_PRECISION;\n const scaled = BigInt(Math.round(priceMinor)) * BigInt(Math.round(quantity * scale));\n const divisor = BigInt(scale);\n return Number((scaled + divisor / 2n) / divisor);\n}\n\n/** {@link extendPrice}, refusing a quantity the unit could never express. */\nexport function extendPriceFor(priceMinor: number, quantity: number, unit: Measurable): number {\n if (!isValidQuantity(quantity, unit))\n throw new Error(`${quantity} ${unit.abbreviation} has more decimals than precision ${unit.precision} allows.`);\n return extendPrice(priceMinor, quantity);\n}\n","import { extendPrice } from '../units/convert';\n\n/**\n * Order-total anchors, defined once for every consumer.\n *\n * These are the figures the order page, the reports and the receipts must all agree on. Keeping\n * the arithmetic here rather than at each call site is the point: the same number was previously\n * reassembled in three places and drifted between them.\n */\n\n/** Wire money is `string | number` on some surfaces (Mongoose Decimal serialises as a string). */\ntype MoneyInput = number | string | null | undefined;\n\nfunction toMinorUnits(value: MoneyInput): number {\n return Number(value) || 0;\n}\n\n/**\n * **Total Collected** — what actually hit the drawer and the processor for one order.\n *\n * ```\n * totalCollected = order.summary.amountPaid + order.summary.tipTotal\n * ```\n *\n * Both inputs are persisted fields written by the POS from the same `paymentMethods[]` array:\n * `amountPaid` is Σ `paymentMethods[].amount` (base only — every leg, liability tenders included),\n * and `tipTotal` is Σ `paymentMethods[].tip.amount`. Cash rounding needs no term of its own: the\n * writer has already folded it into the cash leg's `amount`.\n *\n * Do not substitute `summary.total` — that field is `base + tip` ignoring cash rounding, so it\n * equals neither this anchor nor `totalBeforeTip`.\n *\n * Note this is not `amountCollected` from the Sales Breakdown report\n * (`summary.payments.cardTotal + cashTotal + customTotal`), which is tips-exclusive and skips the\n * `redeem` bucket. That figure answers \"how much settles\", this one answers \"how much the\n * customer handed over\".\n *\n * @param amountPaid `order.summary.amountPaid`\n * @param tipTotal `order.summary.tipTotal`\n * @returns integer minor units\n */\nexport function getTotalCollected(amountPaid: MoneyInput, tipTotal: MoneyInput): number {\n return toMinorUnits(amountPaid) + toMinorUnits(tipTotal);\n}\n\n/**\n * **What one tender leg took** — its principal plus the tip captured on it.\n *\n * `paymentMethods[].amount` is the base only; the tip lives in `.tip.amount`. Cash rounding needs\n * no term because the writer has already folded it into `amount`, so adding it here would\n * double-count it and break `Σ legs ≡ Total Collected`.\n *\n * @param amount `paymentMethods[].amount`\n * @param tipAmount `paymentMethods[].tip.amount`\n * @returns integer minor units\n */\nexport function getPaymentLegTotal(amount: MoneyInput, tipAmount: MoneyInput): number {\n return toMinorUnits(amount) + toMinorUnits(tipAmount);\n}\n\n/**\n * **What a cash leg was owed** before the till rounded it to the nearest increment.\n *\n * `cashRounding` is a signed delta already inside `amount` (`rounded − owed`), so removing it\n * recovers what the cashier actually had to collect. Reads back as the \"Amount due\" line above\n * the rounding line on a receipt.\n *\n * @param amount `paymentMethods[].amount`\n * @param cashRounding `paymentMethods[].cashRounding`\n * @returns integer minor units\n */\nexport function getCashAmountDue(amount: MoneyInput, cashRounding: MoneyInput): number {\n return toMinorUnits(amount) - toMinorUnits(cashRounding);\n}\n\n/** The writer's settlement block — `summary.payments`. Liability (`redeem`) tenders are excluded. */\nexport interface SettlementBuckets {\n cardTotal?: MoneyInput;\n cashTotal?: MoneyInput;\n customTotal?: MoneyInput;\n}\n\n/**\n * **What actually settles** to the bank.\n *\n * The writer already bucketed the tender legs into `summary.payments` and skipped the `redeem`\n * bucket while doing it — a gift-card redemption discharges an obligation taken on when the card\n * was sold, so no new money arrives and nothing settles. Those buckets hold\n * `paymentMethods[].amount` only, and a tip is charged to the card and reaches the bank with it,\n * so the tips are added back — the same thing hub-api's settlement report does before computing\n * the deposit (`cardsCollected = orderCardTotal + grossTips`).\n *\n * Equals {@link getTotalCollected} on any order without a redemption; the difference between them\n * is exactly what was redeemed.\n *\n * @param payments `order.summary.payments`\n * @param tipTotal `order.summary.tipTotal`\n * @returns integer minor units\n */\nexport function getSettlementTotal(payments: SettlementBuckets | undefined | null, tipTotal: MoneyInput): number {\n return (\n toMinorUnits(payments?.cardTotal) +\n toMinorUnits(payments?.cashTotal) +\n toMinorUnits(payments?.customTotal) +\n toMinorUnits(tipTotal)\n );\n}\n\n/**\n * **A line's subtotal** — unit price × quantity, before discounts, fees and tax.\n *\n * Product lines persist this as `lineItems[].subTotal`, so read the field there. Custom sales do\n * not carry it — `OrderCustomSale` has no such property in the schema, and the stored documents\n * confirm it — but the figure is still the first row of the line's breakdown, and it is the\n * definition of the field rather than a re-derivation of one.\n *\n * @param price line `price` (unit price)\n * @param quantity line `quantity`\n * @returns integer minor units\n */\nexport function getLineSubtotal(price: MoneyInput, quantity: MoneyInput): number {\n // `extendPrice`, not a bare multiply: a variant sold by measure carries a real fraction here, and\n // `1800 * 4.234` is `7621.2` — a float, in a function that promises integer minor units. There is\n // one place in the platform that multiplies a price by a quantity, and this is not a second one.\n return extendPrice(toMinorUnits(price), toMinorUnits(quantity));\n}\n\n/**\n * **The goods portion of a line** — its total with the tax taken back out.\n *\n * A refunded custom sale is shown as goods and tax on separate rows, and the stored `total`\n * carries both. Never render the difference as a \"net\" of a *sale* line: tax is rounded on a\n * table-wide aggregate, so a per-line net plus its tax can land a cent off the gross the customer\n * paid. On a refund line the two rows are the refund's own components and do foot.\n *\n * @param total line `total`\n * @param totalTax line `totalTax`\n * @returns integer minor units\n */\nexport function getGoodsPortion(total: MoneyInput, totalTax: MoneyInput): number {\n return toMinorUnits(total) - toMinorUnits(totalTax);\n}\n","import { PricingRegionEnum } from '../enums';\n\nexport interface CurrencyRate {\n rate: number;\n country: string;\n}\n\nexport const REGION_MAPPING: Record<string, PricingRegionEnum> = {\n // North America\n US: PricingRegionEnum.NORTH_AMERICA,\n CA: PricingRegionEnum.NORTH_AMERICA,\n MX: PricingRegionEnum.NORTH_AMERICA,\n\n // Europe\n AT: PricingRegionEnum.EUROPE,\n BE: PricingRegionEnum.EUROPE,\n BG: PricingRegionEnum.EUROPE,\n CH: PricingRegionEnum.EUROPE,\n CY: PricingRegionEnum.EUROPE,\n CZ: PricingRegionEnum.EUROPE,\n DE: PricingRegionEnum.EUROPE,\n DK: PricingRegionEnum.EUROPE,\n EE: PricingRegionEnum.EUROPE,\n ES: PricingRegionEnum.EUROPE,\n FI: PricingRegionEnum.EUROPE,\n FR: PricingRegionEnum.EUROPE,\n GB: PricingRegionEnum.EUROPE, // Stripe uses 'GB' (not 'UK')\n GR: PricingRegionEnum.EUROPE,\n HR: PricingRegionEnum.EUROPE,\n HU: PricingRegionEnum.EUROPE,\n IE: PricingRegionEnum.EUROPE,\n IT: PricingRegionEnum.EUROPE,\n LI: PricingRegionEnum.EUROPE,\n LT: PricingRegionEnum.EUROPE,\n LU: PricingRegionEnum.EUROPE,\n LV: PricingRegionEnum.EUROPE,\n MT: PricingRegionEnum.EUROPE,\n NL: PricingRegionEnum.EUROPE,\n NO: PricingRegionEnum.EUROPE,\n PL: PricingRegionEnum.EUROPE,\n PT: PricingRegionEnum.EUROPE,\n RO: PricingRegionEnum.EUROPE,\n SE: PricingRegionEnum.EUROPE,\n SI: PricingRegionEnum.EUROPE,\n SK: PricingRegionEnum.EUROPE,\n GI: PricingRegionEnum.EUROPE, // Gibraltar (NEW)\n\n // Others (Asia-Pacific, Middle East, South America, etc.)\n AE: PricingRegionEnum.OTHER, // United Arab Emirates\n AU: PricingRegionEnum.OTHER, // Australia\n BR: PricingRegionEnum.OTHER, // Brazil (NEW)\n HK: PricingRegionEnum.OTHER, // Hong Kong\n IN: PricingRegionEnum.OTHER, // India (NEW)\n JP: PricingRegionEnum.OTHER, // Japan\n MY: PricingRegionEnum.OTHER, // Malaysia\n NZ: PricingRegionEnum.OTHER, // New Zealand\n SG: PricingRegionEnum.OTHER, // Singapore\n TH: PricingRegionEnum.OTHER, // Thailand\n};\n\nexport const STRIPE_SUPPORTED_COUNTRIES = new Set([\n // North America\n 'US',\n 'CA',\n 'MX',\n // Europe\n 'AT',\n 'BE',\n 'BG',\n 'CH',\n 'CY',\n 'CZ',\n 'DE',\n 'DK',\n 'EE',\n 'ES',\n 'FI',\n 'FR',\n 'GB',\n 'GR',\n 'HR',\n 'HU',\n 'IE',\n 'IT',\n 'LI',\n 'LT',\n 'LU',\n 'LV',\n 'MT',\n 'NL',\n 'NO',\n 'PL',\n 'PT',\n 'RO',\n 'SE',\n 'SI',\n 'SK',\n // Others\n 'AE', // United Arab Emirates\n 'AU', // Australia\n 'BR', // Brazil (NEW)\n 'GI', // Gibraltar (NEW)\n 'HK', // Hong Kong\n 'IN', // India (NEW)\n 'JP', // Japan\n 'MY', // Malaysia\n 'NZ', // New Zealand\n 'SG', // Singapore\n 'TH', // Thailand\n]);\nexport const NAFixedRates: Record<string, CurrencyRate> = {\n USD: { rate: 30, country: 'United States' },\n CAD: { rate: 20, country: 'Canada' },\n MXN: { rate: 300, country: 'Mexico' },\n};\nexport const EUFixedRates: Record<string, CurrencyRate> = {\n EUR: { rate: 30, country: 'European Union' },\n GBP: { rate: 20, country: 'Great Britain' },\n CHF: { rate: 30, country: 'Switzerland' },\n DKK: { rate: 180, country: 'Denmark' },\n NOK: { rate: 200, country: 'Norway' },\n SEK: { rate: 180, country: 'Sweden' },\n PLN: { rate: 100, country: 'Poland' },\n};\nexport const OtherFixedRates: Record<string, CurrencyRate> = {\n AUD: { rate: 30, country: 'Australia' },\n NZD: { rate: 30, country: 'New Zealand' },\n SGD: { rate: 50, country: 'Singapore' },\n MYR: { rate: 100, country: 'Malaysia' },\n JPY: { rate: 30, country: 'Japan' },\n};\n\nexport const COUNTRY_CURRENCIES: Record<string, string> = {\n US: 'USD', CA: 'CAD', MX: 'MXN',\n AT: 'EUR', BE: 'EUR', BG: 'BGN', CH: 'CHF', CY: 'EUR', CZ: 'CZK',\n DE: 'EUR', DK: 'DKK', EE: 'EUR', ES: 'EUR', FI: 'EUR', FR: 'EUR',\n GB: 'GBP', GI: 'GIP', GR: 'EUR', HR: 'EUR', HU: 'HUF', IE: 'EUR',\n IT: 'EUR', LI: 'CHF', LT: 'EUR', LU: 'EUR', LV: 'EUR', MT: 'EUR',\n NL: 'EUR', NO: 'NOK', PL: 'PLN', PT: 'EUR', RO: 'RON', SE: 'SEK',\n SI: 'EUR', SK: 'EUR',\n AE: 'AED', AU: 'AUD', BR: 'BRL', HK: 'HKD', IN: 'INR', JP: 'JPY',\n MY: 'MYR', NZ: 'NZD', SG: 'SGD', TH: 'THB',\n};","import { PricingRegionEnum } from '../enums';\nimport { REGION_MAPPING, NAFixedRates, EUFixedRates, OtherFixedRates, CurrencyRate } from 'constants/pricing.constants';\n\nexport function getPricingRegionFromCountry(countryCode?: string): PricingRegionEnum {\n const code = (countryCode || '').toUpperCase();\n if (NORTH_AMERICA.has(code)) return PricingRegionEnum.NORTH_AMERICA;\n if (EUROPE.has(code)) return PricingRegionEnum.EUROPE;\n return PricingRegionEnum.OTHER;\n}\n\nexport const NORTH_AMERICA = getCountriesByRegion(PricingRegionEnum.NORTH_AMERICA);\nexport const EUROPE = getCountriesByRegion(PricingRegionEnum.EUROPE);\n\n// TODO_J: Rely on external api to know the exchange rate between USD and the local currency\nexport function convertFixedFeeToLocalCurrency(currency: string, region: PricingRegionEnum): number {\n const currencyCode = currency.toUpperCase();\n let fixedRate: CurrencyRate | undefined;\n\n switch (region) {\n case PricingRegionEnum.NORTH_AMERICA: {\n fixedRate = NAFixedRates[currencyCode];\n break;\n }\n case PricingRegionEnum.EUROPE: {\n fixedRate = EUFixedRates[currencyCode];\n break;\n }\n case PricingRegionEnum.OTHER: {\n fixedRate = OtherFixedRates[currencyCode];\n break;\n }\n }\n return fixedRate?.rate ?? null;\n}\n\nexport function getCountriesByRegion(region: PricingRegionEnum): Set<string> {\n const countries = new Set<string>();\n for (const [country, mappedRegion] of Object.entries(REGION_MAPPING)) {\n if (mappedRegion === region) {\n countries.add(country);\n }\n }\n return countries;\n}\n","import { EndOfSessionReport } from '@/interfaces/Report.interface';\n\n// Paths whose numeric values must be negated when leaving the wire.\n// Backend persists raw positive magnitudes; this is the one place that\n// flips them for display. UI prefix glyphs (\"+ Tips\", \"− Refunds\") are\n// a presentation concern and live in the frontend, not here.\n//\n// Path key uses dot notation. Append `[]` to descend into every array\n// item. Unmatched numeric fields pass through unchanged.\nexport const REPORT_NEGATE_PATHS: ReadonlySet<string> = new Set([\n // Sales summary — reductions to revenue\n 'salesSummary.discounts.netDiscounts',\n 'salesSummary.refundsItems',\n\n // Settlement — money going out of the merchant\n 'settlementBreakdown.cards.refunded',\n 'settlementBreakdown.cards.processingFees',\n 'settlementBreakdown.cash.refunded',\n 'settlementBreakdown.custom[].refunded',\n 'settlementBreakdown.custom[].processingFees',\n\n // Tax breakdown — refunds sub-table renders signed-negative\n 'taxBreakdown.refunds.entries[].taxableSales',\n 'taxBreakdown.refunds.entries[].tax',\n 'taxBreakdown.refunds.total.taxableSales',\n 'taxBreakdown.refunds.total.tax',\n\n // Refunds breakdown — reductions and naturally-signed entries\n 'refundsBreakdown.discountsReversed',\n // 2026 AUG10, cashRoundingRefund is showing as natural sign\n // 'refundsBreakdown.cashRoundingRefund',\n\n // Fees breakdown — refunded magnitudes are money flowing back out\n 'feesBreakdown.productFee.refundedProductFees',\n 'feesBreakdown.cartFee.refundedCartFees',\n\n // Modifiers breakdown — refunded magnitudes are money flowing back out\n 'modifiersBreakdown.refundTotal',\n\n // Discounts breakdown — refunded magnitudes reverse discount reductions\n 'discountsBreakdown.productDiscounts.refundedProductDiscounts',\n 'discountsBreakdown.cartDiscounts.refundedCartDiscounts',\n\n // Staff sales — refunds are money flowing back out\n 'staffSales.staffSales[].refundSales',\n 'staffSales.refundTotal',\n\n // Tips — refunds are money flowing back out\n 'tipsBreakdown.tips[].refundAmount',\n]);\n\nexport function signReportForDisplay(report: EndOfSessionReport): EndOfSessionReport {\n return negateAtPaths(report, '', REPORT_NEGATE_PATHS) as EndOfSessionReport;\n}\n\nfunction negateAtPaths(value: unknown, path: string, paths: ReadonlySet<string>): unknown {\n if (Array.isArray(value)) {\n const next = `${path}[]`;\n return value.map((item) => negateAtPaths(item, next, paths));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n const next = path ? `${path}.${key}` : key;\n out[key] = negateAtPaths(child, next, paths);\n }\n return out;\n }\n if (typeof value === 'number' && paths.has(path)) {\n // Avoid producing negative zero: formatters that branch on `value < 0`\n // miss `-0` (IEEE-754 says `-0 < 0` is false), then render `-0` as\n // `$-0.00` instead of `$0.00`. Normalize zero before negating.\n return value === 0 ? 0 : -value;\n }\n return value;\n}\n","// Mongo-id helpers shared across the POS frontend packages (Render + port-louis).\n\nfunction padHex(value: number, length: number) {\n return value.toString(16).padStart(length, '0');\n}\n\n// Canonical MongoDB ObjectId layout (24 hex = 12 bytes):\n// 4-byte timestamp (seconds) + 5-byte per-process random + 3-byte monotonic counter.\n// `PROCESS_RANDOM` is generated ONCE per session (not per call), and the counter is a\n// real incrementing value seeded randomly — fixing the previous impl where the machine/pid\n// bytes were re-randomized every call and the \"counter\" was effectively random (dead).\n// No external dependency (common stays dependency-light); not crypto-grade, same as before.\nconst PROCESS_RANDOM: string = Array.from({ length: 5 }, () => padHex(Math.floor(Math.random() * 0x100), 2)).join('');\n\nlet objectIdCounter = Math.floor(Math.random() * 0xffffff);\n\nexport function generateMongoID(): string {\n const timestamp = padHex(Math.floor(Date.now() / 1000), 8);\n objectIdCounter = (objectIdCounter + 1) % 0x1000000;\n return timestamp + PROCESS_RANDOM + padHex(objectIdCounter, 6);\n}\n\nexport function getCurrentISODate() {\n const now = new Date(Date.now());\n\n return now.toISOString();\n}\n\n/** Normalize sync / Redux ids (string or `{ $oid }`) to a 24-char hex string when possible. */\nexport function normalizeMongoIdString(value: unknown): string | null {\n if (value == null || value === '') {\n return null;\n }\n if (typeof value === 'string') {\n const t = value.trim();\n return t.length > 0 ? t : null;\n }\n if (typeof value === 'object' && value !== null && '$oid' in value) {\n const oid = (value as { $oid: unknown }).$oid;\n return typeof oid === 'string' && oid.length > 0 ? oid : null;\n }\n return null;\n}\n","import { SYSTEM_FAMILIES } from './system-units';\n\n/**\n * Where a merchant family's code comes from.\n *\n * The code is derived **once**, at creation, from the name and the company: `wine-<companyId>`.\n * After that the merchant renames the family as often as they like and the code does not move —\n * every unit already points at it, and an order line points at a unit whose `ratioToBase` only\n * means anything against its family's base.\n *\n * It is readable in a log and nothing more: **never parse it back**. Pulling `companyId` out of it\n * would freeze the format forever and would lie the first time a row is copied between companies —\n * which already happens, in `cloneCollection`.\n *\n * A code stays taken forever, including by a soft-deleted family, so a family recreated under an\n * old name gets a discriminator: `wine-2-<companyId>`. Freeing the code would retroactively change\n * what old stored numbers mean.\n */\n\n/**\n * Longest the readable part may be. Not arithmetic — the code travels in a URL path\n * (`PATCH /units/families/:code`) and is stored on every unit of the family, and a merchant who\n * types a sentence as a name should not make either of those unwieldy.\n */\nconst MAX_SLUG_LENGTH = 32;\n\n/** What a name slugs to when nothing survives the cleanup. */\nconst FALLBACK_SLUG = 'family';\n\nconst SYSTEM_FAMILY_CODES: ReadonlySet<string> = new Set(SYSTEM_FAMILIES.map((family) => family.familyId));\n\n/**\n * ASCII only, because the code is a URL segment and comparing percent-encoded forms of the same\n * name is a bug waiting to happen. Accents decompose first, so `Bière` still reads as `biere`; a\n * name in a non-Latin script has nothing left afterwards and falls back — the code is decoration,\n * and refusing to create the family over it would be a worse answer than an unreadable code.\n */\nfunction slugify(name: string): string {\n const slug = name\n .normalize('NFKD')\n .replace(/\\p{Diacritic}/gu, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .slice(0, MAX_SLUG_LENGTH)\n .replace(/^-+|-+$/g, '');\n return slug || FALLBACK_SLUG;\n}\n\n/**\n * The code for a new merchant family, free of `takenCodes` and of the seeded codes.\n *\n * Pass every code the company has ever used — deleted families included. The first free candidate\n * wins, so the discriminator counts up only as far as the collisions actually go.\n */\nexport function deriveFamilyCode(name: string, companyId: string, takenCodes: Iterable<string> = []): string {\n if (!companyId) throw new Error(`Cannot derive a family code for \"${name}\" without a companyId.`);\n const taken = new Set(takenCodes);\n const slug = slugify(name);\n for (let attempt = 1; ; attempt++) {\n const code = attempt === 1 ? `${slug}-${companyId}` : `${slug}-${attempt}-${companyId}`;\n if (!taken.has(code) && !isSystemFamilyCode(code)) return code;\n }\n}\n\n/**\n * Would this code shadow a seeded family?\n *\n * `resolveFamily` looks at the seeded list first, so a merchant family carrying a seeded code would\n * be invisible with no error anywhere. The `-<companyId>` suffix makes that unreachable in\n * practice; the check costs a set lookup and does not depend on that argument staying true.\n */\nexport function isSystemFamilyCode(code: string): boolean {\n return SYSTEM_FAMILY_CODES.has(code);\n}\n\n/**\n * The id a merchant unit is known by: `<abbreviation>-<document id>`, e.g. `gl-6a83f19c2b7e…`.\n *\n * Derived once at creation and never again — a variant, an order line and every stock movement\n * point at it, and renaming the unit or changing what it is worth must not move it. The document's\n * own `_id` supplies the uniqueness; the slug is there so a human reading a log or a stored order\n * can tell what they are looking at. **Never parse it back**: the same reasoning as a family code.\n *\n * A seeded unit has no document and no need for this — it carries its Rec 20 code (`KGM`).\n */\nexport function deriveUnitId(abbreviation: string, documentId: string): string {\n if (!documentId) throw new Error(`Cannot derive a unit id for \"${abbreviation}\" without a document id.`);\n return `${slugify(abbreviation)}-${documentId}`;\n}\n","/** Financial lifecycle of an order. */\nexport type PaymentState =\n | 'unpaid'\n | 'payment_pending'\n | 'partially_paid'\n | 'paid'\n | 'partially_refunded'\n | 'refunded'\n | 'voided';\n\n/** Operational lifecycle of an order (goods/services, including returns). */\nexport type FulfillmentState =\n | 'draft'\n | 'pending'\n | 'on_hold'\n | 'in_progress'\n | 'fulfilled'\n | 'partially_fulfilled'\n | 'returned'\n | 'partially_returned'\n | 'cancelled';\n\nexport const PAYMENT_STATES: readonly PaymentState[] = [\n 'unpaid',\n 'payment_pending',\n 'partially_paid',\n 'paid',\n 'partially_refunded',\n 'refunded',\n 'voided',\n] as const;\n\nexport const FULFILLMENT_STATES: readonly FulfillmentState[] = [\n 'draft',\n 'pending',\n 'on_hold',\n 'in_progress',\n 'fulfilled',\n 'partially_fulfilled',\n 'returned',\n 'partially_returned',\n 'cancelled',\n] as const;\n\nexport function isPaymentState(value: string): value is PaymentState {\n return (PAYMENT_STATES as readonly string[]).includes(value);\n}\n\nexport function isFulfillmentState(value: string): value is FulfillmentState {\n return (FULFILLMENT_STATES as readonly string[]).includes(value);\n}\n\n/** Payment × fulfillment pair used by the engine, guards, and `StateConfig.validInitialStates`. */\nexport interface StatePair {\n payment: PaymentState;\n fulfillment: FulfillmentState;\n}\n\n/** Operators for transition conditions (closed set). */\nexport type ConditionOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'in'\n | 'notIn'\n | 'isEmpty'\n | 'isNotEmpty';\n\nexport const CONDITION_OPERATORS: readonly ConditionOperator[] = [\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isEmpty',\n 'isNotEmpty',\n] as const;\n\nexport function isConditionOperator(value: string): value is ConditionOperator {\n return (CONDITION_OPERATORS as readonly string[]).includes(value);\n}\n\n/** Path enforcement mode per axis. */\nexport type PathMode = 'strict' | 'permissive';\n\nexport const PATH_MODES: readonly PathMode[] = [\n 'strict',\n 'permissive',\n] as const;\n","import type { FulfillmentStateDefinition, PaymentStateDefinition } from './interfaces';\nimport type { FulfillmentState, PaymentState } from './types';\n\nexport interface StateSchema {\n readonly paymentStates: readonly PaymentStateDefinition[];\n readonly fulfillmentStates: readonly FulfillmentStateDefinition[];\n}\n\nconst PAYMENT_DEFS: { id: PaymentState; label: string; terminal: boolean }[] = [\n { id: 'unpaid', label: 'Unpaid', terminal: false },\n { id: 'payment_pending', label: 'Payment Pending', terminal: false },\n { id: 'partially_paid', label: 'Partially Paid', terminal: false },\n { id: 'paid', label: 'Paid', terminal: false },\n { id: 'partially_refunded', label: 'Partially Refunded', terminal: false },\n { id: 'refunded', label: 'Refunded', terminal: true },\n { id: 'voided', label: 'Voided', terminal: true },\n];\n\nconst FULFILLMENT_DEFS: { id: FulfillmentState; label: string; terminal: boolean }[] = [\n { id: 'draft', label: 'Draft', terminal: false },\n { id: 'pending', label: 'Pending', terminal: false },\n // 'Parked' is the product term for a held order (OS bug #30) — the atom id\n // stays `on_hold`; only the human label realigns.\n { id: 'on_hold', label: 'Parked', terminal: false },\n { id: 'in_progress', label: 'In Progress', terminal: false },\n { id: 'fulfilled', label: 'Fulfilled', terminal: true },\n { id: 'partially_fulfilled', label: 'Partially Fulfilled', terminal: false },\n { id: 'returned', label: 'Returned', terminal: true },\n { id: 'partially_returned', label: 'Partially Returned', terminal: false },\n { id: 'cancelled', label: 'Cancelled', terminal: true },\n];\n\nexport function basePaymentDefinitions(): PaymentStateDefinition[] {\n return PAYMENT_DEFS.map((d) => ({\n id: d.id,\n label: d.label,\n isBase: true,\n isTerminal: d.terminal,\n }));\n}\n\nexport function baseFulfillmentDefinitions(): FulfillmentStateDefinition[] {\n return FULFILLMENT_DEFS.map((d) => ({\n id: d.id,\n label: d.label,\n isBase: true,\n isTerminal: d.terminal,\n }));\n}\n\nexport const STATE_SCHEMA: Readonly<StateSchema> = Object.freeze({\n paymentStates: Object.freeze(basePaymentDefinitions()),\n fulfillmentStates: Object.freeze(baseFulfillmentDefinitions()),\n});\n","import type { FinancialInvariant } from './interfaces';\nimport type { PaymentState, StatePair } from './types';\n\nconst REFUND_ALLOWED_FULFILLMENT = new Set<string>(['fulfilled', 'returned', 'partially_returned', 'cancelled']);\n\n// Payment states ordered by collection progress. Any move that decreases\n// the index is a regression — money was collected but is being \"un-collected\"\n// without going through a refund flow.\nconst PAYMENT_COLLECTION_ORDER: readonly PaymentState[] = ['unpaid', 'partially_paid', 'paid'];\n\n// Payment states that carry captured money not yet fully returned. Used as a\n// pure pair-level money fact: an order can only reach one of these states by\n// capturing real money, and only leave it through the refund flow (a refund\n// landing carries `refunded`, a void carries `voided`).\nconst UNRETURNED_MONEY_STATES = new Set<PaymentState>(['partially_paid', 'paid', 'partially_refunded']);\n\n// The two canonical fulfillment landings for a fully refunded order:\n// `returned` (was fulfilled) and `cancelled` (never fulfilled).\nconst REFUNDED_FULFILLMENT_LANDINGS = new Set<string>(['returned', 'cancelled']);\n\n/**\n * Layer 1a — hard-coded, non-configurable financial integrity checks.\n * `check` returns true when the requested transition **violates** the invariant.\n */\nexport const FINANCIAL_INVARIANTS: readonly FinancialInvariant[] = [\n {\n id: 'no-leave-refunded',\n description: 'Cannot change payment state after a full refund (no un-refund / reactivation of funds)',\n check: (from: StatePair | null, to: StatePair) => from?.payment === 'refunded' && to.payment !== 'refunded',\n },\n {\n id: 'no-leave-voided',\n description: 'Cannot un-void payment (voided orders stay voided on the payment axis)',\n check: (from: StatePair | null, to: StatePair) => from?.payment === 'voided' && to.payment !== 'voided',\n },\n {\n id: 'no-refund-without-fulfillment',\n description: 'Cannot mark payment as fully refunded unless fulfillment is delivered, returned, or cancelled',\n check: (_from: StatePair | null, to: StatePair) =>\n to.payment === 'refunded' && !REFUND_ALLOWED_FULFILLMENT.has(to.fulfillment),\n },\n {\n id: 'no-partial-refund-in-draft',\n description: 'Cannot partially refund while order is still in draft fulfillment',\n check: (_from: StatePair | null, to: StatePair) =>\n to.payment === 'partially_refunded' && to.fulfillment === 'draft',\n },\n {\n id: 'no-payment-regression',\n description:\n 'Payment cannot regress to a lower collection state without a refund — collected funds must be returned through the refund flow, not by reverting payment state',\n check: (from: StatePair | null, to: StatePair) => {\n if (!from) return false;\n const fromIdx = PAYMENT_COLLECTION_ORDER.indexOf(from.payment);\n const toIdx = PAYMENT_COLLECTION_ORDER.indexOf(to.payment);\n return fromIdx !== -1 && toIdx !== -1 && fromIdx > toIdx;\n },\n },\n {\n id: 'no-cancel-with-unreturned-payments',\n description:\n 'Fulfillment cannot enter cancelled while the payment state carries unreturned captured money (paid / partially_paid / partially_refunded) — return the money first: a full refund of an unfulfilled order lands refunded × cancelled, a void lands voided × cancelled. Scoped to the cancelling MOVE (from.fulfillment !== cancelled) so payment-axis edges evaluated against an already-cancelled fulfillment do not trip it',\n check: (from: StatePair | null, to: StatePair) =>\n from !== null &&\n from.fulfillment !== 'cancelled' &&\n to.fulfillment === 'cancelled' &&\n UNRETURNED_MONEY_STATES.has(to.payment),\n },\n {\n id: 'no-draft-regression-with-captured-payments',\n description:\n 'Fulfillment cannot regress to draft once money has been captured — a money-carrying order is no longer a cart (bug #31: resume lands deposit orders on in_progress for the same reason). New orders and draft-to-draft moves are exempt, so partially_paid × draft remains declarable as an initial state',\n check: (from: StatePair | null, to: StatePair) =>\n from !== null && from.fulfillment !== 'draft' && to.fulfillment === 'draft' && to.payment !== 'unpaid',\n },\n {\n id: 'no-reopen-voided-fulfillment',\n description:\n 'A voided order exists only at cancelled fulfillment: a voided order cannot re-enter fulfillment, and a voided × non-cancelled pair cannot be materialized from nothing (complements no-leave-voided, which only freezes the payment axis). Moves INTO voided from a live payment state are the void flow’s concern, not this rule’s',\n check: (from: StatePair | null, to: StatePair) =>\n (from === null || from.payment === 'voided') && to.payment === 'voided' && to.fulfillment !== 'cancelled',\n },\n {\n id: 'no-reopen-refunded-fulfillment',\n description:\n 'A fully refunded order cannot re-enter fulfillment — it may only relabel between its canonical landings, returned and cancelled (complements no-leave-refunded, which only freezes the payment axis)',\n check: (from: StatePair | null, to: StatePair) =>\n from?.payment === 'refunded' && !REFUNDED_FULFILLMENT_LANDINGS.has(to.fulfillment),\n },\n] as const;\n\n/** Returns IDs of invariants violated by `from` → `to` (empty if none). */\nexport function getFinancialInvariantViolations(from: StatePair | null, to: StatePair): string[] {\n const ids: string[] = [];\n for (const inv of FINANCIAL_INVARIANTS) {\n if (inv.check(from, to)) {\n ids.push(inv.id);\n }\n }\n return ids;\n}\n\nexport function violatesFinancialInvariant(from: StatePair | null, to: StatePair): boolean {\n return getFinancialInvariantViolations(from, to).length > 0;\n}\n","import type { CrossAxisRule } from './interfaces';\n\n/**\n * Default merchant-toggleable cross-axis rules (Layer 1b).\n * Evaluation order and semantics are implemented in Phase 0b (`canTransition`).\n */\nexport const DEFAULT_CROSS_AXIS_RULES: readonly CrossAxisRule[] = [\n {\n id: 'require-payment-before-prep',\n label: 'Require payment before prep',\n description:\n 'When moving fulfillment to in progress, payment must be paid or partially paid',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'in_progress' },\n requires: { axis: 'payment', states: ['paid', 'partially_paid'] },\n },\n {\n id: 'require-fulfillment-or-return-before-full-refund',\n label: 'Require fulfillment or return before full refund',\n description:\n 'When moving payment to refunded, fulfillment must be fulfilled, returned, partially returned, or cancelled',\n enabled: true,\n trigger: { axis: 'payment', to: 'refunded' },\n requires: {\n axis: 'fulfillment',\n states: ['fulfilled', 'returned', 'partially_returned', 'cancelled'],\n },\n },\n {\n id: 'require-return-context-before-partial-refund',\n label: 'Require return path before partial refund',\n description:\n 'When moving payment to partially refunded, fulfillment must reflect a completed or return path',\n enabled: true,\n trigger: { axis: 'payment', to: 'partially_refunded' },\n requires: {\n axis: 'fulfillment',\n states: ['fulfilled', 'partially_returned', 'returned'],\n },\n },\n {\n id: 'block-fulfillment-when-payment-voided',\n label: 'Block fulfillment completion when payment is voided',\n description:\n 'When moving fulfillment to fulfilled, payment must not be voided',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'fulfilled' },\n requires: {\n axis: 'payment',\n states: ['unpaid', 'partially_paid', 'paid', 'partially_refunded', 'refunded'],\n },\n },\n {\n id: 'require-payment-before-fulfillment-complete',\n label: 'Require payment before fulfillment complete',\n description:\n 'When moving fulfillment to fulfilled, payment must be paid or partially paid',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'fulfilled' },\n requires: { axis: 'payment', states: ['paid', 'partially_paid'] },\n },\n];\n","import type { DisplayStateRule, StateConfig, StoredStateConfig } from './interfaces';\nimport type { FulfillmentState, PaymentState } from './types';\nimport { PAYMENT_STATES, FULFILLMENT_STATES } from './types';\nimport { STATE_SCHEMA, basePaymentDefinitions, baseFulfillmentDefinitions } from './state-schema';\n\nconst DEFAULT_EPOCH = new Date(0);\n\nconst PAYMENT_LABELS = new Map<PaymentState, string>(basePaymentDefinitions().map((d) => [d.id, d.label]));\nconst FULFILLMENT_LABELS = new Map<FulfillmentState, string>(baseFulfillmentDefinitions().map((d) => [d.id, d.label]));\n\nconst TERMINAL_PAYMENT_STATES = new Set<PaymentState>(\n basePaymentDefinitions()\n .filter((d) => d.isTerminal)\n .map((d) => d.id),\n);\n\nconst DISPLAY_LABEL_OVERRIDES: Record<string, string> = {\n 'unpaid|draft': 'In Cart',\n 'unpaid|pending': 'Pending Payment',\n 'unpaid|on_hold': 'Parked',\n 'unpaid|cancelled': 'Cancelled',\n 'partially_paid|pending': 'Deposit Received',\n 'partially_paid|on_hold': 'Parked - Deposit Received',\n 'partially_paid|in_progress': 'Partially Paid',\n 'paid|pending': 'Paid - Awaiting Fulfillment',\n 'paid|on_hold': 'Parked - Paid',\n 'paid|fulfilled': 'Completed',\n 'partially_refunded|fulfilled': 'Partially Refunded',\n 'partially_refunded|partially_returned': 'Partially Refunded',\n};\n\n/**\n * Product wording for a terminal payment state, where it differs from the\n * `STATE_SCHEMA` label. A terminal state with no entry here falls back to its\n * schema label, so a newly-added terminal state still gets a single clean label\n * rather than a compound one.\n *\n * `voided` reads \"Cancelled\" rather than \"Voided\" because that is what the one\n * reachable voided pair (`voided|cancelled`) already displayed — see the\n * no-relabel rule below.\n */\nconst TERMINAL_LABEL_OVERRIDES: Partial<Record<PaymentState, string>> = {\n voided: 'Cancelled',\n};\n\n/**\n * Builds one rule per payment × fulfillment pair — all 63, with no gaps.\n *\n * Label precedence is: explicit pair override → terminal payment label →\n * generic `\"<Payment> / <Fulfillment>\"` compound.\n *\n * Terminal payment states (`refunded`, `voided`) resolve by the **money fact\n * alone**: once the money is finally settled the fulfillment axis carries\n * nothing a customer needs, and a compound like \"Refunded / Draft\" reads as a\n * bug. This also matches `mapToLegacyStatus`, where a terminal payment state\n * takes precedence over fulfillment.\n *\n * Terminal rows used to be emitted ONLY where a pair override existed, which\n * left 14 pairs with no rule at all. Those fell through to\n * `deriveDisplayState`'s last-resort branch and printed raw snake_case ids\n * (\"refunded / in_progress\") onto customer-facing surfaces. `validateConfig`\n * had been reporting them as `display_map_missing_combos` all along.\n *\n * NO-RELABEL RULE: every label a reachable pair resolved to before this change\n * still resolves to the same string, so `Order.displayState` — which is\n * persisted at write time by `setOrderState`, not computed on read — needs no\n * backfill. Only previously-unlabelled pairs gained a value. Keep it that way:\n * changing a reachable label here means migrating order documents too.\n */\nfunction buildDefaultDisplayStateMap(): DisplayStateRule[] {\n const rules: DisplayStateRule[] = [];\n for (const p of PAYMENT_STATES) {\n const terminalLabel = TERMINAL_PAYMENT_STATES.has(p)\n ? (TERMINAL_LABEL_OVERRIDES[p] ?? PAYMENT_LABELS.get(p))\n : undefined;\n\n for (const f of FULFILLMENT_STATES) {\n const label =\n DISPLAY_LABEL_OVERRIDES[`${p}|${f}`] ??\n terminalLabel ??\n `${PAYMENT_LABELS.get(p)} / ${FULFILLMENT_LABELS.get(f)}`;\n rules.push({ paymentState: p, fulfillmentState: f, label });\n }\n }\n return rules;\n}\n\nexport const DEFAULT_DISPLAY_STATE_MAP: readonly DisplayStateRule[] = buildDefaultDisplayStateMap();\n\n/**\n * System default state configuration (fallback when no merchant config is synced).\n * Does NOT include paymentStates / fulfillmentStates — those live in STATE_SCHEMA.\n */\nexport const DEFAULT_CONFIG: StoredStateConfig = {\n _id: 'default',\n companyId: 'system',\n version: 1,\n name: 'Default',\n isDefault: true,\n paymentPaths: [],\n fulfillmentPaths: [],\n paymentPathMode: 'permissive',\n fulfillmentPathMode: 'permissive',\n crossAxisRules: [],\n transitionConditions: [],\n validInitialStates: [{ payment: 'unpaid', fulfillment: 'draft' }],\n displayStateMap: [...DEFAULT_DISPLAY_STATE_MAP],\n createdAt: DEFAULT_EPOCH,\n updatedAt: DEFAULT_EPOCH,\n};\n\n/** Merges a StoredStateConfig with STATE_SCHEMA into a full StateConfig. */\nexport function buildResolvedConfig(config: StoredStateConfig): StateConfig {\n return {\n ...config,\n paymentStates: STATE_SCHEMA.paymentStates,\n fulfillmentStates: STATE_SCHEMA.fulfillmentStates,\n };\n}\n\n/** Pre-built default StateConfig for engine fallbacks and tests. */\nexport const DEFAULT_RESOLVED_CONFIG: StateConfig = buildResolvedConfig(DEFAULT_CONFIG);\n","import { DEFAULT_CONFIG, DEFAULT_DISPLAY_STATE_MAP } from './default-config';\nimport type { StoredStateConfig } from './interfaces';\nimport type { StatePair } from './types';\n\n/**\n * POS-specific initial state pairs. Used the first time an order is written\n * to the DB (park, first payment, split payment first leg, gift-card quick\n * sale). A `canTransition` with `from: null` is only allowed when `to` matches\n * one of these pairs.\n *\n * - `partially_paid + in_progress` covers a deposit / first split leg on a\n * brand-new cart — the first payment advances fulfillment off `draft`, so\n * `deriveTargetState(\"pay\")` lands on `partially_paid + in_progress` until\n * a later leg completes the order and flips it to `paid + fulfilled`.\n * - `partially_paid + draft` is kept for POS builds that predate the\n * draft → in_progress writer fix (bug #31) and still emit it.\n *\n * NOTE: this list is documentation + `validateConfig` reachability seeds. It is\n * only enforced at order creation when `enforceValidInitialStates` is set on\n * the config, which the POS preset does not do.\n */\nexport const POS_VALID_INITIAL_STATES: readonly StatePair[] = [\n { payment: 'unpaid', fulfillment: 'draft' },\n { payment: 'unpaid', fulfillment: 'on_hold' },\n { payment: 'unpaid', fulfillment: 'pending' },\n { payment: 'paid', fulfillment: 'fulfilled' },\n { payment: 'partially_paid', fulfillment: 'draft' },\n { payment: 'partially_paid', fulfillment: 'pending' },\n { payment: 'partially_paid', fulfillment: 'in_progress' },\n] as const;\n\n/**\n * Build a POS preset `StoredStateConfig`. This is the baseline config POS\n * clients (Render, Hub-API fallback, tests) use when no merchant-specific\n * config has been synced.\n */\nexport function buildPosPresetConfig(companyId?: string): StoredStateConfig {\n return {\n ...DEFAULT_CONFIG,\n _id: 'pos-preset',\n companyId: companyId ?? DEFAULT_CONFIG.companyId,\n name: 'POS Preset',\n crossAxisRules: [],\n validInitialStates: [...POS_VALID_INITIAL_STATES],\n displayStateMap: [...DEFAULT_DISPLAY_STATE_MAP],\n };\n}\n","import type { OrderContext, OrderLikeForContext, SplitPayment } from './interfaces';\n\nfunction sumNumbers(items: { amount?: number }[] | undefined): number {\n if (!items?.length) return 0;\n let t = 0;\n for (const x of items) {\n const n = x.amount;\n if (typeof n === 'number' && Number.isFinite(n)) t += n;\n }\n return t;\n}\n\nfunction sumRefundQuantities(\n refunds: { quantity?: number }[] | undefined\n): number {\n if (!refunds?.length) return 0;\n let t = 0;\n for (const r of refunds) {\n const q = r.quantity;\n if (typeof q === 'number' && Number.isFinite(q) && q > 0) t += q;\n }\n return t;\n}\n\n/**\n * Builds `OrderContext` for condition evaluation and transition checks.\n */\nexport function buildOrderContext(\n order: OrderLikeForContext | null | undefined,\n extras?: { splitPayment?: SplitPayment }\n): OrderContext {\n const o = order ?? {};\n const total = typeof o.total === 'number' && Number.isFinite(o.total) ? o.total : 0;\n const balance =\n typeof o.balance === 'number' && Number.isFinite(o.balance) ? o.balance : 0;\n const paymentMethods = o.paymentMethods ?? [];\n const refunds = o.refunds ?? o.refund ?? [];\n const lineItems = o.lineItems ?? [];\n\n const totalPaid = sumNumbers(paymentMethods);\n const totalRefunded = sumRefundQuantities(refunds);\n const isFullyPaid = total > 0 ? balance <= 0 : totalPaid > 0 && balance <= 0;\n const hasPartialPayments = totalPaid > 0 && balance > 0;\n\n let itemCount = 0;\n let fulfilledItemCount = 0;\n let returnedItemCount = 0;\n for (const li of lineItems) {\n const q =\n typeof li.quantity === 'number' && Number.isFinite(li.quantity)\n ? Math.max(0, li.quantity)\n : 0;\n itemCount += q;\n const fq =\n typeof li.fulfilledQuantity === 'number' &&\n Number.isFinite(li.fulfilledQuantity)\n ? Math.max(0, li.fulfilledQuantity)\n : 0;\n fulfilledItemCount += Math.min(fq, q);\n const rq =\n typeof li.returnedQuantity === 'number' &&\n Number.isFinite(li.returnedQuantity)\n ? Math.max(0, li.returnedQuantity)\n : 0;\n returnedItemCount += Math.min(rq, q);\n }\n\n const isFullyReturned =\n itemCount > 0 ? returnedItemCount >= itemCount : returnedItemCount > 0;\n const hasPartialReturns = returnedItemCount > 0 && !isFullyReturned;\n\n return {\n order: {\n total,\n balance,\n paymentMethods,\n refunds,\n lineItems,\n },\n computed: {\n balance,\n isFullyPaid,\n hasPartialPayments,\n totalPaid,\n totalRefunded,\n itemCount,\n fulfilledItemCount,\n returnedItemCount,\n isFullyReturned,\n hasPartialReturns,\n },\n splitPayment: extras?.splitPayment,\n };\n}\n","import type { DisplayStateResult, DisplayStateRule, StoredStateConfig } from './interfaces';\nimport { STATE_SCHEMA } from './state-schema';\n\nfunction atomLabel(atom: string, defs: readonly { id: string; label: string }[]): string {\n return defs.find((d) => d.id === atom)?.label ?? atom;\n}\n\nfunction matchesOptional<T extends string>(actual: T, rule?: T | T[]): boolean {\n if (rule === undefined) return true;\n return Array.isArray(rule) ? rule.includes(actual) : rule === actual;\n}\n\n/**\n * Resolves the first matching rule in `config.displayStateMap` (ordered list).\n */\nexport function deriveDisplayState(\n payment: string,\n fulfillment: string,\n config: StoredStateConfig,\n): DisplayStateResult {\n for (const rule of config.displayStateMap) {\n if (matchesOptional(payment, rule.paymentState) && matchesOptional(fulfillment, rule.fulfillmentState)) {\n return { label: rule.label, color: rule.color, icon: rule.icon };\n }\n }\n // No matching rule: humanize from the base STATE_SCHEMA labels rather than\n // echoing raw atom ids. Stored per-company configs snapshot displayStateMap\n // at creation, so configs predating the 63-pair default map fall through\n // here for newer pairs — deployed UIs were showing rows like\n // \"partially_paid / partially_fulfilled\". Schema labels also keep atom\n // relabels (on_hold → \"Parked\") consistent without a config migration.\n // Unknown atoms (not in the schema) keep their raw id.\n return {\n label: `${atomLabel(payment, STATE_SCHEMA.paymentStates)} / ${atomLabel(fulfillment, STATE_SCHEMA.fulfillmentStates)}`,\n };\n}\n\n/** @internal */\nexport function displayRuleMatchesPair(rule: DisplayStateRule, payment: string, fulfillment: string): boolean {\n return matchesOptional(payment, rule.paymentState) && matchesOptional(fulfillment, rule.fulfillmentState);\n}\n","import type {\n Condition,\n FailedCondition,\n OrderContext,\n TransitionConditionSet,\n} from './interfaces';\n\nfunction getByPath(root: unknown, path: string): unknown {\n const parts = path.split('.').filter(Boolean);\n let cur: unknown = root;\n for (const p of parts) {\n if (cur === null || cur === undefined) return undefined;\n if (typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[p];\n }\n return cur;\n}\n\nfunction isEmptyValue(v: unknown): boolean {\n if (v === null || v === undefined) return true;\n if (typeof v === 'string') return v.length === 0;\n if (Array.isArray(v)) return v.length === 0;\n return false;\n}\n\n/**\n * Evaluates a single condition against `OrderContext` (field paths like `order.balance`, `computed.isFullyPaid`).\n */\nexport function evaluateCondition(\n condition: Condition,\n context: OrderContext\n): { ok: boolean; failed?: FailedCondition } {\n const left = getByPath(context, condition.field);\n const op = condition.operator;\n const right = condition.value;\n\n let ok = false;\n switch (op) {\n case 'eq':\n ok = left === right;\n break;\n case 'neq':\n ok = left !== right;\n break;\n case 'gt':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left > right;\n break;\n case 'gte':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left >= right;\n break;\n case 'lt':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left < right;\n break;\n case 'lte':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left <= right;\n break;\n case 'in':\n ok = Array.isArray(right) && right.some((r) => r === left);\n break;\n case 'notIn':\n ok = Array.isArray(right) && !right.some((r) => r === left);\n break;\n case 'isEmpty':\n ok = isEmptyValue(left);\n break;\n case 'isNotEmpty':\n ok = !isEmptyValue(left);\n break;\n default: {\n const _exhaustive: never = op;\n return {\n ok: false,\n failed: {\n field: condition.field,\n operator: condition.operator,\n value: condition.value,\n reason: `Unknown operator: ${_exhaustive as string}`,\n },\n };\n }\n }\n\n if (!ok) {\n return {\n ok: false,\n failed: {\n field: condition.field,\n operator: condition.operator,\n value: condition.value,\n },\n };\n }\n return { ok: true };\n}\n\nfunction groupPasses(\n group: { conditions: Condition[] },\n context: OrderContext\n): { ok: boolean; failed: FailedCondition[] } {\n const failed: FailedCondition[] = [];\n for (const c of group.conditions) {\n const r = evaluateCondition(c, context);\n if (!r.ok && r.failed) failed.push(r.failed);\n }\n return { ok: failed.length === 0, failed };\n}\n\n/** OR of AND groups — true if any group passes. */\nexport function evaluateConditionSet(\n set: TransitionConditionSet | undefined,\n context: OrderContext\n): { ok: boolean; failedConditions: FailedCondition[] } {\n if (!set || set.groups.length === 0) {\n return { ok: true, failedConditions: [] };\n }\n const allFailed: FailedCondition[] = [];\n for (const g of set.groups) {\n const { ok, failed } = groupPasses(g, context);\n if (ok) return { ok: true, failedConditions: [] };\n allFailed.push(...failed);\n }\n return { ok: false, failedConditions: allFailed };\n}\n\nexport function conditionSummary(c: Condition): string {\n return `${c.field} ${c.operator} ${JSON.stringify(c.value)}`;\n}\n","import { conditionSummary, evaluateCondition, evaluateConditionSet } from './condition-eval';\nimport { deriveDisplayState } from './display-state';\nimport { getFinancialInvariantViolations } from './financial-invariants';\nimport type {\n AvailableTransition,\n CrossAxisRule,\n FailedCondition,\n OrderContext,\n StateConfig,\n StoredStateConfig,\n TransitionRequest,\n TransitionResult,\n} from './interfaces';\nimport type { FulfillmentState, PaymentState, StatePair } from './types';\n\nexport type { TransitionRequest } from './interfaces';\n\nfunction pairInInitialList(to: StatePair, config: StoredStateConfig): boolean {\n return config.validInitialStates.some((p) => p.payment === to.payment && p.fulfillment === to.fulfillment);\n}\n\nfunction triggerTargets(rule: CrossAxisRule): string[] {\n const t = rule.trigger.to;\n return Array.isArray(t) ? [...t] : [t];\n}\n\n/**\n * True when this rule applies to the edge `from` → `to` (trigger axis moved onto `trigger.to`).\n */\nexport function crossAxisRuleApplies(rule: CrossAxisRule, from: StatePair | null, to: StatePair): boolean {\n if (!rule.enabled) return false;\n const targets = triggerTargets(rule);\n if (rule.trigger.axis === 'fulfillment') {\n if (!targets.includes(to.fulfillment)) return false;\n if (from !== null && from.fulfillment === to.fulfillment) return false;\n return true;\n }\n if (!targets.includes(to.payment)) return false;\n if (from !== null && from.payment === to.payment) return false;\n return true;\n}\n\nfunction crossAxisSatisfied(rule: CrossAxisRule, to: StatePair): boolean {\n const req = rule.requires;\n if (req.axis === 'payment') {\n return req.states.includes(to.payment);\n }\n return req.states.includes(to.fulfillment);\n}\n\nfunction firstBlockingCrossAxisRule(\n from: StatePair | null,\n to: StatePair,\n config: StoredStateConfig,\n): CrossAxisRule | undefined {\n for (const rule of config.crossAxisRules) {\n if (!crossAxisRuleApplies(rule, from, to)) continue;\n if (!crossAxisSatisfied(rule, to)) return rule;\n }\n return undefined;\n}\n\nfunction findConditionSet(config: StoredStateConfig, id: string | undefined) {\n if (!id) return undefined;\n return config.transitionConditions.find((s) => s.id === id);\n}\n\nfunction pathExists(\n paths: { from: string; to: string; conditionSetId?: string }[],\n fromId: string,\n toId: string,\n): boolean {\n return paths.some((p) => p.from === fromId && p.to === toId);\n}\n\nfunction axisTransitionAllowed(\n mode: 'strict' | 'permissive',\n paths: { from: string; to: string; conditionSetId?: string }[],\n fromId: string,\n toId: string,\n): boolean {\n if (fromId === toId) return true;\n if (mode === 'permissive') return true;\n return pathExists(paths, fromId, toId);\n}\n\nfunction collectPathConditionFailures(\n config: StoredStateConfig,\n from: StatePair | null,\n to: StatePair,\n context: OrderContext,\n): { failed: FailedCondition[] } {\n const failed: FailedCondition[] = [];\n if (from === null) return { failed };\n\n if (from.payment !== to.payment) {\n const p = config.paymentPaths.find((x) => x.from === from.payment && x.to === to.payment);\n const set = findConditionSet(config, p?.conditionSetId);\n const ev = evaluateConditionSet(set, context);\n if (!ev.ok) failed.push(...ev.failedConditions);\n }\n\n if (from.fulfillment !== to.fulfillment) {\n const p = config.fulfillmentPaths.find((x) => x.from === from.fulfillment && x.to === to.fulfillment);\n const set = findConditionSet(config, p?.conditionSetId);\n const ev = evaluateConditionSet(set, context);\n if (!ev.ok) failed.push(...ev.failedConditions);\n }\n\n return { failed };\n}\n\nfunction pathBlocked(config: StoredStateConfig, from: StatePair | null, to: StatePair): boolean {\n if (from === null) return false;\n if (\n from.payment !== to.payment &&\n !axisTransitionAllowed(config.paymentPathMode, config.paymentPaths, from.payment, to.payment)\n ) {\n return true;\n }\n if (\n from.fulfillment !== to.fulfillment &&\n !axisTransitionAllowed(config.fulfillmentPathMode, config.fulfillmentPaths, from.fulfillment, to.fulfillment)\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Three-layer evaluation: financial invariants → cross-axis rules → paths → conditions.\n * Order creation (`from === null`): guards only; paths/conditions skipped. The\n * `validInitialStates` list is enforced only when `config.enforceValidInitialStates`\n * is true (off by default — see the field's doc in `interfaces.ts`).\n */\nexport function canTransition(request: TransitionRequest): TransitionResult {\n const { from, to, config, context } = request;\n\n const fin = getFinancialInvariantViolations(from, to);\n if (fin.length > 0) {\n return {\n allowed: false,\n blockedBy: 'financial_invariant',\n guard: fin[0],\n reason: `Blocked by financial invariant: ${fin[0]}`,\n };\n }\n\n const cross = firstBlockingCrossAxisRule(from, to, config);\n if (cross) {\n return {\n allowed: false,\n blockedBy: 'cross_axis_rule',\n guard: cross.id,\n reason: `Blocked by cross-axis rule: ${cross.label}`,\n };\n }\n\n if (from === null) {\n if (config.enforceValidInitialStates === true && !pairInInitialList(to, config)) {\n return {\n allowed: false,\n blockedBy: 'path',\n reason: 'Target state is not a valid initial state for new orders',\n };\n }\n } else if (pathBlocked(config, from, to)) {\n return {\n allowed: false,\n blockedBy: 'path',\n reason: 'Transition is not allowed by configured path rules',\n };\n }\n\n if (!request.skipConditionEvaluation) {\n const cond = collectPathConditionFailures(config, from, to, context);\n if (cond.failed.length > 0) {\n return {\n allowed: false,\n blockedBy: 'condition',\n reason: 'Transition conditions not satisfied',\n failedConditions: cond.failed,\n };\n }\n }\n\n return { allowed: true };\n}\n\nfunction labelForPayment(id: PaymentState, config: StateConfig): string {\n return config.paymentStates.find((s) => s.id === id)?.label ?? id;\n}\n\nfunction labelForFulfillment(id: FulfillmentState, config: StateConfig): string {\n return config.fulfillmentStates.find((s) => s.id === id)?.label ?? id;\n}\n\nfunction transitionDisplayLabel(to: StatePair, config: StateConfig): string {\n // deriveDisplayState's no-rule fallback is now already humanized from\n // STATE_SCHEMA labels, so its result is always presentable as-is; the old\n // raw-atom-echo detection (`derived !== \"payment / fulfillment\"`) is gone.\n const derived = deriveDisplayState(to.payment, to.fulfillment, config).label;\n if (derived) {\n return derived;\n }\n return `${labelForPayment(to.payment, config)} · ${labelForFulfillment(to.fulfillment, config)}`;\n}\n\nfunction conditionMetLines(\n config: StateConfig,\n from: StatePair,\n to: StatePair,\n context: OrderContext,\n): { met: boolean; description: string }[] {\n const lines: { met: boolean; description: string }[] = [];\n\n const appendForPath = (p: { conditionSetId?: string } | undefined) => {\n const set = findConditionSet(config, p?.conditionSetId);\n if (!set) return;\n for (const g of set.groups) {\n for (const c of g.conditions) {\n const r = evaluateCondition(c, context);\n lines.push({\n met: r.ok,\n description: conditionSummary(c),\n });\n }\n }\n };\n\n if (from.payment !== to.payment) {\n const p = config.paymentPaths.find((x) => x.from === from.payment && x.to === to.payment);\n appendForPath(p);\n }\n if (from.fulfillment !== to.fulfillment) {\n const p = config.fulfillmentPaths.find((x) => x.from === from.fulfillment && x.to === to.fulfillment);\n appendForPath(p);\n }\n\n return lines;\n}\n\n/**\n * All target pairs reachable in one step from `current` that pass `canTransition`.\n *\n * Candidates are FULFILLMENT-AXIS moves only (payment unchanged) — exactly the\n * pairs `applyTransition` can produce. The payment axis moves exclusively\n * through the money operations (pay / refund / void), which derive their own\n * landing pairs from the money actually moved; advertising payment-axis pairs\n * here offered transitions no caller could apply.\n */\nexport function getAvailableTransitions(\n current: StatePair,\n config: StateConfig,\n context: OrderContext,\n): AvailableTransition[] {\n const candidates: StatePair[] = [];\n\n for (const s of config.fulfillmentStates) {\n if (s.id === current.fulfillment) continue;\n candidates.push({ payment: current.payment, fulfillment: s.id });\n }\n\n const out: AvailableTransition[] = [];\n\n for (const to of candidates) {\n const result = canTransition({\n from: current,\n to,\n config,\n context,\n });\n if (!result.allowed) continue;\n\n out.push({\n to,\n displayLabel: transitionDisplayLabel(to, config),\n conditions: conditionMetLines(config, current, to, context),\n });\n }\n\n return out;\n}\n","import { buildOrderContext } from './build-order-context';\nimport { displayRuleMatchesPair } from './display-state';\nimport { canTransition } from './engine';\nimport { getFinancialInvariantViolations } from './financial-invariants';\nimport type {\n ConfigValidationError,\n ConfigValidationResult,\n ConfigValidationWarning,\n Condition,\n StateConfig,\n} from './interfaces';\nimport type { StatePair } from './types';\nimport { CONDITION_OPERATORS, FULFILLMENT_STATES, PAYMENT_STATES } from './types';\n\nfunction paymentStateIds(config: StateConfig): Set<string> {\n return new Set<string>(config.paymentStates.map((s) => s.id));\n}\n\nfunction fulfillmentStateIds(config: StateConfig): Set<string> {\n return new Set<string>(config.fulfillmentStates.map((s) => s.id));\n}\n\nconst VALID_OPERATORS = new Set<string>(CONDITION_OPERATORS);\n\nfunction validateConditionShape(\n c: Condition,\n path: string,\n errors: ConfigValidationError[]\n): void {\n if (!VALID_OPERATORS.has(c.operator)) {\n errors.push({\n code: 'invalid_condition_operator',\n message: `Unknown operator \"${c.operator}\"`,\n path,\n });\n return;\n }\n const needsNumberCompare = ['gt', 'gte', 'lt', 'lte'].includes(c.operator);\n if (needsNumberCompare && typeof c.value !== 'number') {\n errors.push({\n code: 'invalid_condition_value_type',\n message: `Operator \"${c.operator}\" requires a numeric value`,\n path: `${path}.value`,\n });\n }\n if ((c.operator === 'in' || c.operator === 'notIn') && !Array.isArray(c.value)) {\n errors.push({\n code: 'invalid_condition_value_type',\n message: `Operator \"${c.operator}\" requires an array value`,\n path: `${path}.value`,\n });\n }\n}\n\n/** Generous context so reachability probes are not blocked by typical payment conditions. */\nfunction validationContext() {\n return buildOrderContext({\n total: 100,\n balance: 0,\n paymentMethods: [{ amount: 100 }],\n lineItems: [{ quantity: 1, fulfilledQuantity: 1, returnedQuantity: 0 }],\n });\n}\n\nfunction pairKey(p: StatePair): string {\n return `${p.payment}\\0${p.fulfillment}`;\n}\n\n/**\n * Structural + semantic validation for `StateConfig`.\n */\nexport function validateConfig(config: StateConfig): ConfigValidationResult {\n const errors: ConfigValidationError[] = [];\n const warnings: ConfigValidationWarning[] = [];\n\n if (!Number.isFinite(config.version) || config.version < 1) {\n errors.push({\n code: 'invalid_version',\n message: 'version must be a finite number >= 1',\n path: 'version',\n });\n }\n\n if (!config.validInitialStates?.length) {\n errors.push({\n code: 'missing_initial_states',\n message: 'validInitialStates must contain at least one pair',\n path: 'validInitialStates',\n });\n }\n\n const payIds = paymentStateIds(config);\n const fulIds = fulfillmentStateIds(config);\n\n config.validInitialStates?.forEach((pair, i) => {\n if (!payIds.has(pair.payment)) {\n errors.push({\n code: 'initial_unknown_payment',\n message: `validInitialStates[${i}].payment \"${pair.payment}\" is not defined`,\n path: `validInitialStates[${i}].payment`,\n });\n }\n if (!fulIds.has(pair.fulfillment)) {\n errors.push({\n code: 'initial_unknown_fulfillment',\n message: `validInitialStates[${i}].fulfillment \"${pair.fulfillment}\" is not defined`,\n path: `validInitialStates[${i}].fulfillment`,\n });\n }\n });\n\n const conditionSetIds = new Set(config.transitionConditions.map((s) => s.id));\n config.transitionConditions.forEach((set, si) => {\n set.groups.forEach((g, gi) => {\n g.conditions.forEach((c, ci) => {\n validateConditionShape(\n c,\n `transitionConditions[${si}].groups[${gi}].conditions[${ci}]`,\n errors\n );\n });\n });\n });\n\n const pathConditionRef = (\n paths: ReadonlyArray<{ from: string; to: string; conditionSetId?: string }>,\n axis: string\n ) => {\n paths.forEach((p, i) => {\n if (p.conditionSetId && !conditionSetIds.has(p.conditionSetId)) {\n errors.push({\n code: 'unknown_condition_set',\n message: `${axis}Paths[${i}] references unknown conditionSetId \"${p.conditionSetId}\"`,\n path: `${axis}Paths[${i}].conditionSetId`,\n });\n }\n });\n };\n pathConditionRef(config.paymentPaths, 'payment');\n pathConditionRef(config.fulfillmentPaths, 'fulfillment');\n\n config.paymentPaths.forEach((path, i) => {\n if (!payIds.has(path.from) || !payIds.has(path.to)) {\n errors.push({\n code: 'payment_path_unknown_state',\n message: `paymentPaths[${i}] references unknown payment state`,\n path: `paymentPaths[${i}]`,\n });\n return;\n }\n for (const f of config.fulfillmentStates) {\n const from: StatePair = { payment: path.from, fulfillment: f.id };\n const to: StatePair = { payment: path.to, fulfillment: f.id };\n if (getFinancialInvariantViolations(null, from).length > 0) continue;\n const v = getFinancialInvariantViolations(from, to);\n if (v.length > 0) {\n errors.push({\n code: 'payment_path_violates_financial_invariant',\n message: `paymentPaths[${i}] (${path.from}→${path.to}) with fulfillment \"${f.id}\" violates invariant(s): ${v.join(', ')}`,\n path: `paymentPaths[${i}]`,\n });\n }\n }\n });\n\n config.fulfillmentPaths.forEach((path, i) => {\n if (!fulIds.has(path.from) || !fulIds.has(path.to)) {\n errors.push({\n code: 'fulfillment_path_unknown_state',\n message: `fulfillmentPaths[${i}] references unknown fulfillment state`,\n path: `fulfillmentPaths[${i}]`,\n });\n return;\n }\n for (const p of config.paymentStates) {\n const from: StatePair = { payment: p.id, fulfillment: path.from };\n const to: StatePair = { payment: p.id, fulfillment: path.to };\n // Skip pairs that are not valid steady states (e.g. refunded+draft); path checks are for real edges.\n if (getFinancialInvariantViolations(null, from).length > 0) continue;\n const v = getFinancialInvariantViolations(from, to);\n if (v.length > 0) {\n errors.push({\n code: 'fulfillment_path_violates_financial_invariant',\n message: `fulfillmentPaths[${i}] (${path.from}→${path.to}) with payment \"${p.id}\" violates invariant(s): ${v.join(', ')}`,\n path: `fulfillmentPaths[${i}]`,\n });\n }\n }\n });\n\n config.crossAxisRules.forEach((rule, i) => {\n const req = rule.requires;\n if (req.axis === 'payment') {\n for (const id of req.states) {\n if (!payIds.has(id)) {\n errors.push({\n code: 'cross_axis_unknown_payment',\n message: `crossAxisRules[${i}] requires unknown payment state \"${id}\"`,\n path: `crossAxisRules[${i}].requires.states`,\n });\n }\n }\n } else {\n for (const id of req.states) {\n if (!fulIds.has(id)) {\n errors.push({\n code: 'cross_axis_unknown_fulfillment',\n message: `crossAxisRules[${i}] requires unknown fulfillment state \"${id}\"`,\n path: `crossAxisRules[${i}].requires.states`,\n });\n }\n }\n }\n\n const trig = rule.trigger;\n const targets = Array.isArray(trig.to) ? trig.to : [trig.to];\n if (trig.axis === 'payment') {\n for (const id of targets) {\n if (!payIds.has(id)) {\n errors.push({\n code: 'cross_axis_trigger_unknown_payment',\n message: `crossAxisRules[${i}] triggers on unknown payment state \"${id}\"`,\n path: `crossAxisRules[${i}].trigger.to`,\n });\n }\n }\n } else {\n for (const id of targets) {\n if (!fulIds.has(id)) {\n errors.push({\n code: 'cross_axis_trigger_unknown_fulfillment',\n message: `crossAxisRules[${i}] triggers on unknown fulfillment state \"${id}\"`,\n path: `crossAxisRules[${i}].trigger.to`,\n });\n }\n }\n }\n });\n\n strictAxisReachability(config, 'payment', payIds, warnings);\n strictAxisReachability(config, 'fulfillment', fulIds, warnings);\n\n combinedReachability(config, warnings);\n\n if (!config.displayStateMap.length) {\n warnings.push({\n code: 'empty_display_map',\n message: 'displayStateMap is empty; UI will fall back to raw state pair labels',\n path: 'displayStateMap',\n });\n } else {\n const missingDisplay: string[] = [];\n for (const p of PAYMENT_STATES) {\n for (const f of FULFILLMENT_STATES) {\n if (!payIds.has(p) || !fulIds.has(f)) continue;\n const matched = config.displayStateMap.some((rule) =>\n displayRuleMatchesPair(rule, p, f)\n );\n if (!matched) missingDisplay.push(`${p}/${f}`);\n }\n }\n if (missingDisplay.length > 0) {\n const sample = missingDisplay.slice(0, 8).join(', ');\n const more =\n missingDisplay.length > 8\n ? ` (+${missingDisplay.length - 8} more)`\n : '';\n warnings.push({\n code: 'display_map_missing_combos',\n message: `No displayStateMap rule matches ${missingDisplay.length} base pair(s): ${sample}${more}`,\n path: 'displayStateMap',\n });\n }\n }\n\n refundReturnPathWarnings(config, payIds, fulIds, warnings);\n\n if (config.paymentPathMode === 'strict' && config.paymentPaths.length === 0) {\n errors.push({\n code: 'strict_payment_paths_empty',\n message: 'paymentPathMode is strict but paymentPaths is empty',\n path: 'paymentPaths',\n });\n }\n if (config.fulfillmentPathMode === 'strict' && config.fulfillmentPaths.length === 0) {\n errors.push({\n code: 'strict_fulfillment_paths_empty',\n message: 'fulfillmentPathMode is strict but fulfillmentPaths is empty',\n path: 'fulfillmentPaths',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nfunction strictAxisReachability(\n config: StateConfig,\n axis: 'payment' | 'fulfillment',\n ids: Set<string>,\n warnings: ConfigValidationWarning[]\n): void {\n const mode = axis === 'payment' ? config.paymentPathMode : config.fulfillmentPathMode;\n const paths = axis === 'payment' ? config.paymentPaths : config.fulfillmentPaths;\n if (mode !== 'strict' || paths.length === 0) return;\n\n const reachable = new Set<string>();\n const initials = new Set(\n config.validInitialStates.map((p) => (axis === 'payment' ? p.payment : p.fulfillment))\n );\n for (const id of initials) {\n if (ids.has(id)) bfsAxis(id, paths, reachable);\n }\n\n const stateRows =\n axis === 'payment' ? config.paymentStates : config.fulfillmentStates;\n for (const id of stateRows) {\n if (!reachable.has(id.id)) {\n warnings.push({\n code: `${axis}_state_unreachable_strict`,\n message: `State \"${id.id}\" may be unreachable from valid initial ${axis} states under strict paths`,\n path: axis === 'payment' ? 'paymentPaths' : 'fulfillmentPaths',\n });\n }\n if (!id.isTerminal) {\n const hasOut = paths.some((p) => p.from === id.id && p.to !== id.id);\n if (!hasOut) {\n warnings.push({\n code: `${axis}_nonterminal_no_outbound`,\n message: `Non-terminal ${axis} state \"${id.id}\" has no strict outbound path`,\n path: axis === 'payment' ? 'paymentPaths' : 'fulfillmentPaths',\n });\n }\n }\n }\n}\n\nfunction bfsAxis(\n start: string,\n paths: { from: string; to: string }[],\n reachable: Set<string>\n): void {\n const q = [start];\n reachable.add(start);\n while (q.length) {\n const cur = q.pop()!;\n for (const p of paths) {\n if (p.from !== cur) continue;\n if (!reachable.has(p.to)) {\n reachable.add(p.to);\n q.push(p.to);\n }\n }\n }\n}\n\nfunction combinedReachability(\n config: StateConfig,\n warnings: ConfigValidationWarning[]\n): void {\n const ctx = validationContext();\n const payIds = config.paymentStates.map((s) => s.id);\n const fulIds = config.fulfillmentStates.map((s) => s.id);\n const seen = new Set<string>();\n const queue: StatePair[] = [...config.validInitialStates];\n for (const p of queue) {\n seen.add(pairKey(p));\n }\n while (queue.length) {\n const cur = queue.pop()!;\n for (const np of payIds) {\n if (np === cur.payment) continue;\n const to = { payment: np, fulfillment: cur.fulfillment };\n const r = canTransition({\n from: cur,\n to,\n config,\n context: ctx,\n skipConditionEvaluation: true,\n });\n const k = pairKey(to);\n if (r.allowed && !seen.has(k)) {\n seen.add(k);\n queue.push(to);\n }\n }\n for (const nf of fulIds) {\n if (nf === cur.fulfillment) continue;\n const to = { payment: cur.payment, fulfillment: nf };\n const r = canTransition({\n from: cur,\n to,\n config,\n context: ctx,\n skipConditionEvaluation: true,\n });\n const k = pairKey(to);\n if (r.allowed && !seen.has(k)) {\n seen.add(k);\n queue.push(to);\n }\n }\n }\n\n const total = payIds.length * fulIds.length;\n if (\n seen.size < total &&\n (config.paymentPathMode === 'strict' || config.fulfillmentPathMode === 'strict')\n ) {\n warnings.push({\n code: 'combined_pairs_not_all_reachable',\n message:\n 'Some payment×fulfillment pairs appear unreachable under current paths, cross-axis rules, and financial invariants (structural check with generic context)',\n path: 'validInitialStates',\n });\n }\n}\n\nfunction refundReturnPathWarnings(\n config: StateConfig,\n payIds: Set<string>,\n fulIds: Set<string>,\n warnings: ConfigValidationWarning[]\n): void {\n const hasReturned = config.fulfillmentPaths.some(\n (p) => p.to === 'returned' || p.from === 'returned'\n );\n const hasRefunded = config.paymentPaths.some(\n (p) => p.to === 'refunded' || p.from === 'refunded'\n );\n if (\n fulIds.has('returned') &&\n hasReturned &&\n payIds.has('refunded') &&\n !hasRefunded &&\n config.paymentPathMode === 'strict'\n ) {\n warnings.push({\n code: 'refund_path_missing_for_return',\n message:\n 'Fulfillment paths mention \"returned\" but no strict payment path touches \"refunded\"; verify refund workflow',\n path: 'paymentPaths',\n });\n }\n}\n","import { deriveDisplayState } from './display-state';\nimport type { OrderStateWritable, StoredStateConfig } from './interfaces';\nimport type { FulfillmentState, PaymentState, StatePair } from './types';\n\n/**\n * Maps atoms to legacy `status` for dual-write across the full POS vocabulary:\n * 'in-cart' | 'parked' | 'completed' | 'refunded' | 'partial-refund' | 'park-deleted'.\n *\n * Evaluation order matters: refund and void outcomes are terminal and take precedence\n * over fulfillment, so a `voided` order always maps to `park-deleted` regardless of\n * how the fulfillment axis landed (cancelled, returned, etc.). Same for refund terminals.\n */\nexport function mapToLegacyStatus(pair: StatePair): string {\n const { payment, fulfillment } = pair;\n\n // Terminal void — hard-deleted parked order or voided payment.\n if (payment === 'voided') return 'park-deleted';\n\n // Refund outcomes.\n if (payment === 'refunded') return 'refunded';\n if (payment === 'partially_refunded') return 'partial-refund';\n\n // Fully-paid orders. POS auto-fulfills on payment, so fulfilled/in_progress/pending\n // all collapse to 'completed' for the legacy status consumers (web, analytics, etc.).\n if (payment === 'paid') return 'completed';\n\n // Unpaid / partially-paid orders.\n if (fulfillment === 'draft') return 'in-cart';\n if (fulfillment === 'on_hold') return 'parked';\n if (fulfillment === 'pending') return 'parked';\n if (fulfillment === 'cancelled') return 'park-deleted';\n\n return 'parked';\n}\n\n/**\n * Writes payment/fulfillment atoms, derived display label, and legacy `status` in one place.\n */\nexport function setOrderState(\n order: OrderStateWritable,\n paymentState: PaymentState,\n fulfillmentState: FulfillmentState,\n config: StoredStateConfig,\n options?: { includeLegacyStatus?: boolean },\n): void {\n order.paymentState = paymentState;\n order.fulfillmentState = fulfillmentState;\n const display = deriveDisplayState(paymentState, fulfillmentState, config);\n order.displayState = display.label;\n if (options?.includeLegacyStatus !== false) {\n order.status = mapToLegacyStatus({ payment: paymentState, fulfillment: fulfillmentState });\n }\n}\n","import type { OrderLikeForLegacyInference } from './interfaces';\nimport type { StatePair } from './types';\n\nfunction normalizeStatus(raw: string | undefined): string {\n return (raw ?? '').trim().toLowerCase();\n}\n\nfunction hasRefundActivity(order: OrderLikeForLegacyInference): boolean {\n const refunds = order.refunds ?? order.refund ?? [];\n return refunds.some((r) => {\n const q = r.quantity;\n return typeof q === 'number' && q > 0;\n });\n}\n\n/**\n * Deterministic mapping from legacy `order.status` (and payment/refund hints) to state atoms.\n * See plan §2.5 — conservative refund rows assume return tracking on fulfillment.\n */\nexport function inferStatesFromLegacyStatus(\n order: OrderLikeForLegacyInference\n): StatePair {\n const status = normalizeStatus(order.status);\n\n if (status === 'completed') {\n return { payment: 'paid', fulfillment: 'fulfilled' };\n }\n\n if (status === 'in-cart') {\n return { payment: 'unpaid', fulfillment: 'draft' };\n }\n\n if (status === 'park-deleted') {\n return { payment: 'voided', fulfillment: 'cancelled' };\n }\n\n if (status === 'refunded') {\n return { payment: 'refunded', fulfillment: 'returned' };\n }\n\n if (status === 'partial-refund' || status === 'partial_refund') {\n return { payment: 'partially_refunded', fulfillment: 'partially_returned' };\n }\n\n if (status === 'parked') {\n const ctx = order.paymentMethods ?? [];\n const paid = ctx.reduce((s, m) => {\n const a = m.amount;\n return s + (typeof a === 'number' && Number.isFinite(a) ? a : 0);\n }, 0);\n const partial =\n paid > 0 ||\n (typeof order.balance === 'number' &&\n typeof order.total === 'number' &&\n order.total > 0 &&\n order.balance > 0 &&\n order.balance < order.total);\n return {\n payment: partial ? 'partially_paid' : 'unpaid',\n fulfillment: 'on_hold',\n };\n }\n\n if (status === '' && hasRefundActivity(order)) {\n return { payment: 'partially_refunded', fulfillment: 'partially_returned' };\n }\n\n return { payment: 'unpaid', fulfillment: 'pending' };\n}\n","import { setOrderState } from './set-order-state';\nimport { inferStatesFromLegacyStatus } from './legacy-infer';\nimport type { StoredStateConfig, OrderStateWritable, OrderLikeForLegacyInference } from './interfaces';\nimport type { PaymentState, FulfillmentState } from './types';\n\n/**\n * Minimal order shape that both strategies receive at write boundaries.\n * Extends `OrderStateWritable` with legacy fields used for inference.\n */\nexport interface OrderMutationData extends OrderStateWritable {\n total?: number;\n balance?: number;\n paymentMethods?: { amount?: number; [key: string]: unknown }[];\n refunds?: { quantity?: number; [key: string]: unknown }[];\n refund?: { quantity?: number; [key: string]: unknown }[];\n lineItems?: { quantity?: number; fulfilledQuantity?: number; returnedQuantity?: number; [key: string]: unknown }[];\n}\n\n/**\n * Applies order-state fields before persistence.\n * Two implementations exist during Phase 2: legacy (no-op) and dual-write.\n */\nexport interface OrderWriteStrategy {\n applyState(order: OrderMutationData): void;\n}\n\n/**\n * No-op strategy: callers already manage the legacy `status` field; no new atoms are written.\n */\nexport class LegacyWriteStrategy implements OrderWriteStrategy {\n applyState(_order: OrderMutationData): void {\n // Intentionally empty — legacy path leaves atoms untouched.\n }\n}\n\n/**\n * Dual-write strategy (Phase 2): populates paymentState, fulfillmentState, displayState,\n * and keeps legacy `status` consistent via `setOrderState()`.\n *\n * When atoms are already present on the order (e.g. from an explicit transition),\n * they are passed through `setOrderState` to derive displayState and sync legacy status.\n * Otherwise, atoms are inferred from the existing legacy `status` using the\n * deterministic mapper from `@final-commerce/common`.\n */\nexport class DualWriteStrategy implements OrderWriteStrategy {\n constructor(private readonly config: StoredStateConfig) {}\n\n applyState(order: OrderMutationData): void {\n if (order.paymentState && order.fulfillmentState) {\n setOrderState(order, order.paymentState as PaymentState, order.fulfillmentState as FulfillmentState, this.config);\n return;\n }\n\n if (order.status) {\n const inferred = inferStatesFromLegacyStatus(order as OrderLikeForLegacyInference);\n setOrderState(order, inferred.payment, inferred.fulfillment, this.config);\n }\n }\n}\n","import type { FragmentParam, StateConfigFragment } from './interfaces';\n\nexport interface ResolveTemplateResult {\n fragment: StateConfigFragment;\n resolvedValues: Record<string, unknown>;\n}\n\n/**\n * Resolves a parameterized fragment template into a concrete StateConfigFragment.\n *\n * 1. Merges supplied `values` with param defaults (supplied wins).\n * 2. Validates each resolved value against its param definition.\n * 3. Substitutes `{{key}}` placeholders in the raw template string.\n * 4. Parses the result as JSON into a StateConfigFragment.\n */\nexport function resolveTemplate(\n templateJson: string,\n params: FragmentParam[],\n values: Record<string, unknown> = {},\n): ResolveTemplateResult {\n const resolvedValues: Record<string, unknown> = {};\n\n for (const param of params) {\n const raw = values[param.key] ?? param.default;\n if (raw === undefined || raw === null) {\n throw new Error(`Missing required parameter: \"${param.key}\" (${param.label})`);\n }\n\n validateParamValue(param, raw);\n resolvedValues[param.key] = raw;\n }\n\n let resolved = templateJson;\n for (const [key, value] of Object.entries(resolvedValues)) {\n const placeholder = `{{${key}}}`;\n const replacement =\n typeof value === 'string' ? escapeJsonString(value) : String(value);\n resolved = replaceAll(resolved, placeholder, replacement);\n }\n\n let fragment: StateConfigFragment;\n try {\n fragment = JSON.parse(resolved);\n } catch (err) {\n throw new Error(\n `Fragment template produced invalid JSON after substitution: ${(err as Error).message}`,\n );\n }\n\n return { fragment, resolvedValues };\n}\n\nfunction validateParamValue(param: FragmentParam, value: unknown): void {\n const { key, label, type } = param;\n\n if (type === 'string' && typeof value !== 'string') {\n throw new Error(`Parameter \"${key}\" (${label}) must be a string, got ${typeof value}`);\n }\n if (type === 'number') {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new Error(`Parameter \"${key}\" (${label}) must be a number`);\n }\n if (param.min !== undefined && value < param.min) {\n throw new Error(`Parameter \"${key}\" (${label}) must be >= ${param.min}`);\n }\n if (param.max !== undefined && value > param.max) {\n throw new Error(`Parameter \"${key}\" (${label}) must be <= ${param.max}`);\n }\n }\n if (type === 'boolean' && typeof value !== 'boolean') {\n throw new Error(`Parameter \"${key}\" (${label}) must be a boolean`);\n }\n if (param.options && param.options.length > 0 && !param.options.includes(String(value))) {\n throw new Error(\n `Parameter \"${key}\" (${label}) must be one of: ${param.options.join(', ')}`,\n );\n }\n}\n\n/** Escapes a string for safe embedding inside a JSON-quoted value. */\nfunction escapeJsonString(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\nfunction replaceAll(str: string, search: string, replacement: string): string {\n let result = str;\n let idx = result.indexOf(search);\n while (idx !== -1) {\n result = result.slice(0, idx) + replacement + result.slice(idx + search.length);\n idx = result.indexOf(search, idx + replacement.length);\n }\n return result;\n}\n","import type {\n ConfigValidationError,\n StoredStateConfig,\n StateConfigFragment,\n} from './interfaces';\nimport { isFulfillmentState, isPaymentState } from './types';\n\nexport interface FragmentValidationResult {\n valid: boolean;\n errors: ConfigValidationError[];\n}\n\n/**\n * Validates a StateConfigFragment against an existing StateConfig.\n *\n * Checks:\n * 1. All state references are members of the closed PaymentState / FulfillmentState unions.\n * 2. No duplicate path edges (from, to) on the same axis.\n * 3. No duplicate condition set IDs.\n * 4. No duplicate cross-axis rule IDs.\n */\nexport function validateFragmentCompatibility(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n): FragmentValidationResult {\n const errors: ConfigValidationError[] = [];\n\n validateStateReferences(fragment, errors);\n validatePathUniqueness(config, fragment, errors);\n validateConditionSetUniqueness(config, fragment, errors);\n validateCrossAxisRuleUniqueness(config, fragment, errors);\n\n return { valid: errors.length === 0, errors };\n}\n\nfunction validateStateReferences(\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n for (const path of fragment.paymentPaths ?? []) {\n if (!isPaymentState(path.from)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${path.from}\" in paymentPaths`,\n path: `paymentPaths[from=${path.from}]`,\n });\n }\n if (!isPaymentState(path.to)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${path.to}\" in paymentPaths`,\n path: `paymentPaths[to=${path.to}]`,\n });\n }\n }\n\n for (const path of fragment.fulfillmentPaths ?? []) {\n if (!isFulfillmentState(path.from)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${path.from}\" in fulfillmentPaths`,\n path: `fulfillmentPaths[from=${path.from}]`,\n });\n }\n if (!isFulfillmentState(path.to)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${path.to}\" in fulfillmentPaths`,\n path: `fulfillmentPaths[to=${path.to}]`,\n });\n }\n }\n\n for (const rule of fragment.crossAxisRules ?? []) {\n const triggerStates = Array.isArray(rule.trigger.to) ? rule.trigger.to : [rule.trigger.to];\n const check = rule.trigger.axis === 'payment' ? isPaymentState : isFulfillmentState;\n for (const s of triggerStates) {\n if (!check(s)) {\n errors.push({\n code: `invalid_${rule.trigger.axis}_state`,\n message: `Unknown ${rule.trigger.axis} state \"${s}\" in crossAxisRule \"${rule.id}\" trigger`,\n path: `crossAxisRules[${rule.id}].trigger.to`,\n });\n }\n }\n const reqCheck = rule.requires.axis === 'payment' ? isPaymentState : isFulfillmentState;\n for (const s of rule.requires.states) {\n if (!reqCheck(s)) {\n errors.push({\n code: `invalid_${rule.requires.axis}_state`,\n message: `Unknown ${rule.requires.axis} state \"${s}\" in crossAxisRule \"${rule.id}\" requires`,\n path: `crossAxisRules[${rule.id}].requires.states`,\n });\n }\n }\n }\n\n for (const pair of fragment.validInitialStates ?? []) {\n if (!isPaymentState(pair.payment)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${pair.payment}\" in validInitialStates`,\n path: 'validInitialStates',\n });\n }\n if (!isFulfillmentState(pair.fulfillment)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${pair.fulfillment}\" in validInitialStates`,\n path: 'validInitialStates',\n });\n }\n }\n\n for (const rule of fragment.displayStateMap ?? []) {\n const pStates = rule.paymentState\n ? (Array.isArray(rule.paymentState) ? rule.paymentState : [rule.paymentState])\n : [];\n for (const s of pStates) {\n if (!isPaymentState(s)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${s}\" in displayStateMap rule \"${rule.label}\"`,\n path: 'displayStateMap',\n });\n }\n }\n const fStates = rule.fulfillmentState\n ? (Array.isArray(rule.fulfillmentState) ? rule.fulfillmentState : [rule.fulfillmentState])\n : [];\n for (const s of fStates) {\n if (!isFulfillmentState(s)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${s}\" in displayStateMap rule \"${rule.label}\"`,\n path: 'displayStateMap',\n });\n }\n }\n }\n}\n\nfunction validatePathUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingPaymentEdges = new Set(\n config.paymentPaths.map((p) => `${p.from}->${p.to}`),\n );\n for (const path of fragment.paymentPaths ?? []) {\n const edge = `${path.from}->${path.to}`;\n if (existingPaymentEdges.has(edge)) {\n errors.push({\n code: 'duplicate_payment_path',\n message: `Payment path ${path.from} → ${path.to} already exists in the config`,\n path: `paymentPaths[${edge}]`,\n });\n }\n }\n\n const existingFulfillmentEdges = new Set(\n config.fulfillmentPaths.map((p) => `${p.from}->${p.to}`),\n );\n for (const path of fragment.fulfillmentPaths ?? []) {\n const edge = `${path.from}->${path.to}`;\n if (existingFulfillmentEdges.has(edge)) {\n errors.push({\n code: 'duplicate_fulfillment_path',\n message: `Fulfillment path ${path.from} → ${path.to} already exists in the config`,\n path: `fulfillmentPaths[${edge}]`,\n });\n }\n }\n}\n\nfunction validateConditionSetUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingIds = new Set(config.transitionConditions.map((c) => c.id));\n for (const cond of fragment.transitionConditions ?? []) {\n if (existingIds.has(cond.id)) {\n errors.push({\n code: 'duplicate_condition_set_id',\n message: `Condition set ID \"${cond.id}\" already exists in the config`,\n path: `transitionConditions[${cond.id}]`,\n });\n }\n }\n}\n\nfunction validateCrossAxisRuleUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingIds = new Set(config.crossAxisRules.map((r) => r.id));\n for (const rule of fragment.crossAxisRules ?? []) {\n if (existingIds.has(rule.id)) {\n errors.push({\n code: 'duplicate_cross_axis_rule_id',\n message: `Cross-axis rule ID \"${rule.id}\" already exists in the config`,\n path: `crossAxisRules[${rule.id}]`,\n });\n }\n }\n}\n","import type { DisplayStateRule, StoredStateConfig, StateConfigFragment } from './interfaces';\n\nfunction displayRuleKey(rule: DisplayStateRule): string {\n const p = rule.paymentState;\n const f = rule.fulfillmentState;\n const pKey = p === undefined ? '*' : Array.isArray(p) ? p.slice().sort().join(',') : p;\n const fKey = f === undefined ? '*' : Array.isArray(f) ? f.slice().sort().join(',') : f;\n return `${pKey}|${fKey}`;\n}\n\n/**\n * Merges a resolved StateConfigFragment into an existing StateConfig,\n * tagging every contributed item with `_sourceExtensionId`.\n *\n * Returns a new config object (does not mutate the original).\n */\nexport function mergeFragment(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n extensionId: string,\n): StoredStateConfig {\n const merged: StoredStateConfig = JSON.parse(JSON.stringify(config));\n\n for (const path of fragment.paymentPaths ?? []) {\n merged.paymentPaths.push({ ...path, _sourceExtensionId: extensionId });\n }\n for (const path of fragment.fulfillmentPaths ?? []) {\n merged.fulfillmentPaths.push({ ...path, _sourceExtensionId: extensionId });\n }\n for (const rule of fragment.crossAxisRules ?? []) {\n merged.crossAxisRules.push({ ...rule, _sourceExtensionId: extensionId });\n }\n for (const cond of fragment.transitionConditions ?? []) {\n merged.transitionConditions.push({ ...cond, _sourceExtensionId: extensionId });\n }\n for (const pair of fragment.validInitialStates ?? []) {\n merged.validInitialStates.push(pair);\n }\n\n for (const rule of fragment.displayStateMap ?? []) {\n const tagged = { ...rule, _sourceExtensionId: extensionId };\n const key = displayRuleKey(tagged);\n const existingIdx = merged.displayStateMap.findIndex(\n (r) => displayRuleKey(r) === key,\n );\n if (existingIdx !== -1) {\n merged.displayStateMap[existingIdx] = tagged;\n } else {\n merged.displayStateMap.push(tagged);\n }\n }\n\n return merged;\n}\n","import type { StoredStateConfig } from './interfaces';\n\n/**\n * Removes all items contributed by a specific extension from a StateConfig.\n * Items are identified by their `_sourceExtensionId` tag.\n *\n * Returns a new config object (does not mutate the original).\n */\nexport function removeFragment(\n config: StoredStateConfig,\n extensionId: string,\n): StoredStateConfig {\n const cleaned: StoredStateConfig = JSON.parse(JSON.stringify(config));\n\n cleaned.paymentPaths = cleaned.paymentPaths.filter(\n (p) => p._sourceExtensionId !== extensionId,\n );\n cleaned.fulfillmentPaths = cleaned.fulfillmentPaths.filter(\n (p) => p._sourceExtensionId !== extensionId,\n );\n cleaned.crossAxisRules = cleaned.crossAxisRules.filter(\n (r) => r._sourceExtensionId !== extensionId,\n );\n cleaned.transitionConditions = cleaned.transitionConditions.filter(\n (c) => c._sourceExtensionId !== extensionId,\n );\n cleaned.displayStateMap = cleaned.displayStateMap.filter(\n (d) => d._sourceExtensionId !== extensionId,\n );\n\n return cleaned;\n}\n","/**\n * Command-frame action contract types for the order state machine.\n *\n * These define the param/response shapes and canonical action name strings\n * that extensions and hosts agree on. Command-frame itself stays agnostic —\n * extensions use `commandFrameClient.call<P, R>(ACTION_NAME, params)` with\n * these types, and hosts register handlers under the same string keys.\n */\n\nimport type {\n StateConfig,\n AvailableTransition,\n DisplayStateResult,\n TransitionResult,\n StateConfigFragment,\n} from './interfaces';\nimport type { StatePair } from './types';\n\n// ---------------------------------------------------------------------------\n// Action name constants (shared between extension and host)\n// ---------------------------------------------------------------------------\n\nexport const ORDER_STATE_ACTIONS = {\n getOrderStateConfig: 'getOrderStateConfig',\n getAvailableTransitions: 'getAvailableTransitions',\n getOrderDisplayState: 'getOrderDisplayState',\n transitionOrderState: 'transitionOrderState',\n getStateConfigFragment: 'getStateConfigFragment',\n saveStateConfigFragment: 'saveStateConfigFragment',\n deleteStateConfigFragment: 'deleteStateConfigFragment',\n} as const;\n\n// ---------------------------------------------------------------------------\n// Render (POS) actions\n// ---------------------------------------------------------------------------\n\nexport interface GetOrderStateConfigParams {}\nexport interface GetOrderStateConfigResponse {\n config: StateConfig;\n}\n\nexport interface GetAvailableTransitionsParams {\n /** Look up order by ID from local DB to determine current state. */\n orderId?: string;\n /** Or provide the state pair directly. */\n currentState?: StatePair;\n /** Skip condition evaluation (useful for UI that shows all structural paths). */\n skipConditionEvaluation?: boolean;\n}\nexport interface GetAvailableTransitionsResponse {\n transitions: AvailableTransition[];\n}\n\nexport interface GetOrderDisplayStateParams {\n /** Look up order by ID from local DB to determine current state pair. */\n orderId?: string;\n /** Or provide the state pair directly. */\n statePair?: StatePair;\n}\nexport interface GetOrderDisplayStateResponse {\n display: DisplayStateResult;\n}\n\nexport interface TransitionOrderStateParams {\n orderId: string;\n to: StatePair;\n}\nexport interface TransitionOrderStateResponse {\n success: boolean;\n order: Record<string, unknown>;\n result: TransitionResult;\n}\n\n// ---------------------------------------------------------------------------\n// Manage (Code) actions — state config fragment CRUD\n// ---------------------------------------------------------------------------\n\nexport interface GetStateConfigFragmentParams {\n extensionId: string;\n}\nexport interface GetStateConfigFragmentResponse {\n fragment: StateConfigFragment | null;\n}\n\nexport interface SaveStateConfigFragmentParams {\n extensionId: string;\n fragment: StateConfigFragment;\n}\nexport interface SaveStateConfigFragmentResponse {\n success: boolean;\n validation?: {\n valid: boolean;\n errors: { code: string; message: string; path?: string }[];\n warnings: { code: string; message: string; path?: string }[];\n };\n}\n\nexport interface DeleteStateConfigFragmentParams {\n extensionId: string;\n}\nexport interface DeleteStateConfigFragmentResponse {\n success: boolean;\n}\n","/**\n * Pub/sub event payload types for the order state machine.\n *\n * The host publishes these via command-frame's `topicPublisher` under the\n * \"order-state\" topic. Extensions subscribe by string and cast the payload\n * to the typed event interfaces exported here.\n */\n\nimport type {\n DisplayStateResult,\n TransitionBlockedBy,\n} from './interfaces';\nimport type { StatePair } from './types';\n\nexport const ORDER_STATE_TOPIC = 'order-state' as const;\n\nexport const ORDER_STATE_EVENTS = {\n stateTransitionCompleted: 'state-transition-completed',\n stateTransitionBlocked: 'state-transition-blocked',\n configUpdated: 'config-updated',\n} as const;\n\nexport interface StateTransitionCompletedPayload {\n orderId: string;\n from: StatePair;\n to: StatePair;\n display: DisplayStateResult;\n timestamp: string;\n}\n\nexport interface StateTransitionBlockedPayload {\n orderId: string;\n from: StatePair;\n attemptedTo: StatePair;\n blockedBy: TransitionBlockedBy[];\n timestamp: string;\n}\n\nexport interface ConfigUpdatedPayload {\n companyId: string;\n configId: string;\n version: number;\n timestamp: string;\n}\n\nexport type OrderStateEventPayload =\n | StateTransitionCompletedPayload\n | StateTransitionBlockedPayload\n | ConfigUpdatedPayload;\n","/**\n * Where Adyen has been rolled out to merchants — Canada only for now.\n *\n * A ROLLOUT decision, not a statement about Adyen's availability. Adyen for Platforms onboards in ~30\n * countries; what limits us is per-country backend configuration that must exist before a merchant there\n * can transact — a merchant account, a commission split configuration profile, and terminal supply. CA is\n * the only one provisioned.\n *\n * Shared because both sides need the same answer and must not drift: hub-api ENFORCES it (a 403 on\n * `create-business-account`, the only entry point to the Adyen surface) and deerlake uses it to hide the\n * Adyen menu. The frontend copy is a convenience; the backend one is the boundary.\n *\n * Widen this set as each country's backend configuration lands, and delete it once the rollout is\n * complete — it is scaffolding, not a permanent part of the domain.\n */\nexport const ADYEN_ROLLOUT_COUNTRY_CODES = new Set(['CA']);\n\n/** Whether Adyen has been rolled out to the given ISO 3166-1 alpha-2 country code. */\nexport function isAdyenRolloutCountry(alpha2: string): boolean {\n return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIO,IAAK,eAAL,kBAAKA,kBAAL;AAEL,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AAGN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AAGN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAA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","names":["CurrencyCode","TimePeriod","TopMetericsSort","CompanyType","CustomTableAvailability","AttributeType","Platform","OrderPlatform","CustomerPlatform","StationStatus","InventoryBaseActionEnum","InventorySpecificActionType","ExtensionCategory","FeesCustomBillingStatus","PricingPlanEnum","PricingLevel","PricingRegionEnum","MenuProject","UserTypes","OwnerType","PublicationAvailability","PublicationStatus","ResidualStatus","PreviewImageMode","LibraryItemType","ResidualPaymentMethod","PaymentMethod","NonRevenueItemType","ReceiptSendChannel","ReceiptType","StripeStatus","InvoiceStatus","StripeCurrencyCode","ProductType","ProductStatus","PaymentProcessor","unit","toMinorUnits"]}
1
+ {"version":3,"sources":["../index.ts","../enums/currency.enum.ts","../enums/core.enum.ts","../enums/stripe-currencies.enum.ts","../enums/product.enum.ts","../enums/payments.enum.ts","../enums/booking.enum.ts","../utils/currency.util.ts","../units/system-units.ts","../units/convert.ts","../utils/order-totals.util.ts","../constants/pricing.constants.ts","../utils/pricing.util.ts","../utils/report-sign.util.ts","../utils/mongo.util.ts","../units/family-code.ts","../order-state-machine/types.ts","../order-state-machine/state-schema.ts","../order-state-machine/financial-invariants.ts","../order-state-machine/default-cross-axis-rules.ts","../order-state-machine/default-config.ts","../order-state-machine/pos-preset.ts","../order-state-machine/build-order-context.ts","../order-state-machine/display-state.ts","../order-state-machine/condition-eval.ts","../order-state-machine/engine.ts","../order-state-machine/validate-config.ts","../order-state-machine/set-order-state.ts","../order-state-machine/legacy-infer.ts","../order-state-machine/write-strategy.ts","../order-state-machine/resolve-template.ts","../order-state-machine/validate-fragment.ts","../order-state-machine/merge-fragment.ts","../order-state-machine/remove-fragment.ts","../order-state-machine/actions.ts","../order-state-machine/pubsub.ts","../booking/types.ts","../booking/zoned-time.ts","../booking/grid.ts","../booking/availability.ts","../booking/plan.ts","../constants/adyen.constants.ts"],"sourcesContent":["export * from './utils';\nexport * from './enums';\nexport * from './interfaces';\nexport * from './units';\nexport * from './order-state-machine';\nexport * from './booking';\nexport * from './constants/adyen.constants';\nexport * from './constants/pricing.constants';\n","/**\n * ISO 4217 Currency Code Enum\n * Contains all supported currency codes.\n */\nexport enum CurrencyCode {\n // Major currencies with 2 decimal places\n USD = 'USD',\n EUR = 'EUR',\n GBP = 'GBP',\n CAD = 'CAD',\n AUD = 'AUD',\n NZD = 'NZD',\n CHF = 'CHF',\n CNY = 'CNY',\n INR = 'INR',\n MXN = 'MXN',\n BRL = 'BRL',\n ZAR = 'ZAR',\n SGD = 'SGD',\n HKD = 'HKD',\n SEK = 'SEK',\n NOK = 'NOK',\n DKK = 'DKK',\n PLN = 'PLN',\n THB = 'THB',\n MYR = 'MYR',\n PHP = 'PHP',\n IDR = 'IDR',\n AED = 'AED',\n SAR = 'SAR',\n ILS = 'ILS',\n TRY = 'TRY',\n RUB = 'RUB',\n HTG = 'HTG',\n\n // New Currencies with 2 decimal places\n BND = 'BND', // Brunei Dollar\n CRC = 'CRC', // Costa Rican Colón\n BDT = 'BDT', // Bangladeshi Taka\n UAH = 'UAH', // Ukrainian Hryvnia\n NGN = 'NGN', // Nigerian Naira\n AFN = 'AFN', // Afghan Afghani\n ALL = 'ALL', // Albanian Lek\n AMD = 'AMD', // Armenian Dram\n ANG = 'ANG', // Netherlands Antillean Guilder\n AOA = 'AOA', // Angolan Kwanza\n ARS = 'ARS', // Argentine Peso\n AWG = 'AWG', // Aruban Florin\n AZN = 'AZN', // Azerbaijani Manat\n BAM = 'BAM', // Bosnia and Herzegovina Convertible Mark\n BBD = 'BBD', // Barbadian Dollar\n BGN = 'BGN', // Bulgarian Lev\n BMD = 'BMD', // Bermudian Dollar\n BOB = 'BOB', // Bolivian Boliviano\n BSD = 'BSD', // Bahamian Dollar\n BTN = 'BTN', // Bhutanese Ngultrum\n BWP = 'BWP', // Botswana Pula\n BYN = 'BYN', // Belarusian Ruble\n BZD = 'BZD', // Belize Dollar\n COP = 'COP', // Colombian Peso\n CZK = 'CZK', // Czech Koruna\n DOP = 'DOP', // Dominican Peso\n DZD = 'DZD', // Algerian Dinar\n EGP = 'EGP', // Egyptian Pound\n ETB = 'ETB', // Ethiopian Birr\n FJD = 'FJD', // Fijian Dollar\n GEL = 'GEL', // Georgian Lari\n GHS = 'GHS', // Ghanaian Cedi\n GTQ = 'GTQ', // Guatemalan Quetzal\n GYD = 'GYD', // Guyanese Dollar\n HNL = 'HNL', // Honduran Lempira\n IRR = 'IRR', // Iranian Rial\n JMD = 'JMD', // Jamaican Dollar\n KES = 'KES', // Kenyan Shilling\n KGS = 'KGS', // Kyrgyzstani Som\n KHR = 'KHR', // Cambodian Riel\n KYD = 'KYD', // Cayman Islands Dollar\n KZT = 'KZT', // Kazakhstani Tenge\n LAK = 'LAK', // Lao Kip\n LBP = 'LBP', // Lebanese Pound\n LKR = 'LKR', // Sri Lankan Rupee\n MAD = 'MAD', // Moroccan Dirham\n MDL = 'MDL', // Moldovan Leu\n MKD = 'MKD', // Macedonian Denar\n MMK = 'MMK', // Myanmar Kyat\n MNT = 'MNT', // Mongolian Tögrög\n MOP = 'MOP', // Macanese Pataca\n MUR = 'MUR', // Mauritian Rupee\n MVR = 'MVR', // Maldivian Rufiyaa\n MZN = 'MZN', // Mozambican Metical\n NAD = 'NAD', // Namibian Dollar\n NIO = 'NIO', // Nicaraguan Córdoba\n NPR = 'NPR', // Nepalese Rupee\n PAB = 'PAB', // Panamanian Balboa\n PEN = 'PEN', // Peruvian Sol\n PGK = 'PGK', // Papua New Guinean Kina\n PKR = 'PKR', // Pakistani Rupee\n QAR = 'QAR', // Qatari Riyal\n RON = 'RON', // Romanian Leu\n RSD = 'RSD', // Serbian Dinar\n SBD = 'SBD', // Solomon Islands Dollar\n SRD = 'SRD', // Surinamese Dollar\n SYP = 'SYP', // Syrian Pound\n TJS = 'TJS', // Tajikistani Somoni\n TMT = 'TMT', // Turkmenistani Manat\n TOP = 'TOP', // Tongan Paʻanga\n TTD = 'TTD', // Trinidad and Tobago Dollar\n TZS = 'TZS', // Tanzanian Shilling\n UYU = 'UYU', // Uruguayan Peso\n UZS = 'UZS', // Uzbekistani Som\n VES = 'VES', // Venezuelan Bolívar Soberano\n WST = 'WST', // Samoan Tala\n XCD = 'XCD', // East Caribbean Dollar\n YER = 'YER', // Yemeni Rial\n ZMW = 'ZMW', // Zambian Kwacha\n CDF = 'CDF', // Congolese Franc\n CUP = 'CUP', // Cuban Peso\n ERN = 'ERN', // Eritrean Nakfa\n FKP = 'FKP', // Falkland Islands Pound\n GIP = 'GIP', // Gibraltar Pound\n GMD = 'GMD', // Gambian Dalasi\n KPW = 'KPW', // North Korean Won\n LRD = 'LRD', // Liberian Dollar\n LSL = 'LSL', // Lesotho Loti\n MGA = 'MGA', // Malagasy Ariary\n MWK = 'MWK', // Malawian Kwacha\n SCR = 'SCR', // Seychellois Rupee\n SDG = 'SDG', // Sudanese Pound\n SHP = 'SHP', // Saint Helena Pound\n SLE = 'SLE', // Sierra Leonean Leone\n SOS = 'SOS', // Somali Shilling\n SSP = 'SSP', // South Sudanese Pound\n STN = 'STN', // São Tomé and Príncipe Dobra\n SZL = 'SZL', // Swazi Lilangeni\n VED = 'VED', // Venezuelan Bolívar Digital\n XCG = 'XCG', // Caribbean Guilder\n\n // Zero decimal currencies\n JPY = 'JPY',\n KRW = 'KRW',\n VND = 'VND',\n CLP = 'CLP',\n ISK = 'ISK',\n HUF = 'HUF',\n TWD = 'TWD',\n\n // New Currencies with 0 decimal places\n GNF = 'GNF', // Guinean Franc\n BIF = 'BIF', // Burundian Franc\n DJF = 'DJF', // Djiboutian Franc\n KMF = 'KMF', // Comoro Franc\n PYG = 'PYG', // Paraguayan Guaraní\n RWF = 'RWF', // Rwandan Franc\n UGX = 'UGX', // Ugandan Shilling\n VUV = 'VUV', // Vanuatu Vatu\n XAF = 'XAF', // Central African CFA Franc\n XOF = 'XOF', // West African CFA Franc\n XPF = 'XPF', // CFP Franc\n\n // Three decimal currencies\n KWD = 'KWD',\n BHD = 'BHD',\n OMR = 'OMR',\n JOD = 'JOD',\n TND = 'TND',\n LYD = 'LYD',\n IQD = 'IQD',\n}\n","// Dashboard\nexport enum TimePeriod {\n TODAY = 'today',\n THIS_WEEK = 'this week',\n THIS_MONTH = 'this month',\n THIS_YEAR = 'this year',\n All_TIME = 'all_time',\n}\n\nexport enum TopMetericsSort {\n TOTAL_PAYMENT_VOLUME = 'totalPaymentVolume',\n TOTAL_TRANSACTION = 'totalTransaction',\n}\n\nexport enum CompanyType {\n COMPANY = 'company',\n ROOT = 'root',\n ORGANIZATION = 'organization',\n}\n\nexport enum CustomTableAvailability {\n PUBLIC = 'public',\n ORGANIZATION = 'organization',\n}\n\nexport enum AttributeType {\n STRING = 'string',\n NUMBER = 'number',\n BOOLEAN = 'boolean',\n DATE = 'date',\n JSON_STRING = 'json-string',\n}\n\nexport enum Platform {\n WOO_COMMERCE = 'woo-commerce',\n SHOPIFY = 'shopify',\n OLIVER = 'oliver',\n STANDALONE = 'standalone',\n}\n\nexport enum OrderPlatform {\n POS = 'in-store',\n WOO_COMMERCE = 'woo-commerce',\n PUBLIC_API = 'public-api',\n}\n\nexport enum CustomerPlatform {\n POS = 'in-store',\n WOO_COMMERCE = 'woo-commerce',\n}\n\nexport enum StationStatus {\n IN_USE = 'IN_USE',\n AVAILABLE = 'AVAILABLE',\n}\n\n//Inventory\nexport enum InventoryBaseActionEnum {\n ADD = 'ADD',\n REMOVE = 'REMOVE',\n RECOUNT = 'RECOUNT',\n SKIP = 'SKIP',\n}\nexport type InventoryBaseActionType = `${InventoryBaseActionEnum}`;\n\nexport enum InventorySpecificActionType {\n STOCK_RECEIVED = 'STOCK_RECEIVED',\n INVENTORY_RECOUNT = 'INVENTORY_RECOUNT',\n DAMAGE = 'DAMAGE',\n THEFT = 'THEFT',\n LOSS = 'LOSS',\n RESTOCK_RETURN = 'RESTOCK_RETURN',\n // Only for Refund events\n REFUND_RESTOCK_RETURN = 'REFUND_RESTOCK_RETURN',\n REFUND_DAMAGE = 'REFUND_DAMAGE',\n // Only for Order events @see OrderCreated triger under mongoose trigger\n SALE = 'SALE',\n // Drawing a glass out of the bottle pool is a composition, not a loss. Without its own reason\n // code the bottle report reads as shrinkage every time a glass is poured.\n COMPOSED_FOR_SALE = 'COMPOSED_FOR_SALE',\n // The shelf was emptied because the variant left its unit family. A count in one family cannot\n // be reread in another — 500 g is not 500 ml — so the only honest number is zero. Recording it\n // as a recount would blame a stocktake nobody ran.\n UNIT_FAMILY_CHANGED = 'UNIT_FAMILY_CHANGED',\n // Stock transfer events\n TRANSFER = 'TRANSFER',\n BULK_RECOUNT = 'BULK_RECOUNT',\n // TODO(FI-6965): Move it to separate enum for woo-commerce specific actions\n APPLIED_FROM_WOO = 'APPLIED_FROM_WOO',\n PO_RECEIVED = 'PO_RECEIVED',\n // A stock movement that already happened on a connected provider (e.g. a Shopify sale recorded\n // by the sync lane). Must NEVER be rejected for insufficient stock — it lands even into negative\n // (Sarnia ruling #1: the provider sale is a completed fact; clamping at zero would erase it).\n // NOTE: an EXTERNAL_SALE against a pool-borrowing variant skips the COMPOSED_FOR_SALE relabel\n // at updateStock:2316, which is correct — Sarnia excludes pool-involved variants from mapped\n // cells in v1 (verdict: pooled). If that exclusion lifts, revisit viaVariantId stamping here.\n EXTERNAL_SALE = 'EXTERNAL_SALE',\n // A provider-originated restock (return, receipt, or manual correction from the provider side).\n EXTERNAL_RESTOCK = 'EXTERNAL_RESTOCK',\n}\n\nexport enum ExtensionCategory {\n SYNC = 'sync',\n PAYMENT = 'payment',\n HUB = 'hub',\n BUILDER = 'builder',\n}\n\nexport enum FeesCustomBillingStatus {\n UNPAID = 'unpaid',\n PAID = 'paid',\n OPEN = 'open',\n}\n\nexport enum PricingPlanEnum {\n DEFAULT = 'default',\n MINIMUM = 'minimum',\n ORGANIZATION = 'organization',\n PLAN = 'plan',\n COMPANY = 'company',\n}\n\nexport enum PricingLevel {\n ORG = 'org',\n PLAN = 'plan',\n DEFAULT = 'default',\n MINIMUM = 'minimum',\n}\n\nexport enum PricingRegionEnum {\n EUROPE = 'europe',\n OTHER = 'others',\n NORTH_AMERICA = 'northAmerica',\n}\n\nexport enum MenuProject {\n MANAGE = 'Manage',\n SCALE = 'Scale',\n BUILD = 'Build',\n PAY = 'Pay',\n RUN = 'Run',\n}\n\nexport enum UserTypes {\n COMPANY_OWNER = 'owner',\n ORG_USER = 'organization_user',\n ORG_OWNER = 'organization_owner',\n FINAL_USER = 'final_user',\n FINAL_OWNER = 'final_owner',\n EMPLOYEE = 'employee',\n SUPER_ADMIN = 'super_admin',\n MANAGER = 'manager',\n ADMIN = 'admin',\n ASSISTANT_MANAGER = 'assistant',\n CASHIER = 'cashier',\n RESELLER = 'reseller',\n}\n\nexport enum OwnerType {\n API_KEY = 'api-key',\n ORGANIZATION = 'organization',\n COMPANY = 'company',\n}\n\nexport enum PublicationAvailability {\n GLOBAL = 'global',\n PRIVATE = 'private',\n}\n\nexport enum PublicationStatus {\n APPROVED = 'approved',\n REJECTED = 'rejected',\n PENDING = 'pending',\n NOT_APPLICABLE = 'not_applicable',\n}\n\nexport interface PublicationConfig {\n availability: PublicationAvailability;\n status: PublicationStatus;\n}\n\nexport enum ResidualStatus {\n PAID = 'paid',\n DUE = 'due',\n ACCRUING = 'accruing',\n}\n\nexport enum PreviewImageMode {\n STATIC = 'static',\n DYNAMIC = 'dynamic',\n}\n\nexport enum LibraryItemType {\n FLOW = 'flow',\n PAGE = 'page',\n COMPOSITION = 'composition',\n LAYOUT = 'layout',\n}\n\nexport enum ResidualPaymentMethod {\n CHEQUE = 'cheque',\n}\n\nexport enum PaymentMethod {\n CUSTOM = 'Custom',\n CASH = 'Cash',\n TERMINAL = 'Terminal',\n CLOUD = 'Cloud',\n BLUETOOTH = 'Bluetooth',\n}\n\nexport enum NonRevenueItemType {\n GIFT_CARD = 'gift-card',\n}\n\nexport enum ReceiptSendChannel {\n EMAIL = 'email',\n TEXT = 'text',\n}\n\n// Discriminates a digital receipt as a sale receipt vs a refund receipt.\nexport enum ReceiptType {\n ORDER = 'order',\n REFUND = 'refund',\n}\n\nexport enum StripeStatus {\n ACTIVE = 'active', // When custom payment subscription is active\n INACTIVE = 'inactive', // When custom payment extension is uninstalled\n PAYMENT_METHOD_REQUIRED = 'payment_method_required', // Default status when a new customer is created\n PAYMENT_METHOD_ADDED = 'payment_method_added', // When Payment Method is added to the customer\n}\n\nexport enum InvoiceStatus {\n PAID = 'paid',\n PENDING = 'pending',\n EXPIRED = 'expired',\n}\n","/**\n * ISO 4217 Currency Code Enum\n * Contains all stripe supported currency codes.\n */\nexport enum StripeCurrencyCode {\n // Major currencies with 2 decimal places\n USD = 'USD',\n EUR = 'EUR',\n GBP = 'GBP',\n CAD = 'CAD',\n AUD = 'AUD',\n NZD = 'NZD',\n CHF = 'CHF',\n CNY = 'CNY',\n INR = 'INR',\n MXN = 'MXN',\n BRL = 'BRL',\n ZAR = 'ZAR',\n SGD = 'SGD',\n HKD = 'HKD',\n SEK = 'SEK',\n NOK = 'NOK',\n DKK = 'DKK',\n PLN = 'PLN',\n THB = 'THB',\n MYR = 'MYR',\n PHP = 'PHP',\n IDR = 'IDR',\n AED = 'AED',\n SAR = 'SAR',\n ILS = 'ILS',\n TRY = 'TRY',\n RUB = 'RUB',\n\n // Zero decimal currencies\n JPY = 'JPY',\n KRW = 'KRW',\n VND = 'VND',\n CLP = 'CLP',\n ISK = 'ISK',\n HUF = 'HUF',\n TWD = 'TWD',\n\n // Three decimal currencies\n KWD = 'KWD',\n BHD = 'BHD',\n OMR = 'OMR',\n JOD = 'JOD',\n TND = 'TND',\n LYD = 'LYD',\n IQD = 'IQD',\n}\n","/*\n Current supported Product Types, used in Product Schema & Most Front-End Types \n*/\nexport enum ProductType {\n SIMPLE = 'simple',\n VARIABLE = 'variable',\n BOOKING = 'booking',\n}\n\n/*\n Current supported Product Status, used in Product Schema & Most Front-End Types \n*/\nexport enum ProductStatus {\n ACTIVE = 'active',\n INACTIVE = 'inactive',\n DRAFT = 'draft',\n}\n","// Acquiring processor a company's payments are routed through.\nexport enum PaymentProcessor {\n STRIPE = 'stripe',\n ADYEN = 'adyen',\n /**\n * Payment captured outside FinalPay entirely — set by third parties syncing\n * external order data in. Never written by the POS. Distinguishes \"synced\n * from elsewhere\" from an absent value (legacy FinalPay/Stripe record).\n */\n EXTERNAL = 'external',\n}\n","/*\n Bookable products (productType 'booking'). Naming note: the platform word\n \"unit\" is reserved for measurement units — everything bookable is a \"resource\".\n*/\n\n/* The four archetypes a booking product configures itself as. */\nexport enum BookingType {\n RENTAL = 'rental',\n APPOINTMENT = 'appointment',\n OVERNIGHT = 'overnight',\n GROUP = 'group',\n}\n\n/* What one Variant.price buys. No 'hour' — an hourly rate is a 60-minute slot. */\nexport enum BookingRatePeriod {\n SLOT = 'slot',\n DAY = 'day',\n NIGHT = 'night',\n WEEK = 'week',\n MONTH = 'month',\n}\n\n/* What kind of thing a booking resource is — a label plus UI defaults, not behaviour. */\nexport enum BookingResourceKind {\n ASSET = 'asset',\n ROOM = 'room',\n PROPERTY = 'property',\n SPACE = 'space',\n STAFF = 'staff',\n TABLE = 'table',\n}\n\n/* Lifecycle of one reservation entry on an order. Cancelling keeps the order. */\nexport enum ReservationStatus {\n HELD = 'held',\n CONFIRMED = 'confirmed',\n CANCELLED = 'cancelled',\n /** Holds only: released by the expiry sweep, not by a person. */\n EXPIRED = 'expired',\n}\n\n/** A directory entry is either in service or retired. Deactivating never deletes history. */\nexport enum BookingResourceStatus {\n ACTIVE = 'active',\n INACTIVE = 'inactive',\n}\n\n/**\n * Why a resource cannot be picked in the range asked for — the answer the UI reads out.\n *\n * Named rather than an inline union because a second file already compares against these\n * strings, and two hand-kept lists mean a new state passes silently through the copy.\n */\nexport enum ResourceAvailabilityState {\n AVAILABLE = 'available',\n /** Works these days, and every slot is taken. */\n FULLY_BOOKED = 'fullyBooked',\n /** The range never touches this resource's shift at all. */\n NO_HOURS_IN_RANGE = 'noHoursInRange',\n}\n","import { CurrencyCode } from '@/enums/index';\nimport { StripeCurrencyCode } from '@/enums/stripe-currencies.enum';\nimport { Amount, CurrencyConfig } from '@/interfaces/index';\n\n/**\n * Currency utility functions for handling monetary amounts in minor currency units.\n *\n * All monetary values are stored in the database as integers representing the smallest\n * currency unit (e.g., cents for USD, pence for GBP). This avoids floating-point\n * precision issues and ensures accurate financial calculations.\n *\n * @example\n * // Convert $10.50 to cents for storage\n * const cents = toMinorUnits(10.50, 'USD'); // Returns 1050\n *\n * // Convert cents back to dollars for display\n * const dollars = fromMinorUnits(1050, 'USD'); // Returns 10.50\n *\n * // Format for display\n * const formatted = formatCurrency(1050, 'USD'); // Returns '$10.50'\n */\n\n/**\n * Configuration for supported currencies.\n * Currencies are keyed by their ISO 4217 currency code.\n */\nexport const CURRENCY_CONFIG: Record<CurrencyCode | string, CurrencyConfig> = {\n // Major currencies with 2 decimal places\n [CurrencyCode.USD]: { minorUnits: 2, symbol: '$', symbolPosition: 'prefix' },\n [CurrencyCode.EUR]: { minorUnits: 2, symbol: '€', symbolPosition: 'prefix' },\n [CurrencyCode.GBP]: { minorUnits: 2, symbol: '£', symbolPosition: 'prefix' },\n [CurrencyCode.CAD]: { minorUnits: 2, symbol: 'CA$', symbolPosition: 'prefix' },\n [CurrencyCode.AUD]: { minorUnits: 2, symbol: 'A$', symbolPosition: 'prefix' },\n [CurrencyCode.NZD]: { minorUnits: 2, symbol: 'NZ$', symbolPosition: 'prefix' },\n [CurrencyCode.CHF]: { minorUnits: 2, symbol: 'CHF', symbolPosition: 'prefix' },\n [CurrencyCode.CNY]: { minorUnits: 2, symbol: '¥', symbolPosition: 'prefix' },\n [CurrencyCode.INR]: { minorUnits: 2, symbol: '₹', symbolPosition: 'prefix' },\n [CurrencyCode.MXN]: { minorUnits: 2, symbol: 'MX$', symbolPosition: 'prefix' },\n [CurrencyCode.BRL]: { minorUnits: 2, symbol: 'R$', symbolPosition: 'prefix' },\n [CurrencyCode.ZAR]: { minorUnits: 2, symbol: 'R', symbolPosition: 'prefix' },\n [CurrencyCode.SGD]: { minorUnits: 2, symbol: 'S$', symbolPosition: 'prefix' },\n [CurrencyCode.HKD]: { minorUnits: 2, symbol: 'HK$', symbolPosition: 'prefix' },\n [CurrencyCode.SEK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.NOK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.DKK]: { minorUnits: 2, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.PLN]: { minorUnits: 2, symbol: 'zł', symbolPosition: 'suffix' },\n [CurrencyCode.THB]: { minorUnits: 2, symbol: '฿', symbolPosition: 'prefix' },\n [CurrencyCode.MYR]: { minorUnits: 2, symbol: 'RM', symbolPosition: 'prefix' },\n [CurrencyCode.PHP]: { minorUnits: 2, symbol: '₱', symbolPosition: 'prefix' },\n [CurrencyCode.IDR]: { minorUnits: 2, symbol: 'Rp', symbolPosition: 'prefix' },\n [CurrencyCode.AED]: { minorUnits: 2, symbol: 'د.إ', symbolPosition: 'prefix' },\n [CurrencyCode.SAR]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.ILS]: { minorUnits: 2, symbol: '₪', symbolPosition: 'prefix' },\n [CurrencyCode.TRY]: { minorUnits: 2, symbol: '₺', symbolPosition: 'prefix' },\n [CurrencyCode.RUB]: { minorUnits: 2, symbol: '₽', symbolPosition: 'suffix' },\n [CurrencyCode.HTG]: { minorUnits: 2, symbol: 'HTG', symbolPosition: 'prefix' },\n\n // New Currencies with 2 decimal places\n [CurrencyCode.BND]: { minorUnits: 2, symbol: 'BND', symbolPosition: 'prefix' },\n [CurrencyCode.CRC]: { minorUnits: 2, symbol: 'CRC', symbolPosition: 'prefix' },\n [CurrencyCode.BDT]: { minorUnits: 2, symbol: 'BDT', symbolPosition: 'prefix' },\n [CurrencyCode.UAH]: { minorUnits: 2, symbol: 'UAH', symbolPosition: 'prefix' },\n [CurrencyCode.NGN]: { minorUnits: 2, symbol: '₦', symbolPosition: 'prefix' },\n [CurrencyCode.AFN]: { minorUnits: 2, symbol: '؋', symbolPosition: 'prefix' },\n [CurrencyCode.ALL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'suffix' },\n [CurrencyCode.AMD]: { minorUnits: 2, symbol: '֏', symbolPosition: 'suffix' },\n [CurrencyCode.ANG]: { minorUnits: 2, symbol: 'ƒ', symbolPosition: 'prefix' },\n [CurrencyCode.AOA]: { minorUnits: 2, symbol: 'Kz', symbolPosition: 'prefix' },\n [CurrencyCode.ARS]: { minorUnits: 2, symbol: 'AR$', symbolPosition: 'prefix' },\n [CurrencyCode.AWG]: { minorUnits: 2, symbol: 'Afl.', symbolPosition: 'prefix' },\n [CurrencyCode.AZN]: { minorUnits: 2, symbol: '₼', symbolPosition: 'prefix' },\n [CurrencyCode.BAM]: { minorUnits: 2, symbol: 'KM', symbolPosition: 'suffix' },\n [CurrencyCode.BBD]: { minorUnits: 2, symbol: 'Bds$', symbolPosition: 'prefix' },\n [CurrencyCode.BGN]: { minorUnits: 2, symbol: 'лв', symbolPosition: 'suffix' },\n [CurrencyCode.BMD]: { minorUnits: 2, symbol: 'BD$', symbolPosition: 'prefix' },\n [CurrencyCode.BOB]: { minorUnits: 2, symbol: 'Bs.', symbolPosition: 'prefix' },\n [CurrencyCode.BSD]: { minorUnits: 2, symbol: 'B$', symbolPosition: 'prefix' },\n [CurrencyCode.BTN]: { minorUnits: 2, symbol: 'Nu.', symbolPosition: 'prefix' },\n [CurrencyCode.BWP]: { minorUnits: 2, symbol: 'P', symbolPosition: 'prefix' },\n [CurrencyCode.BYN]: { minorUnits: 2, symbol: 'Br', symbolPosition: 'suffix' },\n [CurrencyCode.BZD]: { minorUnits: 2, symbol: 'BZ$', symbolPosition: 'prefix' },\n [CurrencyCode.COP]: { minorUnits: 2, symbol: 'COL$', symbolPosition: 'prefix' },\n [CurrencyCode.CZK]: { minorUnits: 2, symbol: 'Kč', symbolPosition: 'suffix' },\n [CurrencyCode.DOP]: { minorUnits: 2, symbol: 'RD$', symbolPosition: 'prefix' },\n [CurrencyCode.DZD]: { minorUnits: 2, symbol: 'DA', symbolPosition: 'prefix' },\n [CurrencyCode.EGP]: { minorUnits: 2, symbol: 'E£', symbolPosition: 'prefix' },\n [CurrencyCode.ETB]: { minorUnits: 2, symbol: 'Br', symbolPosition: 'prefix' },\n [CurrencyCode.FJD]: { minorUnits: 2, symbol: 'FJ$', symbolPosition: 'prefix' },\n [CurrencyCode.GEL]: { minorUnits: 2, symbol: '₾', symbolPosition: 'prefix' },\n [CurrencyCode.GHS]: { minorUnits: 2, symbol: '₵', symbolPosition: 'prefix' },\n [CurrencyCode.GTQ]: { minorUnits: 2, symbol: 'Q', symbolPosition: 'prefix' },\n [CurrencyCode.GYD]: { minorUnits: 2, symbol: 'G$', symbolPosition: 'prefix' },\n [CurrencyCode.HNL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'prefix' },\n [CurrencyCode.IRR]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.JMD]: { minorUnits: 2, symbol: 'J$', symbolPosition: 'prefix' },\n [CurrencyCode.KES]: { minorUnits: 2, symbol: 'KSh', symbolPosition: 'prefix' },\n [CurrencyCode.KGS]: { minorUnits: 2, symbol: 'с', symbolPosition: 'suffix' },\n [CurrencyCode.KHR]: { minorUnits: 2, symbol: '៛', symbolPosition: 'prefix' },\n [CurrencyCode.KYD]: { minorUnits: 2, symbol: 'CI$', symbolPosition: 'prefix' },\n [CurrencyCode.KZT]: { minorUnits: 2, symbol: '₸', symbolPosition: 'prefix' },\n [CurrencyCode.LAK]: { minorUnits: 2, symbol: '₭', symbolPosition: 'prefix' },\n [CurrencyCode.LBP]: { minorUnits: 2, symbol: 'L£', symbolPosition: 'prefix' },\n [CurrencyCode.LKR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.MAD]: { minorUnits: 2, symbol: 'DH', symbolPosition: 'prefix' },\n [CurrencyCode.MDL]: { minorUnits: 2, symbol: 'L', symbolPosition: 'suffix' },\n [CurrencyCode.MKD]: { minorUnits: 2, symbol: 'ден', symbolPosition: 'suffix' },\n [CurrencyCode.MMK]: { minorUnits: 2, symbol: 'K', symbolPosition: 'prefix' },\n [CurrencyCode.MNT]: { minorUnits: 2, symbol: '₮', symbolPosition: 'prefix' },\n [CurrencyCode.MOP]: { minorUnits: 2, symbol: 'MOP$', symbolPosition: 'prefix' },\n [CurrencyCode.MUR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.MVR]: { minorUnits: 2, symbol: 'Rf', symbolPosition: 'prefix' },\n [CurrencyCode.MZN]: { minorUnits: 2, symbol: 'MT', symbolPosition: 'prefix' },\n [CurrencyCode.NAD]: { minorUnits: 2, symbol: 'N$', symbolPosition: 'prefix' },\n [CurrencyCode.NIO]: { minorUnits: 2, symbol: 'C$', symbolPosition: 'prefix' },\n [CurrencyCode.NPR]: { minorUnits: 2, symbol: 'Rs', symbolPosition: 'prefix' },\n [CurrencyCode.PAB]: { minorUnits: 2, symbol: 'B/.', symbolPosition: 'prefix' },\n [CurrencyCode.PEN]: { minorUnits: 2, symbol: 'S/', symbolPosition: 'prefix' },\n [CurrencyCode.PGK]: { minorUnits: 2, symbol: 'K', symbolPosition: 'prefix' },\n [CurrencyCode.PKR]: { minorUnits: 2, symbol: '₨', symbolPosition: 'prefix' },\n [CurrencyCode.QAR]: { minorUnits: 2, symbol: 'QR', symbolPosition: 'prefix' },\n [CurrencyCode.RON]: { minorUnits: 2, symbol: 'lei', symbolPosition: 'suffix' },\n [CurrencyCode.RSD]: { minorUnits: 2, symbol: 'дин.', symbolPosition: 'suffix' },\n [CurrencyCode.SBD]: { minorUnits: 2, symbol: 'SI$', symbolPosition: 'prefix' },\n [CurrencyCode.SRD]: { minorUnits: 2, symbol: 'Sr$', symbolPosition: 'prefix' },\n [CurrencyCode.SYP]: { minorUnits: 2, symbol: '£S', symbolPosition: 'prefix' },\n [CurrencyCode.TJS]: { minorUnits: 2, symbol: 'SM', symbolPosition: 'prefix' },\n [CurrencyCode.TMT]: { minorUnits: 2, symbol: 'm.', symbolPosition: 'prefix' },\n [CurrencyCode.TOP]: { minorUnits: 2, symbol: 'T$', symbolPosition: 'prefix' },\n [CurrencyCode.TTD]: { minorUnits: 2, symbol: 'TT$', symbolPosition: 'prefix' },\n [CurrencyCode.TZS]: { minorUnits: 2, symbol: 'TSh', symbolPosition: 'prefix' },\n [CurrencyCode.UYU]: { minorUnits: 2, symbol: '$U', symbolPosition: 'prefix' },\n [CurrencyCode.UZS]: { minorUnits: 2, symbol: 'сўм', symbolPosition: 'suffix' },\n [CurrencyCode.VES]: { minorUnits: 2, symbol: 'Bs.', symbolPosition: 'prefix' },\n [CurrencyCode.WST]: { minorUnits: 2, symbol: 'WS$', symbolPosition: 'prefix' },\n [CurrencyCode.XCD]: { minorUnits: 2, symbol: 'EC$', symbolPosition: 'prefix' },\n [CurrencyCode.YER]: { minorUnits: 2, symbol: '﷼', symbolPosition: 'prefix' },\n [CurrencyCode.ZMW]: { minorUnits: 2, symbol: 'ZK', symbolPosition: 'prefix' },\n [CurrencyCode.CDF]: { minorUnits: 2, symbol: 'FC', symbolPosition: 'prefix' },\n [CurrencyCode.CUP]: { minorUnits: 2, symbol: '$MN', symbolPosition: 'prefix' },\n [CurrencyCode.ERN]: { minorUnits: 2, symbol: 'Nfk', symbolPosition: 'prefix' },\n [CurrencyCode.FKP]: { minorUnits: 2, symbol: 'FK£', symbolPosition: 'prefix' },\n [CurrencyCode.GIP]: { minorUnits: 2, symbol: 'GI£', symbolPosition: 'prefix' },\n [CurrencyCode.GMD]: { minorUnits: 2, symbol: 'D', symbolPosition: 'prefix' },\n [CurrencyCode.KPW]: { minorUnits: 2, symbol: 'KPW', symbolPosition: 'prefix' },\n [CurrencyCode.LRD]: { minorUnits: 2, symbol: 'L$', symbolPosition: 'prefix' },\n [CurrencyCode.LSL]: { minorUnits: 2, symbol: 'M', symbolPosition: 'prefix' },\n [CurrencyCode.MGA]: { minorUnits: 2, symbol: 'Ar', symbolPosition: 'prefix' },\n [CurrencyCode.MWK]: { minorUnits: 2, symbol: 'MK', symbolPosition: 'prefix' },\n [CurrencyCode.SCR]: { minorUnits: 2, symbol: 'SR', symbolPosition: 'prefix' },\n [CurrencyCode.SDG]: { minorUnits: 2, symbol: 'SDG', symbolPosition: 'prefix' },\n [CurrencyCode.SHP]: { minorUnits: 2, symbol: 'SH£', symbolPosition: 'prefix' },\n [CurrencyCode.SLE]: { minorUnits: 2, symbol: 'Le', symbolPosition: 'prefix' },\n [CurrencyCode.SOS]: { minorUnits: 2, symbol: 'SSh', symbolPosition: 'prefix' },\n [CurrencyCode.SSP]: { minorUnits: 2, symbol: 'SSP', symbolPosition: 'prefix' },\n [CurrencyCode.STN]: { minorUnits: 2, symbol: 'Db', symbolPosition: 'prefix' },\n [CurrencyCode.SZL]: { minorUnits: 2, symbol: 'E', symbolPosition: 'prefix' },\n [CurrencyCode.VED]: { minorUnits: 2, symbol: 'Bs.D', symbolPosition: 'prefix' },\n [CurrencyCode.XCG]: { minorUnits: 2, symbol: 'Cg', symbolPosition: 'prefix' },\n\n // Zero decimal currencies\n [CurrencyCode.JPY]: { minorUnits: 0, symbol: '¥', symbolPosition: 'prefix' },\n [CurrencyCode.KRW]: { minorUnits: 0, symbol: '₩', symbolPosition: 'prefix' },\n [CurrencyCode.VND]: { minorUnits: 0, symbol: '₫', symbolPosition: 'suffix' },\n [CurrencyCode.CLP]: { minorUnits: 0, symbol: 'CLP$', symbolPosition: 'prefix' },\n [CurrencyCode.ISK]: { minorUnits: 0, symbol: 'kr', symbolPosition: 'suffix' },\n [CurrencyCode.HUF]: { minorUnits: 0, symbol: 'Ft', symbolPosition: 'suffix' },\n [CurrencyCode.TWD]: { minorUnits: 0, symbol: 'NT$', symbolPosition: 'prefix' },\n\n // New Currencies with 0 decimal places\n [CurrencyCode.GNF]: { minorUnits: 0, symbol: 'GNF', symbolPosition: 'prefix' },\n [CurrencyCode.BIF]: { minorUnits: 0, symbol: 'FBu', symbolPosition: 'prefix' },\n [CurrencyCode.DJF]: { minorUnits: 0, symbol: 'Fdj', symbolPosition: 'prefix' },\n [CurrencyCode.KMF]: { minorUnits: 0, symbol: 'CF', symbolPosition: 'prefix' },\n [CurrencyCode.PYG]: { minorUnits: 0, symbol: '₲', symbolPosition: 'prefix' },\n [CurrencyCode.RWF]: { minorUnits: 0, symbol: 'FRw', symbolPosition: 'prefix' },\n [CurrencyCode.UGX]: { minorUnits: 0, symbol: 'USh', symbolPosition: 'prefix' },\n [CurrencyCode.VUV]: { minorUnits: 0, symbol: 'VT', symbolPosition: 'prefix' },\n [CurrencyCode.XAF]: { minorUnits: 0, symbol: 'FCFA', symbolPosition: 'suffix' },\n [CurrencyCode.XOF]: { minorUnits: 0, symbol: 'CFA', symbolPosition: 'suffix' },\n [CurrencyCode.XPF]: { minorUnits: 0, symbol: '₣', symbolPosition: 'suffix' },\n\n // Three decimal currencies\n [CurrencyCode.KWD]: { minorUnits: 3, symbol: 'KD', symbolPosition: 'prefix' },\n [CurrencyCode.BHD]: { minorUnits: 3, symbol: 'BD', symbolPosition: 'prefix' },\n [CurrencyCode.OMR]: { minorUnits: 3, symbol: 'OMR', symbolPosition: 'prefix' },\n [CurrencyCode.JOD]: { minorUnits: 3, symbol: 'JD', symbolPosition: 'prefix' },\n [CurrencyCode.TND]: { minorUnits: 3, symbol: 'DT', symbolPosition: 'prefix' },\n [CurrencyCode.LYD]: { minorUnits: 3, symbol: 'LD', symbolPosition: 'prefix' },\n [CurrencyCode.IQD]: { minorUnits: 3, symbol: 'IQD', symbolPosition: 'prefix' },\n};\n\n/** Default configuration for unknown currencies (assumes 2 decimal places) */\nconst DEFAULT_CURRENCY_CONFIG: CurrencyConfig = {\n minorUnits: 2,\n symbol: '',\n symbolPosition: 'prefix',\n};\n\n/**\n * Gets the currency configuration for a given currency code.\n * Falls back to default configuration (2 decimal places) for unknown currencies.\n *\n * @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')\n * @returns Currency configuration\n */\nexport function getCurrencyConfig(currency: CurrencyCode): CurrencyConfig {\n const upperCurrency = currency.toUpperCase();\n return CURRENCY_CONFIG[upperCurrency] || DEFAULT_CURRENCY_CONFIG;\n}\n\n/**\n * Gets the multiplier for converting between major and minor currency units.\n *\n * @param currency - ISO 4217 currency code (e.g., 'USD', 'EUR')\n * @returns The multiplier (e.g., 100 for USD, 1 for JPY, 1000 for KWD)\n *\n * @example\n * getMinorUnitMultiplier('USD'); // Returns 100\n * getMinorUnitMultiplier('JPY'); // Returns 1\n * getMinorUnitMultiplier('KWD'); // Returns 1000\n */\nexport function getMinorUnitMultiplier(currency: CurrencyCode): number {\n const config = getCurrencyConfig(currency);\n return Math.pow(10, config.minorUnits);\n}\n\n/**\n * Converts a major currency amount to minor units (e.g., dollars to cents).\n * Uses Math.round to handle floating-point precision issues.\n *\n * @param amount - Amount in major currency units (e.g., 10.50 dollars)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @returns Amount in minor units as an integer (e.g., 1050 cents)\n *\n * @example\n * toMinorUnits(10.50, 'USD'); // Returns 1050\n * toMinorUnits(1000, 'JPY'); // Returns 1000 (JPY has no minor units)\n * toMinorUnits(10.500, 'KWD'); // Returns 10500 (KWD has 3 decimal places)\n */\nexport function toMinorUnits(amount: number, currency: CurrencyCode): number {\n const multiplier = getMinorUnitMultiplier(currency);\n // Use Math.round to handle floating-point precision issues\n return Math.round(amount * multiplier);\n}\n\n/**\n * Converts minor currency units to major units (e.g., cents to dollars).\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @returns Amount in major units (e.g., 10.50 dollars)\n *\n * @example\n * fromMinorUnits(1050, 'USD'); // Returns 10.50\n * fromMinorUnits(1000, 'JPY'); // Returns 1000\n * fromMinorUnits(10500, 'KWD'); // Returns 10.500\n */\nexport function fromMinorUnits(minorAmount: number, currency: CurrencyCode): number {\n const multiplier = getMinorUnitMultiplier(currency);\n return minorAmount / multiplier;\n}\n\n/**\n * Formats a minor currency amount for display with currency symbol.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param currency - ISO 4217 currency code (e.g., 'USD')\n * @param options - Formatting options\n * @returns Formatted currency string (e.g., '$10.50')\n *\n * @example\n * formatCurrency(1050, 'USD'); // Returns '$10.50'\n * formatCurrency(1000, 'JPY'); // Returns '¥1000'\n * formatCurrency(10500, 'KWD'); // Returns 'KD10.500'\n */\nexport function formatCurrency(\n minorAmount: number,\n currency: CurrencyCode,\n options: {\n /** Whether to include the currency symbol (default: true) */\n includeSymbol?: boolean;\n /** Whether to use grouping separators for thousands (default: true) */\n useGrouping?: boolean;\n } = {},\n): string {\n const { includeSymbol = true, useGrouping = true } = options;\n const config = getCurrencyConfig(currency);\n const majorAmount = fromMinorUnits(minorAmount, currency);\n\n const formattedNumber = majorAmount.toLocaleString('en-US', {\n minimumFractionDigits: config.minorUnits,\n maximumFractionDigits: config.minorUnits,\n useGrouping,\n });\n\n if (!includeSymbol || !config.symbol) {\n return formattedNumber;\n }\n\n if (config.symbolPosition === 'suffix') {\n return `${formattedNumber}${config.symbol}`;\n }\n\n return `${config.symbol}${formattedNumber}`;\n}\n\n/**\n * Safely adds two amounts in minor units.\n * Both amounts should already be in minor units (integers).\n *\n * @param a - First amount in minor units\n * @param b - Second amount in minor units\n * @returns Sum in minor units\n *\n * @example\n * addAmounts(1050, 250); // Returns 1300\n */\nexport function addAmounts(a: number, b: number): number {\n return Math.round(a + b);\n}\n\n/**\n * Safely subtracts two amounts in minor units.\n * Both amounts should already be in minor units (integers).\n *\n * @param a - First amount in minor units\n * @param b - Second amount to subtract in minor units\n * @returns Difference in minor units\n *\n * @example\n * subtractAmounts(1050, 250); // Returns 800\n */\nexport function subtractAmounts(a: number, b: number): number {\n return Math.round(a - b);\n}\n\n/**\n * Safely multiplies an amount by a factor.\n * The amount should be in minor units, the multiplier can be a decimal.\n *\n * @param amount - Amount in minor units\n * @param multiplier - Factor to multiply by (e.g., quantity or percentage as decimal)\n * @returns Product in minor units, rounded to nearest integer\n *\n * @example\n * multiplyAmount(1050, 2); // Returns 2100 (doubling)\n * multiplyAmount(1050, 0.15); // Returns 158 (15% of amount)\n */\nexport function multiplyAmount(amount: number, multiplier: number): number {\n return Math.round(amount * multiplier);\n}\n\n/**\n * Safely divides an amount by a divisor.\n * The amount should be in minor units.\n *\n * @param amount - Amount in minor units\n * @param divisor - Value to divide by\n * @returns Quotient in minor units, rounded to nearest integer\n *\n * @example\n * divideAmount(1050, 2); // Returns 525 (halving)\n * divideAmount(1000, 3); // Returns 333 (rounded)\n */\nexport function divideAmount(amount: number, divisor: number): number {\n if (divisor === 0) {\n throw new Error('Cannot divide by zero');\n }\n return Math.round(amount / divisor);\n}\n\n/**\n * Calculates a percentage of an amount.\n *\n * @param amount - Base amount in minor units\n * @param percentage - Percentage as a number (e.g., 15 for 15%, not 0.15)\n * @returns The percentage amount in minor units\n *\n * @example\n * calculatePercentage(10000, 15); // Returns 1500 (15% of 10000)\n * calculatePercentage(1050, 8.25); // Returns 87 (8.25% of 1050, rounded)\n */\nexport function calculatePercentage(amount: number, percentage: number): number {\n return Math.round((amount * percentage) / 100);\n}\n\n/**\n * Converts a string amount (e.g., \"10.50\") to minor units.\n * Useful for parsing user input or legacy string amounts.\n *\n * @param amountString - Amount as a string (e.g., \"10.50\")\n * @param currency - ISO 4217 currency code\n * @returns Amount in minor units, or null if parsing fails\n *\n * @example\n * parseAmountToMinorUnits(\"10.50\", \"USD\"); // Returns 1050\n * parseAmountToMinorUnits(\"invalid\", \"USD\"); // Returns null\n */\nexport function parseAmountToMinorUnits(amountString: string, currency: CurrencyCode): number | null {\n const parsed = parseFloat(amountString);\n if (isNaN(parsed)) {\n return null;\n }\n return toMinorUnits(parsed, currency);\n}\n\n/**\n * Checks if a currency code is supported with known configuration.\n *\n * @param currency - ISO 4217 currency code\n * @returns True if the currency has explicit configuration\n */\nexport function isSupportedCurrency(currency: CurrencyCode): boolean {\n return currency.toUpperCase() in CURRENCY_CONFIG;\n}\n\n/**\n * Validates that a string is a supported {@link CurrencyCode} and returns it.\n * @param value - Raw currency string (e.g. from API or DTO)\n * @returns Valid CurrencyCode\n * @throws Error if value is not a supported CurrencyCode\n */\nexport function parseCurrencyCode(value: string): CurrencyCode {\n if (!value || typeof value !== 'string') {\n throw new Error(`Currency value is missing or invalid`);\n }\n const validCodes = Object.values(CurrencyCode) as string[];\n if (!validCodes.includes(value)) {\n throw new Error(`\"${value}\" is not a supported CurrencyCode. Supported codes: ${validCodes.join(', ')}`);\n }\n return value as CurrencyCode;\n}\n\nexport function parseStripeCurrencyCode(value: string): StripeCurrencyCode {\n if (!value || typeof value !== 'string') {\n throw new Error(`Currency value is missing or invalid`);\n }\n const validCodes = Object.values(StripeCurrencyCode) as string[];\n if (!validCodes.includes(value)) {\n throw new Error(`\"${value}\" is not a supported Stripe CurrencyCode. Supported codes: ${validCodes.join(', ')}`);\n }\n return value as StripeCurrencyCode;\n}\n\n/**\n * Converts minor currency units to major units as a number.\n * Uses the minorUnits count directly instead of looking up by currency code.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param minorUnits - Number of decimal places for the currency (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n * @returns Amount in major units as a number (e.g., 10.50 dollars)\n *\n * @example\n * stringifyMinorUnits(1050, 2); // Returns 10.50\n * stringifyMinorUnits(1000, 0); // Returns 1000\n * stringifyMinorUnits(10500, 3); // Returns 10.5\n */\nexport function stringifyMinorUnits(minorAmount: number, minorUnits: number): number {\n const multiplier = Math.pow(10, minorUnits);\n return minorAmount / multiplier;\n}\n\n/**\n * Converts minor currency units to a plain decimal string without symbol or grouping.\n * Useful for APIs like WooCommerce that expect plain numeric strings.\n *\n * @param minorAmount - Amount in minor units (e.g., 1050 cents)\n * @param minorUnits - Number of decimal places for the currency (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n * @returns Plain decimal string (e.g., '10.50')\n *\n * @example\n * formatMinorUnitsToString(1050, 2); // Returns '10.50'\n * formatMinorUnitsToString(1000, 0); // Returns '1000'\n * formatMinorUnitsToString(10500, 3); // Returns '10.5'\n */\nexport function formatMinorUnitsToString(minorAmount: number, minorUnits: number): string {\n const majorAmount = stringifyMinorUnits(minorAmount, minorUnits);\n return majorAmount.toString();\n}\n\n/**\n * Get the number of minor units for a currency.\n * Used in BuilderHub\n * @param currency - ISO 4217 currency code\n * @returns Number of minor unit digits (e.g., 2 for USD, 0 for JPY, 3 for KWD)\n */\nexport function getMinorUnits(currency: CurrencyCode): number {\n return getCurrencyConfig(currency).minorUnits;\n}\n\n/**\n * Creates an Amount object from user input string.\n * Converts \"31.22\" + \"USD\" → { amount: 3122, currency: \"USD\", minorUnits: 2 }\n * Used in BuilderHub\n * @param value - User input value (string like \"31.22\" or number)\n * @param currency - ISO 4217 currency code from company.settings.currency\n * @returns Amount object or undefined if value is empty/invalid\n */\nexport function createAmount(value: string | number | null | undefined, currency: CurrencyCode): Amount | undefined {\n if (value === null || value === undefined || value === '') {\n return undefined;\n }\n\n const numericValue = typeof value === 'string' ? parseFloat(value) : value;\n\n if (isNaN(numericValue)) {\n return undefined;\n }\n\n const minorUnits = getMinorUnits(currency);\n const multiplier = Math.pow(10, minorUnits);\n\n return {\n amount: Math.round(numericValue * multiplier),\n currency,\n minorUnits,\n };\n}\n\n/**\n * Converts an Amount object to a display string for the UI.\n * { amount: 3122, currency: \"USD\", minorUnits: 2 } → \"31.22\"\n * Used in BuilderHub\n * @param amount - Amount object from API response\n * @returns Formatted string (e.g., \"31.22\") or empty string if undefined\n */\nexport function amountToString(amount: Amount | undefined | null): string {\n if (!amount) {\n return '';\n }\n\n const divisor = Math.pow(10, amount.minorUnits);\n const majorValue = amount.amount / divisor;\n return majorValue.toFixed(amount.minorUnits);\n}\n","import type { MeasurementUnit, MeasurementUnitFamily } from './types';\n\n/**\n * Seeded families and units — constants, not rows.\n *\n * Identified by their UN/CEFACT Rec 20 code, the trade standard providers already speak: an import\n * that says `KGM` needs no lookup table to become a kilogram here. Families have no counterpart in\n * Rec 20 — it lists units, not dimensions — so those carry our own readable code.\n *\n * These used to be ObjectIds from a reserved `00000000…` range, so that seeded and merchant units\n * could share one id space without colliding. A code cannot be mistaken for a 24-character hex\n * string, so the reservation is no longer needed: merchant units keep their own generated ids and\n * the two kinds separate themselves.\n *\n * A merchant may add units *inside* these families (a 500 g pack, a 150 ml glass) — those are rows\n * in `measurement-units`. Nothing downstream inspects which kind an id is.\n *\n * ## Why metric and imperial are separate families\n *\n * Conversion is defined only inside a family, and stock is a whole number of one base. For weight\n * and volume the split is arithmetic, not taste: an ounce is `28.349523125` g, and at any decimal\n * base the numerator stays odd — `1 600 000 = 2⁹ × 5⁵` — so a shared base would force\n * `precision 0` on the ounce forever, and half a pound could never be keyed. For length and area a\n * shared base *is* possible; they are split anyway, so that one rule explains all of them.\n *\n * The cost is deliberate: **there is no kg ↔ lb conversion.** A merchant who receives and sells in\n * pounds never needs one. A merchant who receives in kilograms and sells in pounds does, and that\n * case is not solved here.\n *\n * ## Why some bases are not units\n *\n * `weight-imperial` counts in hundred-thousandths of an ounce; nobody trades in those. The base\n * belongs to the family, not to the list a merchant picks from. For metric families it happens to\n * coincide with a real unit — a gram is both — and that unit stays in the list on its own merit.\n *\n * Those four bases still exist as **rows**, generated below as `BASE_UNITS` and marked\n * `sellable: false`. A stock movement records the unit its quantity is counted in, so without a row\n * an imperial family could move no stock at all — it answered `412` on every attempt, which is how\n * this was found. The flag keeps them out of merchant-facing lists while leaving them resolvable by\n * id, because history must still render months later.\n *\n * ### Why the imperial weight base is a hundred-thousandth and not a thousandth\n *\n * Square — the only provider that carries units at all — offers **five** decimals on\n * `IMPERIAL_POUND`, verified against a live sandbox catalogue. At a thousandth of an ounce the\n * pound is `16_000`, `10^5` does not divide it, and `maxPrecisionFor` caps it at three: importing\n * such an item would have to round silently. Scaled down twice more the pound is `1_600_000`, five\n * decimals hold, and `1.00001 lb` is exactly `1_600_016`.\n *\n * It was changed while the imperial families were still empty — they could hold no stock, so no\n * data meant anything yet. Doing the same later is a migration of every stored quantity.\n *\n * ### Why not simply make the ounce the base — read this before \"simplifying\" it\n *\n * Because `10^precision` must divide `ratioToBase`, and with the ounce at `1` the pound is `16`.\n * Ten does not divide sixteen, so both would be pinned to **precision 0**: no `1.5 oz`, no\n * `1.25 lb`, no half a pound, ever.\n *\n * What makes this a trap rather than an obvious error is that it half-works. Storing in ounces,\n * some inputs land on integers and some do not:\n *\n * ```\n * 1.25 lb = 20.00 oz fine 1.1 lb = 17.60 oz not storable\n * 1.5 lb = 24.00 oz fine 1.01 lb = 16.16 oz not storable\n * ```\n *\n * A scale reading `1.25 lb` would sail through and a scale reading `1.1 lb` would not, so the bug\n * arrives long after the change, on a value nobody tested. The invariant is deliberately about\n * *every* admissible input, not the lucky ones. Scaling the ounce down puts the tens into the\n * pound's ratio: at `16_000` a hundred divides it, two decimals hold, and `1.01 lb` is `16_160`.\n *\n * The number is therefore chosen by the finest input any source can hand us, not by what the\n * declared precisions below need — those would be satisfied by far less. Worth knowing before\n * anyone \"corrects\" it downwards.\n */\n\nexport const SYSTEM_FAMILY_IDS = {\n COUNT: 'count',\n WEIGHT: 'weight-metric',\n WEIGHT_IMPERIAL: 'weight-imperial',\n VOLUME: 'volume-metric',\n VOLUME_IMPERIAL: 'volume-imperial',\n LENGTH: 'length-metric',\n LENGTH_IMPERIAL: 'length-imperial',\n AREA: 'area-metric',\n AREA_IMPERIAL: 'area-imperial',\n} as const;\n\nexport const SYSTEM_UNIT_IDS = {\n EACH: 'EA',\n GRAM: 'GRM',\n KILOGRAM: 'KGM',\n /** 100 g is a hectogram; the merchant-facing name stays \"100 g\". */\n HECTOGRAM: 'HGM',\n MILLILITRE: 'MLT',\n LITRE: 'LTR',\n} as const;\n\n/**\n * A family's base is immutable from the moment the family holds its first stock.\n *\n * Every stored quantity — `inventory.quantity`, a stock movement, an order line's `stockQuantity` —\n * is a whole number of its family's base, and nothing stamps the scale on the row. Change a base\n * and every one of those numbers silently means something else: rescaling `weight-metric` by a\n * thousand would turn a stored `6799` from `6.799 kg` into `0.006799 kg`, with no error anywhere.\n *\n * Changing one is therefore a **migration of every stored quantity in that family**, not an edit to\n * a constant here. The imperial weight base was rescaled ×100 on 2026-08-16 precisely because those\n * four families could hold no stock at the time — they answered `412` on every movement — so there\n * was nothing to reinterpret. That window is closed the day the first product is saved.\n *\n * This is also what keeps the door open to storing decimals instead of integers later: with the\n * base declared here and the rule above held, the switch is one division per row. Break the rule and\n * it stops being mechanical, because no one can tell what a given number was divided by.\n */\nexport const SYSTEM_FAMILIES: readonly MeasurementUnitFamily[] = [\n {\n familyId: SYSTEM_FAMILY_IDS.COUNT,\n companyId: null,\n name: 'Count',\n base: { name: 'Piece', abbreviation: 'ea', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.WEIGHT,\n companyId: null,\n name: 'Weight',\n base: { name: 'Gram', abbreviation: 'g', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL,\n companyId: null,\n name: 'Weight (imperial)',\n base: { name: 'Hundred-thousandth of an ounce', abbreviation: '10⁻⁵ oz', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.VOLUME,\n companyId: null,\n name: 'Volume',\n base: { name: 'Millilitre', abbreviation: 'ml', ratioToBase: 1, precision: 0 },\n },\n {\n // Cubic inches, not fluid ounces: a US gallon is 231 in³ and 128 fl oz, and 231 = 3 × 7 × 11.\n // With an ounce base the board foot lands on 6144000/77 — and lumber is the reason this family\n // exists at all.\n familyId: SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL,\n companyId: null,\n name: 'Volume (imperial)',\n base: { name: '1/128000 cubic inch', abbreviation: 'µin³', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.LENGTH,\n companyId: null,\n name: 'Length',\n base: { name: 'Millimetre', abbreviation: 'mm', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL,\n companyId: null,\n name: 'Length (imperial)',\n base: { name: 'Millionth of an inch', abbreviation: 'µin', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.AREA,\n companyId: null,\n name: 'Area',\n base: { name: 'Square millimetre', abbreviation: 'mm²', ratioToBase: 1, precision: 0 },\n },\n {\n familyId: SYSTEM_FAMILY_IDS.AREA_IMPERIAL,\n companyId: null,\n name: 'Area (imperial)',\n base: { name: 'Thousandth of a square inch', abbreviation: 'm-sq in', ratioToBase: 1, precision: 0 },\n },\n];\n\n/**\n * Every seeded unit, by family.\n *\n * `precision` here is the sensible default, not the arithmetic ceiling — `maxPrecisionFor` gives\n * that. Where the two differ it is a judgement: `CEN` (a hundred nails) could arithmetically carry\n * two decimals, but a hundred-and-fifty nails is keyed as 150 pieces, not 1.5 hundreds.\n *\n * Four units were looked at and left out rather than bent into shape:\n *\n * - `MGM` milligram — `1/1000` of a gram, not a whole number of base units. Moving the metric\n * weight base to milligrams would multiply every stored gram by a thousand for a unit nobody\n * retails in.\n * - `GRN` grain — an ounce is `437.5` grains, so the ratio is fractional at its source. No base\n * fixes that without costing the ounce its decimals.\n * - `GLI` imperial gallon — a whole number of neither US fluid ounces nor cubic inches. UK liquid\n * measure is a tenth family, not a row in this one.\n * - `CMQ` cubic centimetre — identical to the millilitre. A second name for one quantity, not a\n * second unit.\n */\nconst unit = (\n unitId: string,\n familyId: string,\n name: string,\n abbreviation: string,\n ratioToBase: number,\n precision: number,\n): MeasurementUnit => ({ unitId, companyId: null, familyId, name, abbreviation, ratioToBase, precision });\n\nconst SELLABLE_UNITS: readonly MeasurementUnit[] = [\n // ── Count ────────────────────────────────────────────────────────────────\n unit('EA', SYSTEM_FAMILY_IDS.COUNT, 'Each', 'ea', 1, 0),\n unit('PR', SYSTEM_FAMILY_IDS.COUNT, 'Pair', 'pr', 2, 0),\n unit('DZN', SYSTEM_FAMILY_IDS.COUNT, 'Dozen', 'dz', 12, 0),\n unit('GRO', SYSTEM_FAMILY_IDS.COUNT, 'Gross', 'gro', 144, 0),\n unit('CEN', SYSTEM_FAMILY_IDS.COUNT, 'Hundred', 'C', 100, 0),\n unit('MIL', SYSTEM_FAMILY_IDS.COUNT, 'Thousand', 'M', 1_000, 0),\n\n // ── Weight, metric ───────────────────────────────────────────────────────\n unit('GRM', SYSTEM_FAMILY_IDS.WEIGHT, 'Gram', 'g', 1, 0),\n unit('HGM', SYSTEM_FAMILY_IDS.WEIGHT, '100 g', '100g', 100, 2),\n unit('KGM', SYSTEM_FAMILY_IDS.WEIGHT, 'Kilogram', 'kg', 1_000, 3),\n unit('TNE', SYSTEM_FAMILY_IDS.WEIGHT, 'Tonne', 't', 1_000_000, 3),\n\n // ── Weight, imperial ─────────────────────────────────────────────────────\n unit('ONZ', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Ounce', 'oz', 100_000, 2),\n unit('LBR', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Pound', 'lb', 1_600_000, 2),\n unit('STI', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Stone', 'st', 22_400_000, 2),\n // `(US)` is not decoration: Rec 20 also carries `CWI`, the UK hundredweight, at 112 lb — 12 % more.\n // The code here is the right one; an unqualified \"cwt\" on screen is what would be ambiguous.\n unit('CWA', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Hundredweight (US)', 'cwt (US)', 160_000_000, 2),\n unit('STN', SYSTEM_FAMILY_IDS.WEIGHT_IMPERIAL, 'Ton (short)', 'tn', 3_200_000_000, 3),\n\n // ── Volume, metric ───────────────────────────────────────────────────────\n unit('MLT', SYSTEM_FAMILY_IDS.VOLUME, 'Millilitre', 'ml', 1, 0),\n unit('CLT', SYSTEM_FAMILY_IDS.VOLUME, 'Centilitre', 'cl', 10, 1),\n unit('LTR', SYSTEM_FAMILY_IDS.VOLUME, 'Litre', 'l', 1_000, 3),\n unit('HLT', SYSTEM_FAMILY_IDS.VOLUME, 'Hectolitre', 'hl', 100_000, 3),\n unit('MTQ', SYSTEM_FAMILY_IDS.VOLUME, 'Cubic metre', 'm³', 1_000_000, 3),\n\n // ── Volume, imperial ─────────────────────────────────────────────────────\n unit('OZA', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Fluid ounce', 'fl oz', 231_000, 2),\n unit('PTL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Pint', 'pt', 3_696_000, 2),\n unit('QTL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Quart', 'qt', 7_392_000, 2),\n unit('GLL', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Gallon', 'gal', 29_568_000, 3),\n unit('INQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic inch', 'in³', 128_000, 2),\n unit('BFT', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Board foot', 'fbm', 18_432_000, 2),\n unit('FTQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic foot', 'ft³', 221_184_000, 3),\n unit('YDQ', SYSTEM_FAMILY_IDS.VOLUME_IMPERIAL, 'Cubic yard', 'yd³', 5_971_968_000, 3),\n\n // ── Length, metric ───────────────────────────────────────────────────────\n unit('MMT', SYSTEM_FAMILY_IDS.LENGTH, 'Millimetre', 'mm', 1, 0),\n unit('CMT', SYSTEM_FAMILY_IDS.LENGTH, 'Centimetre', 'cm', 10, 1),\n unit('MTR', SYSTEM_FAMILY_IDS.LENGTH, 'Metre', 'm', 1_000, 3),\n unit('KMT', SYSTEM_FAMILY_IDS.LENGTH, 'Kilometre', 'km', 1_000_000, 3),\n\n // ── Length, imperial ─────────────────────────────────────────────────────\n // `INH` carries four decimals, not three: an eighth of an inch is 0.125 but a sixteenth is\n // 0.0625, and sixteenths are the everyday fraction on a tape measure. A thirty-second needs five,\n // which is the ceiling; a sixty-fourth has no decimal form at all and is a question about\n // fraction input, not about precision.\n unit('INH', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Inch', 'in', 1_000_000, 4),\n unit('FOT', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Foot', 'ft', 12_000_000, 3),\n unit('LF', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Linear foot', 'lin ft', 12_000_000, 2),\n unit('YRD', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Yard', 'yd', 36_000_000, 3),\n unit('SMI', SYSTEM_FAMILY_IDS.LENGTH_IMPERIAL, 'Mile', 'mi', 63_360_000_000, 3),\n\n // ── Area, metric ─────────────────────────────────────────────────────────\n unit('MMK', SYSTEM_FAMILY_IDS.AREA, 'Square millimetre', 'mm²', 1, 0),\n unit('CMK', SYSTEM_FAMILY_IDS.AREA, 'Square centimetre', 'cm²', 100, 2),\n unit('MTK', SYSTEM_FAMILY_IDS.AREA, 'Square metre', 'm²', 1_000_000, 3),\n unit('HAR', SYSTEM_FAMILY_IDS.AREA, 'Hectare', 'ha', 10_000_000_000, 3),\n\n // ── Area, imperial ───────────────────────────────────────────────────────\n unit('INK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square inch', 'sq in', 1_000, 2),\n unit('FTK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square foot', 'sq ft', 144_000, 2),\n unit('YDK', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square yard', 'sq yd', 1_296_000, 2),\n // A roofing square is exactly 100 square feet — a trade unit with a precise definition, which is\n // why it is a real row and not a label.\n unit('SQR', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Square (roofing)', 'sq', 14_400_000, 2),\n unit('ACR', SYSTEM_FAMILY_IDS.AREA_IMPERIAL, 'Acre', 'ac', 6_272_640_000, 2),\n];\n\n/**\n * The unit rows that exist only to give a family's base an identifier.\n *\n * A stock movement records the unit its quantity is counted in, and stock is counted in the family\n * base — so without a row the four imperial families could move no stock at all. Derived rather\n * than typed out, so a base's name can never drift from the family that defines it, and so a\n * family whose base IS a real unit (a gram, a millilitre, a piece) gets no duplicate.\n *\n * `sellable: false` keeps them out of every merchant-facing list. They still resolve by id, which\n * is the whole point: history has to render `−20 000 10⁻⁵ oz` long after the sale.\n */\nconst BASE_UNITS: readonly MeasurementUnit[] = SYSTEM_FAMILIES.filter(\n (family) => !SELLABLE_UNITS.some((u) => u.familyId === family.familyId && u.ratioToBase === 1),\n).map((family) => ({\n unitId: `${family.familyId}-base`,\n companyId: null,\n familyId: family.familyId,\n name: family.base.name,\n abbreviation: family.base.abbreviation,\n ratioToBase: 1,\n precision: 0,\n sellable: false as const,\n}));\n\nexport const SYSTEM_UNITS: readonly MeasurementUnit[] = [...SELLABLE_UNITS, ...BASE_UNITS];\n\n/** A variant with no `unitId` is sold by the piece. This is that unit. */\nexport const DEFAULT_UNIT_ID = SYSTEM_UNIT_IDS.EACH;\n","import type { Measurable, MeasurementBase, MeasurementUnit, MeasurementUnitFamily } from './types';\nimport { SYSTEM_FAMILIES, SYSTEM_UNITS } from './system-units';\n\n/**\n * The arithmetic of units, defined once.\n *\n * Stock is stored as a whole number of the family's **base** unit — grams, millilitres, pieces.\n * Everything a person types or reads is converted at the edge. That is what keeps a stored\n * quantity from ever being a float: `40 - 1.589` drifts, `40000 - 1589` cannot.\n */\n\nconst EPSILON = 1e-9;\n\n/**\n * Is `value` a whole number, allowing for binary dust?\n *\n * The tolerance has to scale with the value. Float error is proportional to magnitude, and a\n * family's base can be huge: a pound is 1 600 000 base units, an acre 6 272 640 000. Measured,\n * `8.03 * 1_600_000` is `12_847_999.999999998` — off by 1.9e-9, which a fixed 1e-9 threshold reads\n * as \"not whole\" and rejects, though the quantity is perfectly legal. Across the 46 seeded units\n * that rejected 4.6% of all admissible quantities, the hectare 11.8% of them.\n *\n * It cannot swallow a real violation: a quantity finer than the unit allows is off by at least\n * `ratioToBase / 10^(precision+1)`, and the divisibility invariant keeps that above the tolerance\n * at every magnitude — `1.5891` kg misses by 0.1 against a tolerance of 1.6e-6.\n */\nexport function isWhole(value: number): boolean {\n return Math.abs(value - Math.round(value)) <= EPSILON * Math.max(1, Math.abs(value));\n}\n\n/** Finest a unit may be. Bounded so a valid quantity is always whole at `10^MAX_PRECISION`. */\nexport const MAX_PRECISION = 5;\n\n/** Seeded units first, then the company's own. One id space, one lookup. */\nexport function resolveUnit(unitId: string, companyUnits: readonly MeasurementUnit[] = []): MeasurementUnit {\n const unit = SYSTEM_UNITS.find((u) => u.unitId === unitId) ?? companyUnits.find((u) => u.unitId === unitId);\n if (!unit) throw new Error(`Unknown measurement unit: ${unitId}`);\n return unit;\n}\n\nexport function resolveFamily(\n familyId: string,\n companyFamilies: readonly MeasurementUnitFamily[] = [],\n): MeasurementUnitFamily {\n const family =\n SYSTEM_FAMILIES.find((f) => f.familyId === familyId) ?? companyFamilies.find((f) => f.familyId === familyId);\n if (!family) throw new Error(`Unknown measurement unit family: ${familyId}`);\n return family;\n}\n\n/**\n * What stock in this family is counted in.\n *\n * Used to be found by searching the unit list for `ratioToBase === 1`, which made \"exactly one such\n * unit\" an unwritten rule: at zero the lookup threw, at two it silently took whichever came first.\n * The base now belongs to the family, so there is one by construction and nothing to get wrong.\n *\n * It is also not something anyone sells. A thousandth of an ounce exists so `1.25 lb` has an exact\n * integer form; it has no trade code and no place in a dropdown.\n */\nexport function baseOf(familyId: string, companyFamilies: readonly MeasurementUnitFamily[] = []): MeasurementBase {\n return resolveFamily(familyId, companyFamilies).base;\n}\n\n/** The base of whichever family this unit belongs to. */\nexport function baseFor(\n unit: MeasurementUnit,\n companyFamilies: readonly MeasurementUnitFamily[] = [],\n): MeasurementBase {\n return baseOf(unit.familyId, companyFamilies);\n}\n\n/** Two units convert only inside one family. Every caller that mixes units must check this first. */\nexport function sameFamily(a: MeasurementUnit, b: MeasurementUnit): boolean {\n return a.familyId === b.familyId;\n}\n\n/**\n * Rejects a unit whose `precision` could produce a fraction of a base unit.\n *\n * A quantity with at most `p` decimals is `k / 10 ** p`, so it converts to `k * ratio / 10 ** p`\n * base units. That is whole for every possible input exactly when `10 ** p` divides `ratio`.\n *\n * ```\n * Kilogram ratio 1000, precision 3 → 1000 / 1000 = 1 ok\n * Kilogram ratio 1000, precision 4 → 1000 / 10000 1.5891 kg would be 1589.1 g\n * ```\n *\n * Call this before saving a unit. Every function below assumes it passed.\n */\nexport function assertUnitSane(unit: Measurable): void {\n const { ratioToBase, precision, name } = unit;\n if (!Number.isInteger(ratioToBase) || ratioToBase < 1)\n throw new Error(`Unit \"${name}\": ratioToBase must be a positive integer, got ${ratioToBase}`);\n if (!Number.isInteger(precision) || precision < 0 || precision > MAX_PRECISION)\n throw new Error(`Unit \"${name}\": precision must be an integer 0–${MAX_PRECISION}, got ${precision}`);\n if (ratioToBase % 10 ** precision !== 0)\n throw new Error(\n `Unit \"${name}\": precision ${precision} is finer than a ratio of ${ratioToBase} allows — ` +\n `at most ${maxPrecisionFor(ratioToBase)}. For anything finer the family needs a smaller base unit.`,\n );\n}\n\n/**\n * The finest `precision` a unit with this ratio may declare.\n *\n * Not a policy — a consequence. A quantity with `p` decimals is `k / 10^p`, so it converts to\n * `k * ratio / 10^p` base units, and that is whole for every input exactly when `10^p` divides the\n * ratio. Allowing more would let a sale ask for a fraction of the base unit, which does not exist.\n *\n * ```\n * 1000 (kilogram, base gram) → 3 1.589 kg is 1589 g\n * 500 (500 g pack) → 2 0.05 of a pack is 25 g; 0.005 would be 2.5 g\n * 125 (125 g burger) → 0 there is no half burger\n * 1 (the base unit itself) → 0 nothing left to divide\n * ```\n *\n * Whether to divide at all stays the merchant's call — a bottle sells whole, a weight does not.\n * This only says how far that call may go. A merchant who needs finer does not need a bigger\n * number here; they need a smaller base unit in the family (a slice, a millilitre, a half),\n * which is a decision about the family and should be made once.\n *\n * When a merchant reports \"it won't take 1.1 lb\", the answer is here and not at the till: an\n * imperial pound only carries decimals because its family counts in thousandths of an ounce\n * (`16_000`). Move that base up to the ounce itself and the ratio becomes `16`, this returns `0`,\n * and every fractional weight is rejected — while `1.25 lb` keeps working, because `20 oz` happens\n * to be whole. See the header of `system-units.ts` before changing any family's base.\n */\nexport function maxPrecisionFor(ratioToBase: number): number {\n if (!Number.isInteger(ratioToBase) || ratioToBase < 1)\n throw new Error(`ratioToBase must be a positive integer, got ${ratioToBase}`);\n let precision = 0;\n while (precision < MAX_PRECISION && ratioToBase % 10 ** (precision + 1) === 0) precision++;\n return precision;\n}\n\n/** Does this quantity fit the unit's precision? `1.589` kg yes, `1.5891` kg no. */\nexport function isValidQuantity(quantity: number, unit: Measurable): boolean {\n if (!Number.isFinite(quantity) || quantity < 0) return false;\n return isWhole(quantity * 10 ** unit.precision);\n}\n\n/**\n * A quantity in `unit` → whole base units. `1.589` kg → `1589` g.\n *\n * The `Math.round` removes binary dust (`1.589 * 1000` is `1588.9999999999998`), it does not\n * round the value: `assertUnitSane` guarantees the true product is an integer, and the throw\n * below fires rather than letting a bad unit pass silently.\n */\nexport function toBase(quantity: number, unit: Measurable): number {\n const exact = quantity * unit.ratioToBase;\n const whole = Math.round(exact);\n if (!isWhole(exact))\n throw new Error(\n `${quantity} ${unit.abbreviation} is ${exact} base units — not whole. ` +\n `Check the quantity against precision ${unit.precision}.`,\n );\n return whole;\n}\n\n/** Base units → a quantity in `unit`. `38911` g → `38.911` kg. May be fractional; for display. */\nexport function fromBase(baseQuantity: number, unit: Measurable): number {\n return baseQuantity / unit.ratioToBase;\n}\n\n/**\n * How much of `unit` the pool can still serve, at that unit's own precision — NOT a whole count.\n * `38911` g of a 500 g pack at precision 2 is `77.82` packs, and 0.82 of a pack is sellable when\n * the unit says two decimals are. Only precision 0 makes the result an integer.\n */\nexport function availableIn(baseQuantity: number, unit: Measurable): number {\n const step = unit.ratioToBase / 10 ** unit.precision;\n return Math.floor(baseQuantity / step) / 10 ** unit.precision;\n}\n\n/** `38911` g in kilograms → `\"38.911\"`. Rounding happens here, on the way to a screen, never on write. */\nexport function formatQuantity(baseQuantity: number, unit: Measurable): string {\n return fromBase(baseQuantity, unit).toFixed(unit.precision);\n}\n\n/**\n * Format a quantity that is ALREADY on the unit's own scale — a typed amount, a live preview.\n *\n * `formatQuantity` takes base units and divides; this one does not divide. Use it for the number\n * a person is entering, before it becomes stock.\n */\nexport function formatInUnit(quantity: number, unit: Measurable): string {\n return quantity.toFixed(unit.precision);\n}\n\n/** Snap a typed quantity to what the unit accepts. `1.5891` at precision 3 → `1.589`. */\nexport function roundToPrecision(quantity: number, precision: number): number {\n const scale = 10 ** precision;\n return Math.round(quantity * scale) / scale;\n}\n\n/**\n * Line extension: unit price × quantity → minor currency units, with the PRODUCT rounded half-up\n * exactly once.\n *\n * `priceMinor` is normalised on the way in, not rounded a second time: money is integral\n * everywhere upstream, and `BigInt` refuses a fraction outright — without the coercion a stray\n * `1799.6` would throw a RangeError instead of billing 1800.\n *\n * `4.234` litres at `1800` per litre → `7621`, not `7200`.\n *\n * Money is integral everywhere in the platform, so a line total must never be reached by\n * multiplying two floats. But a measured quantity is not an integer, and the usual fix —\n * coercing it to one before the multiply — silently charges for a different amount than left\n * the shelf. Both directions are wrong: `4.6` rounded up overcharges, `0.456` rounded down\n * charges nothing at all for goods that are gone.\n *\n * The quantity is scaled into an integer, multiplied in `BigInt`, and divided back half-up.\n * Nothing is approximate between the inputs and that single final rounding. Fixed per-unit\n * discounts and fees extend the same way.\n *\n * No unit is needed: `assertUnitSane` caps precision at {@link MAX_PRECISION}, so scaling by\n * `10^MAX_PRECISION` makes *any* valid quantity whole. Which quantities are valid is a\n * different question, answered by `isValidQuantity` where the variant is known — see\n * {@link extendPriceFor} when you hold the unit and want both at once.\n */\nexport function extendPrice(priceMinor: number, quantity: number): number {\n const scale = 10 ** MAX_PRECISION;\n const scaled = BigInt(Math.round(priceMinor)) * BigInt(Math.round(quantity * scale));\n const divisor = BigInt(scale);\n return Number((scaled + divisor / 2n) / divisor);\n}\n\n/** {@link extendPrice}, refusing a quantity the unit could never express. */\nexport function extendPriceFor(priceMinor: number, quantity: number, unit: Measurable): number {\n if (!isValidQuantity(quantity, unit))\n throw new Error(`${quantity} ${unit.abbreviation} has more decimals than precision ${unit.precision} allows.`);\n return extendPrice(priceMinor, quantity);\n}\n","import { extendPrice } from '../units/convert';\n\n/**\n * Order-total anchors, defined once for every consumer.\n *\n * These are the figures the order page, the reports and the receipts must all agree on. Keeping\n * the arithmetic here rather than at each call site is the point: the same number was previously\n * reassembled in three places and drifted between them.\n */\n\n/** Wire money is `string | number` on some surfaces (Mongoose Decimal serialises as a string). */\ntype MoneyInput = number | string | null | undefined;\n\nfunction toMinorUnits(value: MoneyInput): number {\n return Number(value) || 0;\n}\n\n/**\n * **Total Collected** — what actually hit the drawer and the processor for one order.\n *\n * ```\n * totalCollected = order.summary.amountPaid + order.summary.tipTotal\n * ```\n *\n * Both inputs are persisted fields written by the POS from the same `paymentMethods[]` array:\n * `amountPaid` is Σ `paymentMethods[].amount` (base only — every leg, liability tenders included),\n * and `tipTotal` is Σ `paymentMethods[].tip.amount`. Cash rounding needs no term of its own: the\n * writer has already folded it into the cash leg's `amount`.\n *\n * Do not substitute `summary.total` — that field is `base + tip` ignoring cash rounding, so it\n * equals neither this anchor nor `totalBeforeTip`.\n *\n * Note this is not `amountCollected` from the Sales Breakdown report\n * (`summary.payments.cardTotal + cashTotal + customTotal`), which is tips-exclusive and skips the\n * `redeem` bucket. That figure answers \"how much settles\", this one answers \"how much the\n * customer handed over\".\n *\n * @param amountPaid `order.summary.amountPaid`\n * @param tipTotal `order.summary.tipTotal`\n * @returns integer minor units\n */\nexport function getTotalCollected(amountPaid: MoneyInput, tipTotal: MoneyInput): number {\n return toMinorUnits(amountPaid) + toMinorUnits(tipTotal);\n}\n\n/**\n * **What one tender leg took** — its principal plus the tip captured on it.\n *\n * `paymentMethods[].amount` is the base only; the tip lives in `.tip.amount`. Cash rounding needs\n * no term because the writer has already folded it into `amount`, so adding it here would\n * double-count it and break `Σ legs ≡ Total Collected`.\n *\n * @param amount `paymentMethods[].amount`\n * @param tipAmount `paymentMethods[].tip.amount`\n * @returns integer minor units\n */\nexport function getPaymentLegTotal(amount: MoneyInput, tipAmount: MoneyInput): number {\n return toMinorUnits(amount) + toMinorUnits(tipAmount);\n}\n\n/**\n * **What a cash leg was owed** before the till rounded it to the nearest increment.\n *\n * `cashRounding` is a signed delta already inside `amount` (`rounded − owed`), so removing it\n * recovers what the cashier actually had to collect. Reads back as the \"Amount due\" line above\n * the rounding line on a receipt.\n *\n * @param amount `paymentMethods[].amount`\n * @param cashRounding `paymentMethods[].cashRounding`\n * @returns integer minor units\n */\nexport function getCashAmountDue(amount: MoneyInput, cashRounding: MoneyInput): number {\n return toMinorUnits(amount) - toMinorUnits(cashRounding);\n}\n\n/** The writer's settlement block — `summary.payments`. Liability (`redeem`) tenders are excluded. */\nexport interface SettlementBuckets {\n cardTotal?: MoneyInput;\n cashTotal?: MoneyInput;\n customTotal?: MoneyInput;\n}\n\n/**\n * **What actually settles** to the bank.\n *\n * The writer already bucketed the tender legs into `summary.payments` and skipped the `redeem`\n * bucket while doing it — a gift-card redemption discharges an obligation taken on when the card\n * was sold, so no new money arrives and nothing settles. Those buckets hold\n * `paymentMethods[].amount` only, and a tip is charged to the card and reaches the bank with it,\n * so the tips are added back — the same thing hub-api's settlement report does before computing\n * the deposit (`cardsCollected = orderCardTotal + grossTips`).\n *\n * Equals {@link getTotalCollected} on any order without a redemption; the difference between them\n * is exactly what was redeemed.\n *\n * @param payments `order.summary.payments`\n * @param tipTotal `order.summary.tipTotal`\n * @returns integer minor units\n */\nexport function getSettlementTotal(payments: SettlementBuckets | undefined | null, tipTotal: MoneyInput): number {\n return (\n toMinorUnits(payments?.cardTotal) +\n toMinorUnits(payments?.cashTotal) +\n toMinorUnits(payments?.customTotal) +\n toMinorUnits(tipTotal)\n );\n}\n\n/**\n * **A line's subtotal** — unit price × quantity, before discounts, fees and tax.\n *\n * Product lines persist this as `lineItems[].subTotal`, so read the field there. Custom sales do\n * not carry it — `OrderCustomSale` has no such property in the schema, and the stored documents\n * confirm it — but the figure is still the first row of the line's breakdown, and it is the\n * definition of the field rather than a re-derivation of one.\n *\n * @param price line `price` (unit price)\n * @param quantity line `quantity`\n * @returns integer minor units\n */\nexport function getLineSubtotal(price: MoneyInput, quantity: MoneyInput): number {\n // `extendPrice`, not a bare multiply: a variant sold by measure carries a real fraction here, and\n // `1800 * 4.234` is `7621.2` — a float, in a function that promises integer minor units. There is\n // one place in the platform that multiplies a price by a quantity, and this is not a second one.\n return extendPrice(toMinorUnits(price), toMinorUnits(quantity));\n}\n\n/**\n * **The goods portion of a line** — its total with the tax taken back out.\n *\n * A refunded custom sale is shown as goods and tax on separate rows, and the stored `total`\n * carries both. Never render the difference as a \"net\" of a *sale* line: tax is rounded on a\n * table-wide aggregate, so a per-line net plus its tax can land a cent off the gross the customer\n * paid. On a refund line the two rows are the refund's own components and do foot.\n *\n * @param total line `total`\n * @param totalTax line `totalTax`\n * @returns integer minor units\n */\nexport function getGoodsPortion(total: MoneyInput, totalTax: MoneyInput): number {\n return toMinorUnits(total) - toMinorUnits(totalTax);\n}\n","import { PricingRegionEnum } from '../enums';\n\nexport interface CurrencyRate {\n rate: number;\n country: string;\n}\n\nexport const REGION_MAPPING: Record<string, PricingRegionEnum> = {\n // North America\n US: PricingRegionEnum.NORTH_AMERICA,\n CA: PricingRegionEnum.NORTH_AMERICA,\n MX: PricingRegionEnum.NORTH_AMERICA,\n\n // Europe\n AT: PricingRegionEnum.EUROPE,\n BE: PricingRegionEnum.EUROPE,\n BG: PricingRegionEnum.EUROPE,\n CH: PricingRegionEnum.EUROPE,\n CY: PricingRegionEnum.EUROPE,\n CZ: PricingRegionEnum.EUROPE,\n DE: PricingRegionEnum.EUROPE,\n DK: PricingRegionEnum.EUROPE,\n EE: PricingRegionEnum.EUROPE,\n ES: PricingRegionEnum.EUROPE,\n FI: PricingRegionEnum.EUROPE,\n FR: PricingRegionEnum.EUROPE,\n GB: PricingRegionEnum.EUROPE, // Stripe uses 'GB' (not 'UK')\n GR: PricingRegionEnum.EUROPE,\n HR: PricingRegionEnum.EUROPE,\n HU: PricingRegionEnum.EUROPE,\n IE: PricingRegionEnum.EUROPE,\n IT: PricingRegionEnum.EUROPE,\n LI: PricingRegionEnum.EUROPE,\n LT: PricingRegionEnum.EUROPE,\n LU: PricingRegionEnum.EUROPE,\n LV: PricingRegionEnum.EUROPE,\n MT: PricingRegionEnum.EUROPE,\n NL: PricingRegionEnum.EUROPE,\n NO: PricingRegionEnum.EUROPE,\n PL: PricingRegionEnum.EUROPE,\n PT: PricingRegionEnum.EUROPE,\n RO: PricingRegionEnum.EUROPE,\n SE: PricingRegionEnum.EUROPE,\n SI: PricingRegionEnum.EUROPE,\n SK: PricingRegionEnum.EUROPE,\n GI: PricingRegionEnum.EUROPE, // Gibraltar (NEW)\n\n // Others (Asia-Pacific, Middle East, South America, etc.)\n AE: PricingRegionEnum.OTHER, // United Arab Emirates\n AU: PricingRegionEnum.OTHER, // Australia\n BR: PricingRegionEnum.OTHER, // Brazil (NEW)\n HK: PricingRegionEnum.OTHER, // Hong Kong\n IN: PricingRegionEnum.OTHER, // India (NEW)\n JP: PricingRegionEnum.OTHER, // Japan\n MY: PricingRegionEnum.OTHER, // Malaysia\n NZ: PricingRegionEnum.OTHER, // New Zealand\n SG: PricingRegionEnum.OTHER, // Singapore\n TH: PricingRegionEnum.OTHER, // Thailand\n};\n\nexport const STRIPE_SUPPORTED_COUNTRIES = new Set([\n // North America\n 'US',\n 'CA',\n 'MX',\n // Europe\n 'AT',\n 'BE',\n 'BG',\n 'CH',\n 'CY',\n 'CZ',\n 'DE',\n 'DK',\n 'EE',\n 'ES',\n 'FI',\n 'FR',\n 'GB',\n 'GR',\n 'HR',\n 'HU',\n 'IE',\n 'IT',\n 'LI',\n 'LT',\n 'LU',\n 'LV',\n 'MT',\n 'NL',\n 'NO',\n 'PL',\n 'PT',\n 'RO',\n 'SE',\n 'SI',\n 'SK',\n // Others\n 'AE', // United Arab Emirates\n 'AU', // Australia\n 'BR', // Brazil (NEW)\n 'GI', // Gibraltar (NEW)\n 'HK', // Hong Kong\n 'IN', // India (NEW)\n 'JP', // Japan\n 'MY', // Malaysia\n 'NZ', // New Zealand\n 'SG', // Singapore\n 'TH', // Thailand\n]);\nexport const NAFixedRates: Record<string, CurrencyRate> = {\n USD: { rate: 30, country: 'United States' },\n CAD: { rate: 20, country: 'Canada' },\n MXN: { rate: 300, country: 'Mexico' },\n};\nexport const EUFixedRates: Record<string, CurrencyRate> = {\n EUR: { rate: 30, country: 'European Union' },\n GBP: { rate: 20, country: 'Great Britain' },\n CHF: { rate: 30, country: 'Switzerland' },\n DKK: { rate: 180, country: 'Denmark' },\n NOK: { rate: 200, country: 'Norway' },\n SEK: { rate: 180, country: 'Sweden' },\n PLN: { rate: 100, country: 'Poland' },\n};\nexport const OtherFixedRates: Record<string, CurrencyRate> = {\n AUD: { rate: 30, country: 'Australia' },\n NZD: { rate: 30, country: 'New Zealand' },\n SGD: { rate: 50, country: 'Singapore' },\n MYR: { rate: 100, country: 'Malaysia' },\n JPY: { rate: 30, country: 'Japan' },\n};\n\nexport const COUNTRY_CURRENCIES: Record<string, string> = {\n US: 'USD', CA: 'CAD', MX: 'MXN',\n AT: 'EUR', BE: 'EUR', BG: 'BGN', CH: 'CHF', CY: 'EUR', CZ: 'CZK',\n DE: 'EUR', DK: 'DKK', EE: 'EUR', ES: 'EUR', FI: 'EUR', FR: 'EUR',\n GB: 'GBP', GI: 'GIP', GR: 'EUR', HR: 'EUR', HU: 'HUF', IE: 'EUR',\n IT: 'EUR', LI: 'CHF', LT: 'EUR', LU: 'EUR', LV: 'EUR', MT: 'EUR',\n NL: 'EUR', NO: 'NOK', PL: 'PLN', PT: 'EUR', RO: 'RON', SE: 'SEK',\n SI: 'EUR', SK: 'EUR',\n AE: 'AED', AU: 'AUD', BR: 'BRL', HK: 'HKD', IN: 'INR', JP: 'JPY',\n MY: 'MYR', NZ: 'NZD', SG: 'SGD', TH: 'THB',\n};","import { PricingRegionEnum } from '../enums';\nimport { REGION_MAPPING, NAFixedRates, EUFixedRates, OtherFixedRates, CurrencyRate } from 'constants/pricing.constants';\n\nexport function getPricingRegionFromCountry(countryCode?: string): PricingRegionEnum {\n const code = (countryCode || '').toUpperCase();\n if (NORTH_AMERICA.has(code)) return PricingRegionEnum.NORTH_AMERICA;\n if (EUROPE.has(code)) return PricingRegionEnum.EUROPE;\n return PricingRegionEnum.OTHER;\n}\n\nexport const NORTH_AMERICA = getCountriesByRegion(PricingRegionEnum.NORTH_AMERICA);\nexport const EUROPE = getCountriesByRegion(PricingRegionEnum.EUROPE);\n\n// TODO_J: Rely on external api to know the exchange rate between USD and the local currency\nexport function convertFixedFeeToLocalCurrency(currency: string, region: PricingRegionEnum): number {\n const currencyCode = currency.toUpperCase();\n let fixedRate: CurrencyRate | undefined;\n\n switch (region) {\n case PricingRegionEnum.NORTH_AMERICA: {\n fixedRate = NAFixedRates[currencyCode];\n break;\n }\n case PricingRegionEnum.EUROPE: {\n fixedRate = EUFixedRates[currencyCode];\n break;\n }\n case PricingRegionEnum.OTHER: {\n fixedRate = OtherFixedRates[currencyCode];\n break;\n }\n }\n return fixedRate?.rate ?? null;\n}\n\nexport function getCountriesByRegion(region: PricingRegionEnum): Set<string> {\n const countries = new Set<string>();\n for (const [country, mappedRegion] of Object.entries(REGION_MAPPING)) {\n if (mappedRegion === region) {\n countries.add(country);\n }\n }\n return countries;\n}\n","import { EndOfSessionReport } from '@/interfaces/Report.interface';\n\n// Paths whose numeric values must be negated when leaving the wire.\n// Backend persists raw positive magnitudes; this is the one place that\n// flips them for display. UI prefix glyphs (\"+ Tips\", \"− Refunds\") are\n// a presentation concern and live in the frontend, not here.\n//\n// Path key uses dot notation. Append `[]` to descend into every array\n// item. Unmatched numeric fields pass through unchanged.\nexport const REPORT_NEGATE_PATHS: ReadonlySet<string> = new Set([\n // Sales summary — reductions to revenue\n 'salesSummary.discounts.netDiscounts',\n 'salesSummary.refundsItems',\n\n // Settlement — money going out of the merchant\n 'settlementBreakdown.cards.refunded',\n 'settlementBreakdown.cards.processingFees',\n 'settlementBreakdown.cash.refunded',\n 'settlementBreakdown.custom[].refunded',\n 'settlementBreakdown.custom[].processingFees',\n\n // Tax breakdown — refunds sub-table renders signed-negative\n 'taxBreakdown.refunds.entries[].taxableSales',\n 'taxBreakdown.refunds.entries[].tax',\n 'taxBreakdown.refunds.total.taxableSales',\n 'taxBreakdown.refunds.total.tax',\n\n // Refunds breakdown — reductions and naturally-signed entries\n 'refundsBreakdown.discountsReversed',\n // 2026 AUG10, cashRoundingRefund is showing as natural sign\n // 'refundsBreakdown.cashRoundingRefund',\n\n // Fees breakdown — refunded magnitudes are money flowing back out\n 'feesBreakdown.productFee.refundedProductFees',\n 'feesBreakdown.cartFee.refundedCartFees',\n\n // Modifiers breakdown — refunded magnitudes are money flowing back out\n 'modifiersBreakdown.refundTotal',\n\n // Discounts breakdown — refunded magnitudes reverse discount reductions\n 'discountsBreakdown.productDiscounts.refundedProductDiscounts',\n 'discountsBreakdown.cartDiscounts.refundedCartDiscounts',\n\n // Staff sales — refunds are money flowing back out\n 'staffSales.staffSales[].refundSales',\n 'staffSales.refundTotal',\n\n // Tips — refunds are money flowing back out\n 'tipsBreakdown.tips[].refundAmount',\n]);\n\nexport function signReportForDisplay(report: EndOfSessionReport): EndOfSessionReport {\n return negateAtPaths(report, '', REPORT_NEGATE_PATHS) as EndOfSessionReport;\n}\n\nfunction negateAtPaths(value: unknown, path: string, paths: ReadonlySet<string>): unknown {\n if (Array.isArray(value)) {\n const next = `${path}[]`;\n return value.map((item) => negateAtPaths(item, next, paths));\n }\n if (value !== null && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n const next = path ? `${path}.${key}` : key;\n out[key] = negateAtPaths(child, next, paths);\n }\n return out;\n }\n if (typeof value === 'number' && paths.has(path)) {\n // Avoid producing negative zero: formatters that branch on `value < 0`\n // miss `-0` (IEEE-754 says `-0 < 0` is false), then render `-0` as\n // `$-0.00` instead of `$0.00`. Normalize zero before negating.\n return value === 0 ? 0 : -value;\n }\n return value;\n}\n","// Mongo-id helpers shared across the POS frontend packages (Render + port-louis).\n\nfunction padHex(value: number, length: number) {\n return value.toString(16).padStart(length, '0');\n}\n\n// Canonical MongoDB ObjectId layout (24 hex = 12 bytes):\n// 4-byte timestamp (seconds) + 5-byte per-process random + 3-byte monotonic counter.\n// `PROCESS_RANDOM` is generated ONCE per session (not per call), and the counter is a\n// real incrementing value seeded randomly — fixing the previous impl where the machine/pid\n// bytes were re-randomized every call and the \"counter\" was effectively random (dead).\n// No external dependency (common stays dependency-light); not crypto-grade, same as before.\nconst PROCESS_RANDOM: string = Array.from({ length: 5 }, () => padHex(Math.floor(Math.random() * 0x100), 2)).join('');\n\nlet objectIdCounter = Math.floor(Math.random() * 0xffffff);\n\nexport function generateMongoID(): string {\n const timestamp = padHex(Math.floor(Date.now() / 1000), 8);\n objectIdCounter = (objectIdCounter + 1) % 0x1000000;\n return timestamp + PROCESS_RANDOM + padHex(objectIdCounter, 6);\n}\n\nexport function getCurrentISODate() {\n const now = new Date(Date.now());\n\n return now.toISOString();\n}\n\n/** Normalize sync / Redux ids (string or `{ $oid }`) to a 24-char hex string when possible. */\nexport function normalizeMongoIdString(value: unknown): string | null {\n if (value == null || value === '') {\n return null;\n }\n if (typeof value === 'string') {\n const t = value.trim();\n return t.length > 0 ? t : null;\n }\n if (typeof value === 'object' && value !== null && '$oid' in value) {\n const oid = (value as { $oid: unknown }).$oid;\n return typeof oid === 'string' && oid.length > 0 ? oid : null;\n }\n return null;\n}\n","import { SYSTEM_FAMILIES } from './system-units';\n\n/**\n * Where a merchant family's code comes from.\n *\n * The code is derived **once**, at creation, from the name and the company: `wine-<companyId>`.\n * After that the merchant renames the family as often as they like and the code does not move —\n * every unit already points at it, and an order line points at a unit whose `ratioToBase` only\n * means anything against its family's base.\n *\n * It is readable in a log and nothing more: **never parse it back**. Pulling `companyId` out of it\n * would freeze the format forever and would lie the first time a row is copied between companies —\n * which already happens, in `cloneCollection`.\n *\n * A code stays taken forever, including by a soft-deleted family, so a family recreated under an\n * old name gets a discriminator: `wine-2-<companyId>`. Freeing the code would retroactively change\n * what old stored numbers mean.\n */\n\n/**\n * Longest the readable part may be. Not arithmetic — the code travels in a URL path\n * (`PATCH /units/families/:code`) and is stored on every unit of the family, and a merchant who\n * types a sentence as a name should not make either of those unwieldy.\n */\nconst MAX_SLUG_LENGTH = 32;\n\n/** What a name slugs to when nothing survives the cleanup. */\nconst FALLBACK_SLUG = 'family';\n\nconst SYSTEM_FAMILY_CODES: ReadonlySet<string> = new Set(SYSTEM_FAMILIES.map((family) => family.familyId));\n\n/**\n * ASCII only, because the code is a URL segment and comparing percent-encoded forms of the same\n * name is a bug waiting to happen. Accents decompose first, so `Bière` still reads as `biere`; a\n * name in a non-Latin script has nothing left afterwards and falls back — the code is decoration,\n * and refusing to create the family over it would be a worse answer than an unreadable code.\n */\nfunction slugify(name: string): string {\n const slug = name\n .normalize('NFKD')\n .replace(/\\p{Diacritic}/gu, '')\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .slice(0, MAX_SLUG_LENGTH)\n .replace(/^-+|-+$/g, '');\n return slug || FALLBACK_SLUG;\n}\n\n/**\n * The code for a new merchant family, free of `takenCodes` and of the seeded codes.\n *\n * Pass every code the company has ever used — deleted families included. The first free candidate\n * wins, so the discriminator counts up only as far as the collisions actually go.\n */\nexport function deriveFamilyCode(name: string, companyId: string, takenCodes: Iterable<string> = []): string {\n if (!companyId) throw new Error(`Cannot derive a family code for \"${name}\" without a companyId.`);\n const taken = new Set(takenCodes);\n const slug = slugify(name);\n for (let attempt = 1; ; attempt++) {\n const code = attempt === 1 ? `${slug}-${companyId}` : `${slug}-${attempt}-${companyId}`;\n if (!taken.has(code) && !isSystemFamilyCode(code)) return code;\n }\n}\n\n/**\n * Would this code shadow a seeded family?\n *\n * `resolveFamily` looks at the seeded list first, so a merchant family carrying a seeded code would\n * be invisible with no error anywhere. The `-<companyId>` suffix makes that unreachable in\n * practice; the check costs a set lookup and does not depend on that argument staying true.\n */\nexport function isSystemFamilyCode(code: string): boolean {\n return SYSTEM_FAMILY_CODES.has(code);\n}\n\n/**\n * The id a merchant unit is known by: `<abbreviation>-<document id>`, e.g. `gl-6a83f19c2b7e…`.\n *\n * Derived once at creation and never again — a variant, an order line and every stock movement\n * point at it, and renaming the unit or changing what it is worth must not move it. The document's\n * own `_id` supplies the uniqueness; the slug is there so a human reading a log or a stored order\n * can tell what they are looking at. **Never parse it back**: the same reasoning as a family code.\n *\n * A seeded unit has no document and no need for this — it carries its Rec 20 code (`KGM`).\n */\nexport function deriveUnitId(abbreviation: string, documentId: string): string {\n if (!documentId) throw new Error(`Cannot derive a unit id for \"${abbreviation}\" without a document id.`);\n return `${slugify(abbreviation)}-${documentId}`;\n}\n","/** Financial lifecycle of an order. */\nexport type PaymentState =\n | 'unpaid'\n | 'payment_pending'\n | 'partially_paid'\n | 'paid'\n | 'partially_refunded'\n | 'refunded'\n | 'voided';\n\n/** Operational lifecycle of an order (goods/services, including returns). */\nexport type FulfillmentState =\n | 'draft'\n | 'pending'\n | 'on_hold'\n | 'in_progress'\n | 'fulfilled'\n | 'partially_fulfilled'\n | 'returned'\n | 'partially_returned'\n | 'cancelled';\n\nexport const PAYMENT_STATES: readonly PaymentState[] = [\n 'unpaid',\n 'payment_pending',\n 'partially_paid',\n 'paid',\n 'partially_refunded',\n 'refunded',\n 'voided',\n] as const;\n\nexport const FULFILLMENT_STATES: readonly FulfillmentState[] = [\n 'draft',\n 'pending',\n 'on_hold',\n 'in_progress',\n 'fulfilled',\n 'partially_fulfilled',\n 'returned',\n 'partially_returned',\n 'cancelled',\n] as const;\n\nexport function isPaymentState(value: string): value is PaymentState {\n return (PAYMENT_STATES as readonly string[]).includes(value);\n}\n\nexport function isFulfillmentState(value: string): value is FulfillmentState {\n return (FULFILLMENT_STATES as readonly string[]).includes(value);\n}\n\n/** Payment × fulfillment pair used by the engine, guards, and `StateConfig.validInitialStates`. */\nexport interface StatePair {\n payment: PaymentState;\n fulfillment: FulfillmentState;\n}\n\n/** Operators for transition conditions (closed set). */\nexport type ConditionOperator =\n | 'eq'\n | 'neq'\n | 'gt'\n | 'gte'\n | 'lt'\n | 'lte'\n | 'in'\n | 'notIn'\n | 'isEmpty'\n | 'isNotEmpty';\n\nexport const CONDITION_OPERATORS: readonly ConditionOperator[] = [\n 'eq',\n 'neq',\n 'gt',\n 'gte',\n 'lt',\n 'lte',\n 'in',\n 'notIn',\n 'isEmpty',\n 'isNotEmpty',\n] as const;\n\nexport function isConditionOperator(value: string): value is ConditionOperator {\n return (CONDITION_OPERATORS as readonly string[]).includes(value);\n}\n\n/** Path enforcement mode per axis. */\nexport type PathMode = 'strict' | 'permissive';\n\nexport const PATH_MODES: readonly PathMode[] = [\n 'strict',\n 'permissive',\n] as const;\n","import type { FulfillmentStateDefinition, PaymentStateDefinition } from './interfaces';\nimport type { FulfillmentState, PaymentState } from './types';\n\nexport interface StateSchema {\n readonly paymentStates: readonly PaymentStateDefinition[];\n readonly fulfillmentStates: readonly FulfillmentStateDefinition[];\n}\n\nconst PAYMENT_DEFS: { id: PaymentState; label: string; terminal: boolean }[] = [\n { id: 'unpaid', label: 'Unpaid', terminal: false },\n { id: 'payment_pending', label: 'Payment Pending', terminal: false },\n { id: 'partially_paid', label: 'Partially Paid', terminal: false },\n { id: 'paid', label: 'Paid', terminal: false },\n { id: 'partially_refunded', label: 'Partially Refunded', terminal: false },\n { id: 'refunded', label: 'Refunded', terminal: true },\n { id: 'voided', label: 'Voided', terminal: true },\n];\n\nconst FULFILLMENT_DEFS: { id: FulfillmentState; label: string; terminal: boolean }[] = [\n { id: 'draft', label: 'Draft', terminal: false },\n { id: 'pending', label: 'Pending', terminal: false },\n // 'Parked' is the product term for a held order (OS bug #30) — the atom id\n // stays `on_hold`; only the human label realigns.\n { id: 'on_hold', label: 'Parked', terminal: false },\n { id: 'in_progress', label: 'In Progress', terminal: false },\n { id: 'fulfilled', label: 'Fulfilled', terminal: true },\n { id: 'partially_fulfilled', label: 'Partially Fulfilled', terminal: false },\n { id: 'returned', label: 'Returned', terminal: true },\n { id: 'partially_returned', label: 'Partially Returned', terminal: false },\n { id: 'cancelled', label: 'Cancelled', terminal: true },\n];\n\nexport function basePaymentDefinitions(): PaymentStateDefinition[] {\n return PAYMENT_DEFS.map((d) => ({\n id: d.id,\n label: d.label,\n isBase: true,\n isTerminal: d.terminal,\n }));\n}\n\nexport function baseFulfillmentDefinitions(): FulfillmentStateDefinition[] {\n return FULFILLMENT_DEFS.map((d) => ({\n id: d.id,\n label: d.label,\n isBase: true,\n isTerminal: d.terminal,\n }));\n}\n\nexport const STATE_SCHEMA: Readonly<StateSchema> = Object.freeze({\n paymentStates: Object.freeze(basePaymentDefinitions()),\n fulfillmentStates: Object.freeze(baseFulfillmentDefinitions()),\n});\n","import type { FinancialInvariant } from './interfaces';\nimport type { PaymentState, StatePair } from './types';\n\nconst REFUND_ALLOWED_FULFILLMENT = new Set<string>(['fulfilled', 'returned', 'partially_returned', 'cancelled']);\n\n// Payment states ordered by collection progress. Any move that decreases\n// the index is a regression — money was collected but is being \"un-collected\"\n// without going through a refund flow.\nconst PAYMENT_COLLECTION_ORDER: readonly PaymentState[] = ['unpaid', 'partially_paid', 'paid'];\n\n// Payment states that carry captured money not yet fully returned. Used as a\n// pure pair-level money fact: an order can only reach one of these states by\n// capturing real money, and only leave it through the refund flow (a refund\n// landing carries `refunded`, a void carries `voided`).\nconst UNRETURNED_MONEY_STATES = new Set<PaymentState>(['partially_paid', 'paid', 'partially_refunded']);\n\n// The two canonical fulfillment landings for a fully refunded order:\n// `returned` (was fulfilled) and `cancelled` (never fulfilled).\nconst REFUNDED_FULFILLMENT_LANDINGS = new Set<string>(['returned', 'cancelled']);\n\n/**\n * Layer 1a — hard-coded, non-configurable financial integrity checks.\n * `check` returns true when the requested transition **violates** the invariant.\n */\nexport const FINANCIAL_INVARIANTS: readonly FinancialInvariant[] = [\n {\n id: 'no-leave-refunded',\n description: 'Cannot change payment state after a full refund (no un-refund / reactivation of funds)',\n check: (from: StatePair | null, to: StatePair) => from?.payment === 'refunded' && to.payment !== 'refunded',\n },\n {\n id: 'no-leave-voided',\n description: 'Cannot un-void payment (voided orders stay voided on the payment axis)',\n check: (from: StatePair | null, to: StatePair) => from?.payment === 'voided' && to.payment !== 'voided',\n },\n {\n id: 'no-refund-without-fulfillment',\n description: 'Cannot mark payment as fully refunded unless fulfillment is delivered, returned, or cancelled',\n check: (_from: StatePair | null, to: StatePair) =>\n to.payment === 'refunded' && !REFUND_ALLOWED_FULFILLMENT.has(to.fulfillment),\n },\n {\n id: 'no-partial-refund-in-draft',\n description: 'Cannot partially refund while order is still in draft fulfillment',\n check: (_from: StatePair | null, to: StatePair) =>\n to.payment === 'partially_refunded' && to.fulfillment === 'draft',\n },\n {\n id: 'no-payment-regression',\n description:\n 'Payment cannot regress to a lower collection state without a refund — collected funds must be returned through the refund flow, not by reverting payment state',\n check: (from: StatePair | null, to: StatePair) => {\n if (!from) return false;\n const fromIdx = PAYMENT_COLLECTION_ORDER.indexOf(from.payment);\n const toIdx = PAYMENT_COLLECTION_ORDER.indexOf(to.payment);\n return fromIdx !== -1 && toIdx !== -1 && fromIdx > toIdx;\n },\n },\n {\n id: 'no-cancel-with-unreturned-payments',\n description:\n 'Fulfillment cannot enter cancelled while the payment state carries unreturned captured money (paid / partially_paid / partially_refunded) — return the money first: a full refund of an unfulfilled order lands refunded × cancelled, a void lands voided × cancelled. Scoped to the cancelling MOVE (from.fulfillment !== cancelled) so payment-axis edges evaluated against an already-cancelled fulfillment do not trip it',\n check: (from: StatePair | null, to: StatePair) =>\n from !== null &&\n from.fulfillment !== 'cancelled' &&\n to.fulfillment === 'cancelled' &&\n UNRETURNED_MONEY_STATES.has(to.payment),\n },\n {\n id: 'no-draft-regression-with-captured-payments',\n description:\n 'Fulfillment cannot regress to draft once money has been captured — a money-carrying order is no longer a cart (bug #31: resume lands deposit orders on in_progress for the same reason). New orders and draft-to-draft moves are exempt, so partially_paid × draft remains declarable as an initial state',\n check: (from: StatePair | null, to: StatePair) =>\n from !== null && from.fulfillment !== 'draft' && to.fulfillment === 'draft' && to.payment !== 'unpaid',\n },\n {\n id: 'no-reopen-voided-fulfillment',\n description:\n 'A voided order exists only at cancelled fulfillment: a voided order cannot re-enter fulfillment, and a voided × non-cancelled pair cannot be materialized from nothing (complements no-leave-voided, which only freezes the payment axis). Moves INTO voided from a live payment state are the void flow’s concern, not this rule’s',\n check: (from: StatePair | null, to: StatePair) =>\n (from === null || from.payment === 'voided') && to.payment === 'voided' && to.fulfillment !== 'cancelled',\n },\n {\n id: 'no-reopen-refunded-fulfillment',\n description:\n 'A fully refunded order cannot re-enter fulfillment — it may only relabel between its canonical landings, returned and cancelled (complements no-leave-refunded, which only freezes the payment axis)',\n check: (from: StatePair | null, to: StatePair) =>\n from?.payment === 'refunded' && !REFUNDED_FULFILLMENT_LANDINGS.has(to.fulfillment),\n },\n] as const;\n\n/** Returns IDs of invariants violated by `from` → `to` (empty if none). */\nexport function getFinancialInvariantViolations(from: StatePair | null, to: StatePair): string[] {\n const ids: string[] = [];\n for (const inv of FINANCIAL_INVARIANTS) {\n if (inv.check(from, to)) {\n ids.push(inv.id);\n }\n }\n return ids;\n}\n\nexport function violatesFinancialInvariant(from: StatePair | null, to: StatePair): boolean {\n return getFinancialInvariantViolations(from, to).length > 0;\n}\n","import type { CrossAxisRule } from './interfaces';\n\n/**\n * Default merchant-toggleable cross-axis rules (Layer 1b).\n * Evaluation order and semantics are implemented in Phase 0b (`canTransition`).\n */\nexport const DEFAULT_CROSS_AXIS_RULES: readonly CrossAxisRule[] = [\n {\n id: 'require-payment-before-prep',\n label: 'Require payment before prep',\n description:\n 'When moving fulfillment to in progress, payment must be paid or partially paid',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'in_progress' },\n requires: { axis: 'payment', states: ['paid', 'partially_paid'] },\n },\n {\n id: 'require-fulfillment-or-return-before-full-refund',\n label: 'Require fulfillment or return before full refund',\n description:\n 'When moving payment to refunded, fulfillment must be fulfilled, returned, partially returned, or cancelled',\n enabled: true,\n trigger: { axis: 'payment', to: 'refunded' },\n requires: {\n axis: 'fulfillment',\n states: ['fulfilled', 'returned', 'partially_returned', 'cancelled'],\n },\n },\n {\n id: 'require-return-context-before-partial-refund',\n label: 'Require return path before partial refund',\n description:\n 'When moving payment to partially refunded, fulfillment must reflect a completed or return path',\n enabled: true,\n trigger: { axis: 'payment', to: 'partially_refunded' },\n requires: {\n axis: 'fulfillment',\n states: ['fulfilled', 'partially_returned', 'returned'],\n },\n },\n {\n id: 'block-fulfillment-when-payment-voided',\n label: 'Block fulfillment completion when payment is voided',\n description:\n 'When moving fulfillment to fulfilled, payment must not be voided',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'fulfilled' },\n requires: {\n axis: 'payment',\n states: ['unpaid', 'partially_paid', 'paid', 'partially_refunded', 'refunded'],\n },\n },\n {\n id: 'require-payment-before-fulfillment-complete',\n label: 'Require payment before fulfillment complete',\n description:\n 'When moving fulfillment to fulfilled, payment must be paid or partially paid',\n enabled: true,\n trigger: { axis: 'fulfillment', to: 'fulfilled' },\n requires: { axis: 'payment', states: ['paid', 'partially_paid'] },\n },\n];\n","import type { DisplayStateRule, StateConfig, StoredStateConfig } from './interfaces';\nimport type { FulfillmentState, PaymentState } from './types';\nimport { PAYMENT_STATES, FULFILLMENT_STATES } from './types';\nimport { STATE_SCHEMA, basePaymentDefinitions, baseFulfillmentDefinitions } from './state-schema';\n\nconst DEFAULT_EPOCH = new Date(0);\n\nconst PAYMENT_LABELS = new Map<PaymentState, string>(basePaymentDefinitions().map((d) => [d.id, d.label]));\nconst FULFILLMENT_LABELS = new Map<FulfillmentState, string>(baseFulfillmentDefinitions().map((d) => [d.id, d.label]));\n\nconst TERMINAL_PAYMENT_STATES = new Set<PaymentState>(\n basePaymentDefinitions()\n .filter((d) => d.isTerminal)\n .map((d) => d.id),\n);\n\nconst DISPLAY_LABEL_OVERRIDES: Record<string, string> = {\n 'unpaid|draft': 'In Cart',\n 'unpaid|pending': 'Pending Payment',\n 'unpaid|on_hold': 'Parked',\n 'unpaid|cancelled': 'Cancelled',\n 'partially_paid|pending': 'Deposit Received',\n 'partially_paid|on_hold': 'Parked - Deposit Received',\n 'partially_paid|in_progress': 'Partially Paid',\n 'paid|pending': 'Paid - Awaiting Fulfillment',\n 'paid|on_hold': 'Parked - Paid',\n 'paid|fulfilled': 'Completed',\n 'partially_refunded|fulfilled': 'Partially Refunded',\n 'partially_refunded|partially_returned': 'Partially Refunded',\n};\n\n/**\n * Product wording for a terminal payment state, where it differs from the\n * `STATE_SCHEMA` label. A terminal state with no entry here falls back to its\n * schema label, so a newly-added terminal state still gets a single clean label\n * rather than a compound one.\n *\n * `voided` reads \"Cancelled\" rather than \"Voided\" because that is what the one\n * reachable voided pair (`voided|cancelled`) already displayed — see the\n * no-relabel rule below.\n */\nconst TERMINAL_LABEL_OVERRIDES: Partial<Record<PaymentState, string>> = {\n voided: 'Cancelled',\n};\n\n/**\n * Builds one rule per payment × fulfillment pair — all 63, with no gaps.\n *\n * Label precedence is: explicit pair override → terminal payment label →\n * generic `\"<Payment> / <Fulfillment>\"` compound.\n *\n * Terminal payment states (`refunded`, `voided`) resolve by the **money fact\n * alone**: once the money is finally settled the fulfillment axis carries\n * nothing a customer needs, and a compound like \"Refunded / Draft\" reads as a\n * bug. This also matches `mapToLegacyStatus`, where a terminal payment state\n * takes precedence over fulfillment.\n *\n * Terminal rows used to be emitted ONLY where a pair override existed, which\n * left 14 pairs with no rule at all. Those fell through to\n * `deriveDisplayState`'s last-resort branch and printed raw snake_case ids\n * (\"refunded / in_progress\") onto customer-facing surfaces. `validateConfig`\n * had been reporting them as `display_map_missing_combos` all along.\n *\n * NO-RELABEL RULE: every label a reachable pair resolved to before this change\n * still resolves to the same string, so `Order.displayState` — which is\n * persisted at write time by `setOrderState`, not computed on read — needs no\n * backfill. Only previously-unlabelled pairs gained a value. Keep it that way:\n * changing a reachable label here means migrating order documents too.\n */\nfunction buildDefaultDisplayStateMap(): DisplayStateRule[] {\n const rules: DisplayStateRule[] = [];\n for (const p of PAYMENT_STATES) {\n const terminalLabel = TERMINAL_PAYMENT_STATES.has(p)\n ? (TERMINAL_LABEL_OVERRIDES[p] ?? PAYMENT_LABELS.get(p))\n : undefined;\n\n for (const f of FULFILLMENT_STATES) {\n const label =\n DISPLAY_LABEL_OVERRIDES[`${p}|${f}`] ??\n terminalLabel ??\n `${PAYMENT_LABELS.get(p)} / ${FULFILLMENT_LABELS.get(f)}`;\n rules.push({ paymentState: p, fulfillmentState: f, label });\n }\n }\n return rules;\n}\n\nexport const DEFAULT_DISPLAY_STATE_MAP: readonly DisplayStateRule[] = buildDefaultDisplayStateMap();\n\n/**\n * System default state configuration (fallback when no merchant config is synced).\n * Does NOT include paymentStates / fulfillmentStates — those live in STATE_SCHEMA.\n */\nexport const DEFAULT_CONFIG: StoredStateConfig = {\n _id: 'default',\n companyId: 'system',\n version: 1,\n name: 'Default',\n isDefault: true,\n paymentPaths: [],\n fulfillmentPaths: [],\n paymentPathMode: 'permissive',\n fulfillmentPathMode: 'permissive',\n crossAxisRules: [],\n transitionConditions: [],\n validInitialStates: [{ payment: 'unpaid', fulfillment: 'draft' }],\n displayStateMap: [...DEFAULT_DISPLAY_STATE_MAP],\n createdAt: DEFAULT_EPOCH,\n updatedAt: DEFAULT_EPOCH,\n};\n\n/** Merges a StoredStateConfig with STATE_SCHEMA into a full StateConfig. */\nexport function buildResolvedConfig(config: StoredStateConfig): StateConfig {\n return {\n ...config,\n paymentStates: STATE_SCHEMA.paymentStates,\n fulfillmentStates: STATE_SCHEMA.fulfillmentStates,\n };\n}\n\n/** Pre-built default StateConfig for engine fallbacks and tests. */\nexport const DEFAULT_RESOLVED_CONFIG: StateConfig = buildResolvedConfig(DEFAULT_CONFIG);\n","import { DEFAULT_CONFIG, DEFAULT_DISPLAY_STATE_MAP } from './default-config';\nimport type { StoredStateConfig } from './interfaces';\nimport type { StatePair } from './types';\n\n/**\n * POS-specific initial state pairs. Used the first time an order is written\n * to the DB (park, first payment, split payment first leg, gift-card quick\n * sale). A `canTransition` with `from: null` is only allowed when `to` matches\n * one of these pairs.\n *\n * - `partially_paid + in_progress` covers a deposit / first split leg on a\n * brand-new cart — the first payment advances fulfillment off `draft`, so\n * `deriveTargetState(\"pay\")` lands on `partially_paid + in_progress` until\n * a later leg completes the order and flips it to `paid + fulfilled`.\n * - `partially_paid + draft` is kept for POS builds that predate the\n * draft → in_progress writer fix (bug #31) and still emit it.\n *\n * NOTE: this list is documentation + `validateConfig` reachability seeds. It is\n * only enforced at order creation when `enforceValidInitialStates` is set on\n * the config, which the POS preset does not do.\n */\nexport const POS_VALID_INITIAL_STATES: readonly StatePair[] = [\n { payment: 'unpaid', fulfillment: 'draft' },\n { payment: 'unpaid', fulfillment: 'on_hold' },\n { payment: 'unpaid', fulfillment: 'pending' },\n { payment: 'paid', fulfillment: 'fulfilled' },\n { payment: 'partially_paid', fulfillment: 'draft' },\n { payment: 'partially_paid', fulfillment: 'pending' },\n { payment: 'partially_paid', fulfillment: 'in_progress' },\n] as const;\n\n/**\n * Build a POS preset `StoredStateConfig`. This is the baseline config POS\n * clients (Render, Hub-API fallback, tests) use when no merchant-specific\n * config has been synced.\n */\nexport function buildPosPresetConfig(companyId?: string): StoredStateConfig {\n return {\n ...DEFAULT_CONFIG,\n _id: 'pos-preset',\n companyId: companyId ?? DEFAULT_CONFIG.companyId,\n name: 'POS Preset',\n crossAxisRules: [],\n validInitialStates: [...POS_VALID_INITIAL_STATES],\n displayStateMap: [...DEFAULT_DISPLAY_STATE_MAP],\n };\n}\n","import type {\n OrderContext,\n OrderLikeForContext,\n OrderLineItem,\n OrderReservationForContext,\n SplitPayment,\n} from './interfaces';\n\nfunction sumNumbers(items: { amount?: number }[] | undefined): number {\n if (!items?.length) return 0;\n let t = 0;\n for (const x of items) {\n const n = x.amount;\n if (typeof n === 'number' && Number.isFinite(n)) t += n;\n }\n return t;\n}\n\nfunction sumRefundQuantities(\n refunds: { quantity?: number }[] | undefined\n): number {\n if (!refunds?.length) return 0;\n let t = 0;\n for (const r of refunds) {\n const q = r.quantity;\n if (typeof q === 'number' && Number.isFinite(q) && q > 0) t += q;\n }\n return t;\n}\n\nconst asCount = (value: unknown): number =>\n typeof value === 'number' && Number.isFinite(value) ? Math.max(0, value) : 0;\n\n/**\n * How much of one sold row was bought, done and given back.\n *\n * One rule for line items and reservations alike: a service is bought, performed and refunded\n * the same way a product is, and the fulfilment axis must not be able to see one and not the\n * other. `fulfilled`/`returned` are clamped to what was actually sold, so a bad row cannot push\n * an order past \"fully fulfilled\".\n */\nfunction countsOf(row: OrderLineItem | OrderReservationForContext): {\n quantity: number;\n fulfilled: number;\n returned: number;\n} {\n const quantity = asCount(row.quantity);\n return {\n quantity,\n fulfilled: Math.min(asCount(row.fulfilledQuantity), quantity),\n returned: Math.min(asCount(row.returnedQuantity), quantity),\n };\n}\n\n/**\n * Builds `OrderContext` for condition evaluation and transition checks.\n */\nexport function buildOrderContext(\n order: OrderLikeForContext | null | undefined,\n extras?: { splitPayment?: SplitPayment }\n): OrderContext {\n const o = order ?? {};\n const total = typeof o.total === 'number' && Number.isFinite(o.total) ? o.total : 0;\n const balance =\n typeof o.balance === 'number' && Number.isFinite(o.balance) ? o.balance : 0;\n const paymentMethods = o.paymentMethods ?? [];\n const refunds = o.refunds ?? o.refund ?? [];\n const lineItems = o.lineItems ?? [];\n // A sold service lives beside the goods, not among them (FT-0064), so it has to be counted\n // explicitly — every count below was blind to it, which made a booking-only order \"0 items\".\n const reservations = o.reservations ?? [];\n\n const totalPaid = sumNumbers(paymentMethods);\n const totalRefunded = sumRefundQuantities(refunds);\n const isFullyPaid = total > 0 ? balance <= 0 : totalPaid > 0 && balance <= 0;\n const hasPartialPayments = totalPaid > 0 && balance > 0;\n\n let itemCount = 0;\n let fulfilledItemCount = 0;\n let returnedItemCount = 0;\n for (const row of [...lineItems, ...reservations]) {\n const { quantity, fulfilled, returned } = countsOf(row);\n itemCount += quantity;\n fulfilledItemCount += fulfilled;\n returnedItemCount += returned;\n }\n\n const isFullyReturned =\n itemCount > 0 ? returnedItemCount >= itemCount : returnedItemCount > 0;\n const hasPartialReturns = returnedItemCount > 0 && !isFullyReturned;\n\n return {\n order: {\n total,\n balance,\n paymentMethods,\n refunds,\n lineItems,\n reservations,\n },\n computed: {\n balance,\n isFullyPaid,\n hasPartialPayments,\n totalPaid,\n totalRefunded,\n itemCount,\n fulfilledItemCount,\n returnedItemCount,\n isFullyReturned,\n hasPartialReturns,\n },\n splitPayment: extras?.splitPayment,\n };\n}\n","import type { DisplayStateResult, DisplayStateRule, StoredStateConfig } from './interfaces';\nimport { STATE_SCHEMA } from './state-schema';\n\nfunction atomLabel(atom: string, defs: readonly { id: string; label: string }[]): string {\n return defs.find((d) => d.id === atom)?.label ?? atom;\n}\n\nfunction matchesOptional<T extends string>(actual: T, rule?: T | T[]): boolean {\n if (rule === undefined) return true;\n return Array.isArray(rule) ? rule.includes(actual) : rule === actual;\n}\n\n/**\n * Resolves the first matching rule in `config.displayStateMap` (ordered list).\n */\nexport function deriveDisplayState(\n payment: string,\n fulfillment: string,\n config: StoredStateConfig,\n): DisplayStateResult {\n for (const rule of config.displayStateMap) {\n if (matchesOptional(payment, rule.paymentState) && matchesOptional(fulfillment, rule.fulfillmentState)) {\n return { label: rule.label, color: rule.color, icon: rule.icon };\n }\n }\n // No matching rule: humanize from the base STATE_SCHEMA labels rather than\n // echoing raw atom ids. Stored per-company configs snapshot displayStateMap\n // at creation, so configs predating the 63-pair default map fall through\n // here for newer pairs — deployed UIs were showing rows like\n // \"partially_paid / partially_fulfilled\". Schema labels also keep atom\n // relabels (on_hold → \"Parked\") consistent without a config migration.\n // Unknown atoms (not in the schema) keep their raw id.\n return {\n label: `${atomLabel(payment, STATE_SCHEMA.paymentStates)} / ${atomLabel(fulfillment, STATE_SCHEMA.fulfillmentStates)}`,\n };\n}\n\n/** @internal */\nexport function displayRuleMatchesPair(rule: DisplayStateRule, payment: string, fulfillment: string): boolean {\n return matchesOptional(payment, rule.paymentState) && matchesOptional(fulfillment, rule.fulfillmentState);\n}\n","import type {\n Condition,\n FailedCondition,\n OrderContext,\n TransitionConditionSet,\n} from './interfaces';\n\nfunction getByPath(root: unknown, path: string): unknown {\n const parts = path.split('.').filter(Boolean);\n let cur: unknown = root;\n for (const p of parts) {\n if (cur === null || cur === undefined) return undefined;\n if (typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[p];\n }\n return cur;\n}\n\nfunction isEmptyValue(v: unknown): boolean {\n if (v === null || v === undefined) return true;\n if (typeof v === 'string') return v.length === 0;\n if (Array.isArray(v)) return v.length === 0;\n return false;\n}\n\n/**\n * Evaluates a single condition against `OrderContext` (field paths like `order.balance`, `computed.isFullyPaid`).\n */\nexport function evaluateCondition(\n condition: Condition,\n context: OrderContext\n): { ok: boolean; failed?: FailedCondition } {\n const left = getByPath(context, condition.field);\n const op = condition.operator;\n const right = condition.value;\n\n let ok = false;\n switch (op) {\n case 'eq':\n ok = left === right;\n break;\n case 'neq':\n ok = left !== right;\n break;\n case 'gt':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left > right;\n break;\n case 'gte':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left >= right;\n break;\n case 'lt':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left < right;\n break;\n case 'lte':\n ok =\n typeof left === 'number' &&\n typeof right === 'number' &&\n left <= right;\n break;\n case 'in':\n ok = Array.isArray(right) && right.some((r) => r === left);\n break;\n case 'notIn':\n ok = Array.isArray(right) && !right.some((r) => r === left);\n break;\n case 'isEmpty':\n ok = isEmptyValue(left);\n break;\n case 'isNotEmpty':\n ok = !isEmptyValue(left);\n break;\n default: {\n const _exhaustive: never = op;\n return {\n ok: false,\n failed: {\n field: condition.field,\n operator: condition.operator,\n value: condition.value,\n reason: `Unknown operator: ${_exhaustive as string}`,\n },\n };\n }\n }\n\n if (!ok) {\n return {\n ok: false,\n failed: {\n field: condition.field,\n operator: condition.operator,\n value: condition.value,\n },\n };\n }\n return { ok: true };\n}\n\nfunction groupPasses(\n group: { conditions: Condition[] },\n context: OrderContext\n): { ok: boolean; failed: FailedCondition[] } {\n const failed: FailedCondition[] = [];\n for (const c of group.conditions) {\n const r = evaluateCondition(c, context);\n if (!r.ok && r.failed) failed.push(r.failed);\n }\n return { ok: failed.length === 0, failed };\n}\n\n/** OR of AND groups — true if any group passes. */\nexport function evaluateConditionSet(\n set: TransitionConditionSet | undefined,\n context: OrderContext\n): { ok: boolean; failedConditions: FailedCondition[] } {\n if (!set || set.groups.length === 0) {\n return { ok: true, failedConditions: [] };\n }\n const allFailed: FailedCondition[] = [];\n for (const g of set.groups) {\n const { ok, failed } = groupPasses(g, context);\n if (ok) return { ok: true, failedConditions: [] };\n allFailed.push(...failed);\n }\n return { ok: false, failedConditions: allFailed };\n}\n\nexport function conditionSummary(c: Condition): string {\n return `${c.field} ${c.operator} ${JSON.stringify(c.value)}`;\n}\n","import { conditionSummary, evaluateCondition, evaluateConditionSet } from './condition-eval';\nimport { deriveDisplayState } from './display-state';\nimport { getFinancialInvariantViolations } from './financial-invariants';\nimport type {\n AvailableTransition,\n CrossAxisRule,\n FailedCondition,\n OrderContext,\n StateConfig,\n StoredStateConfig,\n TransitionRequest,\n TransitionResult,\n} from './interfaces';\nimport type { FulfillmentState, PaymentState, StatePair } from './types';\n\nexport type { TransitionRequest } from './interfaces';\n\nfunction pairInInitialList(to: StatePair, config: StoredStateConfig): boolean {\n return config.validInitialStates.some((p) => p.payment === to.payment && p.fulfillment === to.fulfillment);\n}\n\nfunction triggerTargets(rule: CrossAxisRule): string[] {\n const t = rule.trigger.to;\n return Array.isArray(t) ? [...t] : [t];\n}\n\n/**\n * True when this rule applies to the edge `from` → `to` (trigger axis moved onto `trigger.to`).\n */\nexport function crossAxisRuleApplies(rule: CrossAxisRule, from: StatePair | null, to: StatePair): boolean {\n if (!rule.enabled) return false;\n const targets = triggerTargets(rule);\n if (rule.trigger.axis === 'fulfillment') {\n if (!targets.includes(to.fulfillment)) return false;\n if (from !== null && from.fulfillment === to.fulfillment) return false;\n return true;\n }\n if (!targets.includes(to.payment)) return false;\n if (from !== null && from.payment === to.payment) return false;\n return true;\n}\n\nfunction crossAxisSatisfied(rule: CrossAxisRule, to: StatePair): boolean {\n const req = rule.requires;\n if (req.axis === 'payment') {\n return req.states.includes(to.payment);\n }\n return req.states.includes(to.fulfillment);\n}\n\nfunction firstBlockingCrossAxisRule(\n from: StatePair | null,\n to: StatePair,\n config: StoredStateConfig,\n): CrossAxisRule | undefined {\n for (const rule of config.crossAxisRules) {\n if (!crossAxisRuleApplies(rule, from, to)) continue;\n if (!crossAxisSatisfied(rule, to)) return rule;\n }\n return undefined;\n}\n\nfunction findConditionSet(config: StoredStateConfig, id: string | undefined) {\n if (!id) return undefined;\n return config.transitionConditions.find((s) => s.id === id);\n}\n\nfunction pathExists(\n paths: { from: string; to: string; conditionSetId?: string }[],\n fromId: string,\n toId: string,\n): boolean {\n return paths.some((p) => p.from === fromId && p.to === toId);\n}\n\nfunction axisTransitionAllowed(\n mode: 'strict' | 'permissive',\n paths: { from: string; to: string; conditionSetId?: string }[],\n fromId: string,\n toId: string,\n): boolean {\n if (fromId === toId) return true;\n if (mode === 'permissive') return true;\n return pathExists(paths, fromId, toId);\n}\n\nfunction collectPathConditionFailures(\n config: StoredStateConfig,\n from: StatePair | null,\n to: StatePair,\n context: OrderContext,\n): { failed: FailedCondition[] } {\n const failed: FailedCondition[] = [];\n if (from === null) return { failed };\n\n if (from.payment !== to.payment) {\n const p = config.paymentPaths.find((x) => x.from === from.payment && x.to === to.payment);\n const set = findConditionSet(config, p?.conditionSetId);\n const ev = evaluateConditionSet(set, context);\n if (!ev.ok) failed.push(...ev.failedConditions);\n }\n\n if (from.fulfillment !== to.fulfillment) {\n const p = config.fulfillmentPaths.find((x) => x.from === from.fulfillment && x.to === to.fulfillment);\n const set = findConditionSet(config, p?.conditionSetId);\n const ev = evaluateConditionSet(set, context);\n if (!ev.ok) failed.push(...ev.failedConditions);\n }\n\n return { failed };\n}\n\nfunction pathBlocked(config: StoredStateConfig, from: StatePair | null, to: StatePair): boolean {\n if (from === null) return false;\n if (\n from.payment !== to.payment &&\n !axisTransitionAllowed(config.paymentPathMode, config.paymentPaths, from.payment, to.payment)\n ) {\n return true;\n }\n if (\n from.fulfillment !== to.fulfillment &&\n !axisTransitionAllowed(config.fulfillmentPathMode, config.fulfillmentPaths, from.fulfillment, to.fulfillment)\n ) {\n return true;\n }\n return false;\n}\n\n/**\n * Three-layer evaluation: financial invariants → cross-axis rules → paths → conditions.\n * Order creation (`from === null`): guards only; paths/conditions skipped. The\n * `validInitialStates` list is enforced only when `config.enforceValidInitialStates`\n * is true (off by default — see the field's doc in `interfaces.ts`).\n */\nexport function canTransition(request: TransitionRequest): TransitionResult {\n const { from, to, config, context } = request;\n\n const fin = getFinancialInvariantViolations(from, to);\n if (fin.length > 0) {\n return {\n allowed: false,\n blockedBy: 'financial_invariant',\n guard: fin[0],\n reason: `Blocked by financial invariant: ${fin[0]}`,\n };\n }\n\n const cross = firstBlockingCrossAxisRule(from, to, config);\n if (cross) {\n return {\n allowed: false,\n blockedBy: 'cross_axis_rule',\n guard: cross.id,\n reason: `Blocked by cross-axis rule: ${cross.label}`,\n };\n }\n\n if (from === null) {\n if (config.enforceValidInitialStates === true && !pairInInitialList(to, config)) {\n return {\n allowed: false,\n blockedBy: 'path',\n reason: 'Target state is not a valid initial state for new orders',\n };\n }\n } else if (pathBlocked(config, from, to)) {\n return {\n allowed: false,\n blockedBy: 'path',\n reason: 'Transition is not allowed by configured path rules',\n };\n }\n\n if (!request.skipConditionEvaluation) {\n const cond = collectPathConditionFailures(config, from, to, context);\n if (cond.failed.length > 0) {\n return {\n allowed: false,\n blockedBy: 'condition',\n reason: 'Transition conditions not satisfied',\n failedConditions: cond.failed,\n };\n }\n }\n\n return { allowed: true };\n}\n\nfunction labelForPayment(id: PaymentState, config: StateConfig): string {\n return config.paymentStates.find((s) => s.id === id)?.label ?? id;\n}\n\nfunction labelForFulfillment(id: FulfillmentState, config: StateConfig): string {\n return config.fulfillmentStates.find((s) => s.id === id)?.label ?? id;\n}\n\nfunction transitionDisplayLabel(to: StatePair, config: StateConfig): string {\n // deriveDisplayState's no-rule fallback is now already humanized from\n // STATE_SCHEMA labels, so its result is always presentable as-is; the old\n // raw-atom-echo detection (`derived !== \"payment / fulfillment\"`) is gone.\n const derived = deriveDisplayState(to.payment, to.fulfillment, config).label;\n if (derived) {\n return derived;\n }\n return `${labelForPayment(to.payment, config)} · ${labelForFulfillment(to.fulfillment, config)}`;\n}\n\nfunction conditionMetLines(\n config: StateConfig,\n from: StatePair,\n to: StatePair,\n context: OrderContext,\n): { met: boolean; description: string }[] {\n const lines: { met: boolean; description: string }[] = [];\n\n const appendForPath = (p: { conditionSetId?: string } | undefined) => {\n const set = findConditionSet(config, p?.conditionSetId);\n if (!set) return;\n for (const g of set.groups) {\n for (const c of g.conditions) {\n const r = evaluateCondition(c, context);\n lines.push({\n met: r.ok,\n description: conditionSummary(c),\n });\n }\n }\n };\n\n if (from.payment !== to.payment) {\n const p = config.paymentPaths.find((x) => x.from === from.payment && x.to === to.payment);\n appendForPath(p);\n }\n if (from.fulfillment !== to.fulfillment) {\n const p = config.fulfillmentPaths.find((x) => x.from === from.fulfillment && x.to === to.fulfillment);\n appendForPath(p);\n }\n\n return lines;\n}\n\n/**\n * All target pairs reachable in one step from `current` that pass `canTransition`.\n *\n * Candidates are FULFILLMENT-AXIS moves only (payment unchanged) — exactly the\n * pairs `applyTransition` can produce. The payment axis moves exclusively\n * through the money operations (pay / refund / void), which derive their own\n * landing pairs from the money actually moved; advertising payment-axis pairs\n * here offered transitions no caller could apply.\n */\nexport function getAvailableTransitions(\n current: StatePair,\n config: StateConfig,\n context: OrderContext,\n): AvailableTransition[] {\n const candidates: StatePair[] = [];\n\n for (const s of config.fulfillmentStates) {\n if (s.id === current.fulfillment) continue;\n candidates.push({ payment: current.payment, fulfillment: s.id });\n }\n\n const out: AvailableTransition[] = [];\n\n for (const to of candidates) {\n const result = canTransition({\n from: current,\n to,\n config,\n context,\n });\n if (!result.allowed) continue;\n\n out.push({\n to,\n displayLabel: transitionDisplayLabel(to, config),\n conditions: conditionMetLines(config, current, to, context),\n });\n }\n\n return out;\n}\n","import { buildOrderContext } from './build-order-context';\nimport { displayRuleMatchesPair } from './display-state';\nimport { canTransition } from './engine';\nimport { getFinancialInvariantViolations } from './financial-invariants';\nimport type {\n ConfigValidationError,\n ConfigValidationResult,\n ConfigValidationWarning,\n Condition,\n StateConfig,\n} from './interfaces';\nimport type { StatePair } from './types';\nimport { CONDITION_OPERATORS, FULFILLMENT_STATES, PAYMENT_STATES } from './types';\n\nfunction paymentStateIds(config: StateConfig): Set<string> {\n return new Set<string>(config.paymentStates.map((s) => s.id));\n}\n\nfunction fulfillmentStateIds(config: StateConfig): Set<string> {\n return new Set<string>(config.fulfillmentStates.map((s) => s.id));\n}\n\nconst VALID_OPERATORS = new Set<string>(CONDITION_OPERATORS);\n\nfunction validateConditionShape(\n c: Condition,\n path: string,\n errors: ConfigValidationError[]\n): void {\n if (!VALID_OPERATORS.has(c.operator)) {\n errors.push({\n code: 'invalid_condition_operator',\n message: `Unknown operator \"${c.operator}\"`,\n path,\n });\n return;\n }\n const needsNumberCompare = ['gt', 'gte', 'lt', 'lte'].includes(c.operator);\n if (needsNumberCompare && typeof c.value !== 'number') {\n errors.push({\n code: 'invalid_condition_value_type',\n message: `Operator \"${c.operator}\" requires a numeric value`,\n path: `${path}.value`,\n });\n }\n if ((c.operator === 'in' || c.operator === 'notIn') && !Array.isArray(c.value)) {\n errors.push({\n code: 'invalid_condition_value_type',\n message: `Operator \"${c.operator}\" requires an array value`,\n path: `${path}.value`,\n });\n }\n}\n\n/** Generous context so reachability probes are not blocked by typical payment conditions. */\nfunction validationContext() {\n return buildOrderContext({\n total: 100,\n balance: 0,\n paymentMethods: [{ amount: 100 }],\n lineItems: [{ quantity: 1, fulfilledQuantity: 1, returnedQuantity: 0 }],\n });\n}\n\nfunction pairKey(p: StatePair): string {\n return `${p.payment}\\0${p.fulfillment}`;\n}\n\n/**\n * Structural + semantic validation for `StateConfig`.\n */\nexport function validateConfig(config: StateConfig): ConfigValidationResult {\n const errors: ConfigValidationError[] = [];\n const warnings: ConfigValidationWarning[] = [];\n\n if (!Number.isFinite(config.version) || config.version < 1) {\n errors.push({\n code: 'invalid_version',\n message: 'version must be a finite number >= 1',\n path: 'version',\n });\n }\n\n if (!config.validInitialStates?.length) {\n errors.push({\n code: 'missing_initial_states',\n message: 'validInitialStates must contain at least one pair',\n path: 'validInitialStates',\n });\n }\n\n const payIds = paymentStateIds(config);\n const fulIds = fulfillmentStateIds(config);\n\n config.validInitialStates?.forEach((pair, i) => {\n if (!payIds.has(pair.payment)) {\n errors.push({\n code: 'initial_unknown_payment',\n message: `validInitialStates[${i}].payment \"${pair.payment}\" is not defined`,\n path: `validInitialStates[${i}].payment`,\n });\n }\n if (!fulIds.has(pair.fulfillment)) {\n errors.push({\n code: 'initial_unknown_fulfillment',\n message: `validInitialStates[${i}].fulfillment \"${pair.fulfillment}\" is not defined`,\n path: `validInitialStates[${i}].fulfillment`,\n });\n }\n });\n\n const conditionSetIds = new Set(config.transitionConditions.map((s) => s.id));\n config.transitionConditions.forEach((set, si) => {\n set.groups.forEach((g, gi) => {\n g.conditions.forEach((c, ci) => {\n validateConditionShape(\n c,\n `transitionConditions[${si}].groups[${gi}].conditions[${ci}]`,\n errors\n );\n });\n });\n });\n\n const pathConditionRef = (\n paths: ReadonlyArray<{ from: string; to: string; conditionSetId?: string }>,\n axis: string\n ) => {\n paths.forEach((p, i) => {\n if (p.conditionSetId && !conditionSetIds.has(p.conditionSetId)) {\n errors.push({\n code: 'unknown_condition_set',\n message: `${axis}Paths[${i}] references unknown conditionSetId \"${p.conditionSetId}\"`,\n path: `${axis}Paths[${i}].conditionSetId`,\n });\n }\n });\n };\n pathConditionRef(config.paymentPaths, 'payment');\n pathConditionRef(config.fulfillmentPaths, 'fulfillment');\n\n config.paymentPaths.forEach((path, i) => {\n if (!payIds.has(path.from) || !payIds.has(path.to)) {\n errors.push({\n code: 'payment_path_unknown_state',\n message: `paymentPaths[${i}] references unknown payment state`,\n path: `paymentPaths[${i}]`,\n });\n return;\n }\n for (const f of config.fulfillmentStates) {\n const from: StatePair = { payment: path.from, fulfillment: f.id };\n const to: StatePair = { payment: path.to, fulfillment: f.id };\n if (getFinancialInvariantViolations(null, from).length > 0) continue;\n const v = getFinancialInvariantViolations(from, to);\n if (v.length > 0) {\n errors.push({\n code: 'payment_path_violates_financial_invariant',\n message: `paymentPaths[${i}] (${path.from}→${path.to}) with fulfillment \"${f.id}\" violates invariant(s): ${v.join(', ')}`,\n path: `paymentPaths[${i}]`,\n });\n }\n }\n });\n\n config.fulfillmentPaths.forEach((path, i) => {\n if (!fulIds.has(path.from) || !fulIds.has(path.to)) {\n errors.push({\n code: 'fulfillment_path_unknown_state',\n message: `fulfillmentPaths[${i}] references unknown fulfillment state`,\n path: `fulfillmentPaths[${i}]`,\n });\n return;\n }\n for (const p of config.paymentStates) {\n const from: StatePair = { payment: p.id, fulfillment: path.from };\n const to: StatePair = { payment: p.id, fulfillment: path.to };\n // Skip pairs that are not valid steady states (e.g. refunded+draft); path checks are for real edges.\n if (getFinancialInvariantViolations(null, from).length > 0) continue;\n const v = getFinancialInvariantViolations(from, to);\n if (v.length > 0) {\n errors.push({\n code: 'fulfillment_path_violates_financial_invariant',\n message: `fulfillmentPaths[${i}] (${path.from}→${path.to}) with payment \"${p.id}\" violates invariant(s): ${v.join(', ')}`,\n path: `fulfillmentPaths[${i}]`,\n });\n }\n }\n });\n\n config.crossAxisRules.forEach((rule, i) => {\n const req = rule.requires;\n if (req.axis === 'payment') {\n for (const id of req.states) {\n if (!payIds.has(id)) {\n errors.push({\n code: 'cross_axis_unknown_payment',\n message: `crossAxisRules[${i}] requires unknown payment state \"${id}\"`,\n path: `crossAxisRules[${i}].requires.states`,\n });\n }\n }\n } else {\n for (const id of req.states) {\n if (!fulIds.has(id)) {\n errors.push({\n code: 'cross_axis_unknown_fulfillment',\n message: `crossAxisRules[${i}] requires unknown fulfillment state \"${id}\"`,\n path: `crossAxisRules[${i}].requires.states`,\n });\n }\n }\n }\n\n const trig = rule.trigger;\n const targets = Array.isArray(trig.to) ? trig.to : [trig.to];\n if (trig.axis === 'payment') {\n for (const id of targets) {\n if (!payIds.has(id)) {\n errors.push({\n code: 'cross_axis_trigger_unknown_payment',\n message: `crossAxisRules[${i}] triggers on unknown payment state \"${id}\"`,\n path: `crossAxisRules[${i}].trigger.to`,\n });\n }\n }\n } else {\n for (const id of targets) {\n if (!fulIds.has(id)) {\n errors.push({\n code: 'cross_axis_trigger_unknown_fulfillment',\n message: `crossAxisRules[${i}] triggers on unknown fulfillment state \"${id}\"`,\n path: `crossAxisRules[${i}].trigger.to`,\n });\n }\n }\n }\n });\n\n strictAxisReachability(config, 'payment', payIds, warnings);\n strictAxisReachability(config, 'fulfillment', fulIds, warnings);\n\n combinedReachability(config, warnings);\n\n if (!config.displayStateMap.length) {\n warnings.push({\n code: 'empty_display_map',\n message: 'displayStateMap is empty; UI will fall back to raw state pair labels',\n path: 'displayStateMap',\n });\n } else {\n const missingDisplay: string[] = [];\n for (const p of PAYMENT_STATES) {\n for (const f of FULFILLMENT_STATES) {\n if (!payIds.has(p) || !fulIds.has(f)) continue;\n const matched = config.displayStateMap.some((rule) =>\n displayRuleMatchesPair(rule, p, f)\n );\n if (!matched) missingDisplay.push(`${p}/${f}`);\n }\n }\n if (missingDisplay.length > 0) {\n const sample = missingDisplay.slice(0, 8).join(', ');\n const more =\n missingDisplay.length > 8\n ? ` (+${missingDisplay.length - 8} more)`\n : '';\n warnings.push({\n code: 'display_map_missing_combos',\n message: `No displayStateMap rule matches ${missingDisplay.length} base pair(s): ${sample}${more}`,\n path: 'displayStateMap',\n });\n }\n }\n\n refundReturnPathWarnings(config, payIds, fulIds, warnings);\n\n if (config.paymentPathMode === 'strict' && config.paymentPaths.length === 0) {\n errors.push({\n code: 'strict_payment_paths_empty',\n message: 'paymentPathMode is strict but paymentPaths is empty',\n path: 'paymentPaths',\n });\n }\n if (config.fulfillmentPathMode === 'strict' && config.fulfillmentPaths.length === 0) {\n errors.push({\n code: 'strict_fulfillment_paths_empty',\n message: 'fulfillmentPathMode is strict but fulfillmentPaths is empty',\n path: 'fulfillmentPaths',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\nfunction strictAxisReachability(\n config: StateConfig,\n axis: 'payment' | 'fulfillment',\n ids: Set<string>,\n warnings: ConfigValidationWarning[]\n): void {\n const mode = axis === 'payment' ? config.paymentPathMode : config.fulfillmentPathMode;\n const paths = axis === 'payment' ? config.paymentPaths : config.fulfillmentPaths;\n if (mode !== 'strict' || paths.length === 0) return;\n\n const reachable = new Set<string>();\n const initials = new Set(\n config.validInitialStates.map((p) => (axis === 'payment' ? p.payment : p.fulfillment))\n );\n for (const id of initials) {\n if (ids.has(id)) bfsAxis(id, paths, reachable);\n }\n\n const stateRows =\n axis === 'payment' ? config.paymentStates : config.fulfillmentStates;\n for (const id of stateRows) {\n if (!reachable.has(id.id)) {\n warnings.push({\n code: `${axis}_state_unreachable_strict`,\n message: `State \"${id.id}\" may be unreachable from valid initial ${axis} states under strict paths`,\n path: axis === 'payment' ? 'paymentPaths' : 'fulfillmentPaths',\n });\n }\n if (!id.isTerminal) {\n const hasOut = paths.some((p) => p.from === id.id && p.to !== id.id);\n if (!hasOut) {\n warnings.push({\n code: `${axis}_nonterminal_no_outbound`,\n message: `Non-terminal ${axis} state \"${id.id}\" has no strict outbound path`,\n path: axis === 'payment' ? 'paymentPaths' : 'fulfillmentPaths',\n });\n }\n }\n }\n}\n\nfunction bfsAxis(\n start: string,\n paths: { from: string; to: string }[],\n reachable: Set<string>\n): void {\n const q = [start];\n reachable.add(start);\n while (q.length) {\n const cur = q.pop()!;\n for (const p of paths) {\n if (p.from !== cur) continue;\n if (!reachable.has(p.to)) {\n reachable.add(p.to);\n q.push(p.to);\n }\n }\n }\n}\n\nfunction combinedReachability(\n config: StateConfig,\n warnings: ConfigValidationWarning[]\n): void {\n const ctx = validationContext();\n const payIds = config.paymentStates.map((s) => s.id);\n const fulIds = config.fulfillmentStates.map((s) => s.id);\n const seen = new Set<string>();\n const queue: StatePair[] = [...config.validInitialStates];\n for (const p of queue) {\n seen.add(pairKey(p));\n }\n while (queue.length) {\n const cur = queue.pop()!;\n for (const np of payIds) {\n if (np === cur.payment) continue;\n const to = { payment: np, fulfillment: cur.fulfillment };\n const r = canTransition({\n from: cur,\n to,\n config,\n context: ctx,\n skipConditionEvaluation: true,\n });\n const k = pairKey(to);\n if (r.allowed && !seen.has(k)) {\n seen.add(k);\n queue.push(to);\n }\n }\n for (const nf of fulIds) {\n if (nf === cur.fulfillment) continue;\n const to = { payment: cur.payment, fulfillment: nf };\n const r = canTransition({\n from: cur,\n to,\n config,\n context: ctx,\n skipConditionEvaluation: true,\n });\n const k = pairKey(to);\n if (r.allowed && !seen.has(k)) {\n seen.add(k);\n queue.push(to);\n }\n }\n }\n\n const total = payIds.length * fulIds.length;\n if (\n seen.size < total &&\n (config.paymentPathMode === 'strict' || config.fulfillmentPathMode === 'strict')\n ) {\n warnings.push({\n code: 'combined_pairs_not_all_reachable',\n message:\n 'Some payment×fulfillment pairs appear unreachable under current paths, cross-axis rules, and financial invariants (structural check with generic context)',\n path: 'validInitialStates',\n });\n }\n}\n\nfunction refundReturnPathWarnings(\n config: StateConfig,\n payIds: Set<string>,\n fulIds: Set<string>,\n warnings: ConfigValidationWarning[]\n): void {\n const hasReturned = config.fulfillmentPaths.some(\n (p) => p.to === 'returned' || p.from === 'returned'\n );\n const hasRefunded = config.paymentPaths.some(\n (p) => p.to === 'refunded' || p.from === 'refunded'\n );\n if (\n fulIds.has('returned') &&\n hasReturned &&\n payIds.has('refunded') &&\n !hasRefunded &&\n config.paymentPathMode === 'strict'\n ) {\n warnings.push({\n code: 'refund_path_missing_for_return',\n message:\n 'Fulfillment paths mention \"returned\" but no strict payment path touches \"refunded\"; verify refund workflow',\n path: 'paymentPaths',\n });\n }\n}\n","import { deriveDisplayState } from './display-state';\nimport type { OrderStateWritable, StoredStateConfig } from './interfaces';\nimport type { FulfillmentState, PaymentState, StatePair } from './types';\n\n/**\n * Maps atoms to legacy `status` for dual-write across the full POS vocabulary:\n * 'in-cart' | 'parked' | 'completed' | 'refunded' | 'partial-refund' | 'park-deleted'.\n *\n * Evaluation order matters: refund and void outcomes are terminal and take precedence\n * over fulfillment, so a `voided` order always maps to `park-deleted` regardless of\n * how the fulfillment axis landed (cancelled, returned, etc.). Same for refund terminals.\n */\nexport function mapToLegacyStatus(pair: StatePair): string {\n const { payment, fulfillment } = pair;\n\n // Terminal void — hard-deleted parked order or voided payment.\n if (payment === 'voided') return 'park-deleted';\n\n // Refund outcomes.\n if (payment === 'refunded') return 'refunded';\n if (payment === 'partially_refunded') return 'partial-refund';\n\n // Fully-paid orders. POS auto-fulfills on payment, so fulfilled/in_progress/pending\n // all collapse to 'completed' for the legacy status consumers (web, analytics, etc.).\n if (payment === 'paid') return 'completed';\n\n // Unpaid / partially-paid orders.\n if (fulfillment === 'draft') return 'in-cart';\n if (fulfillment === 'on_hold') return 'parked';\n if (fulfillment === 'pending') return 'parked';\n if (fulfillment === 'cancelled') return 'park-deleted';\n\n return 'parked';\n}\n\n/**\n * Writes payment/fulfillment atoms, derived display label, and legacy `status` in one place.\n */\nexport function setOrderState(\n order: OrderStateWritable,\n paymentState: PaymentState,\n fulfillmentState: FulfillmentState,\n config: StoredStateConfig,\n options?: { includeLegacyStatus?: boolean },\n): void {\n order.paymentState = paymentState;\n order.fulfillmentState = fulfillmentState;\n const display = deriveDisplayState(paymentState, fulfillmentState, config);\n order.displayState = display.label;\n if (options?.includeLegacyStatus !== false) {\n order.status = mapToLegacyStatus({ payment: paymentState, fulfillment: fulfillmentState });\n }\n}\n","import type { OrderLikeForLegacyInference } from './interfaces';\nimport type { StatePair } from './types';\n\nfunction normalizeStatus(raw: string | undefined): string {\n return (raw ?? '').trim().toLowerCase();\n}\n\nfunction hasRefundActivity(order: OrderLikeForLegacyInference): boolean {\n const refunds = order.refunds ?? order.refund ?? [];\n return refunds.some((r) => {\n const q = r.quantity;\n return typeof q === 'number' && q > 0;\n });\n}\n\n/**\n * Deterministic mapping from legacy `order.status` (and payment/refund hints) to state atoms.\n * See plan §2.5 — conservative refund rows assume return tracking on fulfillment.\n */\nexport function inferStatesFromLegacyStatus(\n order: OrderLikeForLegacyInference\n): StatePair {\n const status = normalizeStatus(order.status);\n\n if (status === 'completed') {\n return { payment: 'paid', fulfillment: 'fulfilled' };\n }\n\n if (status === 'in-cart') {\n return { payment: 'unpaid', fulfillment: 'draft' };\n }\n\n if (status === 'park-deleted') {\n return { payment: 'voided', fulfillment: 'cancelled' };\n }\n\n if (status === 'refunded') {\n return { payment: 'refunded', fulfillment: 'returned' };\n }\n\n if (status === 'partial-refund' || status === 'partial_refund') {\n return { payment: 'partially_refunded', fulfillment: 'partially_returned' };\n }\n\n if (status === 'parked') {\n const ctx = order.paymentMethods ?? [];\n const paid = ctx.reduce((s, m) => {\n const a = m.amount;\n return s + (typeof a === 'number' && Number.isFinite(a) ? a : 0);\n }, 0);\n const partial =\n paid > 0 ||\n (typeof order.balance === 'number' &&\n typeof order.total === 'number' &&\n order.total > 0 &&\n order.balance > 0 &&\n order.balance < order.total);\n return {\n payment: partial ? 'partially_paid' : 'unpaid',\n fulfillment: 'on_hold',\n };\n }\n\n if (status === '' && hasRefundActivity(order)) {\n return { payment: 'partially_refunded', fulfillment: 'partially_returned' };\n }\n\n return { payment: 'unpaid', fulfillment: 'pending' };\n}\n","import { setOrderState } from './set-order-state';\nimport { inferStatesFromLegacyStatus } from './legacy-infer';\nimport type { StoredStateConfig, OrderStateWritable, OrderLikeForLegacyInference } from './interfaces';\nimport type { PaymentState, FulfillmentState } from './types';\n\n/**\n * Minimal order shape that both strategies receive at write boundaries.\n * Extends `OrderStateWritable` with legacy fields used for inference.\n */\nexport interface OrderMutationData extends OrderStateWritable {\n total?: number;\n balance?: number;\n paymentMethods?: { amount?: number; [key: string]: unknown }[];\n refunds?: { quantity?: number; [key: string]: unknown }[];\n refund?: { quantity?: number; [key: string]: unknown }[];\n lineItems?: { quantity?: number; fulfilledQuantity?: number; returnedQuantity?: number; [key: string]: unknown }[];\n}\n\n/**\n * Applies order-state fields before persistence.\n * Two implementations exist during Phase 2: legacy (no-op) and dual-write.\n */\nexport interface OrderWriteStrategy {\n applyState(order: OrderMutationData): void;\n}\n\n/**\n * No-op strategy: callers already manage the legacy `status` field; no new atoms are written.\n */\nexport class LegacyWriteStrategy implements OrderWriteStrategy {\n applyState(_order: OrderMutationData): void {\n // Intentionally empty — legacy path leaves atoms untouched.\n }\n}\n\n/**\n * Dual-write strategy (Phase 2): populates paymentState, fulfillmentState, displayState,\n * and keeps legacy `status` consistent via `setOrderState()`.\n *\n * When atoms are already present on the order (e.g. from an explicit transition),\n * they are passed through `setOrderState` to derive displayState and sync legacy status.\n * Otherwise, atoms are inferred from the existing legacy `status` using the\n * deterministic mapper from `@final-commerce/common`.\n */\nexport class DualWriteStrategy implements OrderWriteStrategy {\n constructor(private readonly config: StoredStateConfig) {}\n\n applyState(order: OrderMutationData): void {\n if (order.paymentState && order.fulfillmentState) {\n setOrderState(order, order.paymentState as PaymentState, order.fulfillmentState as FulfillmentState, this.config);\n return;\n }\n\n if (order.status) {\n const inferred = inferStatesFromLegacyStatus(order as OrderLikeForLegacyInference);\n setOrderState(order, inferred.payment, inferred.fulfillment, this.config);\n }\n }\n}\n","import type { FragmentParam, StateConfigFragment } from './interfaces';\n\nexport interface ResolveTemplateResult {\n fragment: StateConfigFragment;\n resolvedValues: Record<string, unknown>;\n}\n\n/**\n * Resolves a parameterized fragment template into a concrete StateConfigFragment.\n *\n * 1. Merges supplied `values` with param defaults (supplied wins).\n * 2. Validates each resolved value against its param definition.\n * 3. Substitutes `{{key}}` placeholders in the raw template string.\n * 4. Parses the result as JSON into a StateConfigFragment.\n */\nexport function resolveTemplate(\n templateJson: string,\n params: FragmentParam[],\n values: Record<string, unknown> = {},\n): ResolveTemplateResult {\n const resolvedValues: Record<string, unknown> = {};\n\n for (const param of params) {\n const raw = values[param.key] ?? param.default;\n if (raw === undefined || raw === null) {\n throw new Error(`Missing required parameter: \"${param.key}\" (${param.label})`);\n }\n\n validateParamValue(param, raw);\n resolvedValues[param.key] = raw;\n }\n\n let resolved = templateJson;\n for (const [key, value] of Object.entries(resolvedValues)) {\n const placeholder = `{{${key}}}`;\n const replacement =\n typeof value === 'string' ? escapeJsonString(value) : String(value);\n resolved = replaceAll(resolved, placeholder, replacement);\n }\n\n let fragment: StateConfigFragment;\n try {\n fragment = JSON.parse(resolved);\n } catch (err) {\n throw new Error(\n `Fragment template produced invalid JSON after substitution: ${(err as Error).message}`,\n );\n }\n\n return { fragment, resolvedValues };\n}\n\nfunction validateParamValue(param: FragmentParam, value: unknown): void {\n const { key, label, type } = param;\n\n if (type === 'string' && typeof value !== 'string') {\n throw new Error(`Parameter \"${key}\" (${label}) must be a string, got ${typeof value}`);\n }\n if (type === 'number') {\n if (typeof value !== 'number' || Number.isNaN(value)) {\n throw new Error(`Parameter \"${key}\" (${label}) must be a number`);\n }\n if (param.min !== undefined && value < param.min) {\n throw new Error(`Parameter \"${key}\" (${label}) must be >= ${param.min}`);\n }\n if (param.max !== undefined && value > param.max) {\n throw new Error(`Parameter \"${key}\" (${label}) must be <= ${param.max}`);\n }\n }\n if (type === 'boolean' && typeof value !== 'boolean') {\n throw new Error(`Parameter \"${key}\" (${label}) must be a boolean`);\n }\n if (param.options && param.options.length > 0 && !param.options.includes(String(value))) {\n throw new Error(\n `Parameter \"${key}\" (${label}) must be one of: ${param.options.join(', ')}`,\n );\n }\n}\n\n/** Escapes a string for safe embedding inside a JSON-quoted value. */\nfunction escapeJsonString(value: string): string {\n return value\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n .replace(/\\t/g, '\\\\t');\n}\n\nfunction replaceAll(str: string, search: string, replacement: string): string {\n let result = str;\n let idx = result.indexOf(search);\n while (idx !== -1) {\n result = result.slice(0, idx) + replacement + result.slice(idx + search.length);\n idx = result.indexOf(search, idx + replacement.length);\n }\n return result;\n}\n","import type {\n ConfigValidationError,\n StoredStateConfig,\n StateConfigFragment,\n} from './interfaces';\nimport { isFulfillmentState, isPaymentState } from './types';\n\nexport interface FragmentValidationResult {\n valid: boolean;\n errors: ConfigValidationError[];\n}\n\n/**\n * Validates a StateConfigFragment against an existing StateConfig.\n *\n * Checks:\n * 1. All state references are members of the closed PaymentState / FulfillmentState unions.\n * 2. No duplicate path edges (from, to) on the same axis.\n * 3. No duplicate condition set IDs.\n * 4. No duplicate cross-axis rule IDs.\n */\nexport function validateFragmentCompatibility(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n): FragmentValidationResult {\n const errors: ConfigValidationError[] = [];\n\n validateStateReferences(fragment, errors);\n validatePathUniqueness(config, fragment, errors);\n validateConditionSetUniqueness(config, fragment, errors);\n validateCrossAxisRuleUniqueness(config, fragment, errors);\n\n return { valid: errors.length === 0, errors };\n}\n\nfunction validateStateReferences(\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n for (const path of fragment.paymentPaths ?? []) {\n if (!isPaymentState(path.from)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${path.from}\" in paymentPaths`,\n path: `paymentPaths[from=${path.from}]`,\n });\n }\n if (!isPaymentState(path.to)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${path.to}\" in paymentPaths`,\n path: `paymentPaths[to=${path.to}]`,\n });\n }\n }\n\n for (const path of fragment.fulfillmentPaths ?? []) {\n if (!isFulfillmentState(path.from)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${path.from}\" in fulfillmentPaths`,\n path: `fulfillmentPaths[from=${path.from}]`,\n });\n }\n if (!isFulfillmentState(path.to)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${path.to}\" in fulfillmentPaths`,\n path: `fulfillmentPaths[to=${path.to}]`,\n });\n }\n }\n\n for (const rule of fragment.crossAxisRules ?? []) {\n const triggerStates = Array.isArray(rule.trigger.to) ? rule.trigger.to : [rule.trigger.to];\n const check = rule.trigger.axis === 'payment' ? isPaymentState : isFulfillmentState;\n for (const s of triggerStates) {\n if (!check(s)) {\n errors.push({\n code: `invalid_${rule.trigger.axis}_state`,\n message: `Unknown ${rule.trigger.axis} state \"${s}\" in crossAxisRule \"${rule.id}\" trigger`,\n path: `crossAxisRules[${rule.id}].trigger.to`,\n });\n }\n }\n const reqCheck = rule.requires.axis === 'payment' ? isPaymentState : isFulfillmentState;\n for (const s of rule.requires.states) {\n if (!reqCheck(s)) {\n errors.push({\n code: `invalid_${rule.requires.axis}_state`,\n message: `Unknown ${rule.requires.axis} state \"${s}\" in crossAxisRule \"${rule.id}\" requires`,\n path: `crossAxisRules[${rule.id}].requires.states`,\n });\n }\n }\n }\n\n for (const pair of fragment.validInitialStates ?? []) {\n if (!isPaymentState(pair.payment)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${pair.payment}\" in validInitialStates`,\n path: 'validInitialStates',\n });\n }\n if (!isFulfillmentState(pair.fulfillment)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${pair.fulfillment}\" in validInitialStates`,\n path: 'validInitialStates',\n });\n }\n }\n\n for (const rule of fragment.displayStateMap ?? []) {\n const pStates = rule.paymentState\n ? (Array.isArray(rule.paymentState) ? rule.paymentState : [rule.paymentState])\n : [];\n for (const s of pStates) {\n if (!isPaymentState(s)) {\n errors.push({\n code: 'invalid_payment_state',\n message: `Unknown payment state \"${s}\" in displayStateMap rule \"${rule.label}\"`,\n path: 'displayStateMap',\n });\n }\n }\n const fStates = rule.fulfillmentState\n ? (Array.isArray(rule.fulfillmentState) ? rule.fulfillmentState : [rule.fulfillmentState])\n : [];\n for (const s of fStates) {\n if (!isFulfillmentState(s)) {\n errors.push({\n code: 'invalid_fulfillment_state',\n message: `Unknown fulfillment state \"${s}\" in displayStateMap rule \"${rule.label}\"`,\n path: 'displayStateMap',\n });\n }\n }\n }\n}\n\nfunction validatePathUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingPaymentEdges = new Set(\n config.paymentPaths.map((p) => `${p.from}->${p.to}`),\n );\n for (const path of fragment.paymentPaths ?? []) {\n const edge = `${path.from}->${path.to}`;\n if (existingPaymentEdges.has(edge)) {\n errors.push({\n code: 'duplicate_payment_path',\n message: `Payment path ${path.from} → ${path.to} already exists in the config`,\n path: `paymentPaths[${edge}]`,\n });\n }\n }\n\n const existingFulfillmentEdges = new Set(\n config.fulfillmentPaths.map((p) => `${p.from}->${p.to}`),\n );\n for (const path of fragment.fulfillmentPaths ?? []) {\n const edge = `${path.from}->${path.to}`;\n if (existingFulfillmentEdges.has(edge)) {\n errors.push({\n code: 'duplicate_fulfillment_path',\n message: `Fulfillment path ${path.from} → ${path.to} already exists in the config`,\n path: `fulfillmentPaths[${edge}]`,\n });\n }\n }\n}\n\nfunction validateConditionSetUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingIds = new Set(config.transitionConditions.map((c) => c.id));\n for (const cond of fragment.transitionConditions ?? []) {\n if (existingIds.has(cond.id)) {\n errors.push({\n code: 'duplicate_condition_set_id',\n message: `Condition set ID \"${cond.id}\" already exists in the config`,\n path: `transitionConditions[${cond.id}]`,\n });\n }\n }\n}\n\nfunction validateCrossAxisRuleUniqueness(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n errors: ConfigValidationError[],\n): void {\n const existingIds = new Set(config.crossAxisRules.map((r) => r.id));\n for (const rule of fragment.crossAxisRules ?? []) {\n if (existingIds.has(rule.id)) {\n errors.push({\n code: 'duplicate_cross_axis_rule_id',\n message: `Cross-axis rule ID \"${rule.id}\" already exists in the config`,\n path: `crossAxisRules[${rule.id}]`,\n });\n }\n }\n}\n","import type { DisplayStateRule, StoredStateConfig, StateConfigFragment } from './interfaces';\n\nfunction displayRuleKey(rule: DisplayStateRule): string {\n const p = rule.paymentState;\n const f = rule.fulfillmentState;\n const pKey = p === undefined ? '*' : Array.isArray(p) ? p.slice().sort().join(',') : p;\n const fKey = f === undefined ? '*' : Array.isArray(f) ? f.slice().sort().join(',') : f;\n return `${pKey}|${fKey}`;\n}\n\n/**\n * Merges a resolved StateConfigFragment into an existing StateConfig,\n * tagging every contributed item with `_sourceExtensionId`.\n *\n * Returns a new config object (does not mutate the original).\n */\nexport function mergeFragment(\n config: StoredStateConfig,\n fragment: StateConfigFragment,\n extensionId: string,\n): StoredStateConfig {\n const merged: StoredStateConfig = JSON.parse(JSON.stringify(config));\n\n for (const path of fragment.paymentPaths ?? []) {\n merged.paymentPaths.push({ ...path, _sourceExtensionId: extensionId });\n }\n for (const path of fragment.fulfillmentPaths ?? []) {\n merged.fulfillmentPaths.push({ ...path, _sourceExtensionId: extensionId });\n }\n for (const rule of fragment.crossAxisRules ?? []) {\n merged.crossAxisRules.push({ ...rule, _sourceExtensionId: extensionId });\n }\n for (const cond of fragment.transitionConditions ?? []) {\n merged.transitionConditions.push({ ...cond, _sourceExtensionId: extensionId });\n }\n for (const pair of fragment.validInitialStates ?? []) {\n merged.validInitialStates.push(pair);\n }\n\n for (const rule of fragment.displayStateMap ?? []) {\n const tagged = { ...rule, _sourceExtensionId: extensionId };\n const key = displayRuleKey(tagged);\n const existingIdx = merged.displayStateMap.findIndex(\n (r) => displayRuleKey(r) === key,\n );\n if (existingIdx !== -1) {\n merged.displayStateMap[existingIdx] = tagged;\n } else {\n merged.displayStateMap.push(tagged);\n }\n }\n\n return merged;\n}\n","import type { StoredStateConfig } from './interfaces';\n\n/**\n * Removes all items contributed by a specific extension from a StateConfig.\n * Items are identified by their `_sourceExtensionId` tag.\n *\n * Returns a new config object (does not mutate the original).\n */\nexport function removeFragment(\n config: StoredStateConfig,\n extensionId: string,\n): StoredStateConfig {\n const cleaned: StoredStateConfig = JSON.parse(JSON.stringify(config));\n\n cleaned.paymentPaths = cleaned.paymentPaths.filter(\n (p) => p._sourceExtensionId !== extensionId,\n );\n cleaned.fulfillmentPaths = cleaned.fulfillmentPaths.filter(\n (p) => p._sourceExtensionId !== extensionId,\n );\n cleaned.crossAxisRules = cleaned.crossAxisRules.filter(\n (r) => r._sourceExtensionId !== extensionId,\n );\n cleaned.transitionConditions = cleaned.transitionConditions.filter(\n (c) => c._sourceExtensionId !== extensionId,\n );\n cleaned.displayStateMap = cleaned.displayStateMap.filter(\n (d) => d._sourceExtensionId !== extensionId,\n );\n\n return cleaned;\n}\n","/**\n * Command-frame action contract types for the order state machine.\n *\n * These define the param/response shapes and canonical action name strings\n * that extensions and hosts agree on. Command-frame itself stays agnostic —\n * extensions use `commandFrameClient.call<P, R>(ACTION_NAME, params)` with\n * these types, and hosts register handlers under the same string keys.\n */\n\nimport type {\n StateConfig,\n AvailableTransition,\n DisplayStateResult,\n TransitionResult,\n StateConfigFragment,\n} from './interfaces';\nimport type { StatePair } from './types';\n\n// ---------------------------------------------------------------------------\n// Action name constants (shared between extension and host)\n// ---------------------------------------------------------------------------\n\nexport const ORDER_STATE_ACTIONS = {\n getOrderStateConfig: 'getOrderStateConfig',\n getAvailableTransitions: 'getAvailableTransitions',\n getOrderDisplayState: 'getOrderDisplayState',\n transitionOrderState: 'transitionOrderState',\n getStateConfigFragment: 'getStateConfigFragment',\n saveStateConfigFragment: 'saveStateConfigFragment',\n deleteStateConfigFragment: 'deleteStateConfigFragment',\n} as const;\n\n// ---------------------------------------------------------------------------\n// Render (POS) actions\n// ---------------------------------------------------------------------------\n\nexport interface GetOrderStateConfigParams {}\nexport interface GetOrderStateConfigResponse {\n config: StateConfig;\n}\n\nexport interface GetAvailableTransitionsParams {\n /** Look up order by ID from local DB to determine current state. */\n orderId?: string;\n /** Or provide the state pair directly. */\n currentState?: StatePair;\n /** Skip condition evaluation (useful for UI that shows all structural paths). */\n skipConditionEvaluation?: boolean;\n}\nexport interface GetAvailableTransitionsResponse {\n transitions: AvailableTransition[];\n}\n\nexport interface GetOrderDisplayStateParams {\n /** Look up order by ID from local DB to determine current state pair. */\n orderId?: string;\n /** Or provide the state pair directly. */\n statePair?: StatePair;\n}\nexport interface GetOrderDisplayStateResponse {\n display: DisplayStateResult;\n}\n\nexport interface TransitionOrderStateParams {\n orderId: string;\n to: StatePair;\n}\nexport interface TransitionOrderStateResponse {\n success: boolean;\n order: Record<string, unknown>;\n result: TransitionResult;\n}\n\n// ---------------------------------------------------------------------------\n// Manage (Code) actions — state config fragment CRUD\n// ---------------------------------------------------------------------------\n\nexport interface GetStateConfigFragmentParams {\n extensionId: string;\n}\nexport interface GetStateConfigFragmentResponse {\n fragment: StateConfigFragment | null;\n}\n\nexport interface SaveStateConfigFragmentParams {\n extensionId: string;\n fragment: StateConfigFragment;\n}\nexport interface SaveStateConfigFragmentResponse {\n success: boolean;\n validation?: {\n valid: boolean;\n errors: { code: string; message: string; path?: string }[];\n warnings: { code: string; message: string; path?: string }[];\n };\n}\n\nexport interface DeleteStateConfigFragmentParams {\n extensionId: string;\n}\nexport interface DeleteStateConfigFragmentResponse {\n success: boolean;\n}\n","/**\n * Pub/sub event payload types for the order state machine.\n *\n * The host publishes these via command-frame's `topicPublisher` under the\n * \"order-state\" topic. Extensions subscribe by string and cast the payload\n * to the typed event interfaces exported here.\n */\n\nimport type {\n DisplayStateResult,\n TransitionBlockedBy,\n} from './interfaces';\nimport type { StatePair } from './types';\n\nexport const ORDER_STATE_TOPIC = 'order-state' as const;\n\nexport const ORDER_STATE_EVENTS = {\n stateTransitionCompleted: 'state-transition-completed',\n stateTransitionBlocked: 'state-transition-blocked',\n configUpdated: 'config-updated',\n} as const;\n\nexport interface StateTransitionCompletedPayload {\n orderId: string;\n from: StatePair;\n to: StatePair;\n display: DisplayStateResult;\n timestamp: string;\n}\n\nexport interface StateTransitionBlockedPayload {\n orderId: string;\n from: StatePair;\n attemptedTo: StatePair;\n blockedBy: TransitionBlockedBy[];\n timestamp: string;\n}\n\nexport interface ConfigUpdatedPayload {\n companyId: string;\n configId: string;\n version: number;\n timestamp: string;\n}\n\nexport type OrderStateEventPayload =\n | StateTransitionCompletedPayload\n | StateTransitionBlockedPayload\n | ConfigUpdatedPayload;\n","import { BookingRatePeriod } from '../enums';\n\n/*\n * Structural inputs for the booking grid.\n *\n * `common` sits BELOW data-layer (data-layer consumes it), so the shared arithmetic cannot\n * import the mongoose classes. It describes the shape it reads instead: hub-api hands it a\n * mongoose document and the till hands it a row from its local database, and both fit.\n */\n\nexport interface WeeklyHours {\n /** 0 = Sunday, matching `Date#getDay`. */\n weekday: number;\n openMinute: number;\n closeMinute: number;\n}\n\nexport interface BookingRulesInput {\n ratePeriod: BookingRatePeriod | `${BookingRatePeriod}`;\n slot: {\n lengthMinutes: number;\n bufferMinutes?: number;\n minimumToRun?: number;\n minStay?: number;\n maxStay?: number;\n sharedAcrossProducts?: boolean;\n };\n window: {\n /** 0 or absent means no limit — see `windowEndsAt`. */\n maxAdvanceDays?: number;\n minNoticeMinutes?: number;\n /** How long an unpaid booking keeps its window. Absent = the platform default. */\n holdMinutes?: number;\n bookableFrom?: Date | string | null;\n bookableTo?: Date | string | null;\n };\n availability: {\n weeklyHours?: WeeklyHours[];\n offMarket?: { from: Date | string; to: Date | string }[];\n /** Period rules: which weekdays a stay may START on. */\n arrivalDays?: number[];\n availableFrom?: Date | string | null;\n };\n /** Overnight only, \"HH:mm\" local. */\n checkInTime?: string | null;\n checkOutTime?: string | null;\n}\n\n/** A window a resource is already busy for, buffer included. */\nexport interface BusyWindow {\n startAt: Date;\n bufferEndAt: Date;\n}\n\nexport interface GridSlot {\n startAt: Date;\n endAt: Date;\n /** End of the turnaround. Equals endAt when the rules have none. */\n bufferEndAt: Date;\n /** Period rules with `arrivalDays`: may a stay START here. Always true otherwise. */\n canStart: boolean;\n}\n\n/**\n * Rules the merchant configured wrongly, or a window that does not line up with the grid.\n * A plain error: `common` knows nothing about HTTP, so the server maps it to a 400 and the\n * till shows it as a refusal.\n */\nexport class BookingRulesError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'BookingRulesError';\n }\n}\n","/*\n * Local wall-clock arithmetic on native `Intl` — no date library.\n *\n * The booking grid is defined in the outlet's LOCAL time (\"open 09:00 Mon–Fri\") and must\n * come out as UTC instants, which is what makes it survive daylight saving: the wall clock\n * stays 09:00 while the instant moves. `common` carries no runtime dependencies and is\n * consumed by every app we ship, so pulling in a timezone library here would land in each\n * of their bundles. `Intl.DateTimeFormat` already knows every zone, in Node and in browsers.\n */\n\nimport { BookingRulesError } from './types';\n\nconst MINUTE = 60_000;\n\nconst formatters = new Map<string, Intl.DateTimeFormat>();\n\nconst formatterFor = (timeZone: string): Intl.DateTimeFormat => {\n const existing = formatters.get(timeZone);\n if (existing) return existing;\n let created: Intl.DateTimeFormat;\n try {\n created = new Intl.DateTimeFormat('en-US', {\n timeZone,\n hour12: false,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n weekday: 'short',\n });\n } catch {\n // A zone the runtime does not know is a merchant's typo in Outlet/Company settings, which\n // is a refusal to state — not a crash. `Intl` throws a bare RangeError, and the server's\n // adapter only converts BookingRulesError into a 400, so this would have been a 500 and an\n // alert instead of \"your timezone is wrong\".\n throw new BookingRulesError(`Booking rules: \"${timeZone}\" is not a known time zone`);\n }\n formatters.set(timeZone, created);\n return created;\n};\n\nconst WEEKDAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n\nexport interface ZonedParts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n /** 0 = Sunday, matching `Date#getDay`. */\n weekday: number;\n}\n\n/** What the wall clock in `timeZone` reads at this instant. */\nexport function zonedParts(instant: Date, timeZone: string): ZonedParts {\n const parts: Record<string, string> = {};\n for (const { type, value } of formatterFor(timeZone).formatToParts(instant)) parts[type] = value;\n // `24` at midnight is legal ISO and some engines emit it; the day is already correct.\n const hour = Number(parts.hour) % 24;\n return {\n year: Number(parts.year),\n month: Number(parts.month),\n day: Number(parts.day),\n hour,\n minute: Number(parts.minute),\n second: Number(parts.second),\n weekday: WEEKDAYS.indexOf(parts.weekday),\n };\n}\n\n/** Offset of `timeZone` at this instant, in ms (positive east of Greenwich). */\nfunction offsetAt(instant: Date, timeZone: string): number {\n const { year, month, day, hour, minute, second } = zonedParts(instant, timeZone);\n return Date.UTC(year, month - 1, day, hour, minute, second) - Math.floor(instant.getTime() / 1000) * 1000;\n}\n\n/**\n * The instant at which `timeZone` reads this local date plus `minutes` from its midnight.\n * Minutes may exceed 1440 (a night ends the next morning) or be negative.\n *\n * Two passes: the offset is a function of the instant, and the instant is what we are\n * solving for. The first guess uses the offset in force at the naive time, the second the\n * offset actually in force there — which is what makes a spring-forward morning land right.\n */\nexport function instantFromLocal(year: number, month: number, day: number, minutes: number, timeZone: string): Date {\n const naive = Date.UTC(year, month - 1, day) + minutes * MINUTE;\n const firstGuess = naive - offsetAt(new Date(naive), timeZone);\n return new Date(naive - offsetAt(new Date(firstGuess), timeZone));\n}\n\n/** Local midnight of the day this instant falls on, as a UTC instant. */\nexport function startOfZonedDay(instant: Date, timeZone: string): Date {\n const { year, month, day } = zonedParts(instant, timeZone);\n return instantFromLocal(year, month, day, 0, timeZone);\n}\n\n/**\n * Local midnight of the day after `dayStart`. Walks the CALENDAR, not 24 hours: on the day\n * a clock shifts, \"tomorrow\" is 23 or 25 hours away and adding a fixed day would drift.\n */\nexport function nextZonedDay(dayStart: Date, timeZone: string): Date {\n const { year, month, day } = zonedParts(dayStart, timeZone);\n return instantFromLocal(year, month, day + 1, 0, timeZone);\n}\n\n/** A wall-clock minute count on the local day of `dayStart`, as a UTC instant. */\nexport function atZonedMinute(dayStart: Date, minutes: number, timeZone: string): Date {\n const { year, month, day } = zonedParts(dayStart, timeZone);\n return instantFromLocal(year, month, day, minutes, timeZone);\n}\n","import { BookingRatePeriod } from '../enums';\nimport { atZonedMinute, nextZonedDay, startOfZonedDay, zonedParts } from './zoned-time';\nimport { BookingRulesError, type BookingRulesInput, type BusyWindow, type GridSlot } from './types';\n\n/*\n * The bookable grid: a PURE function of (rules, timezone, range, now). No database, no state\n * — occupancy is counted by the caller and handed in as `busy`.\n *\n * It lives here, in the package both the server and the till consume, because both must\n * answer \"what times are free?\" and two copies of this arithmetic would drift. The till\n * needs its own answer to keep working with no network, exactly as it already does for\n * stock: hold the data locally, sync afterwards.\n *\n * Two shapes, decided by `ratePeriod`:\n * SLOT — an intraday grid inside the weekly opening hours,\n * stepping `lengthMinutes + bufferMinutes`.\n * DAY | NIGHT | WEEK | MONTH — one slot per local day. A night runs checkIn→checkOut with\n * housekeeping living in the gap, and a stay of N nights\n * simply occupies N consecutive slots.\n *\n * Weekly hours mean LOCAL time of the outlet, so the caller resolves the zone\n * (outlet.timeZone ?? company.timeZone) and the grid returns UTC instants — which is what\n * makes it survive DST: the wall clock stays 09:00, the instant moves.\n */\n\nconst MINUTE = 60_000;\n\n/**\n * The widest range a single call may draw.\n *\n * The walk below is bounded only by the caller's `to`, and the window filter runs AFTER the\n * slots exist — so `maxAdvanceDays` does not bound the work. A year of a five-day week is\n * ~4.7k slots in ~20ms; `to=9999-12-31` is ~2.9M days, minutes of CPU and millions of objects\n * PER RESOURCE, from one request. The refusal belongs here rather than in a controller for the\n * same reason as the rest of the rule: the till has to refuse exactly what the server refuses.\n */\nconst MAX_RANGE_DAYS = 366;\n\n/**\n * A rule's date field as an instant, or `undefined` when the merchant left it empty.\n *\n * Throws on anything unparseable, because the alternative is silence with the worst possible\n * shape: `new Date('garbage').getTime()` is `NaN`, not `undefined`, so a `?? INFINITY` guard\n * never fires and the NaN spreads — `Math.min(x, NaN)` and `Math.max(x, NaN)` are both `NaN`,\n * every comparison against it is false, and the rule it belonged to simply stops applying. One\n * typo in `bookableFrom` was enough to switch off `minNoticeMinutes` as well.\n */\nconst asTime = (value: Date | string | null | undefined, field: string): number | undefined => {\n if (value == null) return undefined;\n const time = new Date(value).getTime();\n if (Number.isNaN(time)) throw new BookingRulesError(`Booking rules: ${field} is not a date, got \"${String(value)}\"`);\n return time;\n};\n\nfunction parseHhMm(value: string, field: string): number {\n const [hours, minutes] = value.split(':').map(Number);\n if (!Number.isInteger(hours) || !Number.isInteger(minutes)) {\n throw new BookingRulesError(`Booking rules: ${field} must be \"HH:mm\", got \"${value}\"`);\n }\n return hours * 60 + minutes;\n}\n\n/**\n * The last instant this rule can still be booked into, or `null` when nothing bounds it.\n *\n * `maxAdvanceDays: 0` — the default — means NO limit, not \"closed today\": a merchant who\n * never thought about how far ahead people may book should get an open calendar, not an\n * empty one. Exported because the UI has to say \"beyond the booking window\" in the very\n * place it would otherwise say \"nothing free\", and it must not re-derive this arithmetic.\n */\nexport function windowEndsAt(rule: BookingRulesInput, now: Date): Date | null {\n const { maxAdvanceDays, bookableTo } = rule.window;\n const ends = Math.min(\n maxAdvanceDays ? now.getTime() + maxAdvanceDays * 1440 * MINUTE : Number.POSITIVE_INFINITY,\n asTime(bookableTo, 'window.bookableTo') ?? Number.POSITIVE_INFINITY,\n );\n return Number.isFinite(ends) ? new Date(ends) : null;\n}\n\n/** One slot per local day — the period shapes. */\nfunction periodSlot(\n dayStart: Date,\n timeZone: string,\n rule: BookingRulesInput,\n openMinute?: number,\n closeMinute?: number,\n): GridSlot {\n const { ratePeriod, slot, checkInTime, checkOutTime } = rule;\n const at = (minutes: number) => atZonedMinute(dayStart, minutes, timeZone);\n\n if (ratePeriod === BookingRatePeriod.NIGHT) {\n // Fail loud: an overnight rule set without its two times has no grid at all, and\n // guessing 15:00/11:00 would silently invent the merchant's housekeeping window.\n if (!checkInTime || !checkOutTime) {\n throw new BookingRulesError('Overnight booking rules need both checkInTime and checkOutTime');\n }\n const checkIn = parseHhMm(checkInTime, 'checkInTime');\n const checkOut = parseHhMm(checkOutTime, 'checkOutTime');\n return {\n startAt: at(checkIn),\n endAt: at(1440 + checkOut),\n // Housekeeping sits between check-out and the next check-in: it costs no night.\n bufferEndAt: at(1440 + checkIn),\n canStart: true,\n };\n }\n\n const from = ratePeriod === BookingRatePeriod.DAY ? (openMinute ?? 0) : 0;\n const to = ratePeriod === BookingRatePeriod.DAY ? (closeMinute ?? 1440) : 1440;\n return {\n startAt: at(from),\n endAt: at(to),\n bufferEndAt: at(to + (slot.bufferMinutes ?? 0)),\n canStart: true,\n };\n}\n\n/**\n * Free stretches inside [open, close). `endsAtBooking` says WHY a gap ends: against another\n * booking the turnaround buffer must fit too, or the slot would be offered and then refused;\n * against closing time the buffer may run past the door, exactly as the day-anchored grid\n * always allowed.\n */\nfunction freeGaps(\n openAt: number,\n closeAt: number,\n busy: BusyWindow[],\n): { from: number; to: number; endsAtBooking: boolean }[] {\n const inside = busy\n .map(({ startAt, bufferEndAt }) => ({ from: +startAt, to: +bufferEndAt }))\n .filter(({ from, to }) => to > openAt && from < closeAt)\n .sort((first, second) => first.from - second.from);\n\n const gaps: { from: number; to: number; endsAtBooking: boolean }[] = [];\n let cursor = openAt;\n for (const { from, to } of inside) {\n // Always a booking here: `inside` is already filtered to `from < closeAt`, so this gap ends\n // against the next booking by construction. Only the trailing gap below ends at the door.\n if (from > cursor) gaps.push({ from: cursor, to: from, endsAtBooking: true });\n cursor = Math.max(cursor, to);\n if (cursor >= closeAt) break;\n }\n if (cursor < closeAt) gaps.push({ from: cursor, to: closeAt, endsAtBooking: false });\n return gaps;\n}\n\n/**\n * The bookable grid.\n *\n * Starts are anchored to the resource's FREE TIME, not to the start of the day, and the\n * length comes from the service. That matters as soon as one resource serves services of\n * different lengths: a 15-minute beard trim at 9:00 leaves the barber free from 9:20, and a\n * 30-minute haircut should then be offered at 9:20 — a day-anchored grid would only offer\n * 9:35 and throw the gap away.\n *\n * The visible consequence, accepted deliberately: offered times SHIFT as the day fills up.\n * `busy` empty (nothing booked) gives exactly the old tidy grid from the opening time.\n *\n * Group sessions are the exception and keep the fixed grid: a class starts at 18:00 because\n * that is when it starts, not because the room happens to be free then. The caller signals\n * that by passing no `busy` for a resource with more than one seat.\n */\nexport function buildGrid(\n rule: BookingRulesInput,\n timeZone: string,\n from: Date,\n to: Date,\n now: Date,\n busy: BusyWindow[] = [],\n): GridSlot[] {\n if (to.getTime() - from.getTime() > MAX_RANGE_DAYS * 1440 * MINUTE) {\n throw new BookingRulesError(`A booking range may span at most ${MAX_RANGE_DAYS} days`);\n }\n const { availability, slot, window, ratePeriod } = rule;\n const periodMode = ratePeriod !== BookingRatePeriod.SLOT;\n const weeklyHours = availability.weeklyHours ?? [];\n\n const notBefore = Math.max(\n now.getTime() + (window.minNoticeMinutes ?? 0) * MINUTE,\n asTime(window.bookableFrom, 'window.bookableFrom') ?? 0,\n asTime(availability.availableFrom, 'availability.availableFrom') ?? 0,\n );\n const notAfter = windowEndsAt(rule, now)?.getTime() ?? Number.POSITIVE_INFINITY;\n const blocked = (availability.offMarket ?? []).map(({ from: blockFrom, to: blockTo }) => ({\n from: asTime(blockFrom, 'availability.offMarket.from') as number,\n to: asTime(blockTo, 'availability.offMarket.to') as number,\n }));\n const arrivalDays = availability.arrivalDays;\n const step = slot.lengthMinutes + (slot.bufferMinutes ?? 0);\n\n const slots: GridSlot[] = [];\n // The range is walked by LOCAL calendar days, so a clock change makes a day 23 or 25\n // hours long without shifting the grid off the merchant's opening times.\n const lastDay = startOfZonedDay(to, timeZone).getTime();\n let dayStart = startOfZonedDay(from, timeZone);\n\n while (dayStart.getTime() <= lastDay) {\n const weekday = zonedParts(dayStart, timeZone).weekday;\n const rows = weeklyHours.filter((entry) => entry.weekday === weekday);\n\n if (periodMode) {\n // A hotel or a long let has no opening hours by nature: NO weekly rows at all means\n // every day is bookable; rows present mean only those weekdays are.\n const openToday = weeklyHours.length === 0 || rows.length > 0;\n if (openToday) {\n const built = periodSlot(dayStart, timeZone, rule, rows[0]?.openMinute, rows[0]?.closeMinute);\n slots.push({ ...built, canStart: !arrivalDays?.length || arrivalDays.includes(weekday) });\n }\n } else {\n for (const row of rows) {\n const openAt = +atZonedMinute(dayStart, row.openMinute, timeZone);\n const closeAt = +atZonedMinute(dayStart, row.closeMinute, timeZone);\n for (const gap of freeGaps(openAt, closeAt, busy)) {\n // Anchored at the gap, stepping by this service's own length + buffer.\n const mustFit = (gap.endsAtBooking ? step : slot.lengthMinutes) * MINUTE;\n for (let start = gap.from; start + mustFit <= gap.to; start += step * MINUTE) {\n slots.push({\n startAt: new Date(start),\n endAt: new Date(start + slot.lengthMinutes * MINUTE),\n bufferEndAt: new Date(start + step * MINUTE),\n canStart: true,\n });\n }\n }\n }\n }\n dayStart = nextZonedDay(dayStart, timeZone);\n }\n\n // The asked-for window bounds the ANSWER, not just which days get walked. The day walk\n // includes `to`'s calendar day on purpose (a zone can make a day 23 or 25 hours long), so\n // without this a caller asking for one day is handed the next one too — and a screen showing\n // \"Sunday\" then lists Monday's times. Half-open: `to` itself belongs to the next request.\n const askedFrom = from.getTime();\n const askedTo = to.getTime();\n\n return slots\n .filter(({ startAt, bufferEndAt }) => {\n const start = startAt.getTime();\n if (start < askedFrom || start >= askedTo) return false;\n if (start < notBefore || start > notAfter) return false;\n return !blocked.some(({ from: blockFrom, to: blockTo }) => start < blockTo && bufferEndAt.getTime() > blockFrom);\n })\n // Ascending, because `slotsForWindow` walks this list expecting it: it finds the start by\n // index and then requires each next slot to begin where the previous turnaround ended. The\n // order was only ever incidental — it came from the merchant's own `weeklyHours` array — so\n // storing an afternoon row before a morning one made a perfectly legal two-slot window\n // \"not line up with the bookable grid\". Verified: rows [10:00, 14:00, 09:00] refused\n // 09:00–11:00.\n .sort((first, second) => +first.startAt - +second.startAt);\n}\n\n/**\n * The slots a requested window covers, or an explanation of why it is not bookable.\n *\n * Alignment is checked against the grid instead of trusted from the client: the start must\n * BE a slot start, each following slot must begin exactly where the previous one's turnaround\n * ended (so a closed hour in the middle cannot be booked through), and the end must land on\n * the last slot's end.\n */\nexport function slotsForWindow(grid: GridSlot[], startAt: Date, endAt: Date): GridSlot[] {\n const startIndex = grid.findIndex((entry) => entry.startAt.getTime() === startAt.getTime());\n if (startIndex < 0) {\n throw new BookingRulesError(`${startAt.toISOString()} is not a bookable slot start for these rules`);\n }\n if (!grid[startIndex].canStart) {\n throw new BookingRulesError(`${startAt.toISOString()} is not an arrival day for these rules`);\n }\n\n const covered: GridSlot[] = [];\n for (let index = startIndex; index < grid.length; index++) {\n const entry = grid[index];\n const previous = covered[covered.length - 1];\n if (previous && entry.startAt.getTime() !== previous.bufferEndAt.getTime()) break;\n covered.push(entry);\n if (entry.endAt.getTime() === endAt.getTime()) return covered;\n if (entry.endAt.getTime() > endAt.getTime()) break;\n }\n throw new BookingRulesError(\n `${startAt.toISOString()} → ${endAt.toISOString()} does not line up with the bookable grid`,\n );\n}\n","import { buildGrid, windowEndsAt } from './grid';\nimport { BookingType, ResourceAvailabilityState } from '../enums';\nimport { atZonedMinute, startOfZonedDay, zonedParts } from './zoned-time';\nimport type { BookingRulesInput, BusyWindow, GridSlot, WeeklyHours } from './types';\n\n/*\n * Availability: the grid crossed with what is already taken.\n *\n * Pure, and keyed by STRING ids, so the same code answers on the server (mongo documents)\n * and on the till (rows from its local database). Occupancy is the bookings themselves —\n * a resource is busy for [startAt, bufferEndAt) — which is why the till can answer this\n * question with no network at all: it already syncs those rows down.\n */\n\n/** A live hold, as either side stores it. */\nexport interface BookingOccupancy {\n resourceId: string;\n productId: string;\n qty: number;\n startAt: Date;\n bufferEndAt: Date;\n}\n\n/** A resource serving the product, with the wall clock it keeps. */\nexport interface BookingResourceInput {\n id: string;\n name: string;\n /** Seats in ONE slot. Absent means one. */\n seats?: number | null;\n timeZone: string;\n /**\n * When this resource is AT the outlet being sold from. Empty or absent = whenever the\n * product is open there.\n *\n * A chain's barber splits her week between two shops, so offering her every day the shop\n * is open would book her where she is not. Whether she works at this outlet at all is the\n * caller's filter — a resource with no row for it is simply not in this list.\n */\n presence?: WeeklyHours[] | null;\n}\n\nexport interface ResourceAvailability {\n resourceId: string;\n name: string;\n capacity: number;\n booked: number;\n free: number;\n}\n\nexport interface AvailabilitySlot extends GridSlot {\n capacity: number;\n booked: number;\n free: number;\n resources: ResourceAvailability[];\n}\n\n/**\n * Every resource that serves this product AT THIS OUTLET, whether or not it has a slot in\n * the range. A resource with nothing free is a fact the engine knows and the UI cannot\n * re-derive: dropping it silently makes \"does not work here\" and \"not in these days\" look\n * identical — like the person does not exist.\n */\nexport interface ResourceInWindow {\n resourceId: string;\n name: string;\n /** Slots OFFERABLE in the range. Zero can mean \"not working\" or \"full\" — read `state`. */\n slots: number;\n /** How many of those still have room. */\n free: number;\n state: ResourceAvailabilityState;\n}\n\nexport interface AvailabilityInput {\n productId: string;\n /** Echoed in the header so a caller can tell which set produced this calendar. */\n bookingRulesId?: string;\n bookingType?: BookingType;\n rule: BookingRulesInput;\n resources: BookingResourceInput[];\n /** Live holds (held or confirmed) overlapping the range, any resource. */\n occupied: BookingOccupancy[];\n from: Date;\n to: Date;\n now: Date;\n}\n\n/**\n * Does the appointment itself fit inside the resource's shift that day?\n *\n * The SERVICE window is what has to fit (`startAt`–`endAt`), not the turnaround after it: a\n * chair being cleaned at 18:05 does not need the barber to still be there, exactly as the grid\n * already lets a buffer run past closing time.\n */\nexport const withinPresence = (slot: GridSlot, timeZone: string, presence?: WeeklyHours[] | null): boolean => {\n if (!presence?.length) return true;\n const dayStart = startOfZonedDay(slot.startAt, timeZone);\n const weekday = zonedParts(dayStart, timeZone).weekday;\n return presence.some(\n (shift) =>\n shift.weekday === weekday &&\n slot.startAt.getTime() >= atZonedMinute(dayStart, shift.openMinute, timeZone).getTime() &&\n slot.endAt.getTime() <= atZonedMinute(dayStart, shift.closeMinute, timeZone).getTime(),\n );\n};\n\nconst overlaps = (entry: BookingOccupancy, startAt: Date, bufferEndAt: Date): boolean =>\n entry.startAt.getTime() < bufferEndAt.getTime() && entry.bufferEndAt.getTime() > startAt.getTime();\n\n/**\n * Seats taken in a window, and whether another PRODUCT is holding it.\n *\n * Overlap alone is not the whole answer once a resource has more than one seat: a room with 12\n * places is not \"free for cycling\" because yoga took 5 of them. Unless the rules say\n * `sharedAcrossProducts`, a window belongs to ONE product and seats only stack within it.\n *\n * Exported because three callers ask it — the calendar, the server's write and the till's.\n */\nexport function occupancyIn(\n occupied: BookingOccupancy[],\n productId: string,\n startAt: Date,\n bufferEndAt: Date,\n shared: boolean,\n): { taken: number; foreignProductId?: string } {\n const clashing = occupied.filter((entry) => overlaps(entry, startAt, bufferEndAt));\n const foreign = shared ? undefined : clashing.find((entry) => entry.productId !== productId);\n return {\n taken: clashing\n .filter((entry) => shared || entry.productId === productId)\n .reduce((sum, entry) => sum + entry.qty, 0),\n foreignProductId: foreign?.productId,\n };\n}\n\n/**\n * \"Not working these days\" and \"booked solid\" both arrive as zero offerable slots, and they are\n * not the same answer: telling a customer a barber does not work on Monday when she is simply\n * full is the exact confusion this field exists to remove. A single-seat resource has its taken\n * windows REMOVED from the grid (that is what anchors a start to what is free), so the count\n * alone cannot tell them apart — the shift has to be measured separately, with nothing busy.\n *\n * Only computed when there is nothing to offer, which is the only case that is ambiguous.\n */\nconst stateFor = (\n hasShift: () => boolean,\n offerable: number,\n free: number,\n): ResourceAvailabilityState => {\n if (offerable === 0) {\n return hasShift() ? ResourceAvailabilityState.FULLY_BOOKED : ResourceAvailabilityState.NO_HOURS_IN_RANGE;\n }\n return free === 0 ? ResourceAvailabilityState.FULLY_BOOKED : ResourceAvailabilityState.AVAILABLE;\n};\n\nexport function buildAvailability({\n productId,\n bookingRulesId,\n bookingType,\n rule,\n resources,\n occupied,\n from,\n to,\n now,\n}: AvailabilityInput) {\n const shared = rule.slot.sharedAcrossProducts ?? false;\n const bookableUntil = windowEndsAt(rule, now);\n const header = {\n productId,\n bookingRulesId,\n bookingType,\n ratePeriod: rule.ratePeriod,\n // Passed through for the UI to label: a group slot under minimumToRun may not run.\n minimumToRun: rule.slot.minimumToRun,\n minStay: rule.slot.minStay,\n maxStay: rule.slot.maxStay,\n // Why a day can come back empty. Past this instant the rule refuses everything, so the UI\n // can say \"beyond the booking window\" where it would otherwise claim \"nothing free\".\n bookableUntil,\n // The comparison itself, not just the boundary: deciding whether a day lies past the\n // window is a rule, and a UI that re-derives it owns a copy of that rule — which is how\n // the same empty grid ends up explained one way on the till and another in a flow.\n beyondWindow: !!bookableUntil && from.getTime() > bookableUntil.getTime(),\n };\n\n const byResource = new Map<string, BookingOccupancy[]>();\n for (const entry of occupied) {\n byResource.set(entry.resourceId, [...(byResource.get(entry.resourceId) ?? []), entry]);\n }\n\n // Deliberately unfiltered: a resource with no slots still travels in `resources` below, so\n // the caller can say WHY it cannot be picked. It contributes nothing to the slot grid.\n const grids = resources.map((resource) => {\n const mine = byResource.get(resource.id) ?? [];\n // A resource with several seats keeps the FIXED grid: a class starts at 18:00 because\n // that is its time, not because the room happens to be free then. Its partial occupancy\n // is counted per slot below instead.\n const busy: BusyWindow[] = (resource.seats ?? 1) === 1 ? mine : [];\n const slots = buildGrid(rule, resource.timeZone, from, to, now, busy).filter((slot) =>\n withinPresence(slot, resource.timeZone, resource.presence),\n );\n return { resource, slots };\n });\n\n // Same wall clock in two zones is two different instants, so grouping by the instant keeps\n // a chain's cities apart without any special case.\n const byInstant = new Map<number, AvailabilitySlot>();\n const freeSlotsPerResource = new Map<string, number>();\n for (const { resource, slots } of grids) {\n const capacity = resource.seats ?? 1;\n const mine = byResource.get(resource.id) ?? [];\n for (const slot of slots) {\n const { taken, foreignProductId } = occupancyIn(mine, productId, slot.startAt, slot.bufferEndAt, shared);\n // Another service in the window means nothing is free here, however many seats the\n // resource has — the room is running that other session.\n const free = foreignProductId ? 0 : Math.max(capacity - taken, 0);\n const entry = byInstant.get(+slot.startAt) ?? { ...slot, capacity: 0, booked: 0, free: 0, resources: [] };\n entry.capacity += capacity;\n entry.booked += foreignProductId ? capacity : taken;\n entry.free += free;\n entry.canStart = entry.canStart || slot.canStart;\n entry.resources.push({ resourceId: resource.id, name: resource.name, capacity, booked: taken, free });\n if (free > 0) freeSlotsPerResource.set(resource.id, (freeSlotsPerResource.get(resource.id) ?? 0) + 1);\n byInstant.set(+slot.startAt, entry);\n }\n }\n\n const inWindow: ResourceInWindow[] = grids.map(({ resource, slots }) => {\n const free = freeSlotsPerResource.get(resource.id) ?? 0;\n return {\n resourceId: resource.id,\n name: resource.name,\n slots: slots.length,\n free,\n // Lazily: the shift grid is a second walk, and only an empty answer needs it.\n state: stateFor(\n () =>\n buildGrid(rule, resource.timeZone, from, to, now).filter((slot) =>\n withinPresence(slot, resource.timeZone, resource.presence),\n ).length > 0,\n slots.length,\n free,\n ),\n };\n });\n\n return {\n ...header,\n resources: inWindow,\n slots: [...byInstant.values()].sort((first, second) => +first.startAt - +second.startAt),\n };\n}\n\n/** A row of `booking-resource-outlets`: where a resource works, and when it is there. */\nexport interface ResourcePresenceRow {\n resourceId: string;\n outletId: string;\n weeklyHours?: WeeklyHours[] | null;\n}\n\n/**\n * Which of these resources works at the outlet being sold from, and when they are there.\n *\n * NO rows at all means everywhere — the state every resource starts in, so a one-shop merchant\n * never has to fill this in and nothing breaks the day the collection appears. A resource that\n * HAS rows works only where they say: a barber splitting her week between two shops must not be\n * offered in the shop she is not in, however open that shop is.\n *\n * With no outlet in context (an API caller that named none) nothing can be narrowed, and\n * pretending otherwise would hide half the calendar — so every resource stays, unnarrowed.\n *\n * Shared because the server and the till must answer this identically: the till draws the\n * calendar offline and the server then validates the very window it offered.\n */\nexport function presentAt<T extends { id: string }>(\n resources: T[],\n rows: ResourcePresenceRow[],\n outletId?: string,\n): { resource: T; presence?: WeeklyHours[] | null }[] {\n const byResource = new Map<string, ResourcePresenceRow[]>();\n for (const row of rows) {\n byResource.set(row.resourceId, [...(byResource.get(row.resourceId) ?? []), row]);\n }\n\n return resources.flatMap((resource) => {\n const own = byResource.get(resource.id) ?? [];\n if (own.length === 0 || !outletId) return [{ resource }];\n const here = own.find((row) => row.outletId === outletId);\n return here ? [{ resource, presence: here.weeklyHours }] : [];\n });\n}\n","import { buildGrid, slotsForWindow } from './grid';\nimport { withinPresence } from './availability';\nimport { BookingRulesError } from './types';\nimport type { BookingRulesInput, BusyWindow, GridSlot, WeeklyHours } from './types';\n\n/*\n * Turning a REQUEST into a booking: the arithmetic both sides run.\n *\n * The till writes bookings itself (it must sell with no network), the server writes them from\n * back office and validates what the till sends. Two copies of \"is this window legal\" would\n * drift into a till offering what the server refuses, so the decision lives here once.\n */\n\n/** How long an unpaid booking keeps its window when the rules do not say. */\nexport const DEFAULT_HOLD_MINUTES = 10;\n\nexport interface PlanWindowInput {\n rule: BookingRulesInput;\n timeZone: string;\n /** The resource's shift at the outlet being sold from. Absent = whenever the product is open. */\n presence?: WeeklyHours[] | null;\n startAt: Date;\n endAt: Date;\n now: Date;\n /**\n * Windows this resource is already busy for. Anchors the grid so a start sitting right after\n * someone else's booking is recognised — pass them only for a single-seat resource, whose\n * grid moves with what is taken; a multi-seat one keeps its fixed times.\n */\n busy?: BusyWindow[];\n}\n\n/**\n * The slots a requested window covers, plus where the booking really ends.\n *\n * `endAt` is taken from the GRID, not from the request: the caller says which slot it wants and\n * the rules decide how long that is, so a client cannot stretch a 30-minute appointment by\n * asking for one. `bufferEndAt` carries the turnaround, which is what occupancy is measured on.\n *\n * Throws `BookingRulesError` when the window is not offerable — a misaligned start, a closed\n * hour in the middle, or a stay outside `minStay`/`maxStay`.\n */\nexport function planWindow({ rule, timeZone, presence, startAt, endAt, now, busy = [] }: PlanWindowInput): {\n slots: GridSlot[];\n endAt: Date;\n bufferEndAt: Date;\n} {\n const grid = buildGrid(rule, timeZone, startAt, endAt, now, busy).filter((slot) =>\n withinPresence(slot, timeZone, presence),\n );\n const slots = slotsForWindow(grid, startAt, endAt);\n const { minStay, maxStay } = rule.slot;\n if (minStay && slots.length < minStay) {\n throw new BookingRulesError(`These rules ask for at least ${minStay} period(s), got ${slots.length}`);\n }\n if (maxStay && slots.length > maxStay) {\n throw new BookingRulesError(`These rules allow at most ${maxStay} period(s), got ${slots.length}`);\n }\n const last = slots[slots.length - 1];\n return { slots, endAt: last.endAt, bufferEndAt: last.bufferEndAt };\n}\n\n/** When an unpaid booking made now gives its window back. */\nexport const holdExpiresAt = (rule: BookingRulesInput, now: Date): Date =>\n new Date(now.getTime() + (rule.window.holdMinutes ?? DEFAULT_HOLD_MINUTES) * 60_000);\n","/**\n * Where Adyen has been rolled out to merchants — Canada only for now.\n *\n * A ROLLOUT decision, not a statement about Adyen's availability. Adyen for Platforms onboards in ~30\n * countries; what limits us is per-country backend configuration that must exist before a merchant there\n * can transact — a merchant account, a commission split configuration profile, and terminal supply. CA is\n * the only one provisioned.\n *\n * Shared because both sides need the same answer and must not drift: hub-api ENFORCES it (a 403 on\n * `create-business-account`, the only entry point to the Adyen surface) and deerlake uses it to hide the\n * Adyen menu. The frontend copy is a convenience; the backend one is the boundary.\n *\n * Widen this set as each country's backend configuration lands, and delete it once the rollout is\n * complete — it is scaffolding, not a permanent part of the domain.\n */\nexport const ADYEN_ROLLOUT_COUNTRY_CODES = new Set(['CA']);\n\n/** Whether Adyen has been rolled out to the given ISO 3166-1 alpha-2 country code. */\nexport function isAdyenRolloutCountry(alpha2: string): boolean {\n return ADYEN_ROLLOUT_COUNTRY_CODES.has(alpha2);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACIO,IAAK,eAAL,kBAAKA,kBAAL;AAEL,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AAGN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,SAAM;AAGN,EAAAA,cAAA,SA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","names":["CurrencyCode","TimePeriod","TopMetericsSort","CompanyType","CustomTableAvailability","AttributeType","Platform","OrderPlatform","CustomerPlatform","StationStatus","InventoryBaseActionEnum","InventorySpecificActionType","ExtensionCategory","FeesCustomBillingStatus","PricingPlanEnum","PricingLevel","PricingRegionEnum","MenuProject","UserTypes","OwnerType","PublicationAvailability","PublicationStatus","ResidualStatus","PreviewImageMode","LibraryItemType","ResidualPaymentMethod","PaymentMethod","NonRevenueItemType","ReceiptSendChannel","ReceiptType","StripeStatus","InvoiceStatus","StripeCurrencyCode","ProductType","ProductStatus","PaymentProcessor","BookingType","BookingRatePeriod","BookingResourceKind","ReservationStatus","BookingResourceStatus","ResourceAvailabilityState","unit","toMinorUnits","MINUTE"]}