@pisell/pisellos 2.2.264 → 2.2.265

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 (152) 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/adapter.d.ts +0 -4
  14. package/dist/model/strategy/adapter/promotion/adapter.js +0 -23
  15. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
  16. package/dist/model/strategy/adapter/promotion/evaluator.js +6 -279
  17. package/dist/model/strategy/adapter/promotion/examples.d.ts +0 -86
  18. package/dist/model/strategy/adapter/promotion/examples.js +0 -99
  19. package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
  20. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  21. package/dist/model/strategy/adapter/promotion/type.d.ts +2 -90
  22. package/dist/model/strategy/adapter/promotion/type.js +0 -45
  23. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +16 -10
  24. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +2 -1
  25. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
  26. package/dist/modules/BookingContext/utils/cacheItemToBookingInput.js +32 -1
  27. package/dist/modules/Discount/index.d.ts +5 -2
  28. package/dist/modules/Discount/index.js +30 -7
  29. package/dist/modules/Discount/types.d.ts +4 -0
  30. package/dist/modules/Order/index.d.ts +41 -10
  31. package/dist/modules/Order/index.js +1370 -808
  32. package/dist/modules/Order/payment-utils.d.ts +26 -0
  33. package/dist/modules/Order/payment-utils.js +225 -0
  34. package/dist/modules/Order/types.d.ts +49 -1
  35. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  36. package/dist/modules/Order/utils/orderCollectionIdentity.js +410 -0
  37. package/dist/modules/Order/utils.d.ts +4 -3
  38. package/dist/modules/Order/utils.js +62 -66
  39. package/dist/modules/Payment/index.d.ts +2 -0
  40. package/dist/modules/Payment/index.js +78 -49
  41. package/dist/modules/Payment/types.d.ts +26 -24
  42. package/dist/modules/Payment/types.js +2 -0
  43. package/dist/modules/Product/types.d.ts +22 -0
  44. package/dist/modules/ProductList/index.d.ts +1 -1
  45. package/dist/modules/ProductList/index.js +4 -2
  46. package/dist/modules/ProductList/types.d.ts +2 -0
  47. package/dist/modules/Rules/index.d.ts +2 -9
  48. package/dist/modules/Rules/index.js +69 -43
  49. package/dist/modules/Rules/types.d.ts +10 -1
  50. package/dist/server/index.d.ts +71 -0
  51. package/dist/server/index.js +2504 -1187
  52. package/dist/server/modules/order/index.d.ts +56 -5
  53. package/dist/server/modules/order/index.js +1718 -834
  54. package/dist/server/modules/order/types.d.ts +15 -3
  55. package/dist/server/modules/order/types.js +1 -1
  56. package/dist/server/modules/products/index.d.ts +31 -8
  57. package/dist/server/modules/products/index.js +549 -390
  58. package/dist/server/modules/products/types.d.ts +18 -0
  59. package/dist/solution/BaseSales/index.d.ts +54 -4
  60. package/dist/solution/BaseSales/index.js +1448 -788
  61. package/dist/solution/BaseSales/types.d.ts +6 -1
  62. package/dist/solution/BaseSales/types.js +1 -1
  63. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
  64. package/dist/solution/BaseSales/utils/cartPromotion.js +50 -97
  65. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  66. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  67. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +14 -1
  68. package/dist/solution/BookingByStep/index.d.ts +1 -1
  69. package/dist/solution/BookingTicket/index.js +61 -26
  70. package/dist/solution/BookingTicket/types.d.ts +2 -0
  71. package/dist/solution/Sales/index.d.ts +1 -0
  72. package/dist/solution/Sales/index.js +10 -2
  73. package/dist/solution/ScanOrder/index.js +20 -31
  74. package/dist/solution/ShopDiscount/index.js +15 -14
  75. package/dist/solution/VenueBooking/index.js +19 -30
  76. package/dist/utils/payment-number.d.ts +9 -0
  77. package/dist/utils/payment-number.js +69 -0
  78. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  79. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  80. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  81. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  82. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  83. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  84. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  85. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  86. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  87. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  88. package/lib/model/strategy/adapter/index.d.ts +4 -0
  89. package/lib/model/strategy/adapter/index.js +13 -2
  90. package/lib/model/strategy/adapter/promotion/adapter.d.ts +0 -4
  91. package/lib/model/strategy/adapter/promotion/adapter.js +0 -20
  92. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +0 -17
  93. package/lib/model/strategy/adapter/promotion/evaluator.js +0 -235
  94. package/lib/model/strategy/adapter/promotion/examples.d.ts +0 -86
  95. package/lib/model/strategy/adapter/promotion/examples.js +0 -91
  96. package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
  97. package/lib/model/strategy/adapter/promotion/index.js +0 -2
  98. package/lib/model/strategy/adapter/promotion/type.d.ts +2 -90
  99. package/lib/model/strategy/adapter/promotion/type.js +0 -2
  100. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +5 -0
  101. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +1 -0
  102. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.d.ts +1 -1
  103. package/lib/modules/BookingContext/utils/cacheItemToBookingInput.js +23 -2
  104. package/lib/modules/Discount/index.d.ts +5 -2
  105. package/lib/modules/Discount/index.js +23 -3
  106. package/lib/modules/Discount/types.d.ts +4 -0
  107. package/lib/modules/Order/index.d.ts +41 -10
  108. package/lib/modules/Order/index.js +505 -119
  109. package/lib/modules/Order/payment-utils.d.ts +26 -0
  110. package/lib/modules/Order/payment-utils.js +224 -0
  111. package/lib/modules/Order/types.d.ts +49 -1
  112. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  113. package/lib/modules/Order/utils/orderCollectionIdentity.js +418 -0
  114. package/lib/modules/Order/utils.d.ts +4 -3
  115. package/lib/modules/Order/utils.js +27 -26
  116. package/lib/modules/Payment/index.d.ts +2 -0
  117. package/lib/modules/Payment/index.js +33 -12
  118. package/lib/modules/Payment/types.d.ts +26 -24
  119. package/lib/modules/Product/types.d.ts +22 -0
  120. package/lib/modules/ProductList/index.d.ts +1 -1
  121. package/lib/modules/ProductList/index.js +4 -2
  122. package/lib/modules/ProductList/types.d.ts +2 -0
  123. package/lib/modules/Rules/index.d.ts +2 -9
  124. package/lib/modules/Rules/index.js +61 -29
  125. package/lib/modules/Rules/types.d.ts +10 -1
  126. package/lib/server/index.d.ts +71 -0
  127. package/lib/server/index.js +1002 -52
  128. package/lib/server/modules/order/index.d.ts +56 -5
  129. package/lib/server/modules/order/index.js +798 -148
  130. package/lib/server/modules/order/types.d.ts +15 -3
  131. package/lib/server/modules/products/index.d.ts +31 -8
  132. package/lib/server/modules/products/index.js +134 -35
  133. package/lib/server/modules/products/types.d.ts +18 -0
  134. package/lib/solution/BaseSales/index.d.ts +54 -4
  135. package/lib/solution/BaseSales/index.js +475 -50
  136. package/lib/solution/BaseSales/types.d.ts +6 -1
  137. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +1 -3
  138. package/lib/solution/BaseSales/utils/cartPromotion.js +25 -64
  139. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +9 -4
  140. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  141. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +8 -0
  142. package/lib/solution/BookingByStep/index.d.ts +1 -1
  143. package/lib/solution/BookingTicket/index.js +35 -9
  144. package/lib/solution/BookingTicket/types.d.ts +2 -0
  145. package/lib/solution/Sales/index.d.ts +1 -0
  146. package/lib/solution/Sales/index.js +5 -3
  147. package/lib/solution/ScanOrder/index.js +0 -8
  148. package/lib/solution/ShopDiscount/index.js +2 -1
  149. package/lib/solution/VenueBooking/index.js +0 -8
  150. package/lib/utils/payment-number.d.ts +9 -0
  151. package/lib/utils/payment-number.js +64 -0
  152. package/package.json +1 -1
