@final-commerce/common 2.2.0-beta.1 → 2.2.0-preprod.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.d.mts CHANGED
@@ -189,7 +189,8 @@ declare enum Platform {
189
189
  }
190
190
  declare enum OrderPlatform {
191
191
  POS = "in-store",
192
- WOO_COMMERCE = "woo-commerce"
192
+ WOO_COMMERCE = "woo-commerce",
193
+ PUBLIC_API = "public-api"
193
194
  }
194
195
  declare enum CustomerPlatform {
195
196
  POS = "in-store",
@@ -217,6 +218,7 @@ declare enum InventorySpecificActionType {
217
218
  REFUND_DAMAGE = "REFUND_DAMAGE",
218
219
  SALE = "SALE",
219
220
  COMPOSED_FOR_SALE = "COMPOSED_FOR_SALE",
221
+ UNIT_FAMILY_CHANGED = "UNIT_FAMILY_CHANGED",
220
222
  TRANSFER = "TRANSFER",
221
223
  BULK_RECOUNT = "BULK_RECOUNT",
222
224
  APPLIED_FROM_WOO = "APPLIED_FROM_WOO",
@@ -1030,6 +1032,40 @@ declare function setOrderState(order: OrderStateWritable, paymentState: PaymentS
1030
1032
 
1031
1033
  declare function inferStatesFromLegacyStatus(order: OrderLikeForLegacyInference): StatePair;
1032
1034
 
1035
+ interface OrderMutationData extends OrderStateWritable {
1036
+ total?: number;
1037
+ balance?: number;
1038
+ paymentMethods?: {
1039
+ amount?: number;
1040
+ [key: string]: unknown;
1041
+ }[];
1042
+ refunds?: {
1043
+ quantity?: number;
1044
+ [key: string]: unknown;
1045
+ }[];
1046
+ refund?: {
1047
+ quantity?: number;
1048
+ [key: string]: unknown;
1049
+ }[];
1050
+ lineItems?: {
1051
+ quantity?: number;
1052
+ fulfilledQuantity?: number;
1053
+ returnedQuantity?: number;
1054
+ [key: string]: unknown;
1055
+ }[];
1056
+ }
1057
+ interface OrderWriteStrategy {
1058
+ applyState(order: OrderMutationData): void;
1059
+ }
1060
+ declare class LegacyWriteStrategy implements OrderWriteStrategy {
1061
+ applyState(_order: OrderMutationData): void;
1062
+ }
1063
+ declare class DualWriteStrategy implements OrderWriteStrategy {
1064
+ private readonly config;
1065
+ constructor(config: StoredStateConfig);
1066
+ applyState(order: OrderMutationData): void;
1067
+ }
1068
+
1033
1069
  interface ResolveTemplateResult {
1034
1070
  fragment: StateConfigFragment;
1035
1071
  resolvedValues: Record<string, unknown>;
@@ -1145,40 +1181,6 @@ interface ConfigUpdatedPayload {
1145
1181
  }
1146
1182
  type OrderStateEventPayload = StateTransitionCompletedPayload | StateTransitionBlockedPayload | ConfigUpdatedPayload;
1147
1183
 
1148
- interface OrderMutationData extends OrderStateWritable {
1149
- total?: number;
1150
- balance?: number;
1151
- paymentMethods?: {
1152
- amount?: number;
1153
- [key: string]: unknown;
1154
- }[];
1155
- refunds?: {
1156
- quantity?: number;
1157
- [key: string]: unknown;
1158
- }[];
1159
- refund?: {
1160
- quantity?: number;
1161
- [key: string]: unknown;
1162
- }[];
1163
- lineItems?: {
1164
- quantity?: number;
1165
- fulfilledQuantity?: number;
1166
- returnedQuantity?: number;
1167
- [key: string]: unknown;
1168
- }[];
1169
- }
1170
- interface OrderWriteStrategy {
1171
- applyState(order: OrderMutationData): void;
1172
- }
1173
- declare class LegacyWriteStrategy implements OrderWriteStrategy {
1174
- applyState(_order: OrderMutationData): void;
1175
- }
1176
- declare class DualWriteStrategy implements OrderWriteStrategy {
1177
- private readonly config;
1178
- constructor(config: StoredStateConfig);
1179
- applyState(order: OrderMutationData): void;
1180
- }
1181
-
1182
1184
  interface CurrencyRate {
1183
1185
  rate: number;
1184
1186
  country: string;
package/dist/index.d.ts CHANGED
@@ -189,7 +189,8 @@ declare enum Platform {
189
189
  }
190
190
  declare enum OrderPlatform {
191
191
  POS = "in-store",
192
- WOO_COMMERCE = "woo-commerce"
192
+ WOO_COMMERCE = "woo-commerce",
193
+ PUBLIC_API = "public-api"
193
194
  }
194
195
  declare enum CustomerPlatform {
195
196
  POS = "in-store",
@@ -217,6 +218,7 @@ declare enum InventorySpecificActionType {
217
218
  REFUND_DAMAGE = "REFUND_DAMAGE",
218
219
  SALE = "SALE",
219
220
  COMPOSED_FOR_SALE = "COMPOSED_FOR_SALE",
221
+ UNIT_FAMILY_CHANGED = "UNIT_FAMILY_CHANGED",
220
222
  TRANSFER = "TRANSFER",
221
223
  BULK_RECOUNT = "BULK_RECOUNT",
222
224
  APPLIED_FROM_WOO = "APPLIED_FROM_WOO",
@@ -1030,6 +1032,40 @@ declare function setOrderState(order: OrderStateWritable, paymentState: PaymentS
1030
1032
 
1031
1033
  declare function inferStatesFromLegacyStatus(order: OrderLikeForLegacyInference): StatePair;
1032
1034
 
1035
+ interface OrderMutationData extends OrderStateWritable {
1036
+ total?: number;
1037
+ balance?: number;
1038
+ paymentMethods?: {
1039
+ amount?: number;
1040
+ [key: string]: unknown;
1041
+ }[];
1042
+ refunds?: {
1043
+ quantity?: number;
1044
+ [key: string]: unknown;
1045
+ }[];
1046
+ refund?: {
1047
+ quantity?: number;
1048
+ [key: string]: unknown;
1049
+ }[];
1050
+ lineItems?: {
1051
+ quantity?: number;
1052
+ fulfilledQuantity?: number;
1053
+ returnedQuantity?: number;
1054
+ [key: string]: unknown;
1055
+ }[];
1056
+ }
1057
+ interface OrderWriteStrategy {
1058
+ applyState(order: OrderMutationData): void;
1059
+ }
1060
+ declare class LegacyWriteStrategy implements OrderWriteStrategy {
1061
+ applyState(_order: OrderMutationData): void;
1062
+ }
1063
+ declare class DualWriteStrategy implements OrderWriteStrategy {
1064
+ private readonly config;
1065
+ constructor(config: StoredStateConfig);
1066
+ applyState(order: OrderMutationData): void;
1067
+ }
1068
+
1033
1069
  interface ResolveTemplateResult {
1034
1070
  fragment: StateConfigFragment;
1035
1071
  resolvedValues: Record<string, unknown>;
@@ -1145,40 +1181,6 @@ interface ConfigUpdatedPayload {
1145
1181
  }
1146
1182
  type OrderStateEventPayload = StateTransitionCompletedPayload | StateTransitionBlockedPayload | ConfigUpdatedPayload;
1147
1183
 
1148
- interface OrderMutationData extends OrderStateWritable {
1149
- total?: number;
1150
- balance?: number;
1151
- paymentMethods?: {
1152
- amount?: number;
1153
- [key: string]: unknown;
1154
- }[];
1155
- refunds?: {
1156
- quantity?: number;
1157
- [key: string]: unknown;
1158
- }[];
1159
- refund?: {
1160
- quantity?: number;
1161
- [key: string]: unknown;
1162
- }[];
1163
- lineItems?: {
1164
- quantity?: number;
1165
- fulfilledQuantity?: number;
1166
- returnedQuantity?: number;
1167
- [key: string]: unknown;
1168
- }[];
1169
- }
1170
- interface OrderWriteStrategy {
1171
- applyState(order: OrderMutationData): void;
1172
- }
1173
- declare class LegacyWriteStrategy implements OrderWriteStrategy {
1174
- applyState(_order: OrderMutationData): void;
1175
- }
1176
- declare class DualWriteStrategy implements OrderWriteStrategy {
1177
- private readonly config;
1178
- constructor(config: StoredStateConfig);
1179
- applyState(order: OrderMutationData): void;
1180
- }
1181
-
1182
1184
  interface CurrencyRate {
1183
1185
  rate: number;
1184
1186
  country: string;
package/dist/index.js CHANGED
@@ -369,6 +369,7 @@ var Platform = /* @__PURE__ */ ((Platform2) => {
369
369
  var OrderPlatform = /* @__PURE__ */ ((OrderPlatform2) => {
370
370
  OrderPlatform2["POS"] = "in-store";
371
371
  OrderPlatform2["WOO_COMMERCE"] = "woo-commerce";
372
+ OrderPlatform2["PUBLIC_API"] = "public-api";
372
373
  return OrderPlatform2;
373
374
  })(OrderPlatform || {});
374
375
  var CustomerPlatform = /* @__PURE__ */ ((CustomerPlatform2) => {
@@ -399,6 +400,7 @@ var InventorySpecificActionType = /* @__PURE__ */ ((InventorySpecificActionType2
399
400
  InventorySpecificActionType2["REFUND_DAMAGE"] = "REFUND_DAMAGE";
400
401
  InventorySpecificActionType2["SALE"] = "SALE";
401
402
  InventorySpecificActionType2["COMPOSED_FOR_SALE"] = "COMPOSED_FOR_SALE";
403
+ InventorySpecificActionType2["UNIT_FAMILY_CHANGED"] = "UNIT_FAMILY_CHANGED";
402
404
  InventorySpecificActionType2["TRANSFER"] = "TRANSFER";
403
405
  InventorySpecificActionType2["BULK_RECOUNT"] = "BULK_RECOUNT";
404
406
  InventorySpecificActionType2["APPLIED_FROM_WOO"] = "APPLIED_FROM_WOO";
@@ -1446,10 +1448,7 @@ function negateAtPaths(value, path, paths) {
1446
1448
  function padHex(value, length) {
1447
1449
  return value.toString(16).padStart(length, "0");
1448
1450
  }
1449
- var PROCESS_RANDOM = Array.from(
1450
- { length: 5 },
1451
- () => padHex(Math.floor(Math.random() * 256), 2)
1452
- ).join("");
1451
+ var PROCESS_RANDOM = Array.from({ length: 5 }, () => padHex(Math.floor(Math.random() * 256), 2)).join("");
1453
1452
  var objectIdCounter = Math.floor(Math.random() * 16777215);
1454
1453
  function generateMongoID() {
1455
1454
  const timestamp = padHex(Math.floor(Date.now() / 1e3), 8);
@@ -1594,6 +1593,8 @@ var STATE_SCHEMA = Object.freeze({
1594
1593
  // order-state-machine/financial-invariants.ts
1595
1594
  var REFUND_ALLOWED_FULFILLMENT = /* @__PURE__ */ new Set(["fulfilled", "returned", "partially_returned", "cancelled"]);
1596
1595
  var PAYMENT_COLLECTION_ORDER = ["unpaid", "partially_paid", "paid"];
1596
+ var UNRETURNED_MONEY_STATES = /* @__PURE__ */ new Set(["partially_paid", "paid", "partially_refunded"]);
1597
+ var REFUNDED_FULFILLMENT_LANDINGS = /* @__PURE__ */ new Set(["returned", "cancelled"]);
1597
1598
  var FINANCIAL_INVARIANTS = [
1598
1599
  {
1599
1600
  id: "no-leave-refunded",
@@ -1624,6 +1625,26 @@ var FINANCIAL_INVARIANTS = [
1624
1625
  const toIdx = PAYMENT_COLLECTION_ORDER.indexOf(to.payment);
1625
1626
  return fromIdx !== -1 && toIdx !== -1 && fromIdx > toIdx;
1626
1627
  }
1628
+ },
1629
+ {
1630
+ id: "no-cancel-with-unreturned-payments",
1631
+ description: "Fulfillment cannot enter cancelled while the payment state carries unreturned captured money (paid / partially_paid / partially_refunded) \u2014 return the money first: a full refund of an unfulfilled order lands refunded \xD7 cancelled, a void lands voided \xD7 cancelled. Scoped to the cancelling MOVE (from.fulfillment !== cancelled) so payment-axis edges evaluated against an already-cancelled fulfillment do not trip it",
1632
+ check: (from, to) => from !== null && from.fulfillment !== "cancelled" && to.fulfillment === "cancelled" && UNRETURNED_MONEY_STATES.has(to.payment)
1633
+ },
1634
+ {
1635
+ id: "no-draft-regression-with-captured-payments",
1636
+ description: "Fulfillment cannot regress to draft once money has been captured \u2014 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 \xD7 draft remains declarable as an initial state",
1637
+ check: (from, to) => from !== null && from.fulfillment !== "draft" && to.fulfillment === "draft" && to.payment !== "unpaid"
1638
+ },
1639
+ {
1640
+ id: "no-reopen-voided-fulfillment",
1641
+ description: "A voided order exists only at cancelled fulfillment: a voided order cannot re-enter fulfillment, and a voided \xD7 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\u2019s concern, not this rule\u2019s",
1642
+ check: (from, to) => (from === null || from.payment === "voided") && to.payment === "voided" && to.fulfillment !== "cancelled"
1643
+ },
1644
+ {
1645
+ id: "no-reopen-refunded-fulfillment",
1646
+ description: "A fully refunded order cannot re-enter fulfillment \u2014 it may only relabel between its canonical landings, returned and cancelled (complements no-leave-refunded, which only freezes the payment axis)",
1647
+ check: (from, to) => from?.payment === "refunded" && !REFUNDED_FULFILLMENT_LANDINGS.has(to.fulfillment)
1627
1648
  }
1628
1649
  ];
1629
1650
  function getFinancialInvariantViolations(from, to) {
@@ -1711,24 +1732,17 @@ var DISPLAY_LABEL_OVERRIDES = {
1711
1732
  "paid|on_hold": "Parked - Paid",
1712
1733
  "paid|fulfilled": "Completed",
1713
1734
  "partially_refunded|fulfilled": "Partially Refunded",
1714
- "partially_refunded|partially_returned": "Partially Refunded",
1715
- "refunded|fulfilled": "Refunded",
1716
- "refunded|returned": "Refunded",
1717
- // Full refund of a never-fulfilled order (kaching refund op lands on
1718
- // cancelled when nothing was delivered). Terminal payment states emit no
1719
- // generic rows, so without this the pair fell through to the raw
1720
- // "refunded / cancelled" engine fallback.
1721
- "refunded|cancelled": "Refunded",
1722
- "voided|cancelled": "Cancelled"
1735
+ "partially_refunded|partially_returned": "Partially Refunded"
1736
+ };
1737
+ var TERMINAL_LABEL_OVERRIDES = {
1738
+ voided: "Cancelled"
1723
1739
  };
1724
1740
  function buildDefaultDisplayStateMap() {
1725
1741
  const rules = [];
1726
1742
  for (const p of PAYMENT_STATES) {
1743
+ const terminalLabel = TERMINAL_PAYMENT_STATES.has(p) ? TERMINAL_LABEL_OVERRIDES[p] ?? PAYMENT_LABELS.get(p) : void 0;
1727
1744
  for (const f of FULFILLMENT_STATES) {
1728
- const key = `${p}|${f}`;
1729
- const override = DISPLAY_LABEL_OVERRIDES[key];
1730
- if (TERMINAL_PAYMENT_STATES.has(p) && !override) continue;
1731
- const label = override ?? `${PAYMENT_LABELS.get(p)} / ${FULFILLMENT_LABELS.get(f)}`;
1745
+ const label = DISPLAY_LABEL_OVERRIDES[`${p}|${f}`] ?? terminalLabel ?? `${PAYMENT_LABELS.get(p)} / ${FULFILLMENT_LABELS.get(f)}`;
1732
1746
  rules.push({ paymentState: p, fulfillmentState: f, label });
1733
1747
  }
1734
1748
  }
@@ -1851,6 +1865,9 @@ function buildOrderContext(order, extras) {
1851
1865
  }
1852
1866
 
1853
1867
  // order-state-machine/display-state.ts
1868
+ function atomLabel(atom, defs) {
1869
+ return defs.find((d) => d.id === atom)?.label ?? atom;
1870
+ }
1854
1871
  function matchesOptional(actual, rule) {
1855
1872
  if (rule === void 0) return true;
1856
1873
  return Array.isArray(rule) ? rule.includes(actual) : rule === actual;
@@ -1861,7 +1878,9 @@ function deriveDisplayState(payment, fulfillment, config) {
1861
1878
  return { label: rule.label, color: rule.color, icon: rule.icon };
1862
1879
  }
1863
1880
  }
1864
- return { label: `${payment} / ${fulfillment}` };
1881
+ return {
1882
+ label: `${atomLabel(payment, STATE_SCHEMA.paymentStates)} / ${atomLabel(fulfillment, STATE_SCHEMA.fulfillmentStates)}`
1883
+ };
1865
1884
  }
1866
1885
  function displayRuleMatchesPair(rule, payment, fulfillment) {
1867
1886
  return matchesOptional(payment, rule.paymentState) && matchesOptional(fulfillment, rule.fulfillmentState);
@@ -2097,13 +2116,11 @@ function labelForFulfillment(id, config) {
2097
2116
  return config.fulfillmentStates.find((s) => s.id === id)?.label ?? id;
2098
2117
  }
2099
2118
  function transitionDisplayLabel(to, config) {
2100
- const pay = labelForPayment(to.payment, config);
2101
- const ful = labelForFulfillment(to.fulfillment, config);
2102
2119
  const derived = deriveDisplayState(to.payment, to.fulfillment, config).label;
2103
- if (derived && derived !== `${to.payment} / ${to.fulfillment}`) {
2120
+ if (derived) {
2104
2121
  return derived;
2105
2122
  }
2106
- return `${pay} \xB7 ${ful}`;
2123
+ return `${labelForPayment(to.payment, config)} \xB7 ${labelForFulfillment(to.fulfillment, config)}`;
2107
2124
  }
2108
2125
  function conditionMetLines(config, from, to, context) {
2109
2126
  const lines = [];
@@ -2132,20 +2149,12 @@ function conditionMetLines(config, from, to, context) {
2132
2149
  }
2133
2150
  function getAvailableTransitions(current, config, context) {
2134
2151
  const candidates = [];
2135
- for (const s of config.paymentStates) {
2136
- if (s.id === current.payment) continue;
2137
- candidates.push({ payment: s.id, fulfillment: current.fulfillment });
2138
- }
2139
2152
  for (const s of config.fulfillmentStates) {
2140
2153
  if (s.id === current.fulfillment) continue;
2141
2154
  candidates.push({ payment: current.payment, fulfillment: s.id });
2142
2155
  }
2143
2156
  const out = [];
2144
- const seen = /* @__PURE__ */ new Set();
2145
2157
  for (const to of candidates) {
2146
- const key = `${to.payment}:${to.fulfillment}`;
2147
- if (seen.has(key)) continue;
2148
- seen.add(key);
2149
2158
  const result = canTransition({
2150
2159
  from: current,
2151
2160
  to,
@@ -2594,6 +2603,27 @@ function inferStatesFromLegacyStatus(order) {
2594
2603
  return { payment: "unpaid", fulfillment: "pending" };
2595
2604
  }
2596
2605
 
2606
+ // order-state-machine/write-strategy.ts
2607
+ var LegacyWriteStrategy = class {
2608
+ applyState(_order) {
2609
+ }
2610
+ };
2611
+ var DualWriteStrategy = class {
2612
+ constructor(config) {
2613
+ this.config = config;
2614
+ }
2615
+ applyState(order) {
2616
+ if (order.paymentState && order.fulfillmentState) {
2617
+ setOrderState(order, order.paymentState, order.fulfillmentState, this.config);
2618
+ return;
2619
+ }
2620
+ if (order.status) {
2621
+ const inferred = inferStatesFromLegacyStatus(order);
2622
+ setOrderState(order, inferred.payment, inferred.fulfillment, this.config);
2623
+ }
2624
+ }
2625
+ };
2626
+
2597
2627
  // order-state-machine/resolve-template.ts
2598
2628
  function resolveTemplate(templateJson, params, values = {}) {
2599
2629
  const resolvedValues = {};
@@ -2895,27 +2925,6 @@ var ORDER_STATE_EVENTS = {
2895
2925
  stateTransitionBlocked: "state-transition-blocked",
2896
2926
  configUpdated: "config-updated"
2897
2927
  };
2898
-
2899
- // order-state-machine/write-strategy.ts
2900
- var LegacyWriteStrategy = class {
2901
- applyState(_order) {
2902
- }
2903
- };
2904
- var DualWriteStrategy = class {
2905
- constructor(config) {
2906
- this.config = config;
2907
- }
2908
- applyState(order) {
2909
- if (order.paymentState && order.fulfillmentState) {
2910
- setOrderState(order, order.paymentState, order.fulfillmentState, this.config);
2911
- return;
2912
- }
2913
- if (order.status) {
2914
- const inferred = inferStatesFromLegacyStatus(order);
2915
- setOrderState(order, inferred.payment, inferred.fulfillment, this.config);
2916
- }
2917
- }
2918
- };
2919
2928
  // Annotate the CommonJS export names for ESM import in node:
2920
2929
  0 && (module.exports = {
2921
2930
  AttributeType,