@pisell/pisellos 2.3.28 → 2.3.29

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 (84) hide show
  1. package/dist/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  2. package/dist/model/strategy/adapter/dataVariant/adapter.js +167 -0
  3. package/dist/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  4. package/dist/model/strategy/adapter/dataVariant/evaluator.js +780 -0
  5. package/dist/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  6. package/dist/model/strategy/adapter/dataVariant/examples.js +277 -0
  7. package/dist/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  8. package/dist/model/strategy/adapter/dataVariant/index.js +4 -0
  9. package/dist/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  10. package/dist/model/strategy/adapter/dataVariant/type.js +54 -0
  11. package/dist/model/strategy/adapter/index.d.ts +4 -0
  12. package/dist/model/strategy/adapter/index.js +5 -1
  13. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  14. package/dist/modules/Discount/index.d.ts +5 -2
  15. package/dist/modules/Discount/index.js +30 -7
  16. package/dist/modules/Discount/types.d.ts +4 -0
  17. package/dist/modules/Order/index.d.ts +7 -1
  18. package/dist/modules/Order/index.js +187 -74
  19. package/dist/modules/Order/types.d.ts +2 -0
  20. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  21. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  22. package/dist/modules/Order/utils.d.ts +2 -1
  23. package/dist/modules/Order/utils.js +2 -8
  24. package/dist/modules/Product/types.d.ts +22 -0
  25. package/dist/modules/ProductList/index.d.ts +1 -1
  26. package/dist/modules/ProductList/index.js +4 -2
  27. package/dist/modules/ProductList/types.d.ts +2 -0
  28. package/dist/server/index.d.ts +50 -0
  29. package/dist/server/index.js +995 -749
  30. package/dist/server/modules/order/index.d.ts +10 -4
  31. package/dist/server/modules/order/index.js +404 -399
  32. package/dist/server/modules/products/index.d.ts +26 -7
  33. package/dist/server/modules/products/index.js +167 -76
  34. package/dist/server/modules/products/types.d.ts +14 -0
  35. package/dist/solution/BaseSales/index.d.ts +9 -1
  36. package/dist/solution/BaseSales/index.js +998 -756
  37. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
  38. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  39. package/dist/solution/BookingByStep/index.d.ts +1 -1
  40. package/dist/solution/BookingTicket/index.d.ts +14 -2
  41. package/dist/solution/BookingTicket/types.d.ts +2 -0
  42. package/dist/solution/ShopDiscount/index.js +15 -14
  43. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  44. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  45. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  46. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  47. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  48. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  49. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  50. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  51. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  52. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  53. package/lib/model/strategy/adapter/index.d.ts +4 -0
  54. package/lib/model/strategy/adapter/index.js +13 -2
  55. package/lib/modules/Discount/index.d.ts +5 -2
  56. package/lib/modules/Discount/index.js +23 -3
  57. package/lib/modules/Discount/types.d.ts +4 -0
  58. package/lib/modules/Order/index.d.ts +7 -1
  59. package/lib/modules/Order/index.js +104 -6
  60. package/lib/modules/Order/types.d.ts +2 -0
  61. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  62. package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
  63. package/lib/modules/Order/utils.d.ts +2 -1
  64. package/lib/modules/Order/utils.js +4 -11
  65. package/lib/modules/Product/types.d.ts +22 -0
  66. package/lib/modules/ProductList/index.d.ts +1 -1
  67. package/lib/modules/ProductList/index.js +4 -2
  68. package/lib/modules/ProductList/types.d.ts +2 -0
  69. package/lib/server/index.d.ts +50 -0
  70. package/lib/server/index.js +206 -29
  71. package/lib/server/modules/order/index.d.ts +10 -4
  72. package/lib/server/modules/order/index.js +198 -139
  73. package/lib/server/modules/products/index.d.ts +26 -7
  74. package/lib/server/modules/products/index.js +114 -35
  75. package/lib/server/modules/products/types.d.ts +14 -0
  76. package/lib/solution/BaseSales/index.d.ts +9 -1
  77. package/lib/solution/BaseSales/index.js +229 -54
  78. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
  79. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  80. package/lib/solution/BookingByStep/index.d.ts +1 -1
  81. package/lib/solution/BookingTicket/index.d.ts +14 -2
  82. package/lib/solution/BookingTicket/types.d.ts +2 -0
  83. package/lib/solution/ShopDiscount/index.js +2 -1
  84. package/package.json +1 -1