@@ -40,6 +40,9 @@ var import_decimal = __toESM(require("decimal.js"));
40
40
  var import_lodash_es = require("lodash-es");
41
41
  var import_types2 = require("../BookingByStep/types");
42
42
  var import_utils = require("../../modules/Order/utils");
43
+ var import_payment_utils = require("../../modules/Order/payment-utils");
44
+ var import_payment_number = require("../../utils/payment-number");
45
+ var import_orderCollectionIdentity = require("../../modules/Order/utils/orderCollectionIdentity");
43
46
  var import_dayjs = __toESM(require("dayjs"));
44
47
  __reExport(BaseSales_exports, require("./types"), module.exports);
45
48
  var import_Quotation = require("../../modules/Quotation");
@@ -79,8 +82,20 @@ function isBaseSalesHistoricalDiscountEntry(discount) {
79
82
  function getBaseSalesUniqueArrayMetadataKey(key) {
80
83
  if (key === "products" || key === "bookings")
81
84
  return "unique_identification_number";
85
+ return null;
86
+ }
87
+ var BASE_SALES_PERSISTENT_ID_FIELD_BY_KIND = {
88
+ product: "order_detail_id",
89
+ booking: "schedule_event_id",
90
+ payment: "order_payment_id"
91
+ };
92
+ function getBaseSalesOrderCollectionKind(key) {
93
+ if (key === "products")
94
+ return "product";
95
+ if (key === "bookings")
96
+ return "booking";
82
97
  if (key === "payments" || key === "payment")
83
- return "unique_payment_number";
98
+ return "payment";
84
99
  return null;
85
100
  }
86
101
  function isSameBaseSalesOrderRecord(left, right) {
@@ -95,6 +110,121 @@ function isSameBaseSalesOrderRecord(left, right) {
95
110
  (value) => value !== void 0 && value !== null && value !== "" && leftIdentities.has(String(value))
96
111
  );
97
112
  }
113
+ function isBaseSalesBlankValue(value) {
114
+ return value === void 0 || value === null || value === "";
115
+ }
116
+ function mergeBaseSalesProductSnapshotFields(currentItem, loadedItem) {
117
+ var _a, _b, _c;
118
+ const mergedItem = (0, import_lodash_es.cloneDeep)(loadedItem);
119
+ if (isBaseSalesBlankValue(mergedItem.product_cover) && !isBaseSalesBlankValue(currentItem == null ? void 0 : currentItem.product_cover)) {
120
+ mergedItem.product_cover = currentItem.product_cover;
121
+ }
122
+ const currentHolderConfig = (_a = currentItem == null ? void 0 : currentItem.metadata) == null ? void 0 : _a.holder_config;
123
+ if ((((_b = mergedItem.metadata) == null ? void 0 : _b.holder_config) === void 0 || ((_c = mergedItem.metadata) == null ? void 0 : _c.holder_config) === null) && currentHolderConfig !== void 0 && currentHolderConfig !== null) {
124
+ mergedItem.metadata = {
125
+ ...mergedItem.metadata || {},
126
+ holder_config: currentHolderConfig
127
+ };
128
+ }
129
+ return mergedItem;
130
+ }
131
+ function mergeBaseSalesCollectionItem(kind, currentItem, incomingItem, uidRemaps) {
132
+ const currentReferenceUid = (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, currentItem);
133
+ const incomingReferenceUid = (0, import_orderCollectionIdentity.getOrderCollectionReferenceUid)(kind, incomingItem);
134
+ const identityMergedItem = (0, import_orderCollectionIdentity.mergeOrderCollectionItems)(
135
+ kind,
136
+ currentItem,
137
+ incomingItem
138
+ );
139
+ const mergedUid = (0, import_orderCollectionIdentity.getOrderCollectionUid)(kind, identityMergedItem);
140
+ if (mergedUid) {
141
+ for (const from of /* @__PURE__ */ new Set([currentReferenceUid, incomingReferenceUid])) {
142
+ if (!from || from === mergedUid)
143
+ continue;
144
+ uidRemaps.push({
145
+ kind,
146
+ from,
147
+ to: mergedUid,
148
+ persistentId: (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, incomingItem) || (0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, currentItem)
149
+ });
150
+ }
151
+ }
152
+ const mergedItem = mergedUid ? (0, import_orderCollectionIdentity.setOrderCollectionUid)(kind, incomingItem, mergedUid) : (0, import_lodash_es.cloneDeep)(incomingItem);
153
+ const persistentIdField = BASE_SALES_PERSISTENT_ID_FIELD_BY_KIND[kind];
154
+ if (isBaseSalesBlankValue(mergedItem[persistentIdField]) && !isBaseSalesBlankValue(identityMergedItem[persistentIdField])) {
155
+ mergedItem[persistentIdField] = identityMergedItem[persistentIdField];
156
+ }
157
+ return kind === "product" ? mergeBaseSalesProductSnapshotFields(currentItem, mergedItem) : mergedItem;
158
+ }
159
+ function mergeBaseSalesOrderCollection(kind, currentValue, incomingValue, strategy, uidRemaps) {
160
+ if (kind === "payment") {
161
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(
162
+ currentValue,
163
+ incomingValue,
164
+ strategy === "preserve-local" ? { preserveUnmatchedExisting: true } : {
165
+ preserveUnmatchedExistingWhen: (payment) => (0, import_payment_utils.isIdentifiedPendingOrderPayment)(payment) || !(0, import_orderCollectionIdentity.getOrderCollectionPersistentId)("payment", payment)
166
+ }
167
+ );
168
+ }
169
+ const currentItems = (0, import_orderCollectionIdentity.normalizeOrderCollection)(kind, currentValue, {
170
+ ensureUid: false
171
+ }).items;
172
+ const incomingItems = (0, import_orderCollectionIdentity.normalizeOrderCollection)(kind, incomingValue, {
173
+ ensureUid: false
174
+ }).items;
175
+ if (strategy === "authoritative-incoming") {
176
+ const result2 = (0, import_lodash_es.cloneDeep)(incomingItems);
177
+ currentItems.forEach((currentItem) => {
178
+ const incomingIndex = result2.findIndex(
179
+ (incomingItem) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem)
180
+ );
181
+ if (incomingIndex !== -1) {
182
+ result2[incomingIndex] = mergeBaseSalesCollectionItem(
183
+ kind,
184
+ currentItem,
185
+ result2[incomingIndex],
186
+ uidRemaps
187
+ );
188
+ return;
189
+ }
190
+ if (!(0, import_orderCollectionIdentity.getOrderCollectionPersistentId)(kind, currentItem)) {
191
+ result2.push((0, import_lodash_es.cloneDeep)(currentItem));
192
+ }
193
+ });
194
+ return result2;
195
+ }
196
+ const result = (0, import_lodash_es.cloneDeep)(currentItems);
197
+ incomingItems.forEach((incomingItem) => {
198
+ const currentIndex = result.findIndex(
199
+ (currentItem) => (0, import_orderCollectionIdentity.isSameOrderCollectionItem)(kind, currentItem, incomingItem)
200
+ );
201
+ if (currentIndex !== -1) {
202
+ result[currentIndex] = mergeBaseSalesCollectionItem(
203
+ kind,
204
+ result[currentIndex],
205
+ incomingItem,
206
+ uidRemaps
207
+ );
208
+ return;
209
+ }
210
+ result.push((0, import_lodash_es.cloneDeep)(incomingItem));
211
+ });
212
+ return result;
213
+ }
214
+ function normalizeBaseSalesRecordCollections(sourceRecord, options) {
215
+ const normalizedRecord = (0, import_orderCollectionIdentity.normalizeOrderCollections)(
216
+ (0, import_lodash_es.cloneDeep)(sourceRecord || {}),
217
+ options
218
+ ).order;
219
+ if (Array.isArray(normalizedRecord.payment)) {
220
+ normalizedRecord.payment = (0, import_orderCollectionIdentity.normalizeOrderCollection)(
221
+ "payment",
222
+ normalizedRecord.payment,
223
+ options
224
+ ).items;
225
+ }
226
+ return normalizedRecord;
227
+ }
98
228
  function getBaseSalesMetadataUid(item, metadataKey) {
99
229
  var _a;
100
230
  const uid = ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a[metadataKey]) ?? (item == null ? void 0 : item[metadataKey]);
