@pisell/pisellos 2.2.265 → 2.2.266

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 (43) hide show
  1. package/dist/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  2. package/dist/model/strategy/adapter/promotion/adapter.js +23 -0
  3. package/dist/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  4. package/dist/model/strategy/adapter/promotion/evaluator.js +279 -6
  5. package/dist/model/strategy/adapter/promotion/examples.d.ts +86 -0
  6. package/dist/model/strategy/adapter/promotion/examples.js +99 -0
  7. package/dist/model/strategy/adapter/promotion/index.d.ts +1 -1
  8. package/dist/model/strategy/adapter/promotion/index.js +0 -9
  9. package/dist/model/strategy/adapter/promotion/type.d.ts +90 -2
  10. package/dist/model/strategy/adapter/promotion/type.js +45 -0
  11. package/dist/modules/Order/index.js +10 -3
  12. package/dist/modules/Order/utils.js +2 -1
  13. package/dist/modules/Rules/index.d.ts +1 -0
  14. package/dist/modules/Rules/index.js +34 -14
  15. package/dist/solution/BaseSales/index.d.ts +14 -1
  16. package/dist/solution/BaseSales/index.js +36 -12
  17. package/dist/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  18. package/dist/solution/BaseSales/utils/cartPromotion.js +90 -31
  19. package/dist/solution/BookingTicket/index.js +33 -28
  20. package/dist/solution/ScanOrder/index.js +31 -20
  21. package/dist/solution/VenueBooking/index.js +30 -19
  22. package/lib/model/strategy/adapter/promotion/adapter.d.ts +4 -0
  23. package/lib/model/strategy/adapter/promotion/adapter.js +20 -0
  24. package/lib/model/strategy/adapter/promotion/evaluator.d.ts +17 -0
  25. package/lib/model/strategy/adapter/promotion/evaluator.js +235 -0
  26. package/lib/model/strategy/adapter/promotion/examples.d.ts +86 -0
  27. package/lib/model/strategy/adapter/promotion/examples.js +91 -0
  28. package/lib/model/strategy/adapter/promotion/index.d.ts +1 -1
  29. package/lib/model/strategy/adapter/promotion/index.js +2 -0
  30. package/lib/model/strategy/adapter/promotion/type.d.ts +90 -2
  31. package/lib/model/strategy/adapter/promotion/type.js +2 -0
  32. package/lib/modules/Order/index.js +9 -3
  33. package/lib/modules/Order/utils.js +6 -1
  34. package/lib/modules/Rules/index.d.ts +1 -0
  35. package/lib/modules/Rules/index.js +23 -4
  36. package/lib/solution/BaseSales/index.d.ts +14 -1
  37. package/lib/solution/BaseSales/index.js +22 -1
  38. package/lib/solution/BaseSales/utils/cartPromotion.d.ts +3 -1
  39. package/lib/solution/BaseSales/utils/cartPromotion.js +63 -12
  40. package/lib/solution/BookingTicket/index.js +4 -2
  41. package/lib/solution/ScanOrder/index.js +8 -0
  42. package/lib/solution/VenueBooking/index.js +8 -0
  43. package/package.json +1 -1
@@ -1,17 +1,17 @@
1
1
  var _excluded = ["_promotionTags"];
2
2
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
3
3
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
4
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
5
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
6
- function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
7
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
8
- function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
9
4
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
10
5
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
11
6
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
12
7
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
13
8
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
14
9
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
10
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
12
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
13
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
14
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
15
  function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
16
16
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
17
17
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
@@ -116,24 +116,50 @@ export function getOrderProductOriginalPriceForPromotion(product) {
116
116
  }
117
117
  return getOrderProductBasePrice(product);
118
118
  }