@@ -0,0 +1,53 @@
1
+ export type OrderCollectionKind = 'product' | 'booking' | 'payment';
2
+ export interface OrderCollectionIdentityStats {
3
+ backfilledUidCount: number;
4
+ collapsedDuplicateCount: number;
5
+ uidConflictCount: number;
6
+ anonymousRowCount: number;
7
+ }
8
+ export interface OrderCollectionUidRemap {
9
+ kind: OrderCollectionKind;
10
+ from: string;
11
+ to: string;
12
+ persistentId: string | null;
13
+ /** 默认全局迁移;UID 冲突时只能迁移能由另一侧 UID 明确定位的引用。 */
14
+ scope?: 'global' | 'linked-owner';
15
+ referenceOwnerUid?: string | null;
16
+ }
17
+ export interface NormalizeOrderCollectionResult<T> {
18
+ items: T[];
19
+ stats: OrderCollectionIdentityStats;
20
+ uidRemaps: OrderCollectionUidRemap[];
21
+ }
22
+ export interface NormalizeOrderCollectionsResult<T> {
23
+ order: T;
24
+ stats: Record<OrderCollectionKind, OrderCollectionIdentityStats>;
25
+ uidRemaps: OrderCollectionUidRemap[];
26
+ }
27
+ export declare function createUuidV4(): string;
28
+ export declare function isBlankOrderCollectionIdentity(value: unknown): boolean;
29
+ export declare function getOrderCollectionPersistentId(kind: OrderCollectionKind, item: unknown): string | null;
30
+ export declare function getOrderCollectionUid(kind: OrderCollectionKind, item: unknown): string | null;
31
+ export declare function buildOrderCollectionFallbackUid(kind: OrderCollectionKind, persistentId: string | number): string;
32
+ export declare function getOrderCollectionReferenceUid(kind: OrderCollectionKind, item: unknown): string | null;
33
+ export declare function setOrderCollectionUid<T>(kind: OrderCollectionKind, item: T, uid: string): T;
34
+ /**
35
+ * 持久化行 ID 是服务端事实主键;只有至少一侧尚未持久化时,才允许用 runtime UID 对齐。
36
+ */
37
+ export declare function isSameOrderCollectionItem(kind: OrderCollectionKind, left: unknown, right: unknown): boolean;
38
+ export declare function mergeOrderCollectionItems<T>(kind: OrderCollectionKind, currentItem: T, incomingItem: T, options?: {
39
+ ensureUid?: boolean;
40
+ createAnonymousUid?: () => string;
41
+ }): T;
42
+ /**
43
+ * 规范化单一数组:强身份重复时保留首次位置、用最后一条业务字段覆盖,并统一补 UID。
44
+ */
45
+ export declare function normalizeOrderCollection<T>(kind: OrderCollectionKind, items: T[] | null | undefined, options?: {
46
+ ensureUid?: boolean;
47
+ createAnonymousUid?: () => string;
48
+ }): NormalizeOrderCollectionResult<T>;
49
+ export declare function applyOrderCollectionUidRemaps<T extends Record<string, any>>(sourceOrder: T, uidRemaps: OrderCollectionUidRemap[]): T;
50
+ export declare function normalizeOrderCollections<T extends Record<string, any>>(sourceOrder: T, options?: {
51
+ ensureUid?: boolean;
52
+ createAnonymousUid?: () => string;
53
+ }): NormalizeOrderCollectionsResult<T>;
@@ -0,0 +1,405 @@
1
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
2
+ 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."); }
3
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
4
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
5
+ 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; } } }; }
6
+ 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); }
7
+ 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; }
8
+ 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); }
9
+ 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; }
10
+ 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; }
11
+ 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; }
12
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
13
+ 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); }
14
+ import { cloneDeep } from 'lodash-es';
15
+ var IDENTITY_CONFIG = {
16
+ product: {
17
+ persistentIdField: 'order_detail_id',
18
+ uidField: 'unique_identification_number',
19
+ fallbackPrefix: 'os-fallback:product:order-detail'
20
+ },
21
+ booking: {
22
+ persistentIdField: 'schedule_event_id',
23
+ uidField: 'unique_identification_number',
24
+ fallbackPrefix: 'os-fallback:booking:schedule-event'
25
+ },
26
+ payment: {
27
+ persistentIdField: 'order_payment_id',
28
+ uidField: 'unique_payment_number',
29
+ fallbackPrefix: 'os-fallback:payment:order-payment'
30
+ }
31
+ };
32
+ export function createUuidV4() {
33
+ var template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
34
+ return template.replace(/[xy]/g, function (char) {
35
+ var randomValue = Math.floor(Math.random() * 16);
36
+ var value = char === 'x' ? randomValue : randomValue & 0x3 | 0x8;
37
+ return value.toString(16);
38
+ });
39
+ }
40
+ export function isBlankOrderCollectionIdentity(value) {
41
+ return value === undefined || value === null || value === '';
42
+ }
43
+ export function getOrderCollectionPersistentId(kind, item) {
44
+ var record = item;
45
+ if (!record) return null;
46
+ var value = record[IDENTITY_CONFIG[kind].persistentIdField];
47
+ if (isBlankOrderCollectionIdentity(value)) return null;
48
+ return String(value);
49
+ }
50
+ export function getOrderCollectionUid(kind, item) {
51
+ var _record$metadata;
52
+ var record = item;
53
+ if (!record) return null;
54
+ var uidField = IDENTITY_CONFIG[kind].uidField;
55
+ var metadataValue = (_record$metadata = record.metadata) === null || _record$metadata === void 0 ? void 0 : _record$metadata[uidField];
56
+ if (!isBlankOrderCollectionIdentity(metadataValue)) return String(metadataValue);
57
+ var topLevelValue = record[uidField];
58
+ if (isBlankOrderCollectionIdentity(topLevelValue)) return null;
59
+ return String(topLevelValue);
60
+ }
61
+ export function buildOrderCollectionFallbackUid(kind, persistentId) {
62
+ return "".concat(IDENTITY_CONFIG[kind].fallbackPrefix, ":").concat(String(persistentId));
63
+ }
64
+ export function getOrderCollectionReferenceUid(kind, item) {
65
+ var uid = getOrderCollectionUid(kind, item);
66
+ if (uid) return uid;
67
+ var persistentId = getOrderCollectionPersistentId(kind, item);
68
+ return persistentId ? buildOrderCollectionFallbackUid(kind, persistentId) : null;
69
+ }
70
+ export function setOrderCollectionUid(kind, item, uid) {
71
+ var record = cloneDeep(item || {});
72
+ var uidField = IDENTITY_CONFIG[kind].uidField;
73
+ record.metadata = _objectSpread(_objectSpread({}, record.metadata && _typeof(record.metadata) === 'object' ? record.metadata : {}), {}, _defineProperty({}, uidField, uid));
74
+ delete record[uidField];
75
+ return record;
76
+ }
77
+
78
+ /**
79
+ * 持久化行 ID 是服务端事实主键;只有至少一侧尚未持久化时,才允许用 runtime UID 对齐。
80
+ */
81
+ export function isSameOrderCollectionItem(kind, left, right) {
82
+ var leftPersistentId = getOrderCollectionPersistentId(kind, left);
83
+ var rightPersistentId = getOrderCollectionPersistentId(kind, right);
84
+ if (leftPersistentId && rightPersistentId) {
85
+ return leftPersistentId === rightPersistentId;
86
+ }
87
+ var leftUid = getOrderCollectionUid(kind, left);
88
+ var rightUid = getOrderCollectionUid(kind, right);
89
+ return Boolean(leftUid && rightUid && leftUid === rightUid);
90
+ }
91
+ export function mergeOrderCollectionItems(kind, currentItem, incomingItem, options) {
92
+ var _options$createAnonym;
93
+ var current = cloneDeep(currentItem || {});
94
+ var incoming = cloneDeep(incomingItem || {});
95
+ var persistentIdField = IDENTITY_CONFIG[kind].persistentIdField;
96
+ var currentPersistentIdValue = current[persistentIdField];
97
+ var incomingPersistentIdValue = incoming[persistentIdField];
98
+ var incomingUid = getOrderCollectionUid(kind, incoming);
99
+ var currentUid = getOrderCollectionUid(kind, current);
100
+ var persistentId = getOrderCollectionPersistentId(kind, incoming) || getOrderCollectionPersistentId(kind, current);
101
+ var merged = _objectSpread(_objectSpread(_objectSpread({}, current), incoming), {}, {
102
+ metadata: _objectSpread(_objectSpread({}, current.metadata && _typeof(current.metadata) === 'object' ? current.metadata : {}), incoming.metadata && _typeof(incoming.metadata) === 'object' ? incoming.metadata : {})
103
+ });
104
+
105
+ // UID 对齐允许一侧尚未持久化,但稀疏 incoming 的 null/空值不能擦掉已存在行 ID。
106
+ if (!isBlankOrderCollectionIdentity(incomingPersistentIdValue)) {
107
+ merged[persistentIdField] = incomingPersistentIdValue;
108
+ } else if (!isBlankOrderCollectionIdentity(currentPersistentIdValue)) {
109
+ merged[persistentIdField] = currentPersistentIdValue;
110
+ }
111
+ var incomingUidIsDerived = Boolean(incomingUid && persistentId && (incomingUid === buildOrderCollectionFallbackUid(kind, persistentId) || incomingUid.startsWith("".concat(buildOrderCollectionFallbackUid(kind, persistentId), ":conflict:"))));
112
+ var uid = (incomingUid && !incomingUidIsDerived ? incomingUid : null) || currentUid || incomingUid || ((options === null || options === void 0 ? void 0 : options.ensureUid) === false ? null : persistentId ? buildOrderCollectionFallbackUid(kind, persistentId) : (options === null || options === void 0 || (_options$createAnonym = options.createAnonymousUid) === null || _options$createAnonym === void 0 ? void 0 : _options$createAnonym.call(options)) || createUuidV4());
113
+ return uid ? setOrderCollectionUid(kind, merged, uid) : merged;
114
+ }
115
+ function createEmptyIdentityStats() {
116
+ return {
117
+ backfilledUidCount: 0,
118
+ collapsedDuplicateCount: 0,
119
+ uidConflictCount: 0,
120
+ anonymousRowCount: 0
121
+ };
122
+ }
123
+ function allocateAnonymousUid(occupiedUids, createAnonymousUid) {
124
+ var uid = createAnonymousUid();
125
+ while (occupiedUids.has(uid)) uid = createAnonymousUid();
126
+ return uid;
127
+ }
128
+ function allocatePersistentConflictUid(kind, persistentId, occupiedUids) {
129
+ var fallbackUid = buildOrderCollectionFallbackUid(kind, persistentId);
130
+ if (!occupiedUids.has(fallbackUid)) return fallbackUid;
131
+
132
+ // 极端情况下其它行可能把本行 fallback 当作显式 UID 使用;继续派生稳定后缀,
133
+ // 避免修复冲突后仍留下重复 UID。规范化结果一旦持久化,后续读取保持幂等。
134
+ var suffix = 1;
135
+ var candidate = "".concat(fallbackUid, ":conflict:").concat(suffix);
136
+ while (occupiedUids.has(candidate)) {
137
+ suffix += 1;
138
+ candidate = "".concat(fallbackUid, ":conflict:").concat(suffix);
139
+ }
140
+ return candidate;
141
+ }
142
+
143
+ /**
144
+ * 规范化单一数组:强身份重复时保留首次位置、用最后一条业务字段覆盖,并统一补 UID。
145
+ */
146
+ export function normalizeOrderCollection(kind, items, options) {
147
+ var stats = createEmptyIdentityStats();
148
+ var uidRemaps = [];
149
+ var result = [];
150
+ var ensureUid = (options === null || options === void 0 ? void 0 : options.ensureUid) !== false;
151
+ var createAnonymousUid = (options === null || options === void 0 ? void 0 : options.createAnonymousUid) || createUuidV4;
152
+ var _iterator = _createForOfIteratorHelper(items || []),
153
+ _step;
154
+ try {
155
+ var _loop = function _loop() {
156
+ var rawItem = _step.value;
157
+ var item = cloneDeep(rawItem);
158
+ var existingIndex = result.findIndex(function (existing) {
159
+ return isSameOrderCollectionItem(kind, existing, item);
160
+ });
161
+ if (existingIndex === -1) {
162
+ result.push(item);
163
+ return 1; // continue
164
+ }
165
+ var previousReferenceUid = getOrderCollectionReferenceUid(kind, result[existingIndex]);
166
+ var incomingReferenceUid = getOrderCollectionReferenceUid(kind, item);
167
+ result[existingIndex] = mergeOrderCollectionItems(kind, result[existingIndex], item, {
168
+ ensureUid: false
169
+ });
170
+ var nextUid = getOrderCollectionUid(kind, result[existingIndex]);
171
+ if (nextUid) {
172
+ var _iterator2 = _createForOfIteratorHelper(new Set([previousReferenceUid, incomingReferenceUid])),
173
+ _step2;
174
+ try {
175
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
176
+ var from = _step2.value;
177
+ if (!from || from === nextUid) continue;
178
+ uidRemaps.push({
179
+ kind: kind,
180
+ from: from,
181
+ to: nextUid,
182
+ persistentId: getOrderCollectionPersistentId(kind, result[existingIndex])
183
+ });
184
+ }
185
+ } catch (err) {
186
+ _iterator2.e(err);
187
+ } finally {
188
+ _iterator2.f();
189
+ }
190
+ }
191
+ stats.collapsedDuplicateCount += 1;
192
+ };
193
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
194
+ if (_loop()) continue;
195
+ }
196
+ } catch (err) {
197
+ _iterator.e(err);
198
+ } finally {
199
+ _iterator.f();
200
+ }
201
+ if (!ensureUid) return {
202
+ items: result,
203
+ stats: stats,
204
+ uidRemaps: uidRemaps
205
+ };
206
+ var occupiedUids = new Set();
207
+ for (var index = 0; index < result.length; index += 1) {
208
+ var item = result[index];
209
+ var persistentId = getOrderCollectionPersistentId(kind, item);
210
+ var uid = getOrderCollectionUid(kind, item);
211
+ if (!uid) {
212
+ uid = persistentId ? buildOrderCollectionFallbackUid(kind, persistentId) : allocateAnonymousUid(occupiedUids, createAnonymousUid);
213
+ item = setOrderCollectionUid(kind, item, uid);
214
+ result[index] = item;
215
+ stats.backfilledUidCount += 1;
216
+ if (!persistentId) stats.anonymousRowCount += 1;
217
+ }
218
+ if (occupiedUids.has(uid)) {
219
+ var _item, _item2, _item3, _item4;
220
+ var replacementUid = persistentId ? allocatePersistentConflictUid(kind, persistentId, occupiedUids) : allocateAnonymousUid(occupiedUids, createAnonymousUid);
221
+ result[index] = setOrderCollectionUid(kind, item, replacementUid);
222
+ uidRemaps.push({
223
+ kind: kind,
224
+ from: uid,
225
+ to: replacementUid,
226
+ persistentId: persistentId,
227
+ scope: 'linked-owner',
228
+ referenceOwnerUid: kind === 'product' ? String(((_item = item) === null || _item === void 0 ? void 0 : _item.booking_uid) || ((_item2 = item) === null || _item2 === void 0 || (_item2 = _item2.metadata) === null || _item2 === void 0 ? void 0 : _item2.booking_uid) || '') || null : kind === 'booking' ? String(((_item3 = item) === null || _item3 === void 0 ? void 0 : _item3.product_uid) || ((_item4 = item) === null || _item4 === void 0 || (_item4 = _item4.metadata) === null || _item4 === void 0 ? void 0 : _item4.product_uid) || '') || null : null
229
+ });
230
+ uid = replacementUid;
231
+ stats.uidConflictCount += 1;
232
+ }
233
+ occupiedUids.add(uid);
234
+ }
235
+ return {
236
+ items: result,
237
+ stats: stats,
238
+ uidRemaps: uidRemaps
239
+ };
240
+ }
241
+ export function applyOrderCollectionUidRemaps(sourceOrder, uidRemaps) {
242
+ if (!uidRemaps.length) return sourceOrder;
243
+ var order = cloneDeep(sourceOrder);
244
+ var hasAmbiguousLinkedOwner = function hasAmbiguousLinkedOwner(remap) {
245
+ if (remap.scope !== 'linked-owner' || !remap.referenceOwnerUid) return false;
246
+ var ownerKind = remap.kind === 'product' ? 'booking' : remap.kind === 'booking' ? 'product' : null;
247
+ if (!ownerKind) return false;
248
+ return uidRemaps.some(function (candidate) {
249
+ return candidate.scope === 'linked-owner' && candidate.kind === ownerKind && candidate.from === remap.referenceOwnerUid;
250
+ });
251
+ };
252
+ var _iterator3 = _createForOfIteratorHelper(uidRemaps),
253
+ _step3;
254
+ try {
255
+ var _loop2 = function _loop2() {
256
+ var remap = _step3.value;
257
+ if (remap.from === remap.to) return 0; // continue
258
+ var linkedOwnerIsAmbiguous = hasAmbiguousLinkedOwner(remap);
259
+ if (remap.kind === 'product') {
260
+ var _order$_extend;
261
+ var _iterator4 = _createForOfIteratorHelper(order.bookings || []),
262
+ _step4;
263
+ try {
264
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
265
+ var _booking$metadata;
266
+ var booking = _step4.value;
267
+ if (remap.scope === 'linked-owner' && (linkedOwnerIsAmbiguous || getOrderCollectionUid('booking', booking) !== remap.referenceOwnerUid)) {
268
+ continue;
269
+ }
270
+ if (String((booking === null || booking === void 0 ? void 0 : booking.product_uid) || '') === remap.from) {
271
+ booking.product_uid = remap.to;
272
+ }
273
+ if (String((booking === null || booking === void 0 || (_booking$metadata = booking.metadata) === null || _booking$metadata === void 0 ? void 0 : _booking$metadata.product_uid) || '') === remap.from) {
274
+ booking.metadata = _objectSpread(_objectSpread({}, booking.metadata || {}), {}, {
275
+ product_uid: remap.to
276
+ });
277
+ }
278
+ }
279
+ // 冲突 UID 仍由第一条持有;赠品父引用缺少可用的持久化行定位时不能全局改写。
280
+ } catch (err) {
281
+ _iterator4.e(err);
282
+ } finally {
283
+ _iterator4.f();
284
+ }
285
+ if (remap.scope !== 'linked-owner') {
286
+ var _iterator5 = _createForOfIteratorHelper(order.products || []),
287
+ _step5;
288
+ try {
289
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
290
+ var _product$metadata, _product$metadata2;
291
+ var product = _step5.value;
292
+ if (String((product === null || product === void 0 || (_product$metadata = product.metadata) === null || _product$metadata === void 0 ? void 0 : _product$metadata.parent_unique_identification_number) || '') === remap.from) {
293
+ product.metadata = _objectSpread(_objectSpread({}, product.metadata || {}), {}, {
294
+ parent_unique_identification_number: remap.to
295
+ });
296
+ }
297
+ var giftInfo = product === null || product === void 0 || (_product$metadata2 = product.metadata) === null || _product$metadata2 === void 0 ? void 0 : _product$metadata2._giftInfo;
298
+ if (giftInfo && _typeof(giftInfo) === 'object') {
299
+ var sourceProductIds = Array.isArray(giftInfo.sourceProductIds) ? giftInfo.sourceProductIds.map(function (uid) {
300
+ return String(uid) === remap.from ? remap.to : uid;
301
+ }) : giftInfo.sourceProductIds;
302
+ var sourceProductId = String(giftInfo.sourceProductId || '') === remap.from ? remap.to : giftInfo.sourceProductId;
303
+ product.metadata = _objectSpread(_objectSpread({}, product.metadata || {}), {}, {
304
+ _giftInfo: _objectSpread(_objectSpread(_objectSpread({}, giftInfo), sourceProductIds !== undefined ? {
305
+ sourceProductIds: sourceProductIds
306
+ } : {}), sourceProductId !== undefined ? {
307
+ sourceProductId: sourceProductId
308
+ } : {})
309
+ });
310
+ }
311
+ }
312
+ } catch (err) {
313
+ _iterator5.e(err);
314
+ } finally {
315
+ _iterator5.f();
316
+ }
317
+ }
318
+ var productsByUid = (_order$_extend = order._extend) === null || _order$_extend === void 0 ? void 0 : _order$_extend.productsByUid;
319
+ var cachedProduct = productsByUid === null || productsByUid === void 0 ? void 0 : productsByUid[remap.from];
320
+ var cachedPersistentId = getOrderCollectionPersistentId('product', (cachedProduct === null || cachedProduct === void 0 ? void 0 : cachedProduct.origin) || cachedProduct);
321
+ if (productsByUid && remap.scope === 'linked-owner') {
322
+ var retainedProduct = (order.products || []).find(function (product) {
323
+ return getOrderCollectionUid('product', product) === remap.from;
324
+ });
325
+ var remappedProduct = (order.products || []).find(function (product) {
326
+ return getOrderCollectionUid('product', product) === remap.to;
327
+ });
328
+ if (cachedProduct && remap.persistentId && cachedPersistentId === remap.persistentId) {
329
+ productsByUid[remap.to] = _objectSpread(_objectSpread({}, cachedProduct || {}), productsByUid[remap.to] || {});
330
+ if (retainedProduct) {
331
+ productsByUid[remap.from] = _objectSpread(_objectSpread({}, cachedProduct || {}), {}, {
332
+ origin: cloneDeep(retainedProduct)
333
+ });
334
+ }
335
+ } else if (remappedProduct && !productsByUid[remap.to]) {
336
+ productsByUid[remap.to] = {
337
+ origin: cloneDeep(remappedProduct)
338
+ };
339
+ }
340
+ return 0; // continue
341
+ }
342
+ if (cachedProduct && remap.scope !== 'linked-owner') {
343
+ productsByUid[remap.to] = _objectSpread(_objectSpread({}, cachedProduct || {}), productsByUid[remap.to] || {});
344
+ delete productsByUid[remap.from];
345
+ }
346
+ }
347
+ if (remap.kind === 'booking') {
348
+ var _iterator6 = _createForOfIteratorHelper(order.products || []),
349
+ _step6;
350
+ try {
351
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
352
+ var _product$metadata3;
353
+ var _product = _step6.value;
354
+ if (remap.scope === 'linked-owner' && (linkedOwnerIsAmbiguous || getOrderCollectionUid('product', _product) !== remap.referenceOwnerUid)) {
355
+ continue;
356
+ }
357
+ if (String((_product === null || _product === void 0 ? void 0 : _product.booking_uid) || '') === remap.from) {
358
+ _product.booking_uid = remap.to;
359
+ }
360
+ if (String((_product === null || _product === void 0 || (_product$metadata3 = _product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.booking_uid) || '') === remap.from) {
361
+ _product.metadata = _objectSpread(_objectSpread({}, _product.metadata || {}), {}, {
362
+ booking_uid: remap.to
363
+ });
364
+ }
365
+ }
366
+ } catch (err) {
367
+ _iterator6.e(err);
368
+ } finally {
369
+ _iterator6.f();
370
+ }
371
+ }
372
+ },
373
+ _ret;
374
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
375
+ _ret = _loop2();
376
+ if (_ret === 0) continue;
377
+ }
378
+ } catch (err) {
379
+ _iterator3.e(err);
380
+ } finally {
381
+ _iterator3.f();
382
+ }
383
+ return order;
384
+ }
385
+ export function normalizeOrderCollections(sourceOrder, options) {
386
+ var order = cloneDeep(sourceOrder || {});
387
+ var orderRecord = order;
388
+ var productResult = normalizeOrderCollection('product', Array.isArray(orderRecord.products) ? orderRecord.products : [], options);
389
+ var bookingResult = normalizeOrderCollection('booking', Array.isArray(orderRecord.bookings) ? orderRecord.bookings : [], options);
390
+ var paymentResult = normalizeOrderCollection('payment', Array.isArray(orderRecord.payments) ? orderRecord.payments : [], options);
391
+ if (Array.isArray(orderRecord.products)) orderRecord.products = productResult.items;
392
+ if (Array.isArray(orderRecord.bookings)) orderRecord.bookings = bookingResult.items;
393
+ if (Array.isArray(orderRecord.payments)) orderRecord.payments = paymentResult.items;
394
+ var uidRemaps = [].concat(_toConsumableArray(productResult.uidRemaps), _toConsumableArray(bookingResult.uidRemaps), _toConsumableArray(paymentResult.uidRemaps));
395
+ order = applyOrderCollectionUidRemaps(order, uidRemaps);
396
+ return {
397
+ order: order,
398
+ stats: {
399
+ product: productResult.stats,
400
+ booking: bookingResult.stats,
401
+ payment: paymentResult.stats
402
+ },
403
+ uidRemaps: uidRemaps
404
+ };
405
+ }
@@ -3,6 +3,7 @@ import type { CartItem } from "../Cart";
3
3
  import type { OrderProductDiscountItem, OrderProduct, OrderSubmitPayload, OrderSubmitProduct, OrderSummary, OrderTempOrder } from './types';
