@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
@@ -28,6 +28,8 @@ var PROMOTION_ACTION_TYPES = {
28
28
  X_ITEMS_FOR_Y_PRICE: "X_ITEMS_FOR_Y_PRICE",
29
29
  /** 买X送Y(买X件送Y件,可累计) */
30
30
  BUY_X_GET_Y_FREE: "BUY_X_GET_Y_FREE",
31
+ /** 商品奖励(满足条件后,订单内指定目标商品享优惠) */
32
+ ITEM_REWARD: "ITEM_REWARD",
31
33
  /** 固定折扣 */
32
34
  DISCOUNT_RATE: "DISCOUNT_RATE",
33
35
  /** 固定减价 */
@@ -85,6 +85,11 @@ function isPaidPaymentRecord(payment) {
85
85
  function isCommittedVoucherPaymentRecord(payment) {
86
86
  return isVoucherPaymentRecord(payment) && (payment == null ? void 0 : payment.status) !== "voided" && (hasSyncedOrderPaymentRecord(payment) || isPaidPaymentRecord(payment));
87
87
  }
88
+ function getVoucherPaymentLifecycleKey(payment) {
89
+ if (!isVoucherPaymentRecord(payment))
90
+ return null;
91
+ return `${String(payment.voucher_id)}::${String(payment.status || "")}`;
92
+ }
88
93
  var OrderModule = class extends import_BaseModule.BaseModule {
89
94
  constructor(name, version) {
90
95
  super(name || "order", version);
@@ -2746,14 +2751,15 @@ var OrderModule = class extends import_BaseModule.BaseModule {
2746
2751
  const committedVoucherPaymentIds = new Set(
2747
2752
  committedVoucherPayments.filter((payment) => hasSyncedOrderPaymentRecord(payment)).map((payment) => String(payment.order_payment_id))
2748
2753
  );
2749
- const committedVoucherIds = new Set(
2750
- committedVoucherPayments.map((payment) => String(payment.voucher_id))
2754
+ const committedVoucherLifecycleKeys = new Set(
2755
+ committedVoucherPayments.map((payment) => getVoucherPaymentLifecycleKey(payment)).filter((key) => key !== null)
2751
2756
  );
2752
2757
  const replaceableVouchers = mappedVouchers.filter((payment) => {
2753
2758
  if (hasSyncedOrderPaymentRecord(payment) && committedVoucherPaymentIds.has(String(payment.order_payment_id))) {
2754
2759
  return false;
2755
2760
  }
2756
- if (payment.voucher_id !== void 0 && committedVoucherIds.has(String(payment.voucher_id))) {
2761
+ const lifecycleKey = getVoucherPaymentLifecycleKey(payment);
2762
+ if (lifecycleKey && committedVoucherLifecycleKeys.has(lifecycleKey)) {
2757
2763
  return false;
2758
2764
  }
2759
2765
  return true;
@@ -444,7 +444,12 @@ function resolveEffectivePerUnitDiscount(product) {
444
444
  (sum, discount) => sum + Number((discount == null ? void 0 : discount.amount) || 0),
445
445
  0
446
446
  );
447
- const hasPromoDiscountItem = discountList.some((item) => (item == null ? void 0 : item.type) === "promotion");
447
+ const hasPromoDiscountItem = discountList.some(
448
+ (item) => {
449
+ var _a, _b;
450
+ return (item == null ? void 0 : item.type) === "promotion" || (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
451
+ }
452
+ );
448
453
  if (hasPromoDiscountItem)
449
454
  return fromList;
450
455
  const metadata = (product == null ? void 0 : product.metadata) || {};
@@ -35,6 +35,7 @@ export declare class RulesModule extends BaseModule implements Module, RulesModu
35
35
  excludeDiscountListByType(discountList: Discount[], type: string): Discount[];
36
36
  /** 手动改价场景:去掉 promotion,保留 type=product 等行内折扣 */
37
37
  resolveDiscountListForManualOverride(discountList: Discount[]): Discount[];
38
+ private isItemRewardProductDiscount;
38
39
  private getUnavailableReason;
39
40
  calcDiscount({ discountList, productList, holders, isFormSubject, orderTotalAmount }: {
40
41
  discountList: Discount[];
@@ -167,6 +167,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
167
167
  resolveDiscountListForManualOverride(discountList) {
168
168
  return this.excludeDiscountListByType(discountList, "promotion");
169
169
  }
170
+ isItemRewardProductDiscount(product) {
171
+ var _a;
172
+ const discountList = Array.isArray(product == null ? void 0 : product.discount_list) ? product.discount_list : [];
173
+ return ((_a = product == null ? void 0 : product._promotion) == null ? void 0 : _a.actionType) === "ITEM_REWARD" && discountList.some(
174
+ (item) => {
175
+ var _a2, _b;
176
+ return (item == null ? void 0 : item.type) === "product" && ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
177
+ }
178
+ );
179
+ }
170
180
  // 获取券不可用的原因
171
181
  getUnavailableReason(discountList, productList) {
172
182
  var _a;
@@ -500,6 +510,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
500
510
  startDate: (_a2 = flatItem.parentProduct) == null ? void 0 : _a2.startDate
501
511
  };
502
512
  }
513
+ if (this.isItemRewardProductDiscount(product)) {
514
+ return false;
515
+ }
503
516
  const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
504
517
  if (!isAvailableProduct) {
505
518
  return false;
@@ -625,6 +638,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
625
638
  };
626
639
  originProduct = flatItem.originProduct;
627
640
  }
641
+ const isItemRewardProductDiscount = this.isItemRewardProductDiscount(product);
628
642
  addModeDiscount.forEach((discount) => {
629
643
  var _a3, _b, _c, _d, _e, _f, _g, _h, _i, _j;
630
644
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
@@ -648,7 +662,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
648
662
  ].includes(discount2.tag || discount2.type)
649
663
  ))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
650
664
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
651
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
665
+ if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
652
666
  (_h = discountApplicability.get(discount.id)) == null ? void 0 : _h.push(product.id);
653
667
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
654
668
  const discountType = discount.tag || discount.type;
@@ -771,6 +785,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
771
785
  }
772
786
  const applicableDiscounts = sortedDiscountList.filter((discount) => {
773
787
  var _a3, _b2, _c2, _d2;
788
+ if (this.isItemRewardProductDiscount(product))
789
+ return false;
774
790
  const discountType = discount.tag || discount.type;
775
791
  const currentOriginUid = getOriginProductUid(originProduct);
776
792
  const isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
@@ -845,6 +861,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
845
861
  );
846
862
  const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
847
863
  let isManualDiscount = false;
864
+ let isItemRewardProductDiscount = false;
848
865
  if (flatItem.type === "main") {
849
866
  isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : ((_g = product.discount_list) == null ? void 0 : _g.some((item) => item.type === "product")) || product.total != product.origin_total && (product.bundle || []).every(
850
867
  (item) => {
@@ -855,7 +872,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
855
872
  _i,
856
873
  (item) => item.type === "product"
857
874
  )));
858
- if (product.inPromotion) {
875
+ isItemRewardProductDiscount = this.isItemRewardProductDiscount(product);
876
+ if (product.inPromotion && !isItemRewardProductDiscount) {
859
877
  isManualDiscount = false;
860
878
  }
861
879
  } else {
@@ -969,7 +987,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
969
987
  } else {
970
988
  let total = product.inPromotion ? ((_w = product == null ? void 0 : product._promotion) == null ? void 0 : _w.finalPrice) ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
971
989
  let main_product_selling_price = product.price;
972
- if ((product.discount_list || []).some((item) => item.type === "promotion") || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
990
+ if ((product.discount_list || []).some((item) => item.type === "promotion") || isItemRewardProductDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
973
991
  total = product.total ?? product.origin_total;
974
992
  main_product_selling_price = product.main_product_selling_price ?? main_product_selling_price;
975
993
  }
@@ -977,7 +995,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
977
995
  this.hooks.setProduct(originProduct, {
978
996
  ...isManualDiscount ? {
979
997
  price: product.price,
980
- main_product_selling_price: product.price
998
+ main_product_selling_price: isItemRewardProductDiscount ? main_product_selling_price : product.price,
999
+ ...isItemRewardProductDiscount ? { total } : {}
981
1000
  } : {
982
1001
  _id: product._id.split("___")[0] + "___" + index,
983
1002
  total,
@@ -48,6 +48,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
48
48
  protected store: BaseSalesState;
49
49
  protected otherParams: Record<string, any>;
50
50
  protected cacheId: string | undefined;
51
+ /**
52
+ * 由已在初始化阶段解析过设备短号的业务解决方案写入。
53
+ * 未设置时,支付编号仍按原逻辑实时读取设备信息。
54
+ */
55
+ protected paymentNumberDevicePrefix: string | null;
51
56
  /**
52
57
  * window / request 暴露为 public:现存外部工具(如 BookingTicket Scan)通过
53
58
  * `solution.window` / `solution.request` 直接访问插件,保持原有契约不破坏。
@@ -141,6 +146,11 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
141
146
  */
142
147
  protected readSessionCacheData(): Record<string, any>;
143
148
  protected getAppData<T>(key: string): T | undefined;
149
+ /**
150
+ * 复用业务解决方案初始化时已解析的支付设备短号。
151
+ * 空值会清除缓存,使后续支付恢复实时读取设备信息的兼容路径。
152
+ */
153
+ protected setPaymentNumberDevicePrefix(prefix: unknown): void;
144
154
  private getPaymentNumberDevicePrefixSync;
145
155
  private getPaymentNumberDevicePrefixAsync;
146
156
  private syncAppDataToTempOrder;
@@ -284,7 +294,10 @@ export declare class BaseSalesImpl extends BaseModule implements Module {
284
294
  * 同步兼容入口。无法等待 IoT 短号时,按调用当下的 device_id 或 LOCAL 生成。
285
295
  */
286
296
  addOrderPayment(payment: OrderPaymentSource): OrderPaymentData[];
287
- /** 创建新支付项时读取最新设备短号,不缓存运行时设备信息。 */
297
+ /**
298
+ * 创建新支付项时优先使用业务解决方案初始化阶段缓存的设备短号;
299
+ * 未缓存的通用 BaseSales 保持实时读取设备信息的兼容语义。
300
+ */
288
301
  addOrderPaymentAsync(payment: OrderPaymentSource): Promise<OrderPaymentData[]>;
289
302
  private addOrderPaymentWithDevicePrefix;
290
303
  /** 更新当前订单中的指定支付项。 */
@@ -332,6 +332,11 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
332
332
  order: void 0
333
333
  };
334
334
  this.otherParams = {};
335
+ /**
336
+ * 由已在初始化阶段解析过设备短号的业务解决方案写入。
337
+ * 未设置时,支付编号仍按原逻辑实时读取设备信息。
338
+ */
339
+ this.paymentNumberDevicePrefix = null;
335
340
  // 当前缓存中已加载的最新 SalesDetail;只读 getter 走它对外暴露详情数据。
336
341
  this.currentSalesDetail = null;
337
342
  this.discountConfigCacheKey = null;
@@ -862,6 +867,14 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
862
867
  const coreData = (_f = (_d = (_c = app == null ? void 0 : app.models) == null ? void 0 : _c.getStore) == null ? void 0 : (_e = _d.call(_c)).getDataByModel) == null ? void 0 : _f.call(_e, "core", "core");
863
868
  return coreData == null ? void 0 : coreData[key];
864
869
  }
870
+ /**
871
+ * 复用业务解决方案初始化时已解析的支付设备短号。
872
+ * 空值会清除缓存,使后续支付恢复实时读取设备信息的兼容路径。
873
+ */
874
+ setPaymentNumberDevicePrefix(prefix) {
875
+ const normalized = String(prefix ?? "").trim();
876
+ this.paymentNumberDevicePrefix = normalized || null;
877
+ }
865
878
  getPaymentNumberDevicePrefixSync() {
866
879
  if (!this.appPlugin)
867
880
  return "LOCAL";
@@ -870,6 +883,9 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
870
883
  getPaymentNumberDevicePrefixAsync() {
871
884
  if (!this.appPlugin)
872
885
  return Promise.resolve("LOCAL");
886
+ if (this.paymentNumberDevicePrefix) {
887
+ return Promise.resolve(this.paymentNumberDevicePrefix);
888
+ }
873
889
  return (0, import_payment_number.resolvePaymentNumberDevicePrefix)((key) => this.getAppData(key));
874
890
  }
875
891
  syncAppDataToTempOrder(tempOrder) {
@@ -912,6 +928,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
912
928
  var _a, _b;
913
929
  this.core = core;
914
930
  this.initializeOptions = options || {};
931
+ this.paymentNumberDevicePrefix = null;
915
932
  this.otherParams = options.otherParams || {};
916
933
  this.cacheId = (_a = this.otherParams) == null ? void 0 : _a.cacheId;
917
934
  this.reusedSharedSubModuleNames.clear();
@@ -973,6 +990,7 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
973
990
  }
974
991
  });
975
992
  this.currentSalesDetail = null;
993
+ this.paymentNumberDevicePrefix = null;
976
994
  this.queuedServerOrderChanges = [];
977
995
  this.salesDetailLoadSequence += 1;
978
996
  await this.core.effects.emit(`${this.name}:onDestroy`, {});
@@ -2032,7 +2050,10 @@ var BaseSalesImpl = class extends import_BaseModule.BaseModule {
2032
2050
  hasPaymentNumber ? "LOCAL" : this.getPaymentNumberDevicePrefixSync()
2033
2051
  );
2034
2052
  }
2035
- /** 创建新支付项时读取最新设备短号,不缓存运行时设备信息。 */
2053
+ /**
2054
+ * 创建新支付项时优先使用业务解决方案初始化阶段缓存的设备短号;
2055
+ * 未缓存的通用 BaseSales 保持实时读取设备信息的兼容语义。
2056
+ */
2036
2057
  async addOrderPaymentAsync(payment) {
2037
2058
  const paymentRecord = payment;
2038
2059
  const hasPaymentNumber = String(paymentRecord.payment_number || "").trim() !== "";
@@ -78,6 +78,7 @@ export interface CartPromotionEvaluator {
78
78
  }>;
79
79
  hasApplicableStrategy: boolean;
80
80
  }>;
81
+ getStrategyConfigs?: () => unknown[];
81
82
  }
82
83
  /** 单个赠品减量项 */
83
84
  export interface GiftReduceItem {
@@ -267,7 +268,8 @@ export declare function appendPromotionTags<T extends Record<string, any>>(produ
267
268
  * 处理购物车的促销计算与赠品差异化。
268
269
  *
269
270
  * 流程:
270
- * 1. 分离 main / gift / edit-product 三类(带 `booking_id` 的编辑态商品不参与促销)
271
+ * 1. 分离 main / gift / edit-product 三类(普通促销下带 `booking_id` 的编辑态商品不参与;
272
+ * 配置 ITEM_REWARD 时,编辑态商品也参与商品奖励重算)
271
273
  * 2. 转 PromotionProduct 喂评估器 → 拿到 `evaluateCartWithPricing` 与 `getProductsApplicableStrategies`
272
274
  * 3. 把 PricedProduct 映射回 OrderProduct 形态:
273
275
  * - 参与促销的,写 `metadata._promotion` + 调整 `selling_price` / `main_product_selling_price`
@@ -77,19 +77,43 @@ function getOrderProductOriginalPriceForPromotion(product) {
77
77
  }
78
78
  return getOrderProductBasePrice(product);
79
79
  }
80
- function updatePromotionDiscountList(item, promotionDiscount) {
80
+ var X_ITEMS_FOR_Y_PRICE = "X_ITEMS_FOR_Y_PRICE";
81
+ var ITEM_REWARD = "ITEM_REWARD";
82
+ function isItemRewardPromotionDiscountItem(item) {
83
+ var _a, _b;
84
+ return (item == null ? void 0 : item.type) === "product" && ((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = item == null ? void 0 : item.metadata) == null ? void 0 : _b.actionType) === ITEM_REWARD;
85
+ }
86
+ function isManagedPromotionDiscountItem(item) {
87
+ if ((item == null ? void 0 : item.type) === "promotion")
88
+ return true;
89
+ return isItemRewardPromotionDiscountItem(item);
90
+ }
91
+ function wasInPromotionBeforeEvaluation(item) {
92
+ var _a, _b;
93
+ if (((_b = (_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a._promotion) == null ? void 0 : _b.inPromotion) === true)
94
+ return true;
95
+ return Array.isArray(item == null ? void 0 : item.discount_list) && item.discount_list.some(isItemRewardPromotionDiscountItem);
96
+ }
97
+ function updatePromotionDiscountList(item, promotionDiscount, options) {
81
98
  let discountList = Array.isArray(item.discount_list) ? [...item.discount_list] : [];
82
- discountList = discountList.filter((d) => (d == null ? void 0 : d.type) !== "promotion");
99
+ discountList = discountList.filter((d) => !isManagedPromotionDiscountItem(d));
83
100
  if (promotionDiscount) {
101
+ const discountType = (options == null ? void 0 : options.discountType) || "promotion";
84
102
  discountList.push({
85
- type: "promotion",
103
+ type: discountType,
86
104
  amount: promotionDiscount.amount,
87
105
  discount: {
88
106
  original_amount: promotionDiscount.original_amount,
89
107
  fixed_amount: promotionDiscount.fixed_amount,
90
108
  title: promotionDiscount.title,
91
109
  resource_id: ""
92
- }
110
+ },
111
+ ...discountType === "product" ? {
112
+ metadata: {
113
+ source: "promotion",
114
+ actionType: (options == null ? void 0 : options.actionType) || ITEM_REWARD
115
+ }
116
+ } : {}
93
117
  });
94
118
  }
95
119
  if (discountList.length > 0) {
@@ -98,7 +122,15 @@ function updatePromotionDiscountList(item, promotionDiscount) {
98
122
  delete item.discount_list;
99
123
  }
100
124
  }
101
- var X_ITEMS_FOR_Y_PRICE = "X_ITEMS_FOR_Y_PRICE";
125
+ function evaluatorHasActionType(evaluator, actionType) {
126
+ var _a;
127
+ const configs = (_a = evaluator == null ? void 0 : evaluator.getStrategyConfigs) == null ? void 0 : _a.call(evaluator);
128
+ if (!Array.isArray(configs))
129
+ return false;
130
+ return configs.some(
131
+ (config) => ((config == null ? void 0 : config.actions) || []).some((action) => (action == null ? void 0 : action.type) === actionType)
132
+ );
133
+ }
102
134
  function applyPromoUnitPriceToLine(item, input) {
103
135
  const metadata = item.metadata || (item.metadata = {});
104
136
  const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(item)).toNumber();
@@ -125,6 +157,9 @@ function applyPromoUnitPriceToLine(item, input) {
125
157
  amount: discountAmount,
126
158
  original_amount: catalogSource,
127
159
  fixed_amount: discountAmount
160
+ }, {
161
+ actionType: input.actionType,
162
+ discountType: input.actionType === ITEM_REWARD ? "product" : "promotion"
128
163
  });
129
164
  } else {
130
165
  updatePromotionDiscountList(item, null);
@@ -396,14 +431,13 @@ function buildConsolidateKeyForPromotion(item) {
396
431
  ].join("#");
397
432
  }
398
433
  function consolidateMainProductsForPromotion(entries) {
399
- var _a, _b;
400
434
  if (!Array.isArray(entries) || entries.length <= 1) {
401
435
  return [...entries || []];
402
436
  }
403
437
  const groups = /* @__PURE__ */ new Map();
404
438
  for (const { item, originalListIndex } of entries) {
405
439
  const key = buildConsolidateKeyForPromotion(item);
406
- const wasInPromotion = ((_b = (_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a._promotion) == null ? void 0 : _b.inPromotion) === true;
440
+ const wasInPromotion = wasInPromotionBeforeEvaluation(item);
407
441
  const existing = groups.get(key);
408
442
  if (!existing) {
409
443
  const mergedItem = (0, import_lodash_es.cloneDeep)(item);
@@ -469,6 +503,9 @@ function splitXItemsPromoLinesByGroup(lines, strategyActionMap) {
469
503
  function generateNumericId() {
470
504
  return Math.floor(Math.random() * 1e9) + Date.now();
471
505
  }
506
+ function isBookingEditProductLine(product) {
507
+ return (product == null ? void 0 : product.booking_id) !== void 0 && (product == null ? void 0 : product.booking_id) !== null && product.booking_id !== 0 && product.booking_id !== "0";
508
+ }
472
509
  function convertToPromotionProduct(product, index) {
473
510
  const metadata = (product == null ? void 0 : product.metadata) || {};
474
511
  const numericId = generateNumericId();
@@ -481,6 +518,7 @@ function convertToPromotionProduct(product, index) {
481
518
  price: getOrderProductOriginalPriceForPromotion(product),
482
519
  quantity: Number((product == null ? void 0 : product.num) ?? 1) || 1,
483
520
  bundle: getProductBundleForEvaluator(product),
521
+ _promotionOnlyForItemReward: isBookingEditProductLine(product),
484
522
  _originalItem: originalItem,
485
523
  _originalId: getOrderProductUid(product),
486
524
  _originalIndex: index
@@ -582,6 +620,9 @@ function resolveStrategyRequiredQuantity(matched) {
582
620
  if (matched.actionType === "BUY_X_GET_Y_FREE") {
583
621
  return Number(detail.buyQuantity) || 1;
584
622
  }
623
+ if (matched.actionType === "ITEM_REWARD") {
624
+ return Number(detail.triggerQuantity) || 1;
625
+ }
585
626
  return 1;
586
627
  }
587
628
  function resolveStrategyEligibleProducts(matched) {
@@ -692,6 +733,10 @@ function processCartPromotion(list, evaluator, options) {
692
733
  };
693
734
  if (!list || list.length === 0 || !evaluator)
694
735
  return empty;
736
+ const shouldIncludeEditProductsForItemReward = evaluatorHasActionType(
737
+ evaluator,
738
+ ITEM_REWARD
739
+ );
695
740
  const mainProductsWithIndex = [];
696
741
  const existingGiftsWithIndex = [];
697
742
  const editProductsWithIndex = [];
@@ -702,8 +747,12 @@ function processCartPromotion(list, evaluator, options) {
702
747
  editProductsWithIndex.push({ item, originalListIndex: i });
703
748
  } else if (giftInfo) {
704
749
  existingGiftsWithIndex.push({ item, originalListIndex: i });
705
- } else if ((item == null ? void 0 : item.booking_id) !== void 0 && (item == null ? void 0 : item.booking_id) !== null && item.booking_id !== 0 && item.booking_id !== "0") {
706
- editProductsWithIndex.push({ item, originalListIndex: i });
750
+ } else if (isBookingEditProductLine(item)) {
751
+ if (shouldIncludeEditProductsForItemReward) {
752
+ mainProductsWithIndex.push({ item, originalListIndex: i });
753
+ } else {
754
+ editProductsWithIndex.push({ item, originalListIndex: i });
755
+ }
707
756
  } else {
708
757
  mainProductsWithIndex.push({ item, originalListIndex: i });
709
758
  }
@@ -746,7 +795,8 @@ function processCartPromotion(list, evaluator, options) {
746
795
  name: ((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.product_name) || (item == null ? void 0 : item.title) || "",
747
796
  price: getOrderProductBasePrice(item),
748
797
  quantity: Number((item == null ? void 0 : item.num) ?? 1) || 1,
749
- bundle: getProductBundleForEvaluator(item)
798
+ bundle: getProductBundleForEvaluator(item),
799
+ _promotionOnlyForItemReward: isBookingEditProductLine(item)
750
800
  };
751
801
  });
752
802
  for (let i = 0; i < consolidatedMainProductsWithIndex.length; i++) {
@@ -815,7 +865,7 @@ function processCartPromotion(list, evaluator, options) {
815
865
  const metadata = newItem.metadata || {};
816
866
  const sourceCartNum = (0, import_utils2.getSafeProductNum)(originalItem.num);
817
867
  newItem._sourceCartNum = sourceCartNum;
818
- const wasInPromotion = ((_a = metadata._promotion) == null ? void 0 : _a.inPromotion) === true || originalItem._wasInPromotionBeforeConsolidate === true;
868
+ const wasInPromotion = wasInPromotionBeforeEvaluation(originalItem) || originalItem._wasInPromotionBeforeConsolidate === true;
819
869
  delete metadata._promotion;
820
870
  if (Array.isArray(newItem.product_bundle)) {
821
871
  for (const b of newItem.product_bundle) {
@@ -832,7 +882,8 @@ function processCartPromotion(list, evaluator, options) {
832
882
  applyPromoUnitPriceToLine(newItem, {
833
883
  promoUnitPrice,
834
884
  originalBasePrice,
835
- strategyTitle: (_b = priced.strategyMetadata) == null ? void 0 : _b.name
885
+ strategyTitle: (_a = priced.strategyMetadata) == null ? void 0 : _a.name,
886
+ actionType: priced.strategyId ? (_b = strategyActionMap.get(priced.strategyId)) == null ? void 0 : _b.actionType : void 0
836
887
  });
837
888
  } else {
838
889
  const optionSum = (0, import_utils.sumOptionUnitPrice)((0, import_utils.getProductSkuOptions)(newItem)).toNumber();
@@ -233,6 +233,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
233
233
  return String(this.getAppData("device_id") || 0).slice(-2);
234
234
  }
235
235
  async configureIdGeneratorFromOpenData() {
236
+ this.setPaymentNumberDevicePrefix(null);
236
237
  let openDataConfig = null;
237
238
  try {
238
239
  openDataConfig = await this.loadOpenDataConfig();
@@ -264,6 +265,7 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
264
265
  const resetReceiptSequenceDaily = typeof (openDataConfig == null ? void 0 : openDataConfig["sale.short_number_daily_reset"]) === "boolean" ? openDataConfig == null ? void 0 : openDataConfig["sale.short_number_daily_reset"] : false;
265
266
  const operatingDayBoundary = this.getAppData("operating_day_boundary");
266
267
  const deviceId = await this.getShortNumberOrDeviceId();
268
+ this.setPaymentNumberDevicePrefix(deviceId);
267
269
  const businessCode = this.getBookingTicketBusinessCode();
268
270
  if (!businessCode) {
269
271
  console.warn("[BookingTicket] businessCode 缺失,跳过 idGenerator 配置");
@@ -1527,8 +1529,8 @@ var BookingTicketImpl = class extends import_BaseSales.BaseSalesImpl {
1527
1529
  return result;
1528
1530
  }
1529
1531
  async setOtherParams(params, { cover = false } = {}) {
1530
- super.setOtherParams(params, { cover });
1531
- if (params == null ? void 0 : params.businessCode) {
1532
+ await super.setOtherParams(params, { cover });
1533
+ if ((params == null ? void 0 : params.businessCode) !== void 0 || (params == null ? void 0 : params.business_code) !== void 0) {
1532
1534
  await this.configureIdGeneratorFromOpenData();
1533
1535
  }
1534
1536
  }
@@ -48,6 +48,10 @@ var import_utils2 = require("../../modules/Order/utils");
48
48
  var import_dayjs = __toESM(require("dayjs"));
49
49
  var import_itemRule = require("../../model/strategy/adapter/itemRule");
50
50
  __reExport(ScanOrder_exports, require("./types"), module.exports);
51
+ function isItemRewardProductDiscount(discount) {
52
+ var _a, _b;
53
+ return (discount == null ? void 0 : discount.type) === "product" && ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
54
+ }
51
55
  var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
52
56
  constructor(name, version) {
53
57
  super(name, version);
@@ -742,6 +746,10 @@ var _ScanOrderImpl = class extends import_BaseModule.BaseModule {
742
746
  for (const product of tempOrder.products) {
743
747
  if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
744
748
  continue;
749
+ if ((product.discount_list || []).some(isItemRewardProductDiscount)) {
750
+ product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
751
+ continue;
752
+ }
745
753
  product.discount_list = (product.discount_list || []).filter((pd) => {
746
754
  var _a2;
747
755
  const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
@@ -65,6 +65,10 @@ var OPEN_DATA_SECTION_CODES = [
65
65
  "workflow",
66
66
  "checkout"
67
67
  ];
68
+ function isItemRewardProductDiscount(discount) {
69
+ var _a, _b;
70
+ return (discount == null ? void 0 : discount.type) === "product" && ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.source) === "promotion" && ((_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.actionType) === "ITEM_REWARD";
71
+ }
68
72
  function cloneCustomDepositData(customDepositData) {
69
73
  if (!customDepositData || typeof customDepositData !== "object")
70
74
  return void 0;
@@ -1339,6 +1343,10 @@ var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
1339
1343
  for (const product of tempOrder.products) {
1340
1344
  if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
1341
1345
  continue;
1346
+ if ((product.discount_list || []).some(isItemRewardProductDiscount)) {
1347
+ product.discount_list = (product.discount_list || []).filter(isItemRewardProductDiscount);
1348
+ continue;
1349
+ }
1342
1350
  product.discount_list = (product.discount_list || []).filter((pd) => {
1343
1351
  var _a2;
1344
1352
  const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.265",
4
+ "version": "2.2.266",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",