@pisell/pisellos 0.10.7 → 0.10.8

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 (57) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +12 -10
  3. package/dist/modules/Order/index.d.ts +12 -5
  4. package/dist/modules/Order/index.js +310 -210
  5. package/dist/modules/Order/types.d.ts +26 -3
  6. package/dist/modules/Order/types.js +11 -0
  7. package/dist/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
  8. package/dist/modules/Order/utils/discountProductLineIdentity.js +227 -0
  9. package/dist/modules/Rules/index.js +125 -52
  10. package/dist/modules/SalesSummary/utils.js +7 -1
  11. package/dist/server/index.d.ts +6 -0
  12. package/dist/server/index.js +810 -729
  13. package/dist/server/modules/order/index.d.ts +1 -0
  14. package/dist/server/modules/order/index.js +9 -2
  15. package/dist/server/modules/order/types.d.ts +1 -1
  16. package/dist/solution/BaseSales/index.d.ts +15 -5
  17. package/dist/solution/BaseSales/index.js +211 -159
  18. package/dist/solution/BaseSales/utils/cartPromotion.js +26 -3
  19. package/dist/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +1 -1
  20. package/dist/solution/BaseSales/utils.js +31 -20
  21. package/dist/solution/BookingByStep/index.d.ts +1 -1
  22. package/dist/solution/BookingTicket/index.js +1 -4
  23. package/dist/solution/BookingTicket/types.d.ts +3 -0
  24. package/dist/solution/BookingTicket/utils/cartView.js +44 -32
  25. package/dist/solution/Sales/index.d.ts +1 -0
  26. package/dist/solution/Sales/index.js +16 -2
  27. package/dist/solution/ScanOrder/utils.js +31 -20
  28. package/dist/solution/UnifiedBookingSales/index.d.ts +5 -4
  29. package/dist/solution/UnifiedBookingSales/index.js +51 -39
  30. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +3 -1
  31. package/lib/modules/Order/index.d.ts +12 -5
  32. package/lib/modules/Order/index.js +148 -43
  33. package/lib/modules/Order/types.d.ts +26 -3
  34. package/lib/modules/Order/utils/discountProductLineIdentity.d.ts +45 -0
  35. package/lib/modules/Order/utils/discountProductLineIdentity.js +170 -0
  36. package/lib/modules/Rules/index.js +100 -20
  37. package/lib/modules/SalesSummary/utils.js +5 -1
  38. package/lib/server/index.d.ts +6 -0
  39. package/lib/server/index.js +51 -0
  40. package/lib/server/modules/order/index.d.ts +1 -0
  41. package/lib/server/modules/order/index.js +9 -3
  42. package/lib/server/modules/order/types.d.ts +1 -1
  43. package/lib/solution/BaseSales/index.d.ts +15 -5
  44. package/lib/solution/BaseSales/index.js +64 -16
  45. package/lib/solution/BaseSales/utils/cartPromotion.js +26 -2
  46. package/lib/solution/BaseSales/utils/transformBaseProductToOrderProduct.js +1 -1
  47. package/lib/solution/BaseSales/utils.js +29 -18
  48. package/lib/solution/BookingByStep/index.d.ts +1 -1
  49. package/lib/solution/BookingTicket/index.js +1 -4
  50. package/lib/solution/BookingTicket/types.d.ts +3 -0
  51. package/lib/solution/BookingTicket/utils/cartView.js +43 -30
  52. package/lib/solution/Sales/index.d.ts +1 -0
  53. package/lib/solution/Sales/index.js +15 -3
  54. package/lib/solution/ScanOrder/utils.js +29 -18
  55. package/lib/solution/UnifiedBookingSales/index.d.ts +5 -4
  56. package/lib/solution/UnifiedBookingSales/index.js +35 -26
  57. package/package.json +1 -1
@@ -466,13 +466,36 @@ function getProductLineNoteSignature(product) {
466
466
  var uid = getOrderProductUid(product);
467
467
  return uid ? "note:".concat(uid) : "note:".concat(normalizedNote);
468
468
  }
469
+ function hasGoodPassDiscount(product) {
470
+ var _product$_extend;
471
+ var productBundle = Array.isArray(product === null || product === void 0 ? void 0 : product.product_bundle) ? product.product_bundle : [];
472
+ var extendedBundle = Array.isArray(product === null || product === void 0 || (_product$_extend = product._extend) === null || _product$_extend === void 0 || (_product$_extend = _product$_extend.other) === null || _product$_extend === void 0 ? void 0 : _product$_extend.bundle) ? product._extend.other.bundle : [];
473
+ var discountLists = [product === null || product === void 0 ? void 0 : product.discount_list].concat(_toConsumableArray(productBundle.map(function (item) {
474
+ return item === null || item === void 0 ? void 0 : item.discount_list;
475
+ })), _toConsumableArray(extendedBundle.map(function (item) {
476
+ return item === null || item === void 0 ? void 0 : item.discount_list;
477
+ })));
478
+ return discountLists.some(function (discountList) {
479
+ return Array.isArray(discountList) && discountList.some(function (item) {
480
+ return (item === null || item === void 0 ? void 0 : item.type) === 'good_pass' || (item === null || item === void 0 ? void 0 : item.tag) === 'good_pass';
481
+ });
482
+ });
483
+ }
469
484
 