@@ -124,14 +254,39 @@ function mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey) {
124
254
  loadedValue.forEach(appendOrReplaceByUid);
125
255
  return result;
126
256
  }
127
- function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord) {
128
- if (!currentTempOrder)
129
- return loadedRecord;
257
+ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord, strategy) {
258
+ const normalizedLoadedRecord = normalizeBaseSalesRecordCollections(
259
+ loadedRecord || {},
260
+ { ensureUid: false }
261
+ );
262
+ if (!currentTempOrder) {
263
+ return normalizeBaseSalesRecordCollections(normalizedLoadedRecord);
264
+ }
265
+ const normalizedCurrentTempOrder = normalizeBaseSalesRecordCollections(
266
+ currentTempOrder,
267
+ { ensureUid: false }
268
+ );
269
+ const uidRemaps = [];
130
270
  const mergedRecord = (0, import_lodash_es.mergeWith)(
131
- (0, import_lodash_es.cloneDeep)(currentTempOrder),
132
- (0, import_lodash_es.cloneDeep)(loadedRecord || {}),
271
+ normalizedCurrentTempOrder,
272
+ normalizedLoadedRecord,
133
273
  (currentValue, loadedValue, key) => {
274
+ const collectionKind = getBaseSalesOrderCollectionKind(key);
275
+ if (collectionKind && Array.isArray(loadedValue)) {
276
+ return mergeBaseSalesOrderCollection(
277
+ collectionKind,
278
+ Array.isArray(currentValue) ? currentValue : [],
279
+ loadedValue,
280
+ strategy,
281
+ uidRemaps
282
+ );
283
+ }
134
284
  if (Array.isArray(currentValue) && Array.isArray(loadedValue)) {
285
+ if (key === "payments" || key === "payment") {
286
+ return (0, import_payment_utils.mergeOrderPaymentListsByIdentity)(currentValue, loadedValue, {
287
+ preserveUnmatchedExisting: true
288
+ });
289
+ }
135
290
  const metadataKey = getBaseSalesUniqueArrayMetadataKey(key);
136
291
  if (metadataKey) {
137
292
  return mergeBaseSalesUniqueArray(currentValue, loadedValue, metadataKey);
@@ -150,7 +305,21 @@ function mergeSalesDetailRecordWithTempOrder(currentTempOrder, loadedRecord) {
150
305
  }
151
306
  );
152
307
  delete mergedRecord.request_unique_idempotency_token;
153
- return mergedRecord;
308
+ return normalizeBaseSalesRecordCollections(
309
+ (0, import_orderCollectionIdentity.applyOrderCollectionUidRemaps)(mergedRecord, uidRemaps)
310
+ );
311
+ }
312
+ function filterPendingPaymentsFromLoadedSalesDetail(sourceRecord) {
313
+ if (!sourceRecord || typeof sourceRecord !== "object")
314
+ return sourceRecord;
315
+ const record = { ...sourceRecord };
316
+ if (Array.isArray(sourceRecord.payments)) {
317
+ record.payments = sourceRecord.payments.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
318
+ }
319
+ if (Array.isArray(sourceRecord.payment)) {
320
+ record.payment = sourceRecord.payment.filter((payment) => !(0, import_payment_utils.isPendingOrderPayment)(payment));
321
+ }
322
+ return record;
154
323
  }
155
324
  var BaseSalesImpl = class extends import_BaseModule.BaseModule {
156
325
  constructor(name, version) {
@@ -172,9 +341,13 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
172
341
  this.queuedAutoPaymentSync = false;
173
342
  this.autoPaymentSyncFlushing = false;
174
343
  this.autoPaymentSyncTimer = null;
175
- this.salesDetailLoadInFlight = false;
344
+ this.salesDetailLoadInFlightCount = 0;
345
+ this.salesDetailLoadSequence = 0;
346
+ this.salesDetailHydrateQueue = Promise.resolve();
176
347
  this.serverOrderChangeUnsubscribe = null;
177
348
  this.serverOrderChangeHydrateInFlight = null;
349
+ this.queuedServerOrderChanges = [];
350
+ this.serverOrderChangeSyncEnabled = false;
178
351
  }
179
352
  /**
180
353
  * 子类可覆盖此方法以追加/收敛要注册的子模块。
@@ -248,19 +421,59 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
248
421
  ].filter(Boolean);
249
422
  return currentRecords.some((record) => isSameBaseSalesOrderRecord(record, order));
250
423
  }
424
+ setServerOrderChangeSyncEnabled(enabled) {
425
+ this.serverOrderChangeSyncEnabled = enabled;
426
+ if (!enabled)
427
+ this.queuedServerOrderChanges = [];
428
+ }
429
+ queueLatestServerOrderChange(order) {
430
+ const snapshot = (0, import_lodash_es.cloneDeep)(order);
431
+ const existingIndex = this.queuedServerOrderChanges.findIndex(
432
+ (queued) => isSameBaseSalesOrderRecord(queued, snapshot)
433
+ );
434
+ if (existingIndex >= 0) {
435
+ this.queuedServerOrderChanges[existingIndex] = snapshot;
436
+ return;
437
+ }
438
+ this.queuedServerOrderChanges.push(snapshot);
439
+ }
440
+ async drainQueuedServerOrderChanges() {
441
+ if (!this.serverOrderChangeSyncEnabled || this.salesDetailLoadInFlightCount > 0 || this.serverOrderChangeHydrateInFlight || this.queuedServerOrderChanges.length === 0)
442
+ return;
443
+ const changedOrders = this.queuedServerOrderChanges;
444
+ this.queuedServerOrderChanges = [];
445
+ await this.syncCurrentSalesDetailFromServerOrderChange({ changedOrders });
446
+ }
251
447
  async syncCurrentSalesDetailFromServerOrderChange(payload) {
252
448
  const changedOrders = Array.isArray(payload) ? payload : Array.isArray(payload == null ? void 0 : payload.changedOrders) ? payload.changedOrders : (payload == null ? void 0 : payload.data) && typeof payload.data === "object" ? [payload.data] : [];
253
- if (this.salesDetailLoadInFlight || this.serverOrderChangeHydrateInFlight)
449
+ if (!this.serverOrderChangeSyncEnabled)
254
450
  return;
451
+ if (this.salesDetailLoadInFlightCount > 0) {
452
+ changedOrders.forEach(
453
+ (order) => this.queueLatestServerOrderChange(order)
454
+ );
455
+ return;
456
+ }
255
457
  const changedOrder = changedOrders.find(
256
458
  (order) => this.isCurrentSalesOrderRecord(order)
257
459
  );
258
460
  if (!changedOrder)
259
461
  return;
462
+ if (this.serverOrderChangeHydrateInFlight) {
463
+ this.queueLatestServerOrderChange(changedOrder);
464
+ return;
465
+ }
260
466
  if (!this.store.order)
261
467
  return;
262
468
  this.serverOrderChangeHydrateInFlight = (async () => {
263
- const sales = await this.store.order.hydrateTempOrderFromRecord(changedOrder, {
469
+ var _a, _b;
470
+ const currentTempOrder = (_b = (_a = this.store.order).getTempOrder) == null ? void 0 : _b.call(_a);
471
+ const record = mergeSalesDetailRecordWithTempOrder(
472
+ currentTempOrder,
473
+ changedOrder,
474
+ "authoritative-incoming"
475
+ );
476
+ const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
264
477
  recalcOnHydrate: false
265
478
  });
266
479
  this.currentSalesDetail = sales;
@@ -270,6 +483,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
270
483
  await this.serverOrderChangeHydrateInFlight;
271
484
  } finally {
272
485
  this.serverOrderChangeHydrateInFlight = null;
486
+ await this.drainQueuedServerOrderChanges();
273
487
  }
274
488
  }
275
489
  registerServerOrderChangeSync() {
@@ -279,13 +493,42 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
279
493
  if (!effects || typeof effects.on !== "function")
280
494
  return;
281
495
  this.serverOrderChangeUnsubscribe = effects.on(SERVER_ORDER_CHANGED_EVENT, (payload) => {
282
- void this.syncCurrentSalesDetailFromServerOrderChange(payload).catch((error) => {
496
+ return this.syncCurrentSalesDetailFromServerOrderChange(payload).catch((error) => {
283
497
  this.logError("sync sales detail from server order change failed", {
284
498
  error: error instanceof Error ? error.message : String(error)
285
499
  });
286
500
  });
287
501
  });
288
502
  }
503
+ async hydrateLatestLoadedSalesDetail(record, loadSequence) {
504
+ let hydratedSales = null;
505
+ let skippedBeforeHydrate = false;
506
+ const hydrateTask = async () => {
507
+ if (loadSequence !== this.salesDetailLoadSequence) {
508
+ skippedBeforeHydrate = true;
509
+ return;
510
+ }
511
+ if (!this.store.order)
512
+ throw new Error("order 模块未初始化");
513
+ const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
514
+ recalcOnHydrate: false
515
+ });
516
+ hydratedSales = sales;
517
+ if (loadSequence !== this.salesDetailLoadSequence)
518
+ return;
519
+ this.currentSalesDetail = sales;
520
+ await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, { sales });
521
+ };
522
+ const queuedTask = this.salesDetailHydrateQueue.then(hydrateTask, hydrateTask);
523
+ this.salesDetailHydrateQueue = queuedTask.then(
524
+ () => void 0,
525
+ () => void 0
526
+ );
527
+ await queuedTask;
528
+ if (skippedBeforeHydrate)
529
+ return record;
530
+ return hydratedSales || this.currentSalesDetail || record;
531
+ }
289
532
  hydrateOrderPaymentNames(payments) {
290
533
  if (!payments.length)
291
534
  return [];
@@ -619,6 +862,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
619
862
  const coreData = (_f = (_d = (_c = app == null ? void 0 : app.models) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core", "core");
620
863
  return coreData == null ? void 0 : coreData[key];
621
864
  }
865
+ getPaymentNumberDevicePrefixSync() {
866
+ if (!this.appPlugin)
867
+ return "LOCAL";
868
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefixFromDeviceId)((key) => this.getAppData(key));
869
+ }
870
+ getPaymentNumberDevicePrefixAsync() {
871
+ if (!this.appPlugin)
872
+ return Promise.resolve("LOCAL");
873
+ return (0, import_payment_number.resolvePaymentNumberDevicePrefix)((key) => this.getAppData(key));
874
+ }
622
875
  syncAppDataToTempOrder(tempOrder) {
623
876
  const isPriceIncludeTax = this.getAppData("is_price_include_tax");
624
877
  const taxCountryCode = this.getAppData("tax_country_code");
@@ -720,6 +973,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
720
973
  }
721
974
  });
722
975
  this.currentSalesDetail = null;
976
+ this.queuedServerOrderChanges = [];
977
+ this.salesDetailLoadSequence += 1;
723
978
  await this.core.effects.emit(`${this.name}:onDestroy`, {});
724
979
  super.destroy();
725
980
  }
@@ -733,7 +988,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
733
988
  async loadSalesDetail(orderIdOrParams) {
734
989
  if (!this.store.order)
735
990
  throw new Error("order 模块未初始化");
736
- this.salesDetailLoadInFlight = true;
991
+ const loadSequence = ++this.salesDetailLoadSequence;
992
+ this.salesDetailLoadInFlightCount += 1;
737
993
  try {
738
994
  const params = typeof orderIdOrParams === "object" ? orderIdOrParams : { orderId: orderIdOrParams };
739
995
  const externalSaleNumber = params.externalSaleNumber || params.external_sale_number;
@@ -750,17 +1006,31 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
750
1006
  const message = loadedRecord && (loadedRecord.message || loadedRecord.msg) || `加载销售详情失败: ${lookup}`;
751
1007
  throw new Error(message);
752
1008
  }
753
- const remoteRecord = preloadedSalesDetail ?? loadedRecord.data;
1009
+ const remoteRecord = filterPendingPaymentsFromLoadedSalesDetail(
1010
+ preloadedSalesDetail ?? loadedRecord.data
1011
+ );
754
1012
  const currentTempOrder = params.merge ? this.store.order.getTempOrder() : null;
755
- const record = params.merge ? mergeSalesDetailRecordWithTempOrder(currentTempOrder, remoteRecord) : remoteRecord;
756
- const sales = await this.store.order.hydrateTempOrderFromRecord(record, {
757
- recalcOnHydrate: false
758
- });
759
- this.currentSalesDetail = sales;
760
- await this.core.effects.emit(`${this.name}:onSalesOrderLoaded`, { sales });
761
- return sales;
1013
+ const mergedRecord = params.merge ? mergeSalesDetailRecordWithTempOrder(
1014
+ currentTempOrder,
1015
+ remoteRecord,
1016
+ "preserve-local"
1017
+ ) : remoteRecord;
1018
+ const record = filterPendingPaymentsFromLoadedSalesDetail(mergedRecord);
1019
+ return await this.hydrateLatestLoadedSalesDetail(record, loadSequence);
762
1020
  } finally {
763
- this.salesDetailLoadInFlight = false;
1021
+ this.salesDetailLoadInFlightCount = Math.max(
1022
+ 0,
1023
+ this.salesDetailLoadInFlightCount - 1
1024
+ );
1025
+ if (this.salesDetailLoadInFlightCount === 0) {
1026
+ try {
1027
+ await this.drainQueuedServerOrderChanges();
1028
+ } catch (error) {
1029
+ this.logError("drain queued server order changes failed", {
1030
+ error: error instanceof Error ? error.message : String(error)
1031
+ });
1032
+ }
1033
+ }
764
1034
  }
765
1035
  }
766
1036
  /** 获取当前已加载的销售详情(只读快照)。未加载过则返回 null。 */
@@ -1094,7 +1364,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1094
1364
  });
1095
1365
  }
1096
1366
  async loadDiscountConfig(params) {
1097
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
1367
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
1098
1368
  if (!this.store.order)
1099
1369
  throw new Error("order 模块未初始化");
1100
1370
  const tempOrder = this.store.order.ensureTempOrder();
@@ -1132,7 +1402,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1132
1402
  if (hasManualDiscountSelection && currentDiscountList.length) {
1133
1403
  return {
1134
1404
  productList: tempOrder.products || [],
1135
- discountList: currentDiscountList
1405
+ discountList: currentDiscountList,
1406
+ availableWalletIds: this.getAvailableWalletIds()
1136
1407
  };
1137
1408
  }
1138
1409
  let nextDiscountList = this.mergeHistoricalDiscountList(
@@ -1161,17 +1432,17 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1161
1432
  });
1162
1433
  return {
1163
1434
  productList: tempOrder.products || [],
1164
- discountList: nextDiscountList
1435
+ discountList: nextDiscountList,
1436
+ availableWalletIds: this.getAvailableWalletIds()
1165
1437
  };
1166
1438
  }