4
4
  import type { RulesParamsHooks } from '../Rules/types';
5
5
  import type { MapOrderPaymentsOptions, OrderPaymentData, OrderPaymentSource } from './types';
6
+ import { createUuidV4 } from './utils/orderCollectionIdentity';
6
7
  export interface OrderProductsDepositProtocol {
7
8
  id: number;
8
9
  title: string;
@@ -177,7 +178,7 @@ export declare const mergeRelationForms: (relationForms: {
177
178
  form_record_ids: number[];
178
179
  }[];
179
180
  export declare const getAllDiscountList: (cartItem: CartItem) => any;
180
- export declare function createUuidV4(): string;
181
+ export { createUuidV4 };
181
182
  export declare function isTempOrder(data: any): data is OrderTempOrder;
182
183
  export declare function formatDateTime(date: Date): string;
183
184
  export declare function normalizeBookingIsAll(booking: Record<string, any>): 0 | 1;
@@ -21,6 +21,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
21
21
  import dayjs from "dayjs";
22
22
  import Decimal from 'decimal.js';
23
23
  import { buildProductLineFingerprint, createEmptySummary } from "../../solution/ScanOrder/utils";
24
+ import { createUuidV4 } from "./utils/orderCollectionIdentity";
24
25
  /**
25
26
  * 把"含 option 的主商品单价"与 bundle 合成"单行 composite 单价"。
26
27
  *
@@ -754,14 +755,7 @@ export var getAllDiscountList = function getAllDiscountList(cartItem) {
754
755
 
755
756
  // ─── 以下为从 ScanOrder/utils.ts 迁入的 Order 专属工具函数 ───
756
757
 
757
- export function createUuidV4() {
758
- var template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';
759
- return template.replace(/[xy]/g, function (char) {
760
- var randomValue = Math.floor(Math.random() * 16);
761
- var value = char === 'x' ? randomValue : randomValue & 0x3 | 0x8;
762
- return value.toString(16);
763
- });
764
- }
758
+ export { createUuidV4 };
765
759
  export function isTempOrder(data) {
766
760
  if (!data || _typeof(data) !== 'object') return false;
767
761
  if (!Array.isArray(data.products)) return false;
@@ -9,6 +9,26 @@ export interface ProductCollection {
9
9
  /** 商品集合封面 */
10
10
  cover: string;
11
11
  }
12
+ /**
13
+ * 商品 Data Variant 记录,结构与后端 data_variant 表对齐。
14
+ */
15
+ export interface ProductDataVariant {
16
+ /** 变体记录 id */
17
+ id: number;
18
+ /** 店铺 id */
19
+ shop_id: number;
20
+ /** 所属模块,商品场景固定为 product */
21
+ module: string;
22
+ /** 模块数据 id,商品场景对应 product.id */
23
+ module_data_id: number;
24
+ /** 关联 data_variant_rule.id */
25
+ data_variant_rule_id: number;
26
+ /** 命中策略后覆盖到商品上的字段 */
27
+ data: Record<string, any>;
28
+ created_at: string | null;
29
+ updated_at: string | null;
30
+ deleted_at: string | null;
31
+ }
12
32
  /**
13
33
  * 商品基本信息接口
14
34
  */
@@ -214,6 +234,8 @@ export interface ProductData {
214
234
  bundle_group_count: number;
215
235
  /** 选项组数量 */
216
236
  option_group_count: number;
237
+ /** 智能定价变体列表,/product/query with dataVariants 返回 */
238
+ data_variants?: ProductDataVariant[];
217
239
  /** 服务时长 */
218
240
  service_times?: any;
219
241
  }
@@ -26,7 +26,7 @@ export declare class ProductList extends BaseModule implements Module {
26
26
  * const products = await productList.getAddTimeProducts({ schedule_date: '2026-06-16' });
27
27
  */
28
28
  getAddTimeProducts(params?: ProductListLoadProductsParams): Promise<any>;
29
- loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, extension_type, status, }?: ProductListLoadProductsParams, options?: {
29
+ loadProducts({ category_ids, product_ids, collection, menu_list_ids, customer_id: paramsCustomerId, with_count, schedule_datetime, schedule_date, cacheId, with_schedule, extension_type, status, strategy_context, }?: ProductListLoadProductsParams, options?: {
30
30
  callback?: (result: any) => void;
31
31
  subscriberId?: string;
32
32
  }): Promise<any>;
@@ -152,6 +152,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
152
152
  extension_type,
153
153
  _ref$status,
154
154
  status,
155
+ strategy_context,
155
156
  options,
156
157
  userPlugin,
157
158
  customer_id,
@@ -162,7 +163,7 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
162
163
  return _regeneratorRuntime().wrap(function _callee4$(_context4) {
163
164
  while (1) switch (_context4.prev = _context4.next) {
164
165
  case 0:
165
- _ref = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {}, _ref$category_ids = _ref.category_ids, category_ids = _ref$category_ids === void 0 ? [] : _ref$category_ids, _ref$product_ids = _ref.product_ids, product_ids = _ref$product_ids === void 0 ? [] : _ref$product_ids, _ref$collection = _ref.collection, collection = _ref$collection === void 0 ? [] : _ref$collection, _ref$menu_list_ids = _ref.menu_list_ids, menu_list_ids = _ref$menu_list_ids === void 0 ? [] : _ref$menu_list_ids, paramsCustomerId = _ref.customer_id, _ref$with_count = _ref.with_count, with_count = _ref$with_count === void 0 ? [] : _ref$with_count, schedule_datetime = _ref.schedule_datetime, schedule_date = _ref.schedule_date, cacheId = _ref.cacheId, with_schedule = _ref.with_schedule, extension_type = _ref.extension_type, _ref$status = _ref.status, status = _ref$status === void 0 ? 'published' : _ref$status;
166
+ _ref = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {}, _ref$category_ids = _ref.category_ids, category_ids = _ref$category_ids === void 0 ? [] : _ref$category_ids, _ref$product_ids = _ref.product_ids, product_ids = _ref$product_ids === void 0 ? [] : _ref$product_ids, _ref$collection = _ref.collection, collection = _ref$collection === void 0 ? [] : _ref$collection, _ref$menu_list_ids = _ref.menu_list_ids, menu_list_ids = _ref$menu_list_ids === void 0 ? [] : _ref$menu_list_ids, paramsCustomerId = _ref.customer_id, _ref$with_count = _ref.with_count, with_count = _ref$with_count === void 0 ? [] : _ref$with_count, schedule_datetime = _ref.schedule_datetime, schedule_date = _ref.schedule_date, cacheId = _ref.cacheId, with_schedule = _ref.with_schedule, extension_type = _ref.extension_type, _ref$status = _ref.status, status = _ref$status === void 0 ? 'published' : _ref$status, strategy_context = _ref.strategy_context;
166
167
  options = _args4.length > 1 ? _args4[1] : undefined;
167
168
  // // 如果 schedule_ids 为空,则需要尝试从 schedule 模块里获取
168
169
  // if (!schedule_ids?.length) {
@@ -206,7 +207,8 @@ export var ProductList = /*#__PURE__*/function (_BaseModule) {
206
207
  is_eject: 1,
207
208
  with_schedule: with_schedule,
208
209
  schedule_datetime: schedule_datetime,
209
- extension_type: extension_type
210
+ extension_type: extension_type,
211
+ strategy_context: strategy_context
210
212
  }, {
211
213
  osServer: true,
212
214
  callback: options === null || options === void 0 ? void 0 : options.callback,
@@ -12,6 +12,8 @@ export interface ProductListLoadProductsParams {
12
12
  with_schedule?: number;
13
13
  extension_type?: string[];
14
14
  status?: string;
15
+ /** 智能定价条件上下文,仅影响策略命中,不参与商品集合筛选 */
16
+ strategy_context?: Record<string, any>;
15
17
  }
16
18
  export interface ProductListData {
17
19
  list: ProductData[];
@@ -47,6 +47,8 @@ declare class Server {
47
47
  private prefixRouterGet;
48
48
  router: Router;
49
49
  private productQuerySubscribers;
50
+ /** subscriberId → 智能定价变价时间点定时器句柄(与 subscriber 分离存储,便于 clear) */
51
+ private productQueryScheduleTimers;
50
52
  private orderQuerySubscribers;
51
53
  private bookingQuerySubscribers;
52
54
  private bookingRemoteQuerySubscribers;
@@ -210,6 +212,48 @@ declare class Server {
210
212
  * 根据 subscriberId 移除商品查询订阅者
211
213
  */
212
214
  removeProductQuerySubscriber(subscriberId?: string): void;
215
+ /**
216
+ * 构建商品 query 响应 data 段,附带智能定价 schedule_time_points 元数据。
217
+ */
218
+ private buildProductQueryResultPayload;
219
+ /**
220
+ * 是否启用商品 query 订阅的 schedule 时间点定时重算。
221
+ * strategy_context.enable_schedule_reload === false 时关闭。
222
+ */
223
+ private shouldScheduleProductQueryReload;
224
+ /**
225
+ * 清除指定 subscriber 的全部 schedule 定时器,防止重复 query 或 unsubscribe 后泄漏。
226
+ */
227
+ private clearSubscriberScheduleTimers;
228
+ /**
229
+ * 从 productQueryScheduleTimers 移除已触发的 timer 引用。
230
+ */
231
+ private removeScheduleTimerRef;
232
+ /**
233
+ * 计算 schedule 变价时间点到当前时刻的延迟(ms)。已过期返回 -1。
234
+ */
235
+ private computeScheduleTimePointDelayMs;
236
+ /**
237
+ * 定时重算前刷新 subscriber schedule 上下文:使用执行瞬间时间,禁止沿用首次 query 的 schedule_datetime。
238
+ */
239
+ private refreshSubscriberScheduleAtExecution;
240
+ /**
241
+ * 为 subscriber 注册智能定价 scheduleTimePoints 定时重算。
242
+ * 必须先 clearSubscriberScheduleTimers,再调用本方法。
243
+ */
244
+ private scheduleSubscriberTimePointReloads;
245
+ /**
246
+ * schedule 变价时间点定时器触发:刷新 schedule_datetime 后重算并 callback。
247
+ */
248
+ private onScheduleTimePointTimerFire;
249
+ /**
250
+ * 对单个商品 query 订阅者重算并推送(定时路径;不新建 schedule timer)。
251
+ */
252
+ private recomputeAndNotifySubscriber;
253
+ /**
254
+ * query 完成后为 subscriber 同步 schedule 定时器(先 clear 再 schedule)。
255
+ */
256
+ private syncProductQueryScheduleTimers;
213
257
  /**
214
258
  * 处理商品查询请求
215
259
  * 存储订阅者信息,便于数据变更时推送最新结果
@@ -570,6 +614,12 @@ declare class Server {
570
614
  * @param options.changedIds 变更的商品 IDs,用于增量更新价格缓存
571
615
  */
572
616
  private computeProductQueryResult;
617
+ /**
618
+ * 构建商品格式化上下文。
619
+ *
620
+ * 智能定价条件使用全量 menuList/scheduleList;Product Query 顶层参数只保留筛选商品集合所需字段。
621
+ */
622
+ private buildProductFormatterContext;
573
623
  /**
574
624
  * 数据变更后,遍历所有订阅者重新计算查询结果并通过 callback 推送
575
625
  * 由 ProductsModule 的 onProductsSyncCompleted 事件触发