470
485
  /**
471
- * 编辑订单时,历史行仍参与整车促销评估,但不能与本次新增行合并。
472
- * 以历史行 uid 作为促销前后的行边界;新增行返回空边界,仍保留原有合并语义。
486
+ * 商品券、自定义商品、称重行以及编辑订单历史行都有各自的促销合并边界。
473
487
  */
474
488
  function getPromotionLineMergeBoundary(product) {
475
- var _product$metadata3;
489
+ var _product$product_sku, _product$metadata3;
490
+ if ((product === null || product === void 0 ? void 0 : product.product_id) === undefined || (product === null || product === void 0 ? void 0 : product.product_id) === null) {
491
+ return "custom:".concat(getOrderProductUid(product));
492
+ }
493
+ if (hasGoodPassDiscount(product)) {
494
+ return "good-pass:".concat(getOrderProductUid(product));
495
+ }
496
+ if (Number((product === null || product === void 0 || (_product$product_sku = product.product_sku) === null || _product$product_sku === void 0 ? void 0 : _product$product_sku.open_sold_weight) || 0) === 1) {
497
+ return "weighing:".concat(getOrderProductUid(product));
498
+ }
476
499
  if ((product === null || product === void 0 || (_product$metadata3 = product.metadata) === null || _product$metadata3 === void 0 ? void 0 : _product$metadata3.is_edit_for_runtime) !== true) return '';
477
500
  return "edit:".concat(getOrderProductUid(product));
478
501
  }
@@ -193,7 +193,7 @@ export function transformBaseProductToOrderProduct(params) {
193
193
  }
194
194
  // 从源头补充商品多语言标题
195
195
  var productTitle = _objectSpread(_objectSpread({}, (sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.title_i18n) || {}), {}, {
196
- original: (sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.title) || ''
196
+ original: (sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.original_title) || (sourceProduct === null || sourceProduct === void 0 ? void 0 : sourceProduct.title) || ''
197
197
  });
198
198
  return {
199
199
  product_id: productId,
@@ -37,35 +37,46 @@ export function createEmptySummary() {
37
37
  * 数组元素先按主键排序再序列化,避免顺序差异导致误判为不同行。
38
38
  */
39
39
  export function buildProductLineFingerprint(productOptionItem, productBundle) {
40
- var optArr = Array.isArray(productOptionItem) ? productOptionItem : [];
41
- var normalizedOpts = optArr.map(function (item) {
42
- var _ref, _item$add_price;
43
- return {
44
- option_group_item_id: Number(item === null || item === void 0 ? void 0 : item.option_group_item_id) || 0,
45
- option_group_id: Number(item === null || item === void 0 ? void 0 : item.option_group_id) || 0,
46
- num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
47
- price: String((_ref = (_item$add_price = item === null || item === void 0 ? void 0 : item.add_price) !== null && _item$add_price !== void 0 ? _item$add_price : item === null || item === void 0 ? void 0 : item.price) !== null && _ref !== void 0 ? _ref : '')
48
- };
49
- }).sort(function (p, q) {
50
- if (p.option_group_item_id !== q.option_group_item_id) {
51
- return p.option_group_item_id - q.option_group_item_id;
52
- }
53
- if (p.option_group_id !== q.option_group_id) return p.option_group_id - q.option_group_id;
54
- if (p.num !== q.num) return p.num - q.num;
55
- return p.price.localeCompare(q.price);
56
- });
40
+ var normalizeOptions = function normalizeOptions(options) {
41
+ var optionArr = Array.isArray(options) ? options : [];
42
+ return optionArr.map(function (item) {
43
+ var _ref, _item$add_price;
44
+ return {
45
+ option_group_item_id: Number(item === null || item === void 0 ? void 0 : item.option_group_item_id) || 0,
46
+ option_group_id: Number(item === null || item === void 0 ? void 0 : item.option_group_id) || 0,
47
+ num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
48
+ price: String((_ref = (_item$add_price = item === null || item === void 0 ? void 0 : item.add_price) !== null && _item$add_price !== void 0 ? _item$add_price : item === null || item === void 0 ? void 0 : item.price) !== null && _ref !== void 0 ? _ref : '')
49
+ };
50
+ }).sort(function (p, q) {
51
+ if (p.option_group_item_id !== q.option_group_item_id) {
52
+ return p.option_group_item_id - q.option_group_item_id;
53
+ }
54
+ if (p.option_group_id !== q.option_group_id) {
55
+ return p.option_group_id - q.option_group_id;
56
+ }
57
+ if (p.num !== q.num) return p.num - q.num;
58
+ return p.price.localeCompare(q.price);
59
+ });
60
+ };
61
+ var normalizedOpts = normalizeOptions(productOptionItem);
57
62
  var bundleArr = Array.isArray(productBundle) ? productBundle : [];
58
63
  var normalizedBundles = bundleArr.map(function (item) {
59
- var _ref2, _item$bundle_id;
64
+ var _ref2, _item$bundle_id, _item$bundle_variant_;
60
65
  return {
61
66
  bundle_id: Number((_ref2 = (_item$bundle_id = item === null || item === void 0 ? void 0 : item.bundle_id) !== null && _item$bundle_id !== void 0 ? _item$bundle_id : item === null || item === void 0 ? void 0 : item.id) !== null && _ref2 !== void 0 ? _ref2 : 0) || 0,
62
67
  product_id: Number(item === null || item === void 0 ? void 0 : item.product_id) || 0,
63
- num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1
68
+ product_variant_id: Number((_item$bundle_variant_ = item === null || item === void 0 ? void 0 : item.bundle_variant_id) !== null && _item$bundle_variant_ !== void 0 ? _item$bundle_variant_ : item === null || item === void 0 ? void 0 : item.product_variant_id) || 0,
69
+ num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
70
+ option: normalizeOptions(item === null || item === void 0 ? void 0 : item.option)
64
71
  };
65
72
  }).sort(function (p, q) {
66
73
  if (p.bundle_id !== q.bundle_id) return p.bundle_id - q.bundle_id;
67
74
  if (p.product_id !== q.product_id) return p.product_id - q.product_id;
68
- return p.num - q.num;
75
+ if (p.product_variant_id !== q.product_variant_id) {
76
+ return p.product_variant_id - q.product_variant_id;
77
+ }
78
+ if (p.num !== q.num) return p.num - q.num;
79
+ return JSON.stringify(p.option).localeCompare(JSON.stringify(q.option));
69
80
  });
70
81
  return JSON.stringify([normalizedOpts, normalizedBundles]);
71
82
  }
@@ -326,7 +326,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
326
326
  date: string;
327
327
  status: string;
328
328
  week: string;
329
- weekNum: 0 | 5 | 2 | 1 | 6 | 4 | 3;
329
+ weekNum: 0 | 2 | 1 | 6 | 4 | 3 | 5;
330
330
  }[]>;
331
331
  submitTimeSlot(timeSlots: TimeSliceItem): void;
332
332
  private getScheduleDataByIds;
@@ -2644,10 +2644,7 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
2644
2644
  _context30.next = 11;
2645
2645
  break;
2646
2646
  }