1167
1439
  if (rulesModule) {
1168
- const holders = ((_l = tempOrder.holder) == null ? void 0 : _l.form_record) || [];
1169
- const orderTotalAmount = Number(((_m = orderStore.summary) == null ? void 0 : _m.total_amount) || 0);
1440
+ const orderTotalAmount = Number(((_l = orderStore.summary) == null ? void 0 : _l.total_amount) || 0);
1170
1441
  console.log("[BaseSales.applyDiscountConfig.calcDiscount]");
1171
1442
  const result = rulesModule.calcDiscount({
1172
1443
  productList: tempOrder.products,
1173
1444
  discountList: nextDiscountList,
1174
- holders,
1445
+ holders: [],
1175
1446
  isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
1176
1447
  orderTotalAmount
1177
1448
  }) || { productList: tempOrder.products, discountList: nextDiscountList };
@@ -1182,8 +1453,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1182
1453
  );
1183
1454
  }
1184
1455
  for (const product of tempOrder.products || []) {
1185
- const productUid = (_n = product.metadata) == null ? void 0 : _n.unique_identification_number;
1186
- const runtimeOrigin = productUid ? (_q = (_p = (_o = tempOrder._extend) == null ? void 0 : _o.productsByUid) == null ? void 0 : _p[productUid]) == null ? void 0 : _q.origin : void 0;
1456
+ const productUid = (_m = product.metadata) == null ? void 0 : _m.unique_identification_number;
1457
+ const runtimeOrigin = productUid ? (_p = (_o = (_n = tempOrder._extend) == null ? void 0 : _n.productsByUid) == null ? void 0 : _o[productUid]) == null ? void 0 : _p.origin : void 0;
1187
1458
  if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || isBaseSalesManualProductDiscountProduct(product))
