@pisell/pisellos 0.10.58 → 0.10.60

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.
Files changed (81) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/inventory/index.d.ts +92 -0
  4. package/dist/inventory/index.js +500 -0
  5. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  6. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
  7. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +25 -2
  8. package/dist/modules/Order/holderRelations.d.ts +14 -0
  9. package/dist/modules/Order/holderRelations.js +154 -0
  10. package/dist/modules/Order/index.d.ts +21 -4
  11. package/dist/modules/Order/index.js +1453 -1060
  12. package/dist/modules/Order/types.d.ts +24 -1
  13. package/dist/modules/Order/types.js +2 -0
  14. package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
  15. package/dist/modules/Order/utils/discountProductLineIdentity.js +142 -7
  16. package/dist/modules/Order/utils/orderCollectionIdentity.js +24 -10
  17. package/dist/modules/Order/utils.d.ts +1 -1
  18. package/dist/modules/Order/utils.js +35 -9
  19. package/dist/modules/ProductList/index.d.ts +1 -3
  20. package/dist/modules/ProductList/index.js +120 -192
  21. package/dist/modules/ProductList/types.d.ts +0 -8
  22. package/dist/modules/ProductList/types.js +0 -2
  23. package/dist/server/index.js +18 -12
  24. package/dist/server/modules/order/index.d.ts +4 -0
  25. package/dist/server/modules/order/index.js +255 -190
  26. package/dist/server/modules/order/types.d.ts +3 -0
  27. package/dist/shared/receipt/small-ticket.js +17 -0
  28. package/dist/shared/sales/loadSalesOrderSnapshot.js +1 -1
  29. package/dist/solution/BaseSales/index.d.ts +8 -0
  30. package/dist/solution/BaseSales/index.js +1478 -1233
  31. package/dist/solution/BaseSales/types.d.ts +2 -1
  32. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
  33. package/dist/solution/BaseSales/utils/parseSalesResponse.js +7 -3
  34. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +12 -3
  35. package/dist/solution/BookingByStep/index.d.ts +1 -1
  36. package/dist/solution/BookingTicket/index.d.ts +1 -13
  37. package/dist/solution/BookingTicket/index.js +7 -4
  38. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +6 -2
  39. package/dist/solution/UnifiedBookingSales/index.d.ts +1 -7
  40. package/dist/solution/UnifiedBookingSales/index.js +446 -586
  41. package/lib/index.d.ts +1 -0
  42. package/lib/index.js +12 -0
  43. package/lib/inventory/index.d.ts +92 -0
  44. package/lib/inventory/index.js +280 -0
  45. package/lib/model/strategy/adapter/promotion/index.js +46 -1
  46. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.d.ts +3 -1
  47. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +16 -1
  48. package/lib/modules/Order/holderRelations.d.ts +14 -0
  49. package/lib/modules/Order/holderRelations.js +98 -0
  50. package/lib/modules/Order/index.d.ts +21 -4
  51. package/lib/modules/Order/index.js +155 -31
  52. package/lib/modules/Order/types.d.ts +24 -1
  53. package/lib/modules/Order/types.js +1 -0
  54. package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +1 -1
  55. package/lib/modules/Order/utils/discountProductLineIdentity.js +51 -2
  56. package/lib/modules/Order/utils/orderCollectionIdentity.js +5 -0
  57. package/lib/modules/Order/utils.d.ts +1 -1
  58. package/lib/modules/Order/utils.js +27 -6
  59. package/lib/modules/ProductList/index.d.ts +1 -3
  60. package/lib/modules/ProductList/index.js +22 -31
  61. package/lib/modules/ProductList/types.d.ts +0 -8
  62. package/lib/modules/ProductList/types.js +0 -1
  63. package/lib/server/index.js +6 -0
  64. package/lib/server/modules/order/index.d.ts +4 -0
  65. package/lib/server/modules/order/index.js +46 -4
  66. package/lib/server/modules/order/types.d.ts +3 -0
  67. package/lib/shared/receipt/small-ticket.js +15 -0
  68. package/lib/shared/sales/loadSalesOrderSnapshot.js +1 -1
  69. package/lib/solution/BaseSales/index.d.ts +8 -0
  70. package/lib/solution/BaseSales/index.js +121 -9
  71. package/lib/solution/BaseSales/types.d.ts +2 -1
  72. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -1
  73. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -0
  74. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +7 -0
  75. package/lib/solution/BookingByStep/index.d.ts +1 -1
  76. package/lib/solution/BookingTicket/index.d.ts +1 -13
  77. package/lib/solution/BookingTicket/index.js +4 -1
  78. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +7 -1
  79. package/lib/solution/UnifiedBookingSales/index.d.ts +1 -7
  80. package/lib/solution/UnifiedBookingSales/index.js +12 -80
  81. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './modules';