2647
- return _context30.abrupt("return", this.store.order.addProductsToOrder(orderLines, {
2648
- skipEditDiscountConfigRefresh: true,
2649
- skipDiscountRecalculation: true
2650
- }));
2647
+ return _context30.abrupt("return", this.store.order.addProductsToOrder(orderLines));
2651
2648
  case 11:
2652
2649
  result = [];
2653
2650
  _iterator2 = _createForOfIteratorHelper(orderLines);
@@ -118,12 +118,15 @@ export interface BookingTicketCartBookingView extends ISalesBooking {
118
118
  canAddTime: boolean;
119
119
  };
120
120
  }
121
+ export type BookingTicketCartLineView = BookingTicketCartBookingView | BookingTicketCartItemView;
121
122
  /**
122
123
  * BookingTicket 面向 UI 的购物车视图。
123
124
  */
124
125
  export interface BookingTicketCartView {
125
126
  bookings: BookingTicketCartBookingView[];
126
127
  items: BookingTicketCartItemView[];
128
+ /** 以 tempOrder.products 为唯一顺序真源的统一购物车行(旧到新)。 */
129
+ lines: BookingTicketCartLineView[];
127
130
  }
128
131
  /**
129
132
  * BookingTicket 面向 UI 的客户展示视图。
@@ -108,33 +108,28 @@ export function buildCartView(lines, bookings) {
108
108
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
109
109
  var productLines = Array.isArray(lines) ? lines : [];
110
110
  var bookingList = Array.isArray(bookings) ? bookings : [];
111
+ var childBookings = bookingList.filter(function (booking) {
112
+ return booking.parent_id !== 0;
113
+ });
114
+ var bookingsByProductUid = indexBookingsByProductUid(childBookings);
111
115
  var linesByUid = indexProductsByUid(productLines);
112
116
  var addTimeLinesByBookingUid = indexAddTimeProductsByBookingUid(productLines);
113
- var claimedUids = new Set();
114
117
  var claimedAddTimeLines = new Set();
115
- var cartBookings = bookingList.filter(function (booking) {
116
- return booking.parent_id !== 0;
117
- }).reduce(function (acc, booking) {
118
- var uid = booking === null || booking === void 0 ? void 0 : booking.product_uid;
118
+ childBookings.forEach(function (booking) {
119
119
  var bookingUid = getBookingUid(booking);
120
- var product = null;
121
- if (uid !== undefined && uid !== null && uid !== '') {
122
- var key = String(uid);
123
- if (!claimedUids.has(key)) {
124
- var line = linesByUid[key];
125
- // 赠品预约只作为提交数据保留,不在购物车顶部预约卡片区展示。
126
- if (isGiftProductLine(line)) return acc;
127
- if (line) {
128
- claimedUids.add(key);
129
- product = line;
130
- }
131
- }
132
- }
133
- var addTimeProduct = bookingUid ? addTimeLinesByBookingUid[bookingUid] || [] : [];
134
- addTimeProduct.forEach(function (line) {
135
- return claimedAddTimeLines.add(line);
120
+ if (!bookingUid) return;
121
+ (addTimeLinesByBookingUid[bookingUid] || []).forEach(function (line) {
122
+ claimedAddTimeLines.add(line);
136
123
  });
137
- acc.push(_objectSpread(_objectSpread({}, booking), {}, {
124
+ });
125
+ var claimedBookings = new Set();
126
+ var cartBookings = [];
127
+ var items = [];
128
+ var orderedLines = [];
129
+ var buildBookingView = function buildBookingView(booking, product) {
130
+ var bookingUid = getBookingUid(booking);
131
+ var addTimeProduct = bookingUid ? addTimeLinesByBookingUid[bookingUid] || [] : [];
132
+ return _objectSpread(_objectSpread({}, booking), {}, {
138
133
  _extend: {
139
134
  product: product,
140
135
  addTimeProduct: addTimeProduct,
@@ -147,21 +142,38 @@ export function buildCartView(lines, bookings) {
147
142
  shopOpeningHours: options.shopOpeningHours
148
143
  })
149
144
  }
150
- }));
151
- return acc;
152
- }, []);
153
- var items = productLines.filter(function (line) {
145
+ });
146
+ };
147
+ productLines.forEach(function (line) {
154
148
  var _line$metadata6;
155
- // 促销赠品行仅通过主商品 Gift 行展示,不在 items 单独占一行(对齐 legacy `isGift: !!_giftInfo`)
156
- if (isGiftProductLine(line)) return false;
157
- if (claimedAddTimeLines.has(line)) return false;
149
+ // 赠品由主商品 Gift 行展示;加时商品挂在 booking._extend.addTimeProduct。
150
+ if (isGiftProductLine(line) || claimedAddTimeLines.has(line)) return;
158
151
  var uid = (_line$metadata6 = line.metadata) === null || _line$metadata6 === void 0 ? void 0 : _line$metadata6.unique_identification_number;
159
- if (uid === undefined || uid === null || uid === '') return true;
160
- return !claimedUids.has(String(uid));
152
+ var matchedBooking = uid === undefined || uid === null || uid === '' ? undefined : (bookingsByProductUid[String(uid)] || []).find(function (booking) {
153
+ return !claimedBookings.has(booking);
154
+ });
155
+ if (matchedBooking) {
156
+ claimedBookings.add(matchedBooking);
157
+ var bookingView = buildBookingView(matchedBooking, line);
158
+ cartBookings.push(bookingView);
159
+ orderedLines.push(bookingView);
160
+ return;
161
+ }
162
+ items.push(line);
163
+ orderedLines.push(line);
164
+ });
165
+ childBookings.forEach(function (booking) {
166
+ if (claimedBookings.has(booking)) return;
167
+ var uid = booking === null || booking === void 0 ? void 0 : booking.product_uid;
168
+ var linkedProduct = uid === undefined || uid === null || uid === '' ? null : linesByUid[String(uid)] || null;
169
+ // 赠品预约只作为提交数据保留,不在购物车预约卡片区展示。
170
+ if (isGiftProductLine(linkedProduct)) return;
171
+ cartBookings.push(buildBookingView(booking, null));
161
172
  });
162
173
  return {
163
174
  bookings: cartBookings,
164
- items: items
175
+ items: items,
176
+ lines: orderedLines
165
177
  };
166
178
  }
167
179
  export function isWalkInCustomer(customer) {
@@ -95,6 +95,7 @@ export declare class SalesImpl extends BaseModule implements Module, SalesModule
95
95
  * 2) 若无 active,返回已超时且仍占用中的预约(允许并发多条)
96
96
  * 3) 若仍无,返回最近一组未来预约(同 start_time 的并发预约全部返回)
97
97
  * 4) 最后兜底返回一条(避免资源有历史预约时完全无反馈)
98
+ * - includeAllFuture 时,保留选中预约并返回当天全部后续预约;仅详情接口启用。
98
99
  */