1188
1459
  continue;
1189
1460
  const totalPerUnitDiscount = (product.discount_list || []).reduce(
@@ -1191,7 +1462,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1191
1462
  0
1192
1463
  );
1193
1464
  const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
1194
- const sourcePrice = ((_r = product.metadata) == null ? void 0 : _r.source_product_price) ?? (((_s = product.metadata) == null ? void 0 : _s.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1465
+ const sourcePrice = ((_q = product.metadata) == null ? void 0 : _q.source_product_price) ?? (((_r = product.metadata) == null ? void 0 : _r.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1195
1466
  const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
1196
1467
  const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
1197
1468
  if (product.metadata) {
@@ -1223,11 +1494,18 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1223
1494
  });
1224
1495
  return {
1225
1496
  productList: tempOrder.products || [],
1226
- discountList: nextDiscountList
1497
+ discountList: nextDiscountList,
1498
+ availableWalletIds: this.getAvailableWalletIds()
1227
1499
  };
1228
1500
  }
1501
+ getAvailableWalletIds() {
1502
+ var _a;
1503
+ if (!((_a = this.store.order) == null ? void 0 : _a.getAvailableWalletIds))
1504
+ return [];
1505
+ return this.store.order.getAvailableWalletIds();
1506
+ }
1229
1507
  async bestDiscount(cb) {
1230
- var _a, _b, _c, _d;
1508
+ var _a, _b, _c;
1231
1509
  if (!this.store.order)
1232
1510
  throw new Error("order 模块未初始化");
1233
1511
  const tempOrder = this.store.order.ensureTempOrder();
@@ -1246,13 +1524,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1246
1524
  };
1247
1525
  await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
1248
1526
  if (rulesModule) {
1249
- const holders = ((_c = tempOrder.holder) == null ? void 0 : _c.form_record) || [];
1250
- const orderTotalAmount = Number(((_d = orderStore.summary) == null ? void 0 : _d.total_amount) || 0);
1527
+ const orderTotalAmount = Number(((_c = orderStore.summary) == null ? void 0 : _c.total_amount) || 0);
1251
1528
  console.log("[BaseSales.bestDiscount.calcDiscount]");
1252
1529
  result = rulesModule.calcDiscount({
1253
1530
  productList: tempOrder.products,
1254
1531
  discountList: nextDiscountList,
1255
- holders,
1532
+ holders: [],
1256
1533
  isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
1257
1534
  orderTotalAmount
1258
1535
  }) || result;
@@ -1278,6 +1555,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1278
1555
  }
1279
1556
  await this.store.order.recalculateSummary({ createIfMissing: true });
1280
1557
  this.store.order.persistTempOrder();
1558
+ await this.effectsEmit("onDiscountApplied", {
1559
+ productList: tempOrder.products || [],
1560
+ discountList: nextDiscountList,
1561
+ selectedDiscountList: tempOrder.discount_list || [],
1562
+ tempOrder
1563
+ });
1281
1564
  cb == null ? void 0 : cb(result);
1282
1565
  return result;
1283
1566
  }
@@ -1286,6 +1569,30 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1286
1569
  return [];
1287
1570
  return this.store.order.getDiscountList();
1288
1571
  }
