@pisell/pisellos 2.3.27 → 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 (83) 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/modules/Discount/index.d.ts +5 -2
  14. package/dist/modules/Discount/index.js +30 -7
  15. package/dist/modules/Discount/types.d.ts +4 -0
  16. package/dist/modules/Order/index.d.ts +7 -1
  17. package/dist/modules/Order/index.js +187 -74
  18. package/dist/modules/Order/types.d.ts +2 -0
  19. package/dist/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  20. package/dist/modules/Order/utils/orderCollectionIdentity.js +405 -0
  21. package/dist/modules/Order/utils.d.ts +2 -1
  22. package/dist/modules/Order/utils.js +2 -8
  23. package/dist/modules/Product/types.d.ts +22 -0
  24. package/dist/modules/ProductList/index.d.ts +1 -1
  25. package/dist/modules/ProductList/index.js +4 -2
  26. package/dist/modules/ProductList/types.d.ts +2 -0
  27. package/dist/server/index.d.ts +50 -0
  28. package/dist/server/index.js +995 -749
  29. package/dist/server/modules/order/index.d.ts +10 -4
  30. package/dist/server/modules/order/index.js +404 -399
  31. package/dist/server/modules/products/index.d.ts +26 -7
  32. package/dist/server/modules/products/index.js +167 -76
  33. package/dist/server/modules/products/types.d.ts +14 -0
  34. package/dist/solution/BaseSales/index.d.ts +9 -1
  35. package/dist/solution/BaseSales/index.js +998 -756
  36. package/dist/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
  37. package/dist/solution/BaseSales/utils/parseSalesResponse.js +6 -8
  38. package/dist/solution/BookingByStep/index.d.ts +1 -1
  39. package/dist/solution/BookingTicket/index.d.ts +14 -2
  40. package/dist/solution/BookingTicket/types.d.ts +2 -0
  41. package/dist/solution/ShopDiscount/index.js +15 -14
  42. package/lib/model/strategy/adapter/dataVariant/adapter.d.ts +50 -0
  43. package/lib/model/strategy/adapter/dataVariant/adapter.js +149 -0
  44. package/lib/model/strategy/adapter/dataVariant/evaluator.d.ts +89 -0
  45. package/lib/model/strategy/adapter/dataVariant/evaluator.js +583 -0
  46. package/lib/model/strategy/adapter/dataVariant/examples.d.ts +39 -0
  47. package/lib/model/strategy/adapter/dataVariant/examples.js +293 -0
  48. package/lib/model/strategy/adapter/dataVariant/index.d.ts +4 -0
  49. package/lib/model/strategy/adapter/dataVariant/index.js +38 -0
  50. package/lib/model/strategy/adapter/dataVariant/type.d.ts +148 -0
  51. package/lib/model/strategy/adapter/dataVariant/type.js +31 -0
  52. package/lib/model/strategy/adapter/index.d.ts +4 -0
  53. package/lib/model/strategy/adapter/index.js +13 -2
  54. package/lib/modules/Discount/index.d.ts +5 -2
  55. package/lib/modules/Discount/index.js +23 -3
  56. package/lib/modules/Discount/types.d.ts +4 -0
  57. package/lib/modules/Order/index.d.ts +7 -1
  58. package/lib/modules/Order/index.js +104 -6
  59. package/lib/modules/Order/types.d.ts +2 -0
  60. package/lib/modules/Order/utils/orderCollectionIdentity.d.ts +53 -0
  61. package/lib/modules/Order/utils/orderCollectionIdentity.js +415 -0
  62. package/lib/modules/Order/utils.d.ts +2 -1
  63. package/lib/modules/Order/utils.js +4 -11
  64. package/lib/modules/Product/types.d.ts +22 -0
  65. package/lib/modules/ProductList/index.d.ts +1 -1
  66. package/lib/modules/ProductList/index.js +4 -2
  67. package/lib/modules/ProductList/types.d.ts +2 -0
  68. package/lib/server/index.d.ts +50 -0
  69. package/lib/server/index.js +206 -29
  70. package/lib/server/modules/order/index.d.ts +10 -4
  71. package/lib/server/modules/order/index.js +199 -141
  72. package/lib/server/modules/products/index.d.ts +26 -7
  73. package/lib/server/modules/products/index.js +114 -35
  74. package/lib/server/modules/products/types.d.ts +14 -0
  75. package/lib/solution/BaseSales/index.d.ts +9 -1
  76. package/lib/solution/BaseSales/index.js +229 -54
  77. package/lib/solution/BaseSales/utils/parseSalesResponse.d.ts +3 -3
  78. package/lib/solution/BaseSales/utils/parseSalesResponse.js +4 -5
  79. package/lib/solution/BookingByStep/index.d.ts +1 -1
  80. package/lib/solution/BookingTicket/index.d.ts +14 -2
  81. package/lib/solution/BookingTicket/types.d.ts +2 -0
  82. package/lib/solution/ShopDiscount/index.js +2 -1
  83. package/package.json +1 -1