99
100
  private pickBookingsForCurrentPoint;
100
101
  /**
@@ -485,11 +485,13 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
485
485
  * 2) 若无 active,返回已超时且仍占用中的预约(允许并发多条)
486
486
  * 3) 若仍无,返回最近一组未来预约(同 start_time 的并发预约全部返回)
487
487
  * 4) 最后兜底返回一条(避免资源有历史预约时完全无反馈)
488
+ * - includeAllFuture 时,保留选中预约并返回当天全部后续预约;仅详情接口启用。
488
489
  */
489
490
  }, {
490
491
  key: "pickBookingsForCurrentPoint",
491
492
  value: function pickBookingsForCurrentPoint(current, bookings) {
492
493
  var _this4 = this;
494
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
493
495
  if (bookings.length === 0) return [];
494
496
  var currentDayStart = current.startOf('day');
495
497
  var currentDayEnd = current.endOf('day');
@@ -504,6 +506,13 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
504
506
  if (dayScopedBookings.length === 0) return [];
505
507
  var appendNextStartGroupIfNeeded = function appendNextStartGroupIfNeeded(selectedBookings) {
506
508
  if (selectedBookings.length === 0) return selectedBookings;
509
+ if (options.includeAllFuture) {
510
+ var allFutureBookings = dayScopedBookings.filter(function (booking) {
511
+ var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
512
+ return startAt.isValid() && startAt.isAfter(current);
513
+ });
514
+ return [].concat(_toConsumableArray(selectedBookings), _toConsumableArray(allFutureBookings));
515
+ }
507
516
  var shouldAppendNextGroup = selectedBookings.some(function (booking) {
508
517
  return booking.status === 'reserved' || booking.status === 'occupied';
509
518
  });
@@ -554,6 +563,7 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
554
563
  return startAt.isValid() && startAt.isAfter(current) && startAt.isSame(current, 'day');
555
564
  });
556
565
  if (upcoming.length > 0) {
566
+ if (options.includeAllFuture) return upcoming;
557
567
  var firstStartAt = this.toBookingDateTime(upcoming[0].start_date, upcoming[0].start_time).valueOf();
558
568
  var upcomingStartGroup = upcoming.filter(function (booking) {
559
569
  var startAt = _this4.toBookingDateTime(booking.start_date, booking.start_time);
@@ -907,7 +917,9 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
907
917
  unpaidBookingList = matchedBookingList.filter(function (booking) {
908
918
  return _this7.isUnpaidBooking(booking);
909
919
  });
910
- bookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, matchedBookingList));
920
+ bookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, matchedBookingList), {
921
+ includeAllFuture: true
922
+ });
911
923
  completedBookings = completedBookingList.map(function (booking) {
912
924
  return _objectSpread(_objectSpread({}, booking), {}, {
913
925
  status: 'compelete',
@@ -919,7 +931,9 @@ export var SalesImpl = /*#__PURE__*/function (_BaseModule) {
919
931
  remainingReserveTime: undefined
920
932
  });
921
933
  });
922
- unpaidBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList));
934
+ unpaidBookings = this.pickBookingsForCurrentPoint(current, this.normalizeResourceBookings(current, deviceCurrent, unpaidBookingList), {
935
+ includeAllFuture: true
936
+ });
923
937
  orderCount = this.countBookingOrders(statsBookingList);