1572
+ /** 读取 Discount 模块原始券列表(未经过 bookingTime 等过滤)。 */
1573
+ getOriginalDiscountList() {
1574
+ var _a, _b;
1575
+ if (!this.store.order)
1576
+ return [];
1577
+ const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
1578
+ return ((_b = discountModule == null ? void 0 : discountModule.getOriginalDiscountList) == null ? void 0 : _b.call(discountModule)) || [];
1579
+ }
1580
+ /**
1581
+ * 同步写入 Discount 模块的 discountList / originalDiscountList。
1582
+ * 供 Holder 补全等场景在 OS store 层更新 machinecode holder 字段。
1583
+ */
1584
+ async replaceDiscountStoreLists(params) {
1585
+ var _a;
1586
+ if (!this.store.order)
1587
+ throw new Error("order 模块未初始化");
1588
+ const discountModule = (_a = this.store.order.store) == null ? void 0 : _a.discount;
1589
+ if (!discountModule)
1590
+ return;
1591
+ if (params.originalDiscountList) {
1592
+ await discountModule.setOriginalDiscountList(params.originalDiscountList);
1593
+ }
1594
+ await discountModule.setDiscountList(params.discountList);
1595
+ }
1289
1596
  async scanPromotionCode(code, customerId) {
1290
1597
  try {
1291
1598
  if (!this.store.order)
@@ -1294,11 +1601,19 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1294
1601
  if (raw.isAvailable) {
1295
1602
  await this.store.order.recalculateSummary({ createIfMissing: true });
1296
1603
  this.store.order.persistTempOrder();
1604
+ const tempOrder = this.store.order.ensureTempOrder();
1605
+ await this.effectsEmit("onDiscountApplied", {
1606
+ productList: tempOrder.products || [],
1607
+ discountList: this.store.order.getDiscountList(),
1608
+ selectedDiscountList: tempOrder.discount_list || [],
1609
+ tempOrder
1610
+ });
1297
1611
  }
1298
1612
  return {
1299
1613
  isAvailable: raw.isAvailable,
1300
1614
  type: raw.type,
1301
- unavailableReason: raw.unavailableReason
1615
+ unavailableReason: raw.unavailableReason,
1616
+ scannedDiscountList: raw.scannedDiscountList
1302
1617
  };
1303
1618
  } catch (error) {
1304
1619
  throw error;
@@ -1306,7 +1621,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1306
1621
  }
1307
1622
  // TODO 需要优化,这段逻辑太长了,里面应该有些历史遗留问题
1308
1623
  async setDiscountSelected(params) {
1309
- var _a, _b, _c, _d, _e, _f, _g, _h;
1624
+ var _a, _b, _c, _d, _e, _f, _g;
1310
1625
  try {
1311
1626
  if (!this.store.order)
1312
1627
  throw new Error("order 模块未初始化");
@@ -1323,17 +1638,16 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1323
1638
  const orderStore = this.store.order.store || {};
1324
1639
  const discountModule = orderStore.discount;
1325
1640
  const rulesModule = orderStore.rules;
1326
- const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record) || [];
1327
1641
  let nextDiscountList = updated;
1328
1642
  await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
1329
1643
  if (rulesModule) {
1330
- const orderTotalAmount = Number(((_b = orderStore.summary) == null ? void 0 : _b.total_amount) || 0);
1644
+ const orderTotalAmount = Number(((_a = orderStore.summary) == null ? void 0 : _a.total_amount) || 0);
1331
1645
  console.log("[BaseSales.setDiscountSelected.calcDiscount]");
1332
1646
  const result = rulesModule.calcDiscount(
1333
1647
  {
1334
1648
  productList: tempOrder.products,
1335
1649
  discountList: updated,
1336
- holders,
1650
+ holders: [],
1337
1651
  isFormSubject: (product) => (0, import_utils.resolveIsFormSubject)(tempOrder, product),
1338
1652
  orderTotalAmount
1339
1653
  },
@@ -1373,8 +1687,8 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1373
1687
  return rid != null && selectedResourceIds.has(rid);
1374
1688
  });
1375
1689
  for (const product of tempOrder.products) {
1376
- const productUid = (_c = product.metadata) == null ? void 0 : _c.unique_identification_number;
1377
- const runtimeOrigin = productUid ? (_f = (_e = (_d = tempOrder._extend) == null ? void 0 : _d.productsByUid) == null ? void 0 : _e[productUid]) == null ? void 0 : _f.origin : void 0;
1690
+ const productUid = (_b = product.metadata) == null ? void 0 : _b.unique_identification_number;
1691
+ const runtimeOrigin = productUid ? (_e = (_d = (_c = tempOrder._extend) == null ? void 0 : _c.productsByUid) == null ? void 0 : _d[productUid]) == null ? void 0 : _e.origin : void 0;
1378
1692
  if ((runtimeOrigin == null ? void 0 : runtimeOrigin.isManualDiscount) || isBaseSalesManualProductDiscountProduct(product))
1379
1693
  continue;
1380
1694
  product.discount_list = filterSelectedDiscountDetails(product.discount_list);
@@ -1398,7 +1712,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1398
1712
  0
1399
1713
  );
1400
1714
  const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(product));
1401
- const sourcePrice = ((_g = product.metadata) == null ? void 0 : _g.source_product_price) ?? (((_h = product.metadata) == null ? void 0 : _h.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1715
+ const sourcePrice = ((_f = product.metadata) == null ? void 0 : _f.source_product_price) ?? (((_g = product.metadata) == null ? void 0 : _g.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
1402
1716
  const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
1403
1717
  const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
1404
1718
  if (product.metadata) {
@@ -1452,6 +1766,12 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1452
1766
  }
1453
1767
  await this.store.order.recalculateSummary({ createIfMissing: true });
1454
1768
  this.store.order.persistTempOrder();
1769
+ await this.effectsEmit("onDiscountApplied", {
1770
+ productList: tempOrder.products || [],
1771
+ discountList: result.discountList || [],
1772
+ selectedDiscountList: tempOrder.discount_list || [],
1773
+ tempOrder
1774
+ });
1455
1775
  } catch (error) {
1456
1776
  throw error;
1457
1777
  }
@@ -1486,6 +1806,20 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1486
1806
  };
1487
1807
  return this.store.order.submitTempOrder(submitParams);
1488
1808
  }
1809
+ async saveSalesOrderDraft(params) {
1810
+ var _a, _b, _c, _d;
1811
+ if (!this.store.order) {
1812
+ throw new Error("BaseSales 解决方案需要 order 模块支持");
1813
+ }
1814
+ return this.store.order.saveTempOrderAsDraft({
1815
+ cacheId: this.cacheId,
1816
+ platform: (params == null ? void 0 : params.platform) ?? ((_a = this.otherParams) == null ? void 0 : _a.platform),
1817
+ businessCode: (params == null ? void 0 : params.businessCode) ?? ((_b = this.otherParams) == null ? void 0 : _b.businessCode) ?? ((_c = this.otherParams) == null ? void 0 : _c.business_code),
1818
+ channel: (params == null ? void 0 : params.channel) ?? this.getSubmitOrderSalesChannel(),
1819
+ type: (params == null ? void 0 : params.type) ?? ((_d = this.otherParams) == null ? void 0 : _d.type),
1820
+ ...(params == null ? void 0 : params.enhancePayload) !== void 0 ? { enhancePayload: params.enhancePayload } : {}
1821
+ });
1822
+ }
1489
1823
  async submitTempOrderAsync(params) {
1490
1824
  var _a, _b, _c, _d;
1491
1825
  if (!this.store.order) {
@@ -1686,8 +2020,26 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1686
2020
  }
1687
2021
  }
1688
2022
  }
1689
- /** 追加单个支付项到当前订单。 */
2023
+ /**
2024
+ * 同步兼容入口。无法等待 IoT 短号时,按调用当下的 device_id 或 LOCAL 生成。
2025
+ */
1690
2026
  addOrderPayment(payment) {
2027
+ const hasPaymentNumber = String(
2028
+ payment.payment_number || ""
2029
+ ).trim() !== "";
2030
+ return this.addOrderPaymentWithDevicePrefix(
2031
+ payment,
2032
+ hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
2033
+ );
2034
+ }
2035
+ /** 创建新支付项时读取最新设备短号,不缓存运行时设备信息。 */
2036
+ async addOrderPaymentAsync(payment) {
2037
+ const paymentRecord = payment;
2038
+ const hasPaymentNumber = String(paymentRecord.payment_number || "").trim() !== "";
2039
+ const devicePrefix = hasPaymentNumber ? "LOCAL" : await this.getPaymentNumberDevicePrefixAsync();
2040
+ return this.addOrderPaymentWithDevicePrefix(payment, devicePrefix);
2041
+ }
2042
+ addOrderPaymentWithDevicePrefix(payment, devicePrefix) {
1691
2043
  var _a;
1692
2044
  if (!this.store.order)
1693
2045
  throw new Error("order 模块未初始化");
@@ -1704,21 +2056,26 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1704
2056
  if (shopWalletPassId !== void 0 && shopWalletPassId !== null) {
1705
2057
  metadata.shop_wallet_pass_id = shopWalletPassId;
1706
2058
  }
1707
- if (!metadata.unique_payment_number) {
1708
- metadata.unique_payment_number = (0, import_utils.createUuidV4)();
1709
- }
2059
+ const normalizedPaymentRecord = (0, import_payment_utils.ensureOrderPaymentNumber)(
2060
+ paymentRecord,
2061
+ devicePrefix,
2062
+ import_utils.createUuidV4
2063
+ );
1710
2064
  const paymentTimestamp = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
1711
2065
  const paymentTime = paymentRecord.payment_time ?? paymentTimestamp;
1712
2066
  const createdAt = paymentRecord.created_at ?? paymentTimestamp;
1713
2067
  const serviceCharge = paymentRecord.service_charge && typeof paymentRecord.service_charge === "object" ? paymentRecord.service_charge : null;
1714
2068
  const calculatedServiceFee = serviceCharge ? new import_decimal.default(paymentRecord.origin_amount ?? paymentRecord.amount ?? 0).times(serviceCharge.percentage || 0).plus(serviceCharge.amount || 0).toDecimalPlaces(2).toFixed(2) : void 0;
1715
2069
  const payments = this.store.order.addOrderPayment({
1716
- ...paymentRecord,
2070
+ ...normalizedPaymentRecord,
1717
2071
  ...calculatedServiceFee !== void 0 ? { service_fee: calculatedServiceFee } : {},
1718
2072
  metadata,
1719
2073
  payment_time: paymentTime,
1720
2074
  created_at: createdAt
1721
2075
  });
2076
+ if (paymentRecord.status === "payment_pending") {
2077
+ return payments;
2078
+ }
1722
2079
  const amountSnapshot = this.store.order.getOrderAmountSnapshot();
1723
2080
  const syncState = this.store.order.getOrderSyncState();
1724
2081
  if (amountSnapshot) {
@@ -1740,10 +2097,73 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1740
2097
  return payments;
1741
2098
  }
1742
2099
  /** 更新当前订单中的指定支付项。 */
1743
- updateOrderPayment(paymentIdentity, updates) {
2100
+ async updateOrderPayment(paymentIdentity, updates, options = {}) {
2101
+ var _a, _b, _c;
1744
2102
  if (!this.store.order)
1745
2103
  throw new Error("order 模块未初始化");
1746
- return this.store.order.updateOrderPayment(paymentIdentity, updates);
2104
+ const matchMode = options.matchBy === "compat" || options.matchBy === "legacy" ? "compat" : "payment_number";
2105
+ const previousMatch = (0, import_payment_utils.resolveOrderPaymentIdentity)(
2106
+ this.store.order.getOrderPayments(),
2107
+ paymentIdentity,
2108
+ matchMode
2109
+ );
2110
+ const previousPayment = previousMatch == null ? void 0 : previousMatch.payment;
2111
+ if ((previousPayment == null ? void 0 : previousPayment.status) === "paid" && !options.applyUpdatesWhenPaid) {
2112
+ const currentPayments = this.store.order.getOrderPayments();
2113
+ let syncResult2;
2114
+ if (options.submitWhenPaid && options.forceSubmitIfPaid) {
2115
+ syncResult2 = await this.syncPaymentsToOrder({
2116
+ payments: currentPayments,
2117
+ paymentStatus: this.getPaymentStatusForSync(currentPayments),
2118
+ submitWhenPaid: true,
2119
+ smallTicketDataFlag: options.smallTicketDataFlag ?? 1
2120
+ });
2121
+ }
2122
+ return {
2123
+ updated: false,
2124
+ payment: previousPayment,
2125
+ payments: currentPayments,
2126
+ summary: ((_a = this.store.order.getOrderAmountSnapshot()) == null ? void 0 : _a.summary) || null,
2127
+ ...syncResult2 !== void 0 ? { syncResult: syncResult2 } : {}
2128
+ };
2129
+ }
2130
+ const result = await this.store.order.updateOrderPayment(paymentIdentity, updates, {
2131
+ matchBy: matchMode
2132
+ });
2133
+ let draftResult;
2134
+ let draftError;
2135
+ if (options.persistDraft !== false) {
2136
+ try {
2137
+ draftResult = await this.saveSalesOrderDraft();
2138
+ } catch (error) {
2139
+ draftError = error;
2140
+ this.logError("updateOrderPayment: 保存支付草稿失败", {
2141
+ paymentIdentity,
2142
+ error: error instanceof Error ? error.message : String(error)
2143
+ });
2144
+ if (!options.submitWhenPaid)
2145
+ throw error;
2146
+ }
2147
+ }
2148
+ const becamePaid = (previousPayment == null ? void 0 : previousPayment.status) !== "paid" && ((_b = result.payment) == null ? void 0 : _b.status) === "paid";
2149
+ const shouldSubmit = Boolean(
2150
+ options.submitWhenPaid && ((_c = result.payment) == null ? void 0 : _c.status) === "paid" && (becamePaid || options.forceSubmitIfPaid)
2151
+ );
2152
+ let syncResult;
2153
+ if (shouldSubmit) {
2154
+ syncResult = await this.syncPaymentsToOrder({
2155
+ payments: result.payments,
2156
+ paymentStatus: this.getPaymentStatusForSync(result.payments),
2157
+ submitWhenPaid: true,
2158
+ smallTicketDataFlag: options.smallTicketDataFlag ?? 1
2159
+ });
2160
+ }
2161
+ return {
2162
+ ...result,
2163
+ ...draftResult !== void 0 ? { draftResult } : {},
2164
+ ...draftError !== void 0 ? { draftError } : {},
2165
+ ...syncResult !== void 0 ? { syncResult } : {}
2166
+ };
1747
2167
  }
1748
2168
  /** 删除当前订单中的指定支付项。 */
1749
2169
  deleteOrderPayment(paymentIdentity) {
@@ -1757,6 +2177,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
1757
2177
  throw new Error("order 模块未初始化");
1758
2178
  return this.store.order.updateVoucherOrderPayments(payments, options);
1759
2179
  }
2180
+ async updateVoucherOrderPaymentsAsync(payments, options) {
2181
+ if (!this.store.order)
2182
+ throw new Error("order 模块未初始化");
2183
+ return this.store.order.updateVoucherOrderPaymentsAsync(payments, options);
2184
+ }
1760
2185
  confirmPendingVoucherPayments() {
1761
2186
  if (!this.store.order)
1762
2187
  throw new Error("order 模块未初始化");