119
+ var X_ITEMS_FOR_Y_PRICE = 'X_ITEMS_FOR_Y_PRICE';
120
+ var BUY_X_GET_Y_FREE = 'BUY_X_GET_Y_FREE';
121
+ var ITEM_REWARD = 'ITEM_REWARD';
122
+ function isItemRewardPromotionDiscountItem(item) {
123
+ var _item$metadata, _item$metadata2;
124
+ return (item === null || item === void 0 ? void 0 : item.type) === 'product' && (item === null || item === void 0 || (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.source) === 'promotion' && (item === null || item === void 0 || (_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.actionType) === ITEM_REWARD;
125
+ }
126
+ function isManagedPromotionDiscountItem(item) {
127
+ if ((item === null || item === void 0 ? void 0 : item.type) === 'promotion') return true;
128
+ return isItemRewardPromotionDiscountItem(item);
129
+ }
130
+
131
+ /**
132
+ * 判断商品行在本轮评估前是否已享受促销。
133
+ *
134
+ * `_promotion` 仅存在于当前运行时;订单保存后会被裁剪,因此编辑态需通过
135
+ * ITEM_REWARD 写入的受管商品折扣恢复上一轮状态。
136
+ */
137
+ function wasInPromotionBeforeEvaluation(item) {
138
+ var _item$metadata3;
139
+ if ((item === null || item === void 0 || (_item$metadata3 = item.metadata) === null || _item$metadata3 === void 0 || (_item$metadata3 = _item$metadata3._promotion) === null || _item$metadata3 === void 0 ? void 0 : _item$metadata3.inPromotion) === true) return true;
140
+ return Array.isArray(item === null || item === void 0 ? void 0 : item.discount_list) && item.discount_list.some(isItemRewardPromotionDiscountItem);
141
+ }
119
142
 
120
143
  /**
121
- * 写入/清除促销 discount_list(type=promotion)。
144
+ * 写入/清除促销 discount_list
122
145
  *
123
146
  * applyDiscount → applyProductDiscountPrices 会从 source_product_price 减去 discount_list 合计
124
147
  * 重算 main_product_selling_price;保留券前 source 时必须同步写入促销差额,否则会还原成原价。
125
148
  *
149
+ * ITEM_REWARD 使用 type=product,复用商品级折扣排他规则,避免客户折扣继续叠加到奖励商品行。
150
+ *
126
151
  * @example
127
152
  * updatePromotionDiscountList(line, { title: '2 items for $10', amount: '17.00', original_amount: '22.00', fixed_amount: '17.00' });
128
153
  */
129
- function updatePromotionDiscountList(item, promotionDiscount) {
154
+ function updatePromotionDiscountList(item, promotionDiscount, options) {
130
155
  var discountList = Array.isArray(item.discount_list) ? _toConsumableArray(item.discount_list) : [];
131
156
  discountList = discountList.filter(function (d) {
132
- return (d === null || d === void 0 ? void 0 : d.type) !== 'promotion';
157
+ return !isManagedPromotionDiscountItem(d);
133
158
  });
134
159
  if (promotionDiscount) {
135
- discountList.push({
136
- type: 'promotion',
160
+ var discountType = (options === null || options === void 0 ? void 0 : options.discountType) || 'promotion';
161
+ discountList.push(_objectSpread({
162
+ type: discountType,
137
163
  amount: promotionDiscount.amount,
138
164
  discount: {
139
165
  original_amount: promotionDiscount.original_amount,
@@ -141,7 +167,12 @@ function updatePromotionDiscountList(item, promotionDiscount) {
141
167
  title: promotionDiscount.title,
142
168
  resource_id: ''
143
169
  }
144
- });
170
+ }, discountType === 'product' ? {
171
+ metadata: {
172
+ source: 'promotion',
173
+ actionType: (options === null || options === void 0 ? void 0 : options.actionType) || ITEM_REWARD
174
+ }
175
+ } : {}));
145
176
  }
146
177
  if (discountList.length > 0) {
147
178
  item.discount_list = discountList;
@@ -149,11 +180,19 @@ function updatePromotionDiscountList(item, promotionDiscount) {
149
180
  delete item.discount_list;
150
181
  }
151
182
  }
152
- var X_ITEMS_FOR_Y_PRICE = 'X_ITEMS_FOR_Y_PRICE';
153
- var BUY_X_GET_Y_FREE = 'BUY_X_GET_Y_FREE';
183
+ function evaluatorHasActionType(evaluator, actionType) {
184
+ var _evaluator$getStrateg;
185
+ var configs = evaluator === null || evaluator === void 0 || (_evaluator$getStrateg = evaluator.getStrategyConfigs) === null || _evaluator$getStrateg === void 0 ? void 0 : _evaluator$getStrateg.call(evaluator);
186
+ if (!Array.isArray(configs)) return false;
187
+ return configs.some(function (config) {
188
+ return ((config === null || config === void 0 ? void 0 : config.actions) || []).some(function (action) {
189
+ return (action === null || action === void 0 ? void 0 : action.type) === actionType;
190
+ });
191
+ });
192
+ }
154
193
 
155
194
  /**
156
- * 将促销单价写入 OrderProduct(含 metadata 三字段 + promotion discount_list)。
195
+ * 将促销单价写入 OrderProduct(含 metadata 三字段 + 行内折扣)。
157
196
  *
158
197
  * @example
159
198
  * applyPromoUnitPriceToLine(newItem, { promoUnitPrice: '5.00', originalBasePrice: 1, strategyTitle: '2 for 10' });
@@ -184,6 +223,9 @@ function applyPromoUnitPriceToLine(item, input) {
184
223
  amount: discountAmount,
185
224
  original_amount: catalogSource,
186
225
  fixed_amount: discountAmount
226
+ }, {
227
+ actionType: input.actionType,
228
+ discountType: input.actionType === ITEM_REWARD ? 'product' : 'promotion'
187
229
  });
188
230
  } else {
189
231
  updatePromotionDiscountList(item, null);
@@ -471,11 +513,11 @@ function getProductBundleForEvaluator(product) {
471
513
  * // => 单行 num=4,清除 _promotion 后重新评估
472
514
  */
473
515
  export function buildConsolidateKeyForPromotion(item) {
474
- var _item$booking_uid, _item$metadata, _item$order_detail_id, _item$product_variant3;
516
+ var _item$booking_uid, _item$metadata4, _item$order_detail_id, _item$product_variant3;
475
517
  var fingerprint = buildProductLineFingerprint(getProductSkuOptions(item), item.product_bundle);
476
518
  var noteSignature = getProductLineNoteSignature(item);
477
519
  var lineMergeBoundary = getPromotionLineMergeBoundary(item);
478
- var bookingUid = (_item$booking_uid = item === null || item === void 0 ? void 0 : item.booking_uid) !== null && _item$booking_uid !== void 0 ? _item$booking_uid : item === null || item === void 0 || (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.booking_uid;
520
+ var bookingUid = (_item$booking_uid = item === null || item === void 0 ? void 0 : item.booking_uid) !== null && _item$booking_uid !== void 0 ? _item$booking_uid : item === null || item === void 0 || (_item$metadata4 = item.metadata) === null || _item$metadata4 === void 0 ? void 0 : _item$metadata4.booking_uid;
479
521
  var orderDetailId = (_item$order_detail_id = item === null || item === void 0 ? void 0 : item.order_detail_id) !== null && _item$order_detail_id !== void 0 ? _item$order_detail_id : item === null || item === void 0 ? void 0 : item.orderDetailId;
480
522
  if (orderDetailId !== undefined && orderDetailId !== null && orderDetailId !== '') {
481
523
  var _item$product_variant;
@@ -496,12 +538,11 @@ function consolidateMainProductsForPromotion(entries) {
496
538
  _step5;
497
539
  try {
498
540
  for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
499
- var _item$metadata2;
500
541
  var _step5$value = _step5.value,
501
542
  item = _step5$value.item,
502
543
  originalListIndex = _step5$value.originalListIndex;
503
544
  var key = buildConsolidateKeyForPromotion(item);
504
- var wasInPromotion = (item === null || item === void 0 || (_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 || (_item$metadata2 = _item$metadata2._promotion) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.inPromotion) === true;
545
+ var wasInPromotion = wasInPromotionBeforeEvaluation(item);
505
546
  var existing = groups.get(key);
506
547
  if (!existing) {
507
548
  var mergedItem = cloneDeep(item);
@@ -598,6 +639,9 @@ function splitXItemsPromoLinesByGroup(lines, strategyActionMap) {
598
639
  function generateNumericId() {
599
640
  return Math.floor(Math.random() * 1000000000) + Date.now();
600
641
  }
642
+ function isBookingEditProductLine(product) {
643
+ return (product === null || product === void 0 ? void 0 : product.booking_id) !== undefined && (product === null || product === void 0 ? void 0 : product.booking_id) !== null && product.booking_id !== 0 && product.booking_id !== '0';
644
+ }
601
645
 
602
646
  /**
603
647
  * 把 OrderProduct 转成 evaluator 的 PromotionProduct(仅评估期使用)。
@@ -618,6 +662,7 @@ function convertToPromotionProduct(product, index) {
618
662
  price: getOrderProductOriginalPriceForPromotion(product),
619
663
  quantity: Number((_product$num = product === null || product === void 0 ? void 0 : product.num) !== null && _product$num !== void 0 ? _product$num : 1) || 1,
620
664
  bundle: getProductBundleForEvaluator(product),
665
+ _promotionOnlyForItemReward: isBookingEditProductLine(product),
621
666
  _originalItem: originalItem,
622
667
  _originalId: getOrderProductUid(product),
623
668
  _originalIndex: index
@@ -825,6 +870,9 @@ export function resolveStrategyRequiredQuantity(matched) {
825
870
  if (matched.actionType === 'BUY_X_GET_Y_FREE') {
826
871
  return Number(detail.buyQuantity) || 1;
827
872
  }
873
+ if (matched.actionType === 'ITEM_REWARD') {
874
+ return Number(detail.triggerQuantity) || 1;
875
+ }
828
876
  return 1;
829
877
  }
830
878
 
@@ -984,7 +1032,8 @@ export function appendPromotionTags(products, evaluator) {
984
1032
  * 处理购物车的促销计算与赠品差异化。
985
1033
  *
986
1034
  * 流程:
987
- * 1. 分离 main / gift / edit-product 三类(带 `booking_id` 的编辑态商品不参与促销)
1035
+ * 1. 分离 main / gift / edit-product 三类(普通促销下带 `booking_id` 的编辑态商品不参与;
1036
+ * 配置 ITEM_REWARD 时,编辑态商品也参与商品奖励重算)
988
1037
  * 2. 转 PromotionProduct 喂评估器 → 拿到 `evaluateCartWithPricing` 与 `getProductsApplicableStrategies`
989
1038
  * 3. 把 PricedProduct 映射回 OrderProduct 形态:
990
1039
  * - 参与促销的,写 `metadata._promotion` + 调整 `selling_price` / `main_product_selling_price`
@@ -1014,6 +1063,7 @@ export function processCartPromotion(list, evaluator, options) {
1014
1063
  if (!list || list.length === 0 || !evaluator) return empty;
1015
1064
 
1016
1065
  // 0. 分类
1066
+ var shouldIncludeEditProductsForItemReward = evaluatorHasActionType(evaluator, ITEM_REWARD);
1017
1067
  var mainProductsWithIndex = [];
1018
1068
  var existingGiftsWithIndex = [];
1019
1069
  var editProductsWithIndex = [];
@@ -1030,11 +1080,18 @@ export function processCartPromotion(list, evaluator, options) {
1030
1080
  item: item,
1031
1081
  originalListIndex: i
1032
1082
  });
1033
- } else if ((item === null || item === void 0 ? void 0 : item.booking_id) !== undefined && (item === null || item === void 0 ? void 0 : item.booking_id) !== null && item.booking_id !== 0 && item.booking_id !== '0') {
1034
- editProductsWithIndex.push({
1035
- item: item,
1036
- originalListIndex: i
1037
- });
1083
+ } else if (isBookingEditProductLine(item)) {
1084
+ if (shouldIncludeEditProductsForItemReward) {
1085
+ mainProductsWithIndex.push({
1086
+ item: item,
1087
+ originalListIndex: i
1088
+ });
1089
+ } else {
1090
+ editProductsWithIndex.push({
1091
+ item: item,
1092
+ originalListIndex: i
1093
+ });
1094
+ }
1038
1095
  } else {
1039
1096
  mainProductsWithIndex.push({
1040
1097
  item: item,
@@ -1089,16 +1146,17 @@ export function processCartPromotion(list, evaluator, options) {
1089
1146
  var promotionProducts = [];
1090
1147
  var originalItemMap = new Map();
1091
1148
  var productsForStrategies = consolidatedMainProductsWithIndex.map(function (_ref16, i) {
1092
- var _item$product_id, _item$product_variant5, _item$metadata3, _item$num;
1149
+ var _item$product_id, _item$product_variant5, _item$metadata5, _item$num;
1093
1150
  var item = _ref16.item;
1094
1151
  return {
1095
1152
  id: i,
1096
1153
  product_id: Number((_item$product_id = item === null || item === void 0 ? void 0 : item.product_id) !== null && _item$product_id !== void 0 ? _item$product_id : 0) || 0,
1097
1154
  product_variant_id: Number((_item$product_variant5 = item === null || item === void 0 ? void 0 : item.product_variant_id) !== null && _item$product_variant5 !== void 0 ? _item$product_variant5 : 0) || 0,
1098
- name: (item === null || item === void 0 || (_item$metadata3 = item.metadata) === null || _item$metadata3 === void 0 ? void 0 : _item$metadata3.product_name) || (item === null || item === void 0 ? void 0 : item.title) || '',
1155
+ name: (item === null || item === void 0 || (_item$metadata5 = item.metadata) === null || _item$metadata5 === void 0 ? void 0 : _item$metadata5.product_name) || (item === null || item === void 0 ? void 0 : item.title) || '',
1099
1156
  price: getOrderProductBasePrice(item),
1100
1157
  quantity: Number((_item$num = item === null || item === void 0 ? void 0 : item.num) !== null && _item$num !== void 0 ? _item$num : 1) || 1,
1101
- bundle: getProductBundleForEvaluator(item)
1158
+ bundle: getProductBundleForEvaluator(item),
1159
+ _promotionOnlyForItemReward: isBookingEditProductLine(item)
1102
1160
  };
1103
1161
  });
1104
1162
  for (var _i = 0; _i < consolidatedMainProductsWithIndex.length; _i++) {
@@ -1206,7 +1264,7 @@ export function processCartPromotion(list, evaluator, options) {
1206
1264
  _step20;
1207
1265
  try {
1208
1266
  for (_iterator20.s(); !(_step20 = _iterator20.n()).done;) {
1209
- var _priced$originalId2, _priced$product_id, _originalItem$product, _metadata$_promotion2;
1267
+ var _priced$originalId2, _priced$product_id, _originalItem$product;
1210
1268
  var _priced = _step20.value;
1211
1269
  var rawSourceId = (_priced$originalId2 = _priced.originalId) !== null && _priced$originalId2 !== void 0 ? _priced$originalId2 : _priced.id;
1212
1270
  var _sourceId = Number(rawSourceId);
@@ -1225,7 +1283,7 @@ export function processCartPromotion(list, evaluator, options) {
1225
1283
  newItem._sourceCartNum = sourceCartNum;
1226
1284
 
1227
1285
  // 清掉历史促销字段
1228
- var wasInPromotion = ((_metadata$_promotion2 = metadata._promotion) === null || _metadata$_promotion2 === void 0 ? void 0 : _metadata$_promotion2.inPromotion) === true || originalItem._wasInPromotionBeforeConsolidate === true;
1286
+ var wasInPromotion = wasInPromotionBeforeEvaluation(originalItem) || originalItem._wasInPromotionBeforeConsolidate === true;
1229
1287
  delete metadata._promotion;
1230
1288
  if (Array.isArray(newItem.product_bundle)) {
1231
1289
  var _iterator23 = _createForOfIteratorHelper(newItem.product_bundle),
@@ -1246,12 +1304,13 @@ export function processCartPromotion(list, evaluator, options) {
1246
1304
  var priceUnchangedPromo = _priced.inPromotion && Number(_priced.finalPrice) === Number(originalBasePrice);
1247
1305
  if (shouldModifyPrice) {
1248
1306
  if (_priced.inPromotion && !priceUnchangedPromo) {
1249
- var _priced$strategyMetad;
1307
+ var _priced$strategyMetad, _strategyActionMap$ge;
1250
1308
  var promoUnitPrice = new Decimal(_priced.finalPrice).toDecimalPlaces(2).toFixed(2);
1251
1309
  applyPromoUnitPriceToLine(newItem, {
1252
1310
  promoUnitPrice: promoUnitPrice,
1253
1311
  originalBasePrice: originalBasePrice,
1254
- strategyTitle: (_priced$strategyMetad = _priced.strategyMetadata) === null || _priced$strategyMetad === void 0 ? void 0 : _priced$strategyMetad.name
1312
+ strategyTitle: (_priced$strategyMetad = _priced.strategyMetadata) === null || _priced$strategyMetad === void 0 ? void 0 : _priced$strategyMetad.name,
1313
+ actionType: _priced.strategyId ? (_strategyActionMap$ge = strategyActionMap.get(_priced.strategyId)) === null || _strategyActionMap$ge === void 0 ? void 0 : _strategyActionMap$ge.actionType : undefined
1255
1314
  });
1256
1315
  } else {
1257
1316
  // 撤销上一轮促销:还原 selling_price 到 main_product_original_price 派生值
@@ -397,49 +397,52 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
397
397
  return _regeneratorRuntime().wrap(function _callee5$(_context5) {
398
398
  while (1) switch (_context5.prev = _context5.next) {
399
399
  case 0:
400
+ // 业务码切换或配置失败时不能复用上一次初始化的短号。
401
+ this.setPaymentNumberDevicePrefix(null);
400
402
  openDataConfig = null;
401
- _context5.prev = 1;
402
- _context5.next = 4;
403
+ _context5.prev = 2;
404
+ _context5.next = 5;
403
405
  return this.loadOpenDataConfig();
404
- case 4:
406
+ case 5:
405
407
  openDataConfig = _context5.sent;
406
- _context5.next = 11;
408
+ _context5.next = 12;
407
409
  break;
408
- case 7:
409
- _context5.prev = 7;
410
- _context5.t0 = _context5["catch"](1);
410
+ case 8:
411
+ _context5.prev = 8;
412
+ _context5.t0 = _context5["catch"](2);
411
413
  console.warn('[BookingTicket] OpenData 配置加载失败,跳过 idGenerator 配置', _context5.t0);
412
414
  return _context5.abrupt("return");
413
- case 11:
415
+ case 12:
414
416
  // if (!openDataConfig) return;
415
417
  idGenerator = this.getIdGeneratorPlugin();
416
418
  if (idGenerator !== null && idGenerator !== void 0 && idGenerator.configure) {
417
- _context5.next = 15;
419
+ _context5.next = 16;
418
420
  break;
419
421
  }
420
422
  console.warn('[BookingTicket] idGenerator 插件不可用,跳过配置');
421
423
  return _context5.abrupt("return");
422
- case 15:
424
+ case 16:
423
425
  receiptSequenceLength = this.normalizePositiveInteger((_openDataConfig = openDataConfig) === null || _openDataConfig === void 0 ? void 0 : _openDataConfig['sale.short_number_digits'], 5);
424
426
  receiptSequenceStart = this.normalizePositiveInteger((_openDataConfig2 = openDataConfig) === null || _openDataConfig2 === void 0 ? void 0 : _openDataConfig2['sale.short_number_start_number'], 1);
425
427
  prefix = this.normalizeIdPrefix((_openDataConfig3 = openDataConfig) === null || _openDataConfig3 === void 0 ? void 0 : _openDataConfig3['sale.short_number_prefix'], '');
426
428
  shopOrderPrefix = this.normalizeIdPrefix((_openDataConfig4 = openDataConfig) === null || _openDataConfig4 === void 0 ? void 0 : _openDataConfig4['sale.sale_number_prefix'], '');
427
429
  resetReceiptSequenceDaily = typeof ((_openDataConfig5 = openDataConfig) === null || _openDataConfig5 === void 0 ? void 0 : _openDataConfig5['sale.short_number_daily_reset']) === 'boolean' ? (_openDataConfig6 = openDataConfig) === null || _openDataConfig6 === void 0 ? void 0 : _openDataConfig6['sale.short_number_daily_reset'] : false;
428
430
  operatingDayBoundary = this.getAppData('operating_day_boundary');
429
- _context5.next = 23;
431
+ _context5.next = 24;
430
432
  return this.getShortNumberOrDeviceId();
431
- case 23:
433
+ case 24:
432
434
  deviceId = _context5.sent;
435
+ this.setPaymentNumberDevicePrefix(deviceId);
433
436
  businessCode = this.getBookingTicketBusinessCode();
434
437
  if (businessCode) {
435
- _context5.next = 28;
438
+ _context5.next = 30;
436
439
  break;
437
440
  }
438
441
  console.warn('[BookingTicket] businessCode 缺失,跳过 idGenerator 配置');
439
442
  return _context5.abrupt("return");
440
- case 28:
441
- _context5.prev = 28;
442
- _context5.next = 31;
443
+ case 30:
444
+ _context5.prev = 30;
445
+ _context5.next = 33;
443
446
  return idGenerator.configure({
444
447
  biz: businessCode,
445
448
  config: {
@@ -454,18 +457,18 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
454
457
  shopOrderPrefix: shopOrderPrefix
455
458
  }
456
459
  });
457
- case 31:
458
- _context5.next = 36;
459
- break;
460
460
  case 33:
461
- _context5.prev = 33;
462
- _context5.t1 = _context5["catch"](28);
461
+ _context5.next = 38;
462
+ break;
463
+ case 35:
464
+ _context5.prev = 35;
465
+ _context5.t1 = _context5["catch"](30);
463
466
  console.warn('[BookingTicket] idGenerator 配置失败', _context5.t1);
464
- case 36:
467
+ case 38:
465
468
  case "end":
466
469
  return _context5.stop();
467
470
  }
468
- }, _callee5, this, [[1, 7], [28, 33]]);
471
+ }, _callee5, this, [[2, 8], [30, 35]]);
469
472
  }));
470
473
  function configureIdGeneratorFromOpenData() {
471
474
  return _configureIdGeneratorFromOpenData.apply(this, arguments);
@@ -2602,16 +2605,18 @@ export var BookingTicketImpl = /*#__PURE__*/function (_BaseSalesImpl) {
2602
2605
  while (1) switch (_context31.prev = _context31.next) {
2603
2606
  case 0:
2604
2607
  _ref19 = _args31.length > 1 && _args31[1] !== undefined ? _args31[1] : {}, _ref19$cover = _ref19.cover, cover = _ref19$cover === void 0 ? false : _ref19$cover;
2605
- _get(_getPrototypeOf(BookingTicketImpl.prototype), "setOtherParams", this).call(this, params, {
2608
+ _context31.next = 3;
2609
+ return _get(_getPrototypeOf(BookingTicketImpl.prototype), "setOtherParams", this).call(this, params, {
2606
2610
  cover: cover
2607
2611
  });
2608
- if (!(params !== null && params !== void 0 && params.businessCode)) {
2609
- _context31.next = 5;
2612
+ case 3:
2613
+ if (!((params === null || params === void 0 ? void 0 : params.businessCode) !== undefined || (params === null || params === void 0 ? void 0 : params.business_code) !== undefined)) {
2614
+ _context31.next = 6;
2610
2615
  break;
2611
2616
  }
2612
- _context31.next = 5;
2617
+ _context31.next = 6;
2613
2618
  return this.configureIdGeneratorFromOpenData();
2614
- case 5:
2619
+ case 6:
2615
2620
  case "end":
2616
2621
  return _context31.stop();
2617
2622
  }
@@ -41,6 +41,10 @@ import { composeLinePrice, createUuidV4, getProductSkuOptions, normalizeSubmitCo
41
41
  import dayjs from 'dayjs';
42
42
  import { ItemRuleEvaluator } from "../../model/strategy/adapter/itemRule";
43
43
  export * from "./types";
44
+ function isItemRewardProductDiscount(discount) {
45
+ var _discount$metadata, _discount$metadata2;
46
+ return (discount === null || discount === void 0 ? void 0 : discount.type) === 'product' && (discount === null || discount === void 0 || (_discount$metadata = discount.metadata) === null || _discount$metadata === void 0 ? void 0 : _discount$metadata.source) === 'promotion' && (discount === null || discount === void 0 || (_discount$metadata2 = discount.metadata) === null || _discount$metadata2 === void 0 ? void 0 : _discount$metadata2.actionType) === 'ITEM_REWARD';
47
+ }
44
48
  export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
45
49
  _inherits(ScanOrderImpl, _BaseModule);
46
50
  var _super = _createSuper(ScanOrderImpl);
@@ -1177,7 +1181,7 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1177
1181
  _iterator3.s();
1178
1182
  case 19:
1179
1183
  if ((_step3 = _iterator3.n()).done) {
1180
- _context15.next = 33;
1184
+ _context15.next = 36;
1181
1185
  break;
1182
1186
  }
1183
1187
  product = _step3.value;
@@ -1185,8 +1189,15 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1185
1189
  _context15.next = 23;
1186
1190
  break;
1187
1191
  }
1188
- return _context15.abrupt("continue", 31);
1192
+ return _context15.abrupt("continue", 34);
1189
1193
  case 23:
1194
+ if (!(product.discount_list || []).some(isItemRewardProductDiscount)) {
1195
+ _context15.next = 26;
1196
+ break;
1197
+ }
1198
+ product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
1199
+ return _context15.abrupt("continue", 34);
1200
+ case 26:
1190
1201
  product.discount_list = (product.discount_list || []).filter(function (pd) {
1191
1202
  var _pd$discount$resource, _pd$discount;
1192
1203
  var rid = (_pd$discount$resource = (_pd$discount = pd.discount) === null || _pd$discount === void 0 ? void 0 : _pd$discount.resource_id) !== null && _pd$discount$resource !== void 0 ? _pd$discount$resource : pd.id;
@@ -1210,47 +1221,47 @@ export var ScanOrderImpl = /*#__PURE__*/function (_BaseModule) {
1210
1221
  mainPrice: newMainSellingPrice,
1211
1222
  bundle: product.product_bundle
1212
1223
  });
1213
- case 31:
1224
+ case 34:
1214
1225
  _context15.next = 19;
1215
1226
  break;
1216
- case 33:
1217
- _context15.next = 38;
1227
+ case 36:
1228
+ _context15.next = 41;
1218
1229
  break;
1219
- case 35:
1220
- _context15.prev = 35;
1221
- _context15.t0 = _context15["catch"](17);
1222
- _iterator3.e(_context15.t0);
1223
1230
  case 38:
1224
1231
  _context15.prev = 38;
1225
- _iterator3.f();
1226
- return _context15.finish(38);
1232
+ _context15.t0 = _context15["catch"](17);
1233
+ _iterator3.e(_context15.t0);
1227
1234
  case 41:
1235
+ _context15.prev = 41;
1236
+ _iterator3.f();
1237
+ return _context15.finish(41);
1238
+ case 44:
1228
1239
  OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
1229
- _context15.next = 44;
1240
+ _context15.next = 47;
1230
1241
  return discountModule === null || discountModule === void 0 ? void 0 : discountModule.setDiscountList(nextDiscountList);
1231
- case 44:
1242
+ case 47:
1232
1243
  tempOrder.discount_list = (nextDiscountList || []).filter(function (d) {
1233
1244
  return d.isSelected;
1234
1245
  });
1235
- _context15.next = 47;
1246
+ _context15.next = 50;
1236
1247
  return this.store.order.recalculateSummary({
1237
1248
  createIfMissing: true
1238
1249
  });
1239
- case 47:
1250
+ case 50:
1240
1251
  this.store.order.persistTempOrder();
1241
1252
  this.logMethodSuccess('setDiscountSelected', params);
1242
- _context15.next = 55;
1253
+ _context15.next = 58;
1243
1254
  break;
1244
- case 51:
1245
- _context15.prev = 51;
1255
+ case 54:
1256
+ _context15.prev = 54;
1246
1257
  _context15.t1 = _context15["catch"](1);
1247
1258
  this.logMethodError('setDiscountSelected', _context15.t1);
1248
1259
  throw _context15.t1;
1249
- case 55:
1260
+ case 58:
1250
1261
  case "end":
1251
1262
  return _context15.stop();
1252
1263
  }
1253
- }, _callee15, this, [[1, 51], [17, 35, 38, 41]]);
1264
+ }, _callee15, this, [[1, 54], [17, 38, 41, 44]]);
1254
1265
  }));
1255
1266
  function setDiscountSelected(_x8) {
1256
1267
  return _setDiscountSelected.apply(this, arguments);
@@ -51,6 +51,10 @@ import { RegisterAndLoginHooks } from "../RegisterAndLogin/types";
51
51
  import Decimal from 'decimal.js';
52
52
  export * from "./types";
53
53
  var OPEN_DATA_SECTION_CODES = ['basic', 'fulfillment', 'reservation', 'sale', 'menu', 'availability', 'workflow', 'checkout'];
54
+ function isItemRewardProductDiscount(discount) {
55
+ var _discount$metadata, _discount$metadata2;
56
+ return (discount === null || discount === void 0 ? void 0 : discount.type) === 'product' && (discount === null || discount === void 0 || (_discount$metadata = discount.metadata) === null || _discount$metadata === void 0 ? void 0 : _discount$metadata.source) === 'promotion' && (discount === null || discount === void 0 || (_discount$metadata2 = discount.metadata) === null || _discount$metadata2 === void 0 ? void 0 : _discount$metadata2.actionType) === 'ITEM_REWARD';
57
+ }
54
58
  function cloneCustomDepositData(customDepositData) {
55
59
  if (!customDepositData || _typeof(customDepositData) !== 'object') return undefined;
56
60
  return _objectSpread(_objectSpread({}, customDepositData), {}, {
@@ -2163,7 +2167,7 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
2163
2167
  _iterator14.s();
2164
2168
  case 21:
2165
2169
  if ((_step14 = _iterator14.n()).done) {
2166
- _context21.next = 35;
2170
+ _context21.next = 38;
2167
2171
  break;
2168
2172
  }
2169
2173
  product = _step14.value;
@@ -2171,8 +2175,15 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
2171
2175
  _context21.next = 25;
2172
2176
  break;
2173
2177
  }
2174
- return _context21.abrupt("continue", 33);
2178
+ return _context21.abrupt("continue", 36);
2175
2179
  case 25:
2180
+ if (!(product.discount_list || []).some(isItemRewardProductDiscount)) {
2181
+ _context21.next = 28;
2182
+ break;
2183
+ }
2184
+ product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
2185
+ return _context21.abrupt("continue", 36);
2186
+ case 28:
2176
2187
  // 1. 把 product.discount_list 和当前选中的 discount 对齐(剔除已取消的券)
2177
2188
  product.discount_list = (product.discount_list || []).filter(function (pd) {
2178
2189
  var _pd$discount$resource, _pd$discount;
@@ -2197,36 +2208,36 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
2197
2208
  mainPrice: newMainSellingPrice,
2198
2209
  bundle: product.product_bundle
2199
2210
  });
2200
- case 33:
2211
+ case 36:
2201
2212
  _context21.next = 21;
2202
2213
  break;
2203
- case 35:
2204
- _context21.next = 40;
2214
+ case 38:
2215
+ _context21.next = 43;
2205
2216
  break;
2206
- case 37:
2207
- _context21.prev = 37;
2208
- _context21.t0 = _context21["catch"](19);
2209
- _iterator14.e(_context21.t0);
2210
2217
  case 40:
2211
2218
  _context21.prev = 40;
2212
- _iterator14.f();
2213
- return _context21.finish(40);
2219
+ _context21.t0 = _context21["catch"](19);
2220
+ _iterator14.e(_context21.t0);
2214
2221
  case 43:
2222
+ _context21.prev = 43;
2223
+ _iterator14.f();
2224
+ return _context21.finish(43);
2225
+ case 46:
2215
2226
  OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
2216
- _context21.next = 46;
2227
+ _context21.next = 49;
2217
2228
  return discountModule === null || discountModule === void 0 ? void 0 : discountModule.setDiscountList(nextDiscountList);
2218
- case 46:
2229
+ case 49:
2219
2230
  tempOrder.discount_list = (nextDiscountList || []).filter(function (d) {
2220
2231
  return d.isSelected;
2221
2232
  });
2222
2233
  afterApplyTarget = this.store.order.getDiscountList().find(function (d) {
2223
2234
  return d.id === params.discountId;
2224
2235
  }) || null;
2225
- _context21.next = 50;
2236
+ _context21.next = 53;
2226
2237
  return this.store.order.recalculateSummary({
2227
2238
  createIfMissing: true
2228
2239
  });
2229
- case 50:
2240
+ case 53:
2230
2241
  this.store.order.persistTempOrder();
2231
2242
  finalSummary = ((_this$store$order$get = this.store.order.getTempOrder()) === null || _this$store$order$get === void 0 ? void 0 : _this$store$order$get.summary) || null;
2232
2243
  finalProduct = ((_this$store$order$get2 = this.store.order.getTempOrder()) === null || _this$store$order$get2 === void 0 || (_this$store$order$get2 = _this$store$order$get2.products) === null || _this$store$order$get2 === void 0 ? void 0 : _this$store$order$get2[0]) || null;
@@ -2235,16 +2246,16 @@ export var VenueBookingImpl = /*#__PURE__*/function (_BaseModule) {
2235
2246
  return d.id === params.discountId;
2236
2247
  }) || null;
2237
2248
  return _context21.abrupt("return", this.store.order.getDiscountList());
2238
- case 58:
2239
- _context21.prev = 58;
2249
+ case 61:
2250
+ _context21.prev = 61;
2240
2251
  _context21.t1 = _context21["catch"](1);
2241
2252
  this.logMethodError('setDiscountSelected', _context21.t1);
2242
2253
  throw _context21.t1;
2243
- case 62:
2254
+ case 65:
2244
2255
  case "end":
2245
2256
  return _context21.stop();
2246
2257
  }
2247
- }, _callee21, this, [[1, 58], [19, 37, 40, 43]]);
2258
+ }, _callee21, this, [[1, 61], [19, 40, 43, 46]]);
2248
2259
  }));
2249
2260
  function setDiscountSelected(_x15) {
2250
2261
  return _setDiscountSelected.apply(this, arguments);
@@ -48,6 +48,10 @@ export declare class PromotionAdapter implements BusinessAdapter {
48
48
  * 解析 买X送Y Action
49
49
  */
50
50
  private parseBuyXGetYFreeAction;
51
+ /**
52
+ * 解析 商品奖励 Action
53
+ */
54
+ private parseItemRewardAction;
51
55
  /**
52
56
  * 获取适用的商品列表
53
57
  *