924
938
  bookingCount = statsBookingList.length;
925
939
  compeleteBookingCount = this.countCompletedBookings(statsBookingList);
@@ -388,35 +388,46 @@ export function attachItemRuleLimitsToTopLevelProducts(productList, limits) {
388
388
  * 数组元素先按主键排序再序列化,避免顺序差异导致误判为不同行。
389
389
  */
390
390
  export function buildProductLineFingerprint(productOptionItem, productBundle) {
391
- var optArr = Array.isArray(productOptionItem) ? productOptionItem : [];
392
- var normalizedOpts = optArr.map(function (item) {
393
- var _ref, _item$add_price;
394
- return {
395
- option_group_item_id: Number(item === null || item === void 0 ? void 0 : item.option_group_item_id) || 0,
396
- option_group_id: Number(item === null || item === void 0 ? void 0 : item.option_group_id) || 0,
397
- num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
398
- price: String((_ref = (_item$add_price = item === null || item === void 0 ? void 0 : item.add_price) !== null && _item$add_price !== void 0 ? _item$add_price : item === null || item === void 0 ? void 0 : item.price) !== null && _ref !== void 0 ? _ref : '')
399
- };
400
- }).sort(function (p, q) {
401
- if (p.option_group_item_id !== q.option_group_item_id) {
402
- return p.option_group_item_id - q.option_group_item_id;
403
- }
404
- if (p.option_group_id !== q.option_group_id) return p.option_group_id - q.option_group_id;
405
- if (p.num !== q.num) return p.num - q.num;
406
- return p.price.localeCompare(q.price);
407
- });
391
+ var normalizeOptions = function normalizeOptions(options) {
392
+ var optionArr = Array.isArray(options) ? options : [];
393
+ return optionArr.map(function (item) {
394
+ var _ref, _item$add_price;
395
+ return {
396
+ option_group_item_id: Number(item === null || item === void 0 ? void 0 : item.option_group_item_id) || 0,
397
+ option_group_id: Number(item === null || item === void 0 ? void 0 : item.option_group_id) || 0,
398
+ num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
399
+ price: String((_ref = (_item$add_price = item === null || item === void 0 ? void 0 : item.add_price) !== null && _item$add_price !== void 0 ? _item$add_price : item === null || item === void 0 ? void 0 : item.price) !== null && _ref !== void 0 ? _ref : '')
400
+ };
401
+ }).sort(function (p, q) {
402
+ if (p.option_group_item_id !== q.option_group_item_id) {
403
+ return p.option_group_item_id - q.option_group_item_id;
404
+ }
405
+ if (p.option_group_id !== q.option_group_id) {
406
+ return p.option_group_id - q.option_group_id;
407
+ }
408
+ if (p.num !== q.num) return p.num - q.num;
409
+ return p.price.localeCompare(q.price);
410
+ });
411
+ };
412
+ var normalizedOpts = normalizeOptions(productOptionItem);
408
413
  var bundleArr = Array.isArray(productBundle) ? productBundle : [];
409
414
  var normalizedBundles = bundleArr.map(function (item) {
410
- var _ref2, _item$bundle_id;
415
+ var _ref2, _item$bundle_id, _item$bundle_variant_;
411
416
  return {
412
417
  bundle_id: Number((_ref2 = (_item$bundle_id = item === null || item === void 0 ? void 0 : item.bundle_id) !== null && _item$bundle_id !== void 0 ? _item$bundle_id : item === null || item === void 0 ? void 0 : item.id) !== null && _ref2 !== void 0 ? _ref2 : 0) || 0,
413
418
  product_id: Number(item === null || item === void 0 ? void 0 : item.product_id) || 0,
414
- num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1
419
+ product_variant_id: Number((_item$bundle_variant_ = item === null || item === void 0 ? void 0 : item.bundle_variant_id) !== null && _item$bundle_variant_ !== void 0 ? _item$bundle_variant_ : item === null || item === void 0 ? void 0 : item.product_variant_id) || 0,
420
+ num: typeof (item === null || item === void 0 ? void 0 : item.num) === 'number' && !Number.isNaN(item.num) ? Math.max(1, Math.floor(item.num)) : 1,
421
+ option: normalizeOptions(item === null || item === void 0 ? void 0 : item.option)
415
422
  };
416
423
  }).sort(function (p, q) {
417
424
  if (p.bundle_id !== q.bundle_id) return p.bundle_id - q.bundle_id;
418
425
  if (p.product_id !== q.product_id) return p.product_id - q.product_id;
419
- return p.num - q.num;
426
+ if (p.product_variant_id !== q.product_variant_id) {
427
+ return p.product_variant_id - q.product_variant_id;
428
+ }
429
+ if (p.num !== q.num) return p.num - q.num;
430
+ return JSON.stringify(p.option).localeCompare(JSON.stringify(q.option));
420
431
  });
421
432
  return JSON.stringify([normalizedOpts, normalizedBundles]);
422
433
  }
@@ -76,6 +76,11 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
76
76
  * value 为 undefined 时删除该 key;存储失败不阻断业务流程。
77
77
  */
78
78
  setSessionStateValue(key: string, value: unknown): void;
79
+ /**
80
+ * 清除当前 cacheId 的可恢复订单快照,同时保留 Solution UI sessionState。
81
+ * 用于支付跳转等终态场景,避免浏览器返回时恢复已提交订单。
82
+ */
83
+ clearSessionStorageOrderSnapshot(): void;
79
84
  /**
80
85
  * Kiosk 不能把已收款订单留在本地等待重试:默认直接等待云端 checkout。
81
86
  * 兼容仍需要 WebPOS 待同步模式的入口可显式传 checkoutSyncTaskEnabled: true。
@@ -122,10 +127,6 @@ export declare class UnifiedBookingSalesImpl extends BookingTicket {
122
127
  * Read-only compatibility view for salesSdk skins. It reconnects a booking to its product but
123
128
  * must not be used to mutate tempOrder; all writes go through BaseSales / planner APIs.
124
129
  */
125
- getCart(): {
126
- items: any[];
127
- bookings: any[];
128
- };
129
130
  /**
130
131
  * Loads the current customer's product coupons and discount cards after planner lines exist,
131
132
  * then optionally lets the existing Rules engine select the best valid combination. This is a
@@ -584,6 +584,17 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
584
584
  });
585
585
  }
586
586
 
587
+ /**
588
+ * 清除当前 cacheId 的可恢复订单快照,同时保留 Solution UI sessionState。
589
+ * 用于支付跳转等终态场景,避免浏览器返回时恢复已提交订单。
590
+ */
591
+ }, {
592
+ key: "clearSessionStorageOrderSnapshot",
593
+ value: function clearSessionStorageOrderSnapshot() {
594
+ var _this$store$order, _this$store$order$cle;
595
+ (_this$store$order = this.store.order) === null || _this$store$order === void 0 || (_this$store$order$cle = _this$store$order.clearSessionStoragePersistedTempOrder) === null || _this$store$order$cle === void 0 || _this$store$order$cle.call(_this$store$order);
596
+ }
597
+
587
598
  /**
588
599
  * Kiosk 不能把已收款订单留在本地等待重试:默认直接等待云端 checkout。
589
600
  * 兼容仍需要 WebPOS 待同步模式的入口可显式传 checkoutSyncTaskEnabled: true。
@@ -622,12 +633,12 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
622
633
  key: "addNewOrder",
623
634
  value: function () {
624
635
  var _addNewOrder = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
625
- var _this$store$order, _this$store$order$con, _this$store$order3;
626
- var sessionRecord, tempOrder, _this$store$order2, didSyncAuthenticatedCustomer;
636
+ var _this$store$order2, _this$store$order2$co, _this$store$order4;
637
+ var sessionRecord, tempOrder, _this$store$order3, didSyncAuthenticatedCustomer;
627
638
  return _regeneratorRuntime().wrap(function _callee$(_context) {
628
639
  while (1) switch (_context.prev = _context.next) {
629
640
  case 0:
630
- sessionRecord = this.isSessionStoragePersistEnabled() ? (_this$store$order = this.store.order) === null || _this$store$order === void 0 || (_this$store$order$con = _this$store$order.consumeSessionStorageRestore) === null || _this$store$order$con === void 0 ? void 0 : _this$store$order$con.call(_this$store$order) : null;
641
+ sessionRecord = this.isSessionStoragePersistEnabled() ? (_this$store$order2 = this.store.order) === null || _this$store$order2 === void 0 || (_this$store$order2$co = _this$store$order2.consumeSessionStorageRestore) === null || _this$store$order2$co === void 0 ? void 0 : _this$store$order2$co.call(_this$store$order2) : null;
631
642
  if (!sessionRecord) {
632
643
  _context.next = 4;
633
644
  break;
@@ -643,7 +654,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
643
654
  case 6:
644
655
  tempOrder = _context.sent;
645
656
  if (sessionRecord) {
646
- (_this$store$order2 = this.store.order) === null || _this$store$order2 === void 0 || _this$store$order2.persistTempOrder();
657
+ (_this$store$order3 = this.store.order) === null || _this$store$order3 === void 0 || _this$store$order3.persistTempOrder();
647
658
  }
648
659
  if (!this.isAuthenticatedCustomerUserPlatform()) {
649
660
  _context.next = 23;
@@ -686,7 +697,7 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
686
697
  _context.t1 = _context["catch"](24);
687
698
  console.warn('[UnifiedBookingSales] Failed to refresh cached customer discounts after addNewOrder', _context.t1);
688
699
  case 32:
689
- return _context.abrupt("return", ((_this$store$order3 = this.store.order) === null || _this$store$order3 === void 0 ? void 0 : _this$store$order3.getTempOrder()) || tempOrder);
700
+ return _context.abrupt("return", ((_this$store$order4 = this.store.order) === null || _this$store$order4 === void 0 ? void 0 : _this$store$order4.getTempOrder()) || tempOrder);
690
701
  case 33:
691
702
  case "end":
692
703
  return _context.stop();
@@ -757,8 +768,8 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
757
768
  }, {
758
769
  key: "resolveDiscountOrderIdentity",
759
770
  value: function resolveDiscountOrderIdentity(tempOrder) {
760
- var _this$store$order4, _this$store$order4$ge;
761
- return (tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.order_id) || ((_this$store$order4 = this.store.order) === null || _this$store$order4 === void 0 || (_this$store$order4$ge = _this$store$order4.getOrderIdentity) === null || _this$store$order4$ge === void 0 || (_this$store$order4$ge = _this$store$order4$ge.call(_this$store$order4)) === null || _this$store$order4$ge === void 0 ? void 0 : _this$store$order4$ge.orderId) || null;
771
+ var _this$store$order5, _this$store$order5$ge;
772
+ return (tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.order_id) || ((_this$store$order5 = this.store.order) === null || _this$store$order5 === void 0 || (_this$store$order5$ge = _this$store$order5.getOrderIdentity) === null || _this$store$order5$ge === void 0 || (_this$store$order5$ge = _this$store$order5$ge.call(_this$store$order5)) === null || _this$store$order5$ge === void 0 ? void 0 : _this$store$order5$ge.orderId) || null;
762
773
  }
763
774
  }, {
764
775
  key: "resolveDiscountAction",
@@ -770,16 +781,16 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
770
781
  key: "resetCachedCustomerDiscountState",
771
782
  value: function () {
772
783
  var _resetCachedCustomerDiscountState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
773
- var _this$store$order5, _this$store$order5$cl, _this$store$customer2, _this$store$customer3, _this$store$order6, _discountModule$getOr, _discountModule$getDi, _discountModule$setOr, _discountModule$setDi, _this$store$order7, _this$store$order7$ap, _this$store$order8, _this$store$order8$re, _this$store$order9, _this$store$order9$pe;
784
+ var _this$store$order6, _this$store$order6$cl, _this$store$customer2, _this$store$customer3, _this$store$order7, _discountModule$getOr, _discountModule$getDi, _discountModule$setOr, _discountModule$setDi, _this$store$order8, _this$store$order8$ap, _this$store$order9, _this$store$order9$re, _this$store$order10, _this$store$order10$p;
774
785
  var orderStore, discountModule, filteredOriginalDiscounts, filteredCurrentDiscounts;
775
786
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
776
787
  while (1) switch (_context3.prev = _context3.next) {
777
788
  case 0:
778
- (_this$store$order5 = this.store.order) === null || _this$store$order5 === void 0 || (_this$store$order5$cl = _this$store$order5.clearOrderCustomer) === null || _this$store$order5$cl === void 0 || _this$store$order5$cl.call(_this$store$order5);
789
+ (_this$store$order6 = this.store.order) === null || _this$store$order6 === void 0 || (_this$store$order6$cl = _this$store$order6.clearOrderCustomer) === null || _this$store$order6$cl === void 0 || _this$store$order6$cl.call(_this$store$order6);
779
790
  (_this$store$customer2 = this.store.customer) === null || _this$store$customer2 === void 0 || (_this$store$customer3 = _this$store$customer2.setSelectedCustomer) === null || _this$store$customer3 === void 0 || _this$store$customer3.call(_this$store$customer2, null);
780
791
  this.discountConfigCacheKey = null;
781
792
  this.hasManualDiscountSelection = false;
782
- orderStore = ((_this$store$order6 = this.store.order) === null || _this$store$order6 === void 0 ? void 0 : _this$store$order6.store) || {};
793
+ orderStore = ((_this$store$order7 = this.store.order) === null || _this$store$order7 === void 0 ? void 0 : _this$store$order7.store) || {};
783
794
  discountModule = orderStore.discount;
784
795
  filteredOriginalDiscounts = filterCustomerBoundDiscounts((discountModule === null || discountModule === void 0 || (_discountModule$getOr = discountModule.getOriginalDiscountList) === null || _discountModule$getOr === void 0 ? void 0 : _discountModule$getOr.call(discountModule)) || []);
785
796
  filteredCurrentDiscounts = filterCustomerBoundDiscounts((discountModule === null || discountModule === void 0 || (_discountModule$getDi = discountModule.getDiscountList) === null || _discountModule$getDi === void 0 ? void 0 : _discountModule$getDi.call(discountModule)) || []);
@@ -789,13 +800,13 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
789
800
  _context3.next = 12;
790
801
  return discountModule === null || discountModule === void 0 || (_discountModule$setDi = discountModule.setDiscountList) === null || _discountModule$setDi === void 0 ? void 0 : _discountModule$setDi.call(discountModule, filteredCurrentDiscounts);
791
802
  case 12:
792
- (_this$store$order7 = this.store.order) === null || _this$store$order7 === void 0 || (_this$store$order7$ap = _this$store$order7.applyDiscount) === null || _this$store$order7$ap === void 0 || _this$store$order7$ap.call(_this$store$order7);
803
+ (_this$store$order8 = this.store.order) === null || _this$store$order8 === void 0 || (_this$store$order8$ap = _this$store$order8.applyDiscount) === null || _this$store$order8$ap === void 0 || _this$store$order8$ap.call(_this$store$order8);
793
804
  _context3.next = 15;
794
- return (_this$store$order8 = this.store.order) === null || _this$store$order8 === void 0 || (_this$store$order8$re = _this$store$order8.recalculateSummary) === null || _this$store$order8$re === void 0 ? void 0 : _this$store$order8$re.call(_this$store$order8, {
805
+ return (_this$store$order9 = this.store.order) === null || _this$store$order9 === void 0 || (_this$store$order9$re = _this$store$order9.recalculateSummary) === null || _this$store$order9$re === void 0 ? void 0 : _this$store$order9$re.call(_this$store$order9, {
795
806
  createIfMissing: true
796
807
  });
797
808
  case 15:
798
- (_this$store$order9 = this.store.order) === null || _this$store$order9 === void 0 || (_this$store$order9$pe = _this$store$order9.persistTempOrder) === null || _this$store$order9$pe === void 0 || _this$store$order9$pe.call(_this$store$order9);
809
+ (_this$store$order10 = this.store.order) === null || _this$store$order10 === void 0 || (_this$store$order10$p = _this$store$order10.persistTempOrder) === null || _this$store$order10$p === void 0 || _this$store$order10$p.call(_this$store$order10);
799
810
  case 16:
800
811
  case "end":
801
812
  return _context3.stop();
@@ -1188,32 +1199,33 @@ export var UnifiedBookingSalesImpl = /*#__PURE__*/function (_BookingTicket) {
1188
1199
  * Read-only compatibility view for salesSdk skins. It reconnects a booking to its product but
1189
1200
  * must not be used to mutate tempOrder; all writes go through BaseSales / planner APIs.
1190
1201
  */
1191
- }, {
1192
- key: "getCart",
1193
- value: function getCart() {
1194
- var tempOrder = this.getTempOrder();
1195
- var salesDetail = this.getSalesOrder();
1196
- var items = (tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.products) || [];
1197
- var bookings = (salesDetail === null || salesDetail === void 0 ? void 0 : salesDetail.bookings) || (tempOrder === null || tempOrder === void 0 ? void 0 : tempOrder.bookings) || [];
1198
- return {
1199
- items: items,
1200
- bookings: bookings.map(function (booking) {
1201
- var productUid = booking === null || booking === void 0 ? void 0 : booking.product_uid;
1202
- var product = productUid ? items.find(function (item) {
1203
- var _item$metadata;
1204
- var uid = (item === null || item === void 0 || (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.unique_identification_number) || (item === null || item === void 0 ? void 0 : item.unique_identification_number);
1205
- return String(uid || '') === String(productUid);
1206
- }) || null : null;
1207
- return _objectSpread(_objectSpread({}, booking), {}, {
1208
- _extend: _objectSpread(_objectSpread({}, (booking === null || booking === void 0 ? void 0 : booking._extend) || {}), {}, {
1209
- product: product,
1210
- addTimeProduct: [],
1211
- canAddTime: false
1212
- })
1213
- });
1214
- })
1215
- };
1216
- }
1202
+ // getCart(): BookingTicketCartView {
1203
+ // const tempOrder = this.getTempOrder();
1204
+ // const salesDetail = this.getSalesOrder();
1205
+ // const items = tempOrder?.products || [];
1206
+ // const bookings = salesDetail?.bookings || tempOrder?.bookings || [];
1207
+ // return {
1208
+ // items,
1209
+ // bookings: bookings.map((booking: any) => {
1210
+ // const productUid = booking?.product_uid;
1211
+ // const product = productUid
1212
+ // ? items.find((item: any) => {
1213
+ // const uid = item?.metadata?.unique_identification_number || item?.unique_identification_number;
1214
+ // return String(uid || '') === String(productUid);
1215
+ // }) || null
1216
+ // : null;
1217
+ // return {
1218
+ // ...booking,
1219
+ // _extend: {
1220
+ // ...(booking?._extend || {}),
1221
+ // product,
1222
+ // addTimeProduct: [],
1223
+ // canAddTime: false,
1224
+ // },
1225
+ // };
1226
+ // }),
1227
+ // };
1228
+ // }
1217
1229
 
1218
1230
  /**
1219
1231
  * Loads the current customer's product coupons and discount cards after planner lines exist,
@@ -149,7 +149,9 @@ function mapOrderBundleToOtherBundle(bundle) {
149
149
  return bundle.map((item) => {
150
150
  return {
151
151
  ...item,
152
- original_price: item.original_price ?? item.bundle_selling_price ?? item.price
152
+ // 后端历史订单可能没有 original_price;此时 price 是折前毛价,
153
+ // bundle_selling_price 已包含折扣,不能把它当成编辑时的新原价。
154
+ original_price: item.original_price ?? item.product_price ?? item.price ?? item.bundle_selling_price
153
155
  };
154
156
  });
155
157
  }