@@ -68,6 +68,10 @@ export interface DiscountWithReason {
68
68
  discountList: Discount[];
69
69
  unavailableReasonKey: DiscountFilterRejectKey | null;
70
70
  }
71
+ export interface DiscountPrepareConfigResult {
72
+ discountList: Discount[];
73
+ availableWalletIds: number[];
74
+ }
71
75
  interface ExtensionData {
72
76
  id: number;
73
77
  shop_id: number;
@@ -75,6 +75,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
75
75
  apply?: boolean;
76
76
  }): Promise<Discount[]>;
77
77
  getDiscountList(): Discount[];
78
+ getAvailableWalletIds(): number[];
78
79
  private syncScannedDiscountsToOriginalDiscountList;
79
80
  private ensureEditDiscountConfigForProductChange;
80
81
  scanCode(code: string, customerId?: number): Promise<{
@@ -467,7 +468,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
467
468
  generateIdempotencyToken(): string;
468
469
  syncPaymentsToOrder<T = any>(params: SyncPaymentsToOrderParams): Promise<SyncPaymentsToOrderResult<T>>;
469
470
  createOrder(params: CommitOrderParams['query']): {
470
- type: "virtual" | "appointment_booking";
471
+ type: "appointment_booking" | "virtual";
471
472
  platform: string;
472
473
  sales_channel: string;
473
474
  order_sales_channel: string;
@@ -524,6 +525,11 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
524
525
  * this.normalizeHydratedBookingHolder({ metadata: { holder: { form_record: [1] } } });
525
526
  */
526
527
  private normalizeHydratedBookingHolder;
528
+ /**
529
+ * 匿名 booking 没有服务端行 ID 时,商品侧已有的 booking_uid 就是唯一可用的强引用。
530
+ * 在统一规范化生成 UUID 前先复用它;已落库 booking 仍按 schedule_event_id 派生稳定 UID。
531
+ */
532
+ private seedAnonymousBookingUidsFromProducts;
527
533
  private normalizeTempOrderForRuntime;
528
534
  private hydrateLinkedBookingIdentity;
529
535
  private pickHydratedDisplayText;
@@ -39,6 +39,7 @@ import { processCartPromotion, appendPromotionTags as _appendPromotionTags, getO
39
39
  import { buildProductLineFingerprint, getProductIdentityIndex, getSafeProductNum, isIdentityMatch, normalizeOrderProduct } from "../../solution/ScanOrder/utils";
40
40
  import { syncManualProductDiscountProductNum } from "./utils/manualProductDiscount";
41
41
  import { expandHydratedProductsForDiscountCollection, restoreHydratedBundleDiscounts } from "./utils/bundleDiscountHydration";
42
+ import { getOrderCollectionPersistentId, getOrderCollectionUid, normalizeOrderCollections, setOrderCollectionUid } from "./utils/orderCollectionIdentity";
42
43
  import { DiscountModule } from "../Discount";
43
44
  import { RulesModule } from "../Rules";
44
45
  import { UnavailableReason } from "../Rules/types";
@@ -295,14 +296,17 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
295
296
  if (!this.store.summary) {
296
297
  this.store.summary = createEmptySummary();
297
298
  }
299
+ if (!Array.isArray(this.store.availableWalletIds)) {
300
+ this.store.availableWalletIds = [];
301
+ }
298
302
  this.request = this.core.getPlugin('request');
299
303
  appPlugin = this.core.getPlugin('app');
300
304
  if (appPlugin) {
301
- _context.next = 8;
305
+ _context.next = 9;
302
306
  break;
303
307
  }
304
308
  throw new Error('Order 模块需要 app 插件支持');
305
- case 8:
309
+ case 9:
306
310
  app = appPlugin.getApp();
307
311
  this.logger = app.logger;
308
312
  this.window = this.core.getPlugin('window');
@@ -315,7 +319,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
315
319
  this.otherParams = otherParams;
316
320
  this.registerDiscountModules(options);
317
321
  this.logInfo('OrderModule initialized successfully');
318
- case 20:
322
+ case 21:
319
323
  case "end":
320
324
  return _context.stop();
321
325
  }
@@ -492,7 +496,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
492
496
  value: function () {
493
497
  var _loadDiscountConfig = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(params) {
494
498
  var _this$store$tempOrder, _this$store$discount, _this$store$tempOrder2;
495
- var orderId, discountList, _this$store$discount2, _this$store$discount3, _this$store$discount4, currentDiscountList, currentEditDiscounts, currentScanDiscounts, currentScanDiscountIds, runtimeDiscountIds, runtimeDiscounts, mergedDiscountList;
499
+ var orderId, prepareConfigResult, discountList, _this$store$discount2, _this$store$discount3, _this$store$discount4, currentDiscountList, currentEditDiscounts, currentScanDiscounts, currentScanDiscountIds, runtimeDiscountIds, runtimeDiscounts, mergedDiscountList;
496
500
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
497
501
  while (1) switch (_context3.prev = _context3.next) {
498
502
  case 0:
@@ -504,14 +508,18 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
504
508
  with_good_pass: 1,
505
509
  with_discount_card: 1,
506
510
  with_wallet_pass_holder: 1,
511
+ with_available_wallet_flag: 1,
512
+ with_available_wallet_pass_flag: 1,
507
513
  request_timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
508
514
  }, orderId ? {
509
515
  order_id: orderId
510
516
  } : {}));
511
517
  case 3:
512
- discountList = _context3.sent;
518
+ prepareConfigResult = _context3.sent;
519
+ discountList = prepareConfigResult === null || prepareConfigResult === void 0 ? void 0 : prepareConfigResult.discountList;
520
+ this.store.availableWalletIds = (prepareConfigResult === null || prepareConfigResult === void 0 ? void 0 : prepareConfigResult.availableWalletIds) || [];
513
521
  if (!discountList) {
514
- _context3.next = 16;
522
+ _context3.next = 18;
515
523
  break;
516
524
  }
517
525
  currentDiscountList = ((_this$store$discount2 = this.store.discount) === null || _this$store$discount2 === void 0 ? void 0 : _this$store$discount2.getDiscountList()) || [];
@@ -532,17 +540,17 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
532
540
  return true;
533
541
  });