7
7
  export * from './plugins';
8
8
  export * from './solution';
9
9
  export * from './model';
10
+ export * from './inventory';
10
11
  export { PisellOSCore } from './core';
11
12
  import PisellOSCore from './core';
12
13
  export default PisellOSCore;
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export * from "./modules";
9
9
  export * from "./plugins";
10
10
  export * from "./solution";
11
11
  export * from "./model";
12
+ export * from "./inventory";
12
13
 
13
14
  // 导出核心实现
14
15
  export { PisellOSCore } from "./core";
@@ -0,0 +1,92 @@
1
+ /** Optional, instance-scoped sales inventory. Never stored in ProductData or order payloads. */
2
+ export type InventoryRecord = Record<string, any>;
3
+ export type InventoryRefreshReason = 'catalog-entry' | 'detail-open' | 'checkout' | 'manual';
4
+ export interface InventoryAvailability {
5
+ status: 'ready' | 'loading' | 'stale' | 'error' | 'unmapped';
6
+ quantity?: number;
7
+ message?: string;
8
+ }
9
+ export interface InventorySelectionAvailability {
10
+ availability: InventoryAvailability;
11
+ /** Stock remaining after other cart lines using the same inventory key. */
12
+ availableQuantity: number;
13
+ /** The existing line can still be reduced when stock is unavailable. */
14
+ retainedQuantity: number;
15
+ maxQuantity: number;
16
+ }
17
+ export interface InventorySource {
18
+ readonly scopeKey: string;
19
+ assertCurrent(): void;
20
+ keyOf(product: InventoryRecord, variant?: InventoryRecord): string | undefined;
21
+ read(context: {
22
+ reason: InventoryRefreshReason;
23
+ signal: AbortSignal;
24
+ }): Promise<ReadonlyMap<string, {
25
+ quantity: number | null;
26
+ message?: string;
27
+ }>>;
28
+ message(reason: 'unavailable' | 'unmapped' | 'insufficient', values?: {
29
+ key: string;
30
+ quantity: number;
31
+ }): string;
32
+ }
33
+ export interface CheckoutInventoryLine {
34
+ readonly lineId: string;
35
+ readonly productId: string | number;
36
+ readonly variantId: string | number;
37
+ readonly quantity: number;
38
+ readonly inventoryKey: string;
39
+ }
40
+ export interface CheckoutRuntimeSnapshot {
41
+ readonly scopeKey: string;
42
+ readonly revision: number;
43
+ readonly lines: readonly CheckoutInventoryLine[];
44
+ }
45
+ export interface SalesCheckoutHooks {
46
+ beforeCheckout?(context: {
47
+ items: readonly InventoryRecord[];
48
+ signal?: AbortSignal;
49
+ }): Promise<void>;
50
+ }
51
+ export declare const salesGuardError: (message: string) => Error & {
52
+ code: string;
53
+ };
54
+ export declare class InventoryController {
55
+ private readonly source;
56
+ readonly identity: symbol;
57
+ readonly scopeKey: string;
58
+ private entries;
59
+ private lastQuantities;
60
+ private products;
61
+ private keys;
62
+ private catalogProducts;
63
+ private listeners;
64
+ private revision;
65
+ private state;
66
+ private pending?;
67
+ private disposed;
68
+ constructor(source: InventorySource);
69
+ getRevision: () => number;
70
+ subscribe: (listener: () => void) => () => void;
71
+ private publish;
72
+ private assertCurrent;
73
+ activate(): void;
74
+ dispose(): void;
75
+ invalidate(): void;
76
+ /** Catalog replaces identities; partial detail only merges its variants, never its prices. */
77
+ registerProducts(products: readonly InventoryRecord[], complete?: boolean): void;
78
+ /** Consumers share I/O; cancelling one detail does not cancel another consumer. */
79
+ refresh(context: {
80
+ reason: InventoryRefreshReason;
81
+ signal?: AbortSignal;
82
+ force?: boolean;
83
+ }): Promise<void>;
84
+ availabilityForKey(key?: string): InventoryAvailability;
85
+ availability(product: InventoryRecord, variantId?: string | number): InventoryAvailability;
86
+ private keyForLine;
87
+ /** Advisory UI limit only. The serialized cart guard remains authoritative. */
88
+ selectionAvailability(product: InventoryRecord, variantId: string | number, items: readonly InventoryRecord[], editingItem?: InventoryRecord): InventorySelectionAvailability;
89
+ private totals;
90
+ validate(proposed: readonly InventoryRecord[], current?: readonly InventoryRecord[], allowReductions?: boolean): void;
91
+ freezeCheckout(items: readonly InventoryRecord[]): CheckoutRuntimeSnapshot;
92
+ }
@@ -0,0 +1,500 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
5
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
6
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
7
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
8
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
9
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
10
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
11
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
12
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
13
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
14
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
15
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
16
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
17
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
18
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
19
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
20
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
21
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
22
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
23
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
24
+ /** Optional, instance-scoped sales inventory. Never stored in ProductData or order payloads. */
25
+
26
+ export var salesGuardError = function salesGuardError(message) {
27
+ return Object.assign(new Error(message), {
28
+ code: 'SALES_GUARD_REJECTED'
29
+ });
30
+ };
31
+ var cancelled = function cancelled() {
32
+ return Object.assign(new Error('Inventory request cancelled'), {
33
+ name: 'AbortError'
34
+ });
35
+ };
36
+ var variantIdentity = function variantIdentity(productId, variantId) {
37
+ return JSON.stringify([String(productId), String(variantId !== null && variantId !== void 0 ? variantId : 0)]);
38
+ };
39
+ export var InventoryController = /*#__PURE__*/function () {
40
+ function InventoryController(source) {
41
+ var _this = this;
42
+ _classCallCheck(this, InventoryController);
43
+ _defineProperty(this, "identity", Symbol('sales-inventory-instance'));
44
+ _defineProperty(this, "scopeKey", void 0);
45
+ _defineProperty(this, "entries", new Map());
46
+ _defineProperty(this, "lastQuantities", new Map());
47
+ _defineProperty(this, "products", new Map());
48
+ _defineProperty(this, "keys", new Map());
49
+ _defineProperty(this, "catalogProducts", new Map());
50
+ _defineProperty(this, "listeners", new Set());
51
+ _defineProperty(this, "revision", 0);
52
+ _defineProperty(this, "state", 'stale');
53
+ _defineProperty(this, "pending", void 0);
54
+ _defineProperty(this, "disposed", false);
55
+ _defineProperty(this, "getRevision", function () {
56
+ return _this.revision;
57
+ });
58
+ _defineProperty(this, "subscribe", function (listener) {
59
+ _this.listeners.add(listener);
60
+ return function () {
61
+ _this.listeners.delete(listener);
62
+ };
63
+ });
64
+ this.source = source;
65
+ this.scopeKey = source.scopeKey;
66
+ }
67
+ _createClass(InventoryController, [{
68
+ key: "publish",
69
+ value: function publish() {
70
+ this.revision += 1;
71
+ this.listeners.forEach(function (listener) {
72
+ try {
73
+ listener();
74
+ } catch (_unused) {/* A view cannot interrupt a stock update. */}
75
+ });
76
+ }
77
+ }, {
78
+ key: "assertCurrent",
79
+ value: function assertCurrent(signal) {
80
+ if (this.disposed || signal !== null && signal !== void 0 && signal.aborted) throw cancelled();
81
+ this.source.assertCurrent();
82
+ }
83
+ }, {
84
+ key: "activate",
85
+ value: function activate() {
86
+ this.disposed = false;
87
+ }
88
+ }, {
89
+ key: "dispose",
90
+ value: function dispose() {
91
+ this.disposed = true;
92
+ this.invalidate();
93
+ }
94
+ }, {
95
+ key: "invalidate",
96
+ value: function invalidate() {
97
+ var _this$pending;
98
+ (_this$pending = this.pending) === null || _this$pending === void 0 || _this$pending.controller.abort();
99
+ this.pending = undefined;
100
+ this.state = 'stale';
101
+ this.publish();
102
+ }
103
+
104
+ /** Catalog replaces identities; partial detail only merges its variants, never its prices. */
105
+ }, {
106
+ key: "registerProducts",
107
+ value: function registerProducts(products) {
108
+ var _this2 = this;
109
+ var complete = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
110
+ this.assertCurrent();
111
+ var changed = false;
112
+ var _iterator = _createForOfIteratorHelper(products),
113
+ _step;
114
+ try {
115
+ var _loop = function _loop() {
116
+ var _product$id, _product$variant;
117
+ var product = _step.value;
118
+ var id = String((_product$id = product.id) !== null && _product$id !== void 0 ? _product$id : product.product_id);
119
+ if (complete && _this2.catalogProducts.get(id) === product) return 1; // continue
120
+ if (complete) _this2.catalogProducts.set(id, product);
121
+ var previous = _this2.products.get(id);
122
+ if (complete) {
123
+ var _iterator2 = _createForOfIteratorHelper((previous === null || previous === void 0 ? void 0 : previous.keys()) || []),
124
+ _step2;
125
+ try {
126
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
127
+ var variantId = _step2.value;
128
+ _this2.keys.delete(variantIdentity(id, variantId));
129
+ }
130
+ } catch (err) {
131
+ _iterator2.e(err);
132
+ } finally {
133
+ _iterator2.f();
134
+ }
135
+ }
136
+ var variants = complete ? new Map() : new Map(previous);
137
+ var list = (_product$variant = product.variant) !== null && _product$variant !== void 0 && _product$variant.length ? product.variant : [{
138
+ id: 0,
139
+ code: product.code
140
+ }];
141
+ var _iterator3 = _createForOfIteratorHelper(list),
142
+ _step3;
143
+ try {
144
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
145
+ var _ref3, _variant$id, _this2$source$keyOf;
146
+ var _variant = _step3.value;
147
+ var _variantId = String((_ref3 = (_variant$id = _variant.id) !== null && _variant$id !== void 0 ? _variant$id : _variant.product_variant_id) !== null && _ref3 !== void 0 ? _ref3 : 0);
148
+ var key = (_this2$source$keyOf = _this2.source.keyOf(product, _variant)) !== null && _this2$source$keyOf !== void 0 ? _this2$source$keyOf : previous === null || previous === void 0 ? void 0 : previous.get(_variantId);
149
+ variants.set(_variantId, key);
150
+ _this2.keys.set(variantIdentity(id, _variantId), key);
151
+ }
152
+ } catch (err) {
153
+ _iterator3.e(err);
154
+ } finally {
155
+ _iterator3.f();
156
+ }
157
+ if (!previous || previous.size !== variants.size || _toConsumableArray(variants).some(function (_ref) {
158
+ var _ref2 = _slicedToArray(_ref, 2),
159
+ id = _ref2[0],
160
+ key = _ref2[1];
161
+ return previous.get(id) !== key;
162
+ })) changed = true;
163
+ _this2.products.set(id, variants);
164
+ };
165
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
166
+ if (_loop()) continue;
167
+ }
168
+ } catch (err) {
169
+ _iterator.e(err);
170
+ } finally {
171
+ _iterator.f();
172
+ }
173
+ if (changed) this.publish();
174
+ }
175
+
176
+ /** Consumers share I/O; cancelling one detail does not cancel another consumer. */
177
+ }, {
178
+ key: "refresh",
179
+ value: (function () {
180
+ var _refresh = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(context) {
181
+ var _this3 = this;
182
+ var read, current;
183
+ return _regeneratorRuntime().wrap(function _callee2$(_context2) {
184
+ while (1) switch (_context2.prev = _context2.next) {
185
+ case 0:
186
+ this.assertCurrent(context.signal);
187
+ if (context.force) this.invalidate();
188
+ read = this.pending;
189
+ if (!read) {
190
+ read = {
191
+ controller: new AbortController(),
192
+ consumers: 0,
193
+ promise: Promise.resolve()
194
+ };
195
+ current = read;
196
+ this.pending = current;
197
+ this.state = 'loading';
198
+ this.publish();
199
+ current.promise = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
200
+ var entries, _iterator4, _step4, _step4$value, key, stock;
201
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
202
+ while (1) switch (_context.prev = _context.next) {
203
+ case 0:
204
+ _context.prev = 0;
205
+ _context.next = 3;
206
+ return _this3.source.read({
207
+ reason: context.reason,
208
+ signal: current.controller.signal
209
+ });
210
+ case 3:
211
+ entries = _context.sent;
212
+ _this3.assertCurrent(current.controller.signal);
213
+ if (!(_this3.pending !== current)) {
214
+ _context.next = 7;
215
+ break;
216
+ }
217
+ throw cancelled();
218
+ case 7:
219
+ _this3.entries = entries;
220
+ _iterator4 = _createForOfIteratorHelper(entries);
221
+ try {
222
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
223
+ _step4$value = _slicedToArray(_step4.value, 2), key = _step4$value[0], stock = _step4$value[1];
224
+ if (stock.quantity !== null && Number.isSafeInteger(stock.quantity) && stock.quantity >= 0) _this3.lastQuantities.set(key, stock.quantity);
225
+ }
226
+ } catch (err) {
227
+ _iterator4.e(err);
228
+ } finally {
229
+ _iterator4.f();
230
+ }
231
+ _this3.state = 'ready';
232
+ _context.next = 19;
233
+ break;
234
+ case 13:
235
+ _context.prev = 13;
236
+ _context.t0 = _context["catch"](0);
237
+ if (!(_this3.pending !== current || current.controller.signal.aborted)) {
238
+ _context.next = 17;
239
+ break;
240
+ }
241
+ throw cancelled();
242
+ case 17:
243
+ _this3.state = 'error';
244
+ throw _context.t0;
245
+ case 19:
246
+ _context.prev = 19;
247
+ if (_this3.pending === current) {
248
+ _this3.pending = undefined;
249
+ _this3.publish();
250
+ }
251
+ return _context.finish(19);
252
+ case 22:
253
+ case "end":
254
+ return _context.stop();
255
+ }
256
+ }, _callee, null, [[0, 13, 19, 22]]);
257
+ }))();
258
+ }
259
+ read.consumers += 1;
260
+ _context2.prev = 5;
261
+ if (context.signal) {
262
+ _context2.next = 11;
263
+ break;
264
+ }
265
+ _context2.next = 9;
266
+ return read.promise;
267
+ case 9:
268
+ _context2.next = 13;
269
+ break;
270
+ case 11:
271
+ _context2.next = 13;
272
+ return new Promise(function (resolve, reject) {
273
+ var signal = context.signal;
274
+ var abort = function abort() {
275
+ return reject(cancelled());
276
+ };
277
+ signal.addEventListener('abort', abort, {
278
+ once: true
279
+ });
280
+ read.promise.then(resolve, reject).finally(function () {
281
+ return signal.removeEventListener('abort', abort);
282
+ });
283
+ if (signal.aborted) abort();
284
+ });
285
+ case 13:
286
+ this.assertCurrent(context.signal);
287
+ case 14:
288
+ _context2.prev = 14;
289
+ read.consumers -= 1;
290
+ if (this.pending === read && read.consumers === 0) this.invalidate();
291
+ return _context2.finish(14);
292
+ case 18:
293
+ case "end":
294
+ return _context2.stop();
295
+ }
296
+ }, _callee2, this, [[5,, 14, 18]]);
297
+ }));
298
+ function refresh(_x) {
299
+ return _refresh.apply(this, arguments);
300
+ }
301
+ return refresh;
302
+ }())
303
+ }, {
304
+ key: "availabilityForKey",
305
+ value: function availabilityForKey(key) {
306
+ var stock = key ? this.entries.get(key) : undefined;
307
+ var quantity = key ? this.lastQuantities.get(key) : undefined;
308
+ if (this.state !== 'ready') return {
309
+ status: this.state,
310
+ quantity: quantity,
311
+ message: this.source.message('unavailable')
312
+ };
313
+ if (!stock) return {
314
+ status: 'unmapped',
315
+ quantity: quantity,
316
+ message: this.source.message('unmapped')
317
+ };
318
+ if (stock.quantity === null || !Number.isSafeInteger(stock.quantity) || stock.quantity < 0) return {
319
+ status: 'error',
320
+ quantity: quantity,
321
+ message: stock.message || this.source.message('unavailable')
322
+ };
323
+ return {
324
+ status: 'ready',
325
+ quantity: stock.quantity
326
+ };
327
+ }
328
+ }, {
329
+ key: "availability",
330
+ value: function availability(product, variantId) {
331
+ var _product$id2,
332
+ _this$products$get,
333
+ _this4 = this;
334
+ var id = (_product$id2 = product.id) !== null && _product$id2 !== void 0 ? _product$id2 : product.product_id;
335
+ if (variantId !== undefined && variantId !== null) return this.availabilityForKey(this.keys.get(variantIdentity(id, variantId)));
336
+ var keys = _toConsumableArray(new Set(((_this$products$get = this.products.get(String(id))) === null || _this$products$get === void 0 ? void 0 : _this$products$get.values()) || []));
337
+ var states = keys.map(function (key) {
338
+ return _this4.availabilityForKey(key);
339
+ });
340
+ if (!states.length) return this.availabilityForKey();
341
+ var quantity = states.every(function (entry) {
342
+ return entry.quantity !== undefined;
343
+ }) ? states.reduce(function (sum, entry) {
344
+ return sum + entry.quantity;
345
+ }, 0) : undefined;
346
+ var failed = states.find(function (entry) {
347
+ return entry.status !== 'ready';
348
+ });
349
+ if (quantity !== undefined && !Number.isSafeInteger(quantity)) return {
350
+ status: 'error',
351
+ message: this.source.message('unavailable')
352
+ };
353
+ return {
354
+ status: (failed === null || failed === void 0 ? void 0 : failed.status) || 'ready',
355
+ quantity: quantity,
356
+ message: failed === null || failed === void 0 ? void 0 : failed.message
357
+ };
358
+ }
359
+ }, {
360
+ key: "keyForLine",
361
+ value: function keyForLine(item) {
362
+ var _item$product_variant, _item$product_sku;
363
+ return this.keys.get(variantIdentity(item.product_id, (_item$product_variant = item.product_variant_id) !== null && _item$product_variant !== void 0 ? _item$product_variant : (_item$product_sku = item.product_sku) === null || _item$product_sku === void 0 ? void 0 : _item$product_sku.product_variant_id));
364
+ }
365
+ /** Advisory UI limit only. The serialized cart guard remains authoritative. */
366
+ }, {
367
+ key: "selectionAvailability",
368
+ value: function selectionAvailability(product, variantId, items, editingItem) {
369
+ var _product$id3;
370
+ var identity = variantIdentity((_product$id3 = product.id) !== null && _product$id3 !== void 0 ? _product$id3 : product.product_id, variantId);
371
+ var key = this.keys.get(identity);
372
+ var availability = this.availabilityForKey(key);
373
+ var reserved = 0;
374
+ var retainedQuantity = 0;
375
+ var _iterator5 = _createForOfIteratorHelper(items),
376
+ _step5;
377
+ try {
378
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
379
+ var _item$product_variant2, _item$product_sku2, _item$num;
380
+ var item = _step5.value;
381
+ var matches = key ? this.keyForLine(item) === key : variantIdentity(item.product_id, (_item$product_variant2 = item.product_variant_id) !== null && _item$product_variant2 !== void 0 ? _item$product_variant2 : (_item$product_sku2 = item.product_sku) === null || _item$product_sku2 === void 0 ? void 0 : _item$product_sku2.product_variant_id) === identity;
382
+ if (!matches) continue;
383
+ var count = Number((_item$num = item.num) !== null && _item$num !== void 0 ? _item$num : item.quantity);
384
+ if (!Number.isSafeInteger(count) || count < 0) {
385
+ availability = _objectSpread(_objectSpread({}, availability), {}, {
386
+ status: 'error',
387
+ message: this.source.message('unavailable')
388
+ });
389
+ continue;
390
+ }
391
+ if (item === editingItem) retainedQuantity = count;else reserved += count;
392
+ }
393
+ } catch (err) {
394
+ _iterator5.e(err);
395
+ } finally {
396
+ _iterator5.f();
397
+ }
398
+ if (!Number.isSafeInteger(reserved)) {
399
+ availability = _objectSpread(_objectSpread({}, availability), {}, {
400
+ status: 'error',
401
+ message: this.source.message('unavailable')
402
+ });
403
+ }
404
+ var availableQuantity = availability.status === 'ready' ? Math.max(0, availability.quantity - reserved) : 0;
405
+ return {
406
+ availability: availability,
407
+ availableQuantity: availableQuantity,
408
+ retainedQuantity: retainedQuantity,
409
+ maxQuantity: Math.max(availableQuantity, retainedQuantity)
410
+ };
411
+ }
412
+ }, {
413
+ key: "totals",
414
+ value: function totals(items) {
415
+ var totals = new Map();
416
+ var _iterator6 = _createForOfIteratorHelper(items),
417
+ _step6;
418
+ try {
419
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
420
+ var _item$num2, _totals$get;
421
+ var item = _step6.value;
422
+ var key = this.keyForLine(item);
423
+ var identity = key ? JSON.stringify(['inventory', key]) : variantIdentity(item.product_id, item.product_variant_id);
424
+ var quantity = Number((_item$num2 = item.num) !== null && _item$num2 !== void 0 ? _item$num2 : item.quantity);
425
+ if (!Number.isSafeInteger(quantity) || quantity < 0) throw salesGuardError(this.source.message('unavailable'));
426
+ if (!quantity) continue;
427
+ var total = (((_totals$get = totals.get(identity)) === null || _totals$get === void 0 ? void 0 : _totals$get.quantity) || 0) + quantity;
428
+ if (!Number.isSafeInteger(total)) throw salesGuardError(this.source.message('unavailable'));
429
+ totals.set(identity, {
430
+ key: key,
431
+ quantity: total
432
+ });
433
+ }
434
+ } catch (err) {
435
+ _iterator6.e(err);
436
+ } finally {
437
+ _iterator6.f();
438
+ }
439
+ return totals;
440
+ }
441
+ }, {
442
+ key: "validate",
443
+ value: function validate(proposed) {
444
+ var current = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
445
+ var allowReductions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
446
+ this.assertCurrent();
447
+ var previous = this.totals(current);
448
+ var _iterator7 = _createForOfIteratorHelper(this.totals(proposed)),
449
+ _step7;
450
+ try {
451
+ for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
452
+ var _previous$get;
453
+ var _step7$value = _slicedToArray(_step7.value, 2),
454
+ identity = _step7$value[0],
455
+ _step7$value$ = _step7$value[1],
456
+ key = _step7$value$.key,
457
+ quantity = _step7$value$.quantity;
458
+ if (allowReductions && quantity <= (((_previous$get = previous.get(identity)) === null || _previous$get === void 0 ? void 0 : _previous$get.quantity) || 0)) continue;
459
+ var stock = this.availabilityForKey(key);
460
+ if (stock.status !== 'ready') throw salesGuardError(stock.message || this.source.message('unavailable'));
461
+ if (quantity > stock.quantity) throw salesGuardError(this.source.message('insufficient', {
462
+ key: key,
463
+ quantity: stock.quantity
464
+ }));
465
+ }
466
+ } catch (err) {
467
+ _iterator7.e(err);
468
+ } finally {
469
+ _iterator7.f();
470
+ }
471
+ }
472
+ }, {
473
+ key: "freezeCheckout",
474
+ value: function freezeCheckout(items) {
475
+ var _this5 = this;
476
+ if (!items.length || items.some(function (item) {
477
+ var _item$num3;
478
+ return Number((_item$num3 = item.num) !== null && _item$num3 !== void 0 ? _item$num3 : item.quantity) <= 0;
479
+ })) {
480
+ throw salesGuardError(this.source.message('unavailable'));
481
+ }
482
+ this.validate(items, [], false);
483
+ return Object.freeze({
484
+ scopeKey: this.scopeKey,
485
+ revision: this.revision,
486
+ lines: Object.freeze(items.map(function (item, index) {
487
+ var _ref5, _ref6, _item$metadata$unique, _item$metadata, _ref7, _item$product_variant3, _item$product_sku3, _item$num4;
488
+ return Object.freeze({
489
+ lineId: String((_ref5 = (_ref6 = (_item$metadata$unique = (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.unique_identification_number) !== null && _item$metadata$unique !== void 0 ? _item$metadata$unique : item.unique_identification_number) !== null && _ref6 !== void 0 ? _ref6 : item.order_detail_id) !== null && _ref5 !== void 0 ? _ref5 : index),
490
+ productId: item.product_id,
491
+ variantId: (_ref7 = (_item$product_variant3 = item.product_variant_id) !== null && _item$product_variant3 !== void 0 ? _item$product_variant3 : (_item$product_sku3 = item.product_sku) === null || _item$product_sku3 === void 0 ? void 0 : _item$product_sku3.product_variant_id) !== null && _ref7 !== void 0 ? _ref7 : 0,
492
+ quantity: Number((_item$num4 = item.num) !== null && _item$num4 !== void 0 ? _item$num4 : item.quantity),
493
+ inventoryKey: _this5.keyForLine(item)
494
+ });
495
+ }))
496
+ });
497
+ }
498
+ }]);
499
+ return InventoryController;
500
+ }();
@@ -1,9 +0,0 @@
1
- // 导出评估器
2
- export { PromotionEvaluator } from "./evaluator";
3
-
4
- // 导出适配器
5
- export { PromotionAdapter } from "./adapter";
6
- export { default } from "./adapter";
7
-
8
- // 导出策略配置示例常量
9
- export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
@@ -1,8 +1,10 @@
1
- import type { OrderProduct } from '../../Order/types';
1
+ import type { OrderHolderRelation, OrderProduct } from '../../Order/types';
2
2
  export interface BuildNormalProductCacheItemFromOrderLineInput {
3
3
  /** tempOrder.products 中的一行(普通商品,无关联 booking) */
4
4
  product: OrderProduct;
5
5
  /** 商品 catalog / 详情,用于 variant / option / bundle 模板字段 */
6
6
  sourceProduct?: Record<string, any> | null;
7
+ /** 整单关系集合,按商品行 UID 回填。 */
8
+ holder_relations?: OrderHolderRelation[];
7
9
  }
8
10
  export declare function buildNormalProductCacheItemFromOrderLine(input: BuildNormalProductCacheItemFromOrderLineInput): Record<string, any>;