534
542
  mergedDiscountList = [].concat(_toConsumableArray(currentEditDiscounts), _toConsumableArray(currentScanDiscounts), _toConsumableArray(runtimeDiscounts));
535
- _context3.next = 14;
536
- return (_this$store$discount3 = this.store.discount) === null || _this$store$discount3 === void 0 ? void 0 : _this$store$discount3.setOriginalDiscountList(mergedDiscountList);
537
- case 14:
538
543
  _context3.next = 16;
539
- return (_this$store$discount4 = this.store.discount) === null || _this$store$discount4 === void 0 ? void 0 : _this$store$discount4.setDiscountList(mergedDiscountList);
544
+ return (_this$store$discount3 = this.store.discount) === null || _this$store$discount3 === void 0 ? void 0 : _this$store$discount3.setOriginalDiscountList(mergedDiscountList);
540
545
  case 16:
546
+ _context3.next = 18;
547
+ return (_this$store$discount4 = this.store.discount) === null || _this$store$discount4 === void 0 ? void 0 : _this$store$discount4.setDiscountList(mergedDiscountList);
548
+ case 18:
541
549
  if (params.apply !== false && (_this$store$tempOrder2 = this.store.tempOrder) !== null && _this$store$tempOrder2 !== void 0 && (_this$store$tempOrder2 = _this$store$tempOrder2.products) !== null && _this$store$tempOrder2 !== void 0 && _this$store$tempOrder2.length) {
542
550
  this.applyDiscount();
543
551
  }
544
552
  return _context3.abrupt("return", this.getDiscountList());
545
- case 18:
553
+ case 20:
546
554
  case "end":
547
555
  return _context3.stop();
548
556
  }
@@ -559,6 +567,11 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
559
567
  var _this$store$discount5;
560
568
  return ((_this$store$discount5 = this.store.discount) === null || _this$store$discount5 === void 0 ? void 0 : _this$store$discount5.getDiscountList()) || [];
561
569
  }
570
+ }, {
571
+ key: "getAvailableWalletIds",
572
+ value: function getAvailableWalletIds() {
573
+ return Array.isArray(this.store.availableWalletIds) ? _toConsumableArray(this.store.availableWalletIds) : [];
574
+ }
562
575
  }, {
563
576
  key: "syncScannedDiscountsToOriginalDiscountList",
564
577
  value: function () {
@@ -3194,6 +3207,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3194
3207
  }
3195
3208
  var nextCustomerId = (_tempOrder$customer_i5 = tempOrder.customer_id) !== null && _tempOrder$customer_i5 !== void 0 ? _tempOrder$customer_i5 : null;
3196
3209
  if (String(previousCustomerId !== null && previousCustomerId !== void 0 ? previousCustomerId : '') !== String(nextCustomerId !== null && nextCustomerId !== void 0 ? nextCustomerId : '')) {
3210
+ this.store.availableWalletIds = [];
3197
3211
  clearTempOrderHolderAssignments(tempOrder);
3198
3212
  this.clearCustomerBoundDiscounts(tempOrder);
3199
3213
  this.applyDiscount();
@@ -3238,6 +3252,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
3238
3252
  tempOrder.email = '';
3239
3253
  tempOrder.customer = null;
3240
3254
  if (tempOrder._extend) delete tempOrder._extend.customerSnapshot;
3255
+ this.store.availableWalletIds = [];
3241
3256
  this.clearCustomerBoundDiscounts(tempOrder);
3242
3257
  this.persistTempOrder();
3243
3258
  this.saveDraftInBackground();
@@ -5483,11 +5498,31 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5483
5498
  value: (function () {
5484
5499
  var _hydrateTempOrderFromRecord = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee40(record, options) {
5485
5500
  var _this$store$discount19;
5486
- var raw, nextTempOrder, rawSummary, summarySurcharges, hydratedEditDiscounts, currentDiscounts, currentScanDiscounts, hydratedDiscountIds, retainedScanDiscounts, nextDiscounts, shouldSkipEmptyDiscountSync, _this$store$discount20, _this$store$discount21;
5501
+ var sourceRaw, identityReadySource, normalizedCollections, raw, hasIdentityChanges, identityLogMetadata, hasIdentityWarnings, nextTempOrder, rawSummary, summarySurcharges, hydratedEditDiscounts, currentDiscounts, currentScanDiscounts, hydratedDiscountIds, retainedScanDiscounts, nextDiscounts, shouldSkipEmptyDiscountSync, _this$store$discount20, _this$store$discount21;
5487
5502
  return _regeneratorRuntime().wrap(function _callee40$(_context43) {
5488
5503
  while (1) switch (_context43.prev = _context43.next) {
5489
5504
  case 0:
5490
- raw = record && _typeof(record) === 'object' && record.data && record.order_id == null ? record.data : record || {};
5505
+ sourceRaw = record && _typeof(record) === 'object' && record.data && record.order_id == null ? record.data : record || {};
5506
+ identityReadySource = this.seedAnonymousBookingUidsFromProducts(sourceRaw);
5507
+ normalizedCollections = normalizeOrderCollections(identityReadySource);
5508
+ raw = normalizedCollections.order;
5509
+ hasIdentityChanges = Object.values(normalizedCollections.stats).some(function (stats) {
5510
+ return stats.backfilledUidCount > 0 || stats.collapsedDuplicateCount > 0 || stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
5511
+ });
5512
+ if (hasIdentityChanges) {
5513
+ identityLogMetadata = {
5514
+ collections: normalizedCollections.stats,
5515
+ uidRemapCount: normalizedCollections.uidRemaps.length
5516
+ };
5517
+ hasIdentityWarnings = Object.values(normalizedCollections.stats).some(function (stats) {
5518
+ return stats.uidConflictCount > 0 || stats.anonymousRowCount > 0;
5519
+ });
5520
+ if (hasIdentityWarnings) {
5521
+ this.logWarning('Normalized hydrated order collection identities', identityLogMetadata);
5522
+ } else {
5523
+ this.logInfo('Normalized hydrated order collection identities', identityLogMetadata);
5524
+ }
5525
+ }
5491
5526
  nextTempOrder = this.normalizeTempOrderForRuntime(raw, {
5492
5527
  makeEditMark: true
5493
5528
  });
@@ -5503,13 +5538,17 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5503
5538
  originalSalesSnapshot: {
5504
5539
  summary: cloneDeep(this.store.summary),
5505
5540
  products: cloneDeep(nextTempOrder.products || []),
5541
+ bookings: cloneDeep(nextTempOrder.bookings || []),
5506
5542
  payments: cloneDeep(nextTempOrder.payments || []),
5507
5543
  surcharges: cloneDeep(nextTempOrder.surcharges || []),
5508
5544
  shop_discount: nextTempOrder.shop_discount || '0.00',
5509
5545
  productFingerprint: this.buildOrderProductsFingerprint(nextTempOrder.products || [])
5510
5546
  }
5511
5547
  });
5512
- this.store.lastOrderInfo = raw.lastOrderInfo || raw;
5548
+ // lastOrderInfo carries the exact backend snapshot used by deposit/type recovery.
5549
+ // Runtime collection repair lives in tempOrder/originalSalesSnapshot and must not
5550
+ // rewrite this protocol snapshot as a side effect of hydration.
5551
+ this.store.lastOrderInfo = sourceRaw.lastOrderInfo || sourceRaw;
5513
5552
  hydratedEditDiscounts = this.collectHydratedEditDiscounts(nextTempOrder.products);
5514
5553
  currentDiscounts = typeof ((_this$store$discount19 = this.store.discount) === null || _this$store$discount19 === void 0 ? void 0 : _this$store$discount19.getDiscountList) === 'function' ? this.store.discount.getDiscountList() || [] : [];
5515
5554
  currentScanDiscounts = currentDiscounts.filter(function (discount) {
@@ -5524,28 +5563,28 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5524
5563
  nextDiscounts = [].concat(_toConsumableArray(hydratedEditDiscounts), _toConsumableArray(retainedScanDiscounts));
5525
5564
  shouldSkipEmptyDiscountSync = nextDiscounts.length === 0 && currentDiscounts.length === 0;
5526
5565
  if (shouldSkipEmptyDiscountSync) {
5527
- _context43.next = 21;
5566
+ _context43.next = 26;
5528
5567
  break;
5529
5568
  }
5530
5569
  OrderModule.populateSavedAmounts(nextTempOrder.products, nextDiscounts);
5531
- _context43.next = 19;
5570
+ _context43.next = 24;
5532
5571
  return (_this$store$discount20 = this.store.discount) === null || _this$store$discount20 === void 0 ? void 0 : _this$store$discount20.setOriginalDiscountList(nextDiscounts);
5533
- case 19:
5534
- _context43.next = 21;
5572
+ case 24:
5573
+ _context43.next = 26;
5535
5574
  return (_this$store$discount21 = this.store.discount) === null || _this$store$discount21 === void 0 ? void 0 : _this$store$discount21.setDiscountList(nextDiscounts);
5536
- case 21:
5575
+ case 26:
5537
5576
  if (!(options !== null && options !== void 0 && options.recalcOnHydrate)) {
5538
- _context43.next = 24;
5577
+ _context43.next = 29;
5539
5578
  break;
5540
5579
  }
5541
- _context43.next = 24;
5580
+ _context43.next = 29;
5542
5581
  return this.recalculateSummary({
5543
5582
  createIfMissing: false
5544
5583
  });
5545
- case 24:
5584
+ case 29:
5546
5585
  this.persistTempOrder();
5547
5586
  return _context43.abrupt("return", nextTempOrder);
5548
- case 26:
5587
+ case 31:
5549
5588
  case "end":
5550
5589
  return _context43.stop();
5551
5590
  }
@@ -5589,6 +5628,79 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5589
5628
  }
5590
5629
  return next;
5591
5630
  }
5631
+
5632
+ /**
5633
+ * 匿名 booking 没有服务端行 ID 时,商品侧已有的 booking_uid 就是唯一可用的强引用。
5634
+ * 在统一规范化生成 UUID 前先复用它;已落库 booking 仍按 schedule_event_id 派生稳定 UID。
5635
+ */
5636
+ }, {
5637
+ key: "seedAnonymousBookingUidsFromProducts",
5638
+ value: function seedAnonymousBookingUidsFromProducts(raw) {
5639
+ if (!raw || _typeof(raw) !== 'object') return {};
5640
+ if (!Array.isArray(raw.bookings) || !Array.isArray(raw.products)) return raw;
5641
+ var bookingUidsByProductUid = new Map();
5642
+ var _iterator22 = _createForOfIteratorHelper(raw.products),
5643
+ _step22;
5644
+ try {
5645
+ for (_iterator22.s(); !(_step22 = _iterator22.n()).done;) {
5646
+ var _product$metadata10;
5647
+ var product = _step22.value;
5648
+ var productUid = getOrderCollectionUid('product', product);
5649
+ var bookingUid = (product === null || product === void 0 ? void 0 : product.booking_uid) || (product === null || product === void 0 || (_product$metadata10 = product.metadata) === null || _product$metadata10 === void 0 ? void 0 : _product$metadata10.booking_uid);
5650
+ if (!productUid || bookingUid === undefined || bookingUid === null || bookingUid === '') {
5651
+ continue;
5652
+ }
5653
+ var candidates = bookingUidsByProductUid.get(productUid) || new Set();
5654
+ candidates.add(String(bookingUid));
5655
+ bookingUidsByProductUid.set(productUid, candidates);
5656
+ }
5657
+ } catch (err) {
5658
+ _iterator22.e(err);
5659
+ } finally {
5660
+ _iterator22.f();
5661
+ }
5662
+ if (bookingUidsByProductUid.size === 0) return raw;
5663
+ var anonymousBookingCountByProductUid = new Map();
5664
+ var _iterator23 = _createForOfIteratorHelper(raw.bookings),
5665
+ _step23;
5666
+ try {
5667
+ for (_iterator23.s(); !(_step23 = _iterator23.n()).done;) {
5668
+ var _booking$metadata7;
5669
+ var booking = _step23.value;
5670
+ if (getOrderCollectionPersistentId('booking', booking) || getOrderCollectionUid('booking', booking)) {
5671
+ continue;
5672
+ }
5673
+ var _productUid = (booking === null || booking === void 0 ? void 0 : booking.product_uid) || (booking === null || booking === void 0 || (_booking$metadata7 = booking.metadata) === null || _booking$metadata7 === void 0 ? void 0 : _booking$metadata7.product_uid);
5674
+ if (_productUid === undefined || _productUid === null || _productUid === '') continue;
5675
+ var key = String(_productUid);
5676
+ anonymousBookingCountByProductUid.set(key, (anonymousBookingCountByProductUid.get(key) || 0) + 1);
5677
+ }
5678
+ } catch (err) {
5679
+ _iterator23.e(err);
5680
+ } finally {
5681
+ _iterator23.f();
5682
+ }
5683
+ return _objectSpread(_objectSpread({}, raw), {}, {
5684
+ bookings: raw.bookings.map(function (booking) {
5685
+ var _booking$metadata6;
5686
+ if (getOrderCollectionPersistentId('booking', booking) || getOrderCollectionUid('booking', booking)) {
5687
+ return booking;
5688
+ }
5689
+ var productUid = (booking === null || booking === void 0 ? void 0 : booking.product_uid) || (booking === null || booking === void 0 || (_booking$metadata6 = booking.metadata) === null || _booking$metadata6 === void 0 ? void 0 : _booking$metadata6.product_uid);
5690
+ if (productUid === undefined || productUid === null || productUid === '') {
5691
+ return booking;
5692
+ }
5693
+ var productUidKey = String(productUid);
5694
+ // 多条匿名 booking 共用同一商品引用时身份仍然不明确,不能借商品字段猜测合并。
5695
+ if (anonymousBookingCountByProductUid.get(productUidKey) !== 1) {
5696
+ return booking;
5697
+ }
5698
+ var bookingUidCandidates = bookingUidsByProductUid.get(productUidKey);
5699
+ var bookingUid = (bookingUidCandidates === null || bookingUidCandidates === void 0 ? void 0 : bookingUidCandidates.size) === 1 ? _toConsumableArray(bookingUidCandidates)[0] : null;
5700
+ return bookingUid ? setOrderCollectionUid('booking', booking, bookingUid) : booking;
5701
+ })
5702
+ });
5703
+ }
5592
5704
  }, {
5593
5705
  key: "normalizeTempOrderForRuntime",
5594
5706
  value: function normalizeTempOrderForRuntime(raw, options) {
@@ -5646,15 +5758,15 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5646
5758
  };
5647
5759
  var tempOrderExtend = nextTempOrder._extend;
5648
5760
  var productsByUid = tempOrderExtend.productsByUid || {};
5649
- var _iterator22 = _createForOfIteratorHelper(nextTempOrder.products.entries()),
5650
- _step22;
5761
+ var _iterator24 = _createForOfIteratorHelper(nextTempOrder.products.entries()),
5762
+ _step24;
5651
5763
  try {
5652
- for (_iterator22.s(); !(_step22 = _iterator22.n()).done;) {
5653
- var _product$metadata10, _ref74, _ref75, _existed$origin, _rawProduct$metadata;
5654
- var _step22$value = _slicedToArray(_step22.value, 2),
5655
- index = _step22$value[0],
5656
- product = _step22$value[1];
5657
- var uid = (_product$metadata10 = product.metadata) === null || _product$metadata10 === void 0 ? void 0 : _product$metadata10.unique_identification_number;
5764
+ for (_iterator24.s(); !(_step24 = _iterator24.n()).done;) {
5765
+ var _product$metadata11, _ref74, _ref75, _existed$origin, _rawProduct$metadata;
5766
+ var _step24$value = _slicedToArray(_step24.value, 2),
5767
+ index = _step24$value[0],
5768
+ product = _step24$value[1];
5769
+ var uid = (_product$metadata11 = product.metadata) === null || _product$metadata11 === void 0 ? void 0 : _product$metadata11.unique_identification_number;
5658
5770
  if (!uid) continue;
5659
5771
  var existed = productsByUid[uid] && _typeof(productsByUid[uid]) === 'object' ? productsByUid[uid] : {};
5660
5772
  var rawProduct = rawProducts[index] && _typeof(rawProducts[index]) === 'object' ? rawProducts[index] : product;
@@ -5674,9 +5786,9 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5674
5786
  });
5675
5787
  }
5676
5788
  } catch (err) {
5677
- _iterator22.e(err);
5789
+ _iterator24.e(err);
5678
5790
  } finally {
5679
- _iterator22.f();
5791
+ _iterator24.f();
5680
5792
  }
5681
5793
  tempOrderExtend.productsByUid = productsByUid;
5682
5794
  this.hydrateLinkedBookingIdentity(nextTempOrder);
@@ -5692,8 +5804,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5692
5804
  var bookingUidByProductUid = new Map();
5693
5805
  var productByUid = new Map();
5694
5806
  (tempOrder.products || []).forEach(function (product) {
5695
- var _product$metadata11;
5696
- var productUid = (product === null || product === void 0 || (_product$metadata11 = product.metadata) === null || _product$metadata11 === void 0 ? void 0 : _product$metadata11.unique_identification_number) || (product === null || product === void 0 ? void 0 : product.unique_identification_number);
5807
+ var _product$metadata12;
5808
+ var productUid = (product === null || product === void 0 || (_product$metadata12 = product.metadata) === null || _product$metadata12 === void 0 ? void 0 : _product$metadata12.unique_identification_number) || (product === null || product === void 0 ? void 0 : product.unique_identification_number);
5697
5809
  if (productUid !== undefined && productUid !== null && String(productUid) !== '') {
5698
5810
  productByUid.set(String(productUid), product);
5699
5811
  }
@@ -5714,15 +5826,16 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5714
5826
  bookingUidByProductUid.set(String(productUid), bookingUid);
5715
5827
  });
5716
5828
  (tempOrder.products || []).forEach(function (product) {
5717
- var _product$metadata12;
5718
- var productUid = (product === null || product === void 0 || (_product$metadata12 = product.metadata) === null || _product$metadata12 === void 0 ? void 0 : _product$metadata12.unique_identification_number) || (product === null || product === void 0 ? void 0 : product.unique_identification_number);
5829
+ var _product$metadata13;
5830
+ var productUid = (product === null || product === void 0 || (_product$metadata13 = product.metadata) === null || _product$metadata13 === void 0 ? void 0 : _product$metadata13.unique_identification_number) || (product === null || product === void 0 ? void 0 : product.unique_identification_number);
5719
5831
  if (productUid === undefined || productUid === null || String(productUid) === '') return;
5720
5832
  var bookingUid = bookingUidByProductUid.get(String(productUid));
5721
5833
  if (!bookingUid) return;
5722
5834
  if (!product.metadata || _typeof(product.metadata) !== 'object') {
5723
5835
  product.metadata = {};
5724
5836
  }
5725
- var linkedBookingUid = String(product.booking_uid || product.metadata.booking_uid || bookingUid);
5837
+ // booking 已经过统一身份规范化;以它为准同步商品侧旧引用,避免两侧 UID 断链。
5838
+ var linkedBookingUid = String(bookingUid);
5726
5839
  product.booking_uid = linkedBookingUid;
5727
5840
  product.metadata.booking_uid = linkedBookingUid;
5728
5841
  });
@@ -5750,18 +5863,18 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5750
5863
  var segments = [];
5751
5864
  var sku = (product === null || product === void 0 ? void 0 : product.product_sku) || {};
5752
5865
  if (Array.isArray(sku.variant)) {
5753
- var _iterator23 = _createForOfIteratorHelper(sku.variant),
5754
- _step23;
5866
+ var _iterator25 = _createForOfIteratorHelper(sku.variant),
5867
+ _step25;
5755
5868
  try {
5756
- for (_iterator23.s(); !(_step23 = _iterator23.n()).done;) {
5757
- var variant = _step23.value;
5869
+ for (_iterator25.s(); !(_step25 = _iterator25.n()).done;) {
5870
+ var variant = _step25.value;
5758
5871
  var segment = this.formatHydratedNamePair(variant === null || variant === void 0 ? void 0 : variant.group, variant === null || variant === void 0 ? void 0 : variant.item);
5759
5872
  if (segment) segments.push(segment);
5760
5873
  }
5761
5874
  } catch (err) {
5762
- _iterator23.e(err);
5875
+ _iterator25.e(err);
5763
5876
  } finally {
5764
- _iterator23.f();
5877
+ _iterator25.f();
5765
5878
  }
5766
5879
  }
5767
5880
  return segments.join(', ');
@@ -5890,70 +6003,70 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5890
6003
  addDiscountAmount(savedMap, discountKey, amount);
5891
6004
  addDiscountAmount(isPersistedProduct || discount.order_discount_id != null ? editModeSavedMap : runtimeSavedMap, discountKey, amount);
5892
6005
  };
5893
- var _iterator24 = _createForOfIteratorHelper(productList),
5894
- _step24;
6006
+ var _iterator26 = _createForOfIteratorHelper(productList),
6007
+ _step26;
5895
6008
  try {
5896
- for (_iterator24.s(); !(_step24 = _iterator24.n()).done;) {
5897
- var product = _step24.value;
6009
+ for (_iterator26.s(); !(_step26 = _iterator26.n()).done;) {
6010
+ var product = _step26.value;
5898
6011
  var qty = product.num || 1;
5899
6012
  var isPersistedProduct = Boolean(product.order_detail_id || product.orderDetailId || product.booking_id);
5900
- var _iterator26 = _createForOfIteratorHelper(product.discount_list || []),
5901
- _step26;
6013
+ var _iterator28 = _createForOfIteratorHelper(product.discount_list || []),
6014
+ _step28;
5902
6015
  try {
5903
- for (_iterator26.s(); !(_step26 = _iterator26.n()).done;) {
5904
- var pd = _step26.value;
6016
+ for (_iterator28.s(); !(_step28 = _iterator28.n()).done;) {
6017
+ var pd = _step28.value;
5905
6018
  addProductDiscountAmount(pd, qty, isPersistedProduct);
5906
6019
  }
5907
6020
  } catch (err) {
5908
- _iterator26.e(err);
6021
+ _iterator28.e(err);
5909
6022
  } finally {
5910
- _iterator26.f();
6023
+ _iterator28.f();
5911
6024
  }
5912
- var _iterator27 = _createForOfIteratorHelper(product.product_bundle || []),
5913
- _step27;
6025
+ var _iterator29 = _createForOfIteratorHelper(product.product_bundle || []),
6026
+ _step29;
5914
6027
  try {
5915
- for (_iterator27.s(); !(_step27 = _iterator27.n()).done;) {
6028
+ for (_iterator29.s(); !(_step29 = _iterator29.n()).done;) {
5916
6029
  var _ref78, _bundle$num3;
5917
- var bundle = _step27.value;
6030
+ var bundle = _step29.value;
5918
6031
  var isPersistedBundleProduct = isPersistedProduct || Boolean((bundle === null || bundle === void 0 ? void 0 : bundle.order_detail_id) || (bundle === null || bundle === void 0 ? void 0 : bundle.orderDetailId) || (bundle === null || bundle === void 0 ? void 0 : bundle.booking_id));
5919
6032
  var bundleQty = new Decimal(Number(qty) || 1).times(Number((_ref78 = (_bundle$num3 = bundle === null || bundle === void 0 ? void 0 : bundle.num) !== null && _bundle$num3 !== void 0 ? _bundle$num3 : bundle === null || bundle === void 0 ? void 0 : bundle.quantity) !== null && _ref78 !== void 0 ? _ref78 : 1) || 1).toNumber();
5920
- var _iterator28 = _createForOfIteratorHelper((bundle === null || bundle === void 0 ? void 0 : bundle.discount_list) || []),
5921
- _step28;
6033
+ var _iterator30 = _createForOfIteratorHelper((bundle === null || bundle === void 0 ? void 0 : bundle.discount_list) || []),
6034
+ _step30;
5922
6035
  try {
5923
- for (_iterator28.s(); !(_step28 = _iterator28.n()).done;) {
5924
- var _pd = _step28.value;
6036
+ for (_iterator30.s(); !(_step30 = _iterator30.n()).done;) {
6037
+ var _pd = _step30.value;
5925
6038
  addProductDiscountAmount(_pd, bundleQty, isPersistedBundleProduct);
5926
6039
  }
5927
6040
  } catch (err) {
5928
- _iterator28.e(err);
6041
+ _iterator30.e(err);
5929
6042
  } finally {
5930
- _iterator28.f();
6043
+ _iterator30.f();
5931
6044
  }
5932
6045
  }
5933
6046
  } catch (err) {
5934
- _iterator27.e(err);
6047
+ _iterator29.e(err);
5935
6048
  } finally {
5936
- _iterator27.f();
6049
+ _iterator29.f();
5937
6050
  }
5938
6051
  }
5939
6052
  } catch (err) {
5940
- _iterator24.e(err);
6053
+ _iterator26.e(err);
5941
6054
  } finally {
5942
- _iterator24.f();
6055
+ _iterator26.f();
5943
6056
  }
5944
- var _iterator25 = _createForOfIteratorHelper(discountList),
5945
- _step25;
6057
+ var _iterator27 = _createForOfIteratorHelper(discountList),
6058
+ _step27;
5946
6059
  try {
5947
- for (_iterator25.s(); !(_step25 = _iterator25.n()).done;) {
5948
- var d = _step25.value;
6060
+ for (_iterator27.s(); !(_step27 = _iterator27.n()).done;) {
6061
+ var d = _step27.value;
5949
6062
  var key = d.id;
5950
6063
  var sourceMap = d.isEditMode ? editModeSavedMap : editModeDiscountKeys.has(key) ? runtimeSavedMap : savedMap;
5951
6064
  d.savedAmount = d.isSelected && key != null && sourceMap.has(key) ? sourceMap.get(key).toNumber() : 0;
5952
6065
  }
5953
6066
  } catch (err) {
5954
- _iterator25.e(err);
6067
+ _iterator27.e(err);
5955
6068
  } finally {
5956
- _iterator25.f();
6069
+ _iterator27.f();
5957
6070
  }
5958
6071
  }
5959
6072
  }]);
@@ -309,6 +309,7 @@ export interface OrderState {
309
309
  lastOrderInfo?: Record<string, any>;
310
310
  syncState?: OrderSyncState;
311
311
  discountList: any[];
312
+ availableWalletIds?: number[];
312
313
  discount: DiscountModule | null;
313
314
  rules: RulesModule | null;
314
315
  }
@@ -775,6 +776,7 @@ export interface OrderModuleAPI {
775
776
  apply?: boolean;
776
777
  }) => Promise<Discount[]>;
777
778
  getDiscountList: () => Discount[];
779
+ getAvailableWalletIds: () => number[];
778
780
  applyDiscount: () => void;
779
781
  /**
780
782
  * 注入促销评估器。
@@ -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>;