@pisell/pisellos 2.1.150 → 2.1.151

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 (201) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/model/strategy/adapter/promotion/evaluator.js +99 -26
  4. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  5. package/dist/model/strategy/adapter/walletPass/evaluator.js +61 -8
  6. package/dist/model/strategy/adapter/walletPass/locales.js +12 -3
  7. package/dist/model/strategy/engine.d.ts +18 -5
  8. package/dist/model/strategy/engine.js +145 -45
  9. package/dist/model/strategy/type.d.ts +17 -0
  10. package/dist/model/strategy/type.js +4 -0
  11. package/dist/modules/Cart/types.d.ts +2 -0
  12. package/dist/modules/Cart/utils/cartProduct.js +56 -25
  13. package/dist/modules/Discount/index.d.ts +2 -6
  14. package/dist/modules/Discount/index.js +8 -14
  15. package/dist/modules/Discount/types.d.ts +19 -1
  16. package/dist/modules/Order/index.d.ts +1 -65
  17. package/dist/modules/Order/index.js +30 -901
  18. package/dist/modules/Order/types.d.ts +12 -174
  19. package/dist/modules/Order/types.js +0 -2
  20. package/dist/modules/Order/utils.d.ts +0 -118
  21. package/dist/modules/Order/utils.js +2 -586
  22. package/dist/modules/Payment/index.d.ts +2 -1
  23. package/dist/modules/Payment/index.js +10 -7
  24. package/dist/modules/Payment/utils.js +3 -0
  25. package/dist/modules/Payment/walletpass.d.ts +23 -0
  26. package/dist/modules/Payment/walletpass.js +191 -95
  27. package/dist/modules/Product/utils.js +2 -2
  28. package/dist/modules/ProductList/index.d.ts +1 -1
  29. package/dist/modules/ProductList/index.js +3 -4
  30. package/dist/modules/Rules/index.d.ts +9 -5
  31. package/dist/modules/Rules/index.js +677 -168
  32. package/dist/modules/Rules/types.d.ts +2 -0
  33. package/dist/modules/Schedule/getDateIsInSchedule.js +18 -11
  34. package/dist/modules/Schedule/utils.d.ts +1 -1
  35. package/dist/modules/Summary/types.d.ts +2 -0
  36. package/dist/modules/Summary/utils.d.ts +9 -3
  37. package/dist/modules/Summary/utils.js +52 -41
  38. package/dist/modules/index.d.ts +0 -4
  39. package/dist/modules/index.js +1 -5
  40. package/dist/plugins/window.d.ts +2 -0
  41. package/dist/solution/BookingByStep/index.d.ts +3 -2
  42. package/dist/solution/BookingByStep/index.js +43 -46
  43. package/dist/solution/BookingByStep/types.d.ts +1 -3
  44. package/dist/solution/BookingByStep/types.js +1 -5
  45. package/dist/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  46. package/dist/solution/BookingByStep/utils/timeslots.js +12 -19
  47. package/dist/solution/Checkout/index.js +2 -0
  48. package/dist/solution/ShopDiscount/index.d.ts +2 -2
  49. package/dist/solution/ShopDiscount/index.js +41 -37
  50. package/dist/solution/ShopDiscount/types.d.ts +1 -1
  51. package/dist/solution/ShopDiscount/types.js +2 -1
  52. package/dist/solution/ShopDiscount/utils.js +26 -12
  53. package/dist/solution/index.d.ts +0 -2
  54. package/dist/solution/index.js +1 -3
  55. package/lib/index.d.ts +1 -0
  56. package/lib/index.js +3 -1
  57. package/lib/model/strategy/adapter/promotion/evaluator.js +57 -8
  58. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  59. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  60. package/lib/model/strategy/adapter/walletPass/evaluator.js +34 -3
  61. package/lib/model/strategy/adapter/walletPass/locales.js +12 -3
  62. package/lib/model/strategy/engine.d.ts +18 -5
  63. package/lib/model/strategy/engine.js +85 -21
  64. package/lib/model/strategy/type.d.ts +17 -0
  65. package/lib/modules/Cart/types.d.ts +2 -0
  66. package/lib/modules/Cart/utils/cartProduct.js +39 -12
  67. package/lib/modules/Discount/index.d.ts +2 -6
  68. package/lib/modules/Discount/index.js +1 -3
  69. package/lib/modules/Discount/types.d.ts +19 -1
  70. package/lib/modules/Order/index.d.ts +1 -65
  71. package/lib/modules/Order/index.js +1 -513
  72. package/lib/modules/Order/types.d.ts +12 -174
  73. package/lib/modules/Order/utils.d.ts +0 -118
  74. package/lib/modules/Order/utils.js +2 -483
  75. package/lib/modules/Payment/index.d.ts +2 -1
  76. package/lib/modules/Payment/index.js +1 -0
  77. package/lib/modules/Payment/utils.js +3 -0
  78. package/lib/modules/Payment/walletpass.d.ts +23 -0
  79. package/lib/modules/Payment/walletpass.js +94 -17
  80. package/lib/modules/Product/utils.js +2 -2
  81. package/lib/modules/ProductList/index.d.ts +1 -1
  82. package/lib/modules/ProductList/index.js +3 -5
  83. package/lib/modules/Rules/index.d.ts +9 -5
  84. package/lib/modules/Rules/index.js +780 -288
  85. package/lib/modules/Rules/types.d.ts +2 -0
  86. package/lib/modules/Schedule/getDateIsInSchedule.js +11 -9
  87. package/lib/modules/Schedule/utils.d.ts +1 -1
  88. package/lib/modules/Summary/types.d.ts +2 -0
  89. package/lib/modules/Summary/utils.d.ts +9 -3
  90. package/lib/modules/Summary/utils.js +31 -22
  91. package/lib/modules/index.d.ts +0 -4
  92. package/lib/modules/index.js +1 -9
  93. package/lib/plugins/window.d.ts +2 -0
  94. package/lib/solution/BookingByStep/index.d.ts +3 -2
  95. package/lib/solution/BookingByStep/index.js +4 -6
  96. package/lib/solution/BookingByStep/types.d.ts +1 -3
  97. package/lib/solution/BookingByStep/types.js +0 -10
  98. package/lib/solution/BookingByStep/utils/timeslots.d.ts +1 -3
  99. package/lib/solution/BookingByStep/utils/timeslots.js +11 -19
  100. package/lib/solution/Checkout/index.js +2 -0
  101. package/lib/solution/ShopDiscount/index.d.ts +2 -2
  102. package/lib/solution/ShopDiscount/index.js +24 -16
  103. package/lib/solution/ShopDiscount/types.d.ts +1 -1
  104. package/lib/solution/ShopDiscount/utils.js +10 -6
  105. package/lib/solution/index.d.ts +0 -2
  106. package/lib/solution/index.js +1 -5
  107. package/package.json +1 -1
  108. package/dist/apis/picoding.d.ts +0 -0
  109. package/dist/apis/picoding.js +0 -1
  110. package/dist/modules/OpenData/index.d.ts +0 -24
  111. package/dist/modules/OpenData/index.js +0 -173
  112. package/dist/modules/OpenData/types.d.ts +0 -73
  113. package/dist/modules/OpenData/types.js +0 -1
  114. package/dist/modules/OpenData/utils.d.ts +0 -2
  115. package/dist/modules/OpenData/utils.js +0 -75
  116. package/dist/modules/Quotation/index.d.ts +0 -48
  117. package/dist/modules/Quotation/index.js +0 -248
  118. package/dist/modules/Quotation/types.d.ts +0 -42
  119. package/dist/modules/Quotation/types.js +0 -1
  120. package/dist/modules/SalesSummary/index.d.ts +0 -63
  121. package/dist/modules/SalesSummary/index.js +0 -174
  122. package/dist/modules/SalesSummary/types.d.ts +0 -60
  123. package/dist/modules/SalesSummary/types.js +0 -1
  124. package/dist/modules/SalesSummary/utils.d.ts +0 -30
  125. package/dist/modules/SalesSummary/utils.js +0 -480
  126. package/dist/modules/ScanOrderLogger/index.d.ts +0 -23
  127. package/dist/modules/ScanOrderLogger/index.js +0 -174
  128. package/dist/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  129. package/dist/modules/ScanOrderLogger/providers/feishu.js +0 -221
  130. package/dist/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  131. package/dist/modules/ScanOrderLogger/providers/grafana.js +0 -50
  132. package/dist/modules/ScanOrderLogger/types.d.ts +0 -53
  133. package/dist/modules/ScanOrderLogger/types.js +0 -1
  134. package/dist/solution/ScanOrder/index.d.ts +0 -152
  135. package/dist/solution/ScanOrder/index.js +0 -3132
  136. package/dist/solution/ScanOrder/types.d.ts +0 -287
  137. package/dist/solution/ScanOrder/types.js +0 -35
  138. package/dist/solution/ScanOrder/utils.d.ts +0 -167
  139. package/dist/solution/ScanOrder/utils.js +0 -764
  140. package/dist/solution/VenueBooking/index.d.ts +0 -199
  141. package/dist/solution/VenueBooking/index.js +0 -3459
  142. package/dist/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  143. package/dist/solution/VenueBooking/types.d.ts +0 -154
  144. package/dist/solution/VenueBooking/types.js +0 -21
  145. package/dist/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  146. package/dist/solution/VenueBooking/utils/dateSummary.js +0 -104
  147. package/dist/solution/VenueBooking/utils/resource.d.ts +0 -14
  148. package/dist/solution/VenueBooking/utils/resource.js +0 -131
  149. package/dist/solution/VenueBooking/utils/slotMerge.d.ts +0 -38
  150. package/dist/solution/VenueBooking/utils/slotMerge.js +0 -239
  151. package/dist/solution/VenueBooking/utils/timeSlot.d.ts +0 -32
  152. package/dist/solution/VenueBooking/utils/timeSlot.js +0 -453
  153. package/dist/solution/VenueBooking/utils.d.ts +0 -1
  154. package/dist/solution/VenueBooking/utils.js +0 -1
  155. package/lib/apis/picoding.d.ts +0 -0
  156. package/lib/apis/picoding.js +0 -0
  157. package/lib/modules/OpenData/index.d.ts +0 -24
  158. package/lib/modules/OpenData/index.js +0 -119
  159. package/lib/modules/OpenData/types.d.ts +0 -73
  160. package/lib/modules/OpenData/types.js +0 -17
  161. package/lib/modules/OpenData/utils.d.ts +0 -2
  162. package/lib/modules/OpenData/utils.js +0 -111
  163. package/lib/modules/Quotation/index.d.ts +0 -48
  164. package/lib/modules/Quotation/index.js +0 -152
  165. package/lib/modules/Quotation/types.d.ts +0 -42
  166. package/lib/modules/Quotation/types.js +0 -17
  167. package/lib/modules/SalesSummary/index.d.ts +0 -63
  168. package/lib/modules/SalesSummary/index.js +0 -105
  169. package/lib/modules/SalesSummary/types.d.ts +0 -60
  170. package/lib/modules/SalesSummary/types.js +0 -17
  171. package/lib/modules/SalesSummary/utils.d.ts +0 -30
  172. package/lib/modules/SalesSummary/utils.js +0 -420
  173. package/lib/modules/ScanOrderLogger/index.d.ts +0 -23
  174. package/lib/modules/ScanOrderLogger/index.js +0 -147
  175. package/lib/modules/ScanOrderLogger/providers/feishu.d.ts +0 -2
  176. package/lib/modules/ScanOrderLogger/providers/feishu.js +0 -157
  177. package/lib/modules/ScanOrderLogger/providers/grafana.d.ts +0 -2
  178. package/lib/modules/ScanOrderLogger/providers/grafana.js +0 -52
  179. package/lib/modules/ScanOrderLogger/types.d.ts +0 -53
  180. package/lib/modules/ScanOrderLogger/types.js +0 -17
  181. package/lib/solution/ScanOrder/index.d.ts +0 -152
  182. package/lib/solution/ScanOrder/index.js +0 -1901
  183. package/lib/solution/ScanOrder/types.d.ts +0 -287
  184. package/lib/solution/ScanOrder/types.js +0 -36
  185. package/lib/solution/ScanOrder/utils.d.ts +0 -167
  186. package/lib/solution/ScanOrder/utils.js +0 -635
  187. package/lib/solution/VenueBooking/index.d.ts +0 -199
  188. package/lib/solution/VenueBooking/index.js +0 -1926
  189. package/lib/solution/VenueBooking/sales-section-4-annotated.json +0 -343
  190. package/lib/solution/VenueBooking/types.d.ts +0 -154
  191. package/lib/solution/VenueBooking/types.js +0 -44
  192. package/lib/solution/VenueBooking/utils/dateSummary.d.ts +0 -11
  193. package/lib/solution/VenueBooking/utils/dateSummary.js +0 -110
  194. package/lib/solution/VenueBooking/utils/resource.d.ts +0 -14
  195. package/lib/solution/VenueBooking/utils/resource.js +0 -92
  196. package/lib/solution/VenueBooking/utils/slotMerge.d.ts +0 -38
  197. package/lib/solution/VenueBooking/utils/slotMerge.js +0 -237
  198. package/lib/solution/VenueBooking/utils/timeSlot.d.ts +0 -32
  199. package/lib/solution/VenueBooking/utils/timeSlot.js +0 -339
  200. package/lib/solution/VenueBooking/utils.d.ts +0 -1
  201. package/lib/solution/VenueBooking/utils.js +0 -69
@@ -50,6 +50,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
50
50
  this.core = core;
51
51
  this.hooks = options == null ? void 0 : options.hooks;
52
52
  this.store = options == null ? void 0 : options.store;
53
+ this.window = core.getPlugin("window");
53
54
  }
54
55
  async setRulesList(rulesList) {
55
56
  this.store.rulesList = rulesList;
@@ -71,11 +72,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
71
72
  return false;
72
73
  return (productHolderId || orderHolderId) === discount.holder.holder_id;
73
74
  }
75
+ getWalletPassEvaluator() {
76
+ var _a, _b;
77
+ return (_b = (_a = this.window).getWalletPassEvaluator) == null ? void 0 : _b.call(_a);
78
+ }
74
79
  // 判断discountList 是否可以对当前productList生效
75
80
  isDiscountListAvailable({
76
81
  oldDiscountList,
77
82
  newDiscountList,
78
83
  productList,
84
+ orderTotalAmount,
79
85
  holders,
80
86
  isFormSubject
81
87
  }) {
@@ -108,6 +114,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
108
114
  const result = this.calcDiscount({
109
115
  discountList: mergedDiscountList,
110
116
  productList: [...productList],
117
+ orderTotalAmount,
111
118
  holders,
112
119
  isFormSubject
113
120
  }, {
@@ -183,7 +190,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
183
190
  discountList,
184
191
  productList,
185
192
  holders,
186
- isFormSubject
193
+ isFormSubject,
194
+ orderTotalAmount
187
195
  }, options) {
188
196
  const editModeDiscount = [];
189
197
  const addModeDiscount = [];
@@ -362,7 +370,63 @@ var RulesModule = class extends import_BaseModule.BaseModule {
362
370
  }
363
371
  return priceB.minus(priceA).toNumber();
364
372
  });
373
+ const evaluator = this.getWalletPassEvaluator();
374
+ if (evaluator) {
375
+ addModeDiscount.forEach((discount) => {
376
+ var _a, _b;
377
+ const discountType = discount.tag || discount.type;
378
+ if (["good_pass", "discount_card", "product_discount_card"].includes(
379
+ discountType
380
+ )) {
381
+ const voucher = {
382
+ id: discount.id,
383
+ amount: Number(discount.par_value || 0),
384
+ balance: Number(discount.balance || 0),
385
+ type: discountType,
386
+ product_id: discount.product_id,
387
+ unified_available_status: 1,
388
+ available_product_type: (_a = discount.limited_relation_product_data) == null ? void 0 : _a.type,
389
+ available_product_ids: (_b = discount.limited_relation_product_data) == null ? void 0 : _b.product_ids
390
+ };
391
+ const productsForEvaluate = sortedFlattenedList.map((item) => {
392
+ var _a2;
393
+ return {
394
+ product_id: item.id,
395
+ price: item.price || 0,
396
+ quantity: item.quantity || item.num || 1,
397
+ selling_price: item.price || 0,
398
+ product_options: item.type === "main" ? (_a2 = item.product) == null ? void 0 : _a2.options : void 0
399
+ };
400
+ });
401
+ const result = evaluator.checkVoucherAvailability({
402
+ orderTotalAmount,
403
+ products: productsForEvaluate,
404
+ vouchers: [voucher]
405
+ });
406
+ if (result.isAvailable) {
407
+ discount.config = {
408
+ ...result.config,
409
+ isAvailable: true
410
+ };
411
+ } else {
412
+ discount.config = {
413
+ isAvailable: false
414
+ };
415
+ }
416
+ }
417
+ });
418
+ }
365
419
  const usedDiscounts = /* @__PURE__ */ new Map();
420
+ const usedProductIdCounts = /* @__PURE__ */ new Map();
421
+ const usedDiscountCardLimitCounts = /* @__PURE__ */ new Map();
422
+ editModeDiscount.forEach((discount) => {
423
+ var _a;
424
+ const discountType = discount.tag || discount.type;
425
+ if (["discount_card", "product_discount_card"].includes(discountType)) {
426
+ const currentCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
427
+ usedDiscountCardLimitCounts.set(discount.id, currentCount + (((_a = discount.metadata) == null ? void 0 : _a.num) || 1));
428
+ }
429
+ });
366
430
  const discountApplicability = /* @__PURE__ */ new Map();
367
431
  const discountApplicableProducts = /* @__PURE__ */ new Map();
368
432
  addModeDiscount.forEach((discount) => {
@@ -502,6 +566,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
502
566
  originProduct = flatItem.originProduct;
503
567
  } else {
504
568
  product = {
569
+ startDate: (_a = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _a.startDate,
505
570
  _id: flatItem._id,
506
571
  id: flatItem.id,
507
572
  price: flatItem.price,
@@ -510,13 +575,12 @@ var RulesModule = class extends import_BaseModule.BaseModule {
510
575
  total: flatItem.total,
511
576
  origin_total: flatItem.origin_total,
512
577
  booking_id: flatItem.booking_id,
513
- discount_list: flatItem.discount_list || [],
514
- startDate: (_a = flatItem.parentProduct) == null ? void 0 : _a.startDate
578
+ discount_list: flatItem.discount_list || []
515
579
  };
516
580
  originProduct = flatItem.originProduct;
517
581
  }
518
582
  addModeDiscount.forEach((discount) => {
519
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
583
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
520
584
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
521
585
  const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
522
586
  const isHolderMatch = this.checkHolderMatch(
@@ -529,7 +593,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
529
593
  );
530
594
  let timeLimit = true;
531
595
  timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
532
- const isLimitedProduct = (limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
596
+ const isLimitedProduct = (limitedData.type === "product_all" && limitedData.filter !== 1 || limitedData.type === "product_all" && limitedData.filter === 1 && !limitedData.exclude_product_ids.includes(product.id) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
533
597
  const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a2 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a2.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every(
534
598
  (discount2) => discount2.id && [
535
599
  "good_pass",
@@ -538,8 +602,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
538
602
  ].includes(discount2.tag || discount2.type)
539
603
  ))) : !((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)));
540
604
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
541
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
542
- (_g = discountApplicability.get(discount.id)) == null ? void 0 : _g.push(product.id);
605
+ if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && ((_g = discount.config) == null ? void 0 : _g.isAvailable)) {
606
+ (_h = discountApplicability.get(discount.id)) == null ? void 0 : _h.push(product.id);
543
607
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
544
608
  const discountType = discount.tag || discount.type;
545
609
  const isGoodPass = discountType === "good_pass";
@@ -549,14 +613,15 @@ var RulesModule = class extends import_BaseModule.BaseModule {
549
613
  type: discountType,
550
614
  tag: discountType,
551
615
  discount: {
552
- discount_card_type: (_h = discount == null ? void 0 : discount.metadata) == null ? void 0 : _h.discount_card_type,
616
+ discount_card_type: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_card_type,
553
617
  fixed_amount: product.price,
554
- discount_calculation_mode: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_calculation_mode,
618
+ discount_calculation_mode: (_j = discount == null ? void 0 : discount.metadata) == null ? void 0 : _j.discount_calculation_mode,
555
619
  resource_id: discount.id,
556
620
  title: discount.format_title,
557
621
  original_amount: product.price || product.origin_total,
558
622
  pre_value: discount.par_value,
559
- product_id: originProduct.id
623
+ product_id: originProduct.id,
624
+ discount_product_id: discount.product_id
560
625
  },
561
626
  metadata: {
562
627
  num,
@@ -569,44 +634,102 @@ var RulesModule = class extends import_BaseModule.BaseModule {
569
634
  });
570
635
  });
571
636
  const processedFlatItemsMap = /* @__PURE__ */ new Map();
637
+ const applyDiscountToOptions = (options2, discount) => {
638
+ if (!(options2 == null ? void 0 : options2.length))
639
+ return { discountedOptions: options2, optionDiscountAmount: 0 };
640
+ let optionDiscountAmount = 0;
641
+ const discountedOptions = options2.map((option) => {
642
+ const rawUnit = option._original_price ?? option._original_add_price ?? option.price ?? option.add_price;
643
+ const baseUnitNum = Number(rawUnit ?? 0);
644
+ if (baseUnitNum <= 0)
645
+ return option;
646
+ const discountedPrice = (0, import_utils.getDiscountAmount)(discount, baseUnitNum, baseUnitNum);
647
+ const optQty = Number(option.num ?? option.quantity ?? 1);
648
+ optionDiscountAmount = new import_decimal.default(optionDiscountAmount).plus(new import_decimal.default(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
649
+ const { _original_add_price, ...rest } = option;
650
+ const tmpl = rest.price ?? rest.add_price;
651
+ const nextPrice = typeof tmpl === "string" ? String(discountedPrice) : discountedPrice;
652
+ return {
653
+ ...rest,
654
+ _original_price: option._original_price ?? (_original_add_price !== void 0 ? _original_add_price : rawUnit),
655
+ price: nextPrice
656
+ };
657
+ });
658
+ return { discountedOptions, optionDiscountAmount };
659
+ };
660
+ const restoreOptionPrices = (options2) => {
661
+ if (!(options2 == null ? void 0 : options2.length))
662
+ return options2;
663
+ return options2.map((option) => {
664
+ const orig = option._original_price !== void 0 ? option._original_price : option._original_add_price;
665
+ if (orig !== void 0) {
666
+ const { _original_price, _original_add_price, ...rest } = option;
667
+ return { ...rest, price: orig };
668
+ }
669
+ return option;
670
+ });
671
+ };
672
+ const getOptionTotal = (options2) => {
673
+ if (!(options2 == null ? void 0 : options2.length))
674
+ return 0;
675
+ return options2.reduce((sum, opt) => {
676
+ const unit = Number(opt.price ?? opt.add_price ?? 0);
677
+ const n = Number(opt.num ?? opt.quantity ?? 1);
678
+ return new import_decimal.default(sum).plus(new import_decimal.default(unit).mul(n)).toNumber();
679
+ }, 0);
680
+ };
572
681
  sortedFlattenedList.forEach((flatItem, index) => {
573
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C;
682
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M;
574
683
  let product, originProduct;
575
684
  if (flatItem.type === "main") {
576
685
  product = flatItem.product;
577
686
  originProduct = flatItem.originProduct;
578
687
  } else {
579
688
  product = {
689
+ startDate: (_a = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _a.startDate,
580
690
  _id: flatItem._id,
581
691
  id: flatItem.id,
582
692
  price: flatItem.price,
583
693
  quantity: flatItem.quantity,
584
694
  num: flatItem.num,
585
695
  total: flatItem.total,
586
- original_price: (_a = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _a.original_price,
587
- origin_total: (_b = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _b.original_price,
696
+ original_price: (_b = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _b.original_price,
697
+ origin_total: (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.original_price,
588
698
  booking_id: flatItem.booking_id,
589
- discount_list: ((_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) || [],
590
- startDate: (_d = flatItem.parentProduct) == null ? void 0 : _d.startDate
699
+ discount_list: ((_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) || []
591
700
  };
592
701
  originProduct = flatItem.originProduct;
593
702
  }
594
- if ((product == null ? void 0 : product.booking_id) && ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
703
+ if ((product == null ? void 0 : product.booking_id) && ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every(
704
+ (discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(
705
+ discount.tag || discount.type
706
+ )
707
+ ))) {
595
708
  if (flatItem.type === "main") {
596
709
  processedProductsMap.set(product._id, [originProduct]);
597
710
  } else {
598
- processedFlatItemsMap.set(flatItem._id, [{
599
- ...flatItem,
600
- processed: true
601
- }]);
711
+ processedFlatItemsMap.set(flatItem._id, [
712
+ {
713
+ ...flatItem,
714
+ processed: true
715
+ }
716
+ ]);
602
717
  }
603
718
  return;
604
719
  }
605
720
  const applicableDiscounts = sortedDiscountList.filter((discount) => {
606
- var _a2, _b2;
607
- if ((Number(product.price) <= 0 || !product.price) && !((_a2 = product.discount_list) == null ? void 0 : _a2.length) && (discount.tag || discount.type) === "good_pass")
721
+ var _a2, _b2, _c2, _d2, _e2;
722
+ const discountType2 = discount.tag || discount.type;
723
+ if (["good_pass", "discount_card", "product_discount_card"].includes(
724
+ discountType2
725
+ )) {
726
+ if (discount.config === void 0 || !((_a2 = discount == null ? void 0 : discount.config) == null ? void 0 : _a2.isAvailable)) {
727
+ return false;
728
+ }
729
+ }
730
+ if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.length) && (discount.tag || discount.type) === "good_pass")
608
731
  return false;
609
- if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.find((n) => {
732
+ if ((Number(product.total) <= 0 || !product.total) && !((_c2 = product.discount_list) == null ? void 0 : _c2.find((n) => {
610
733
  var _a3;
611
734
  return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
612
735
  })) && (discount.tag || discount.type) !== "good_pass")
@@ -614,6 +737,25 @@ var RulesModule = class extends import_BaseModule.BaseModule {
614
737
  const targetUsedDiscounts = usedDiscounts.get(discount.id);
615
738
  if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
616
739
  return false;
740
+ if ((discount.tag || discount.type) === "good_pass") {
741
+ const maxUsagePerOrder = (_d2 = discount.config) == null ? void 0 : _d2.maxUsagePerOrder;
742
+ if (maxUsagePerOrder && maxUsagePerOrder > 0) {
743
+ const currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
744
+ if (currentUsedCount >= maxUsagePerOrder) {
745
+ return false;
746
+ }
747
+ }
748
+ }
749
+ const discountTypeForLimit = discount.tag || discount.type;
750
+ if (["discount_card", "product_discount_card"].includes(discountTypeForLimit)) {
751
+ const applicableProductLimitConfig = ((_e2 = discount.config) == null ? void 0 : _e2.applicableProductLimit) || 0;
752
+ if (applicableProductLimitConfig > 0) {
753
+ const currentUsedLimitCount = usedDiscountCardLimitCounts.get(discount.id) || 0;
754
+ if (currentUsedLimitCount >= applicableProductLimitConfig) {
755
+ return false;
756
+ }
757
+ }
758
+ }
617
759
  const limitedData = discount.limited_relation_product_data;
618
760
  const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
619
761
  const isHolderMatch = this.checkHolderMatch(
@@ -632,6 +774,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
632
774
  return false;
633
775
  }
634
776
  if (limitedData.type === "product_all") {
777
+ if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
778
+ return false;
779
+ }
635
780
  if (!this.checkPackageSubItemUsageRules(discount, flatItem)) {
636
781
  return false;
637
782
  }
@@ -644,21 +789,36 @@ var RulesModule = class extends import_BaseModule.BaseModule {
644
789
  }
645
790
  return false;
646
791
  });
647
- const selectedDiscountCard = applicableDiscounts.find((n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass");
792
+ const selectedDiscountCard = applicableDiscounts.find(
793
+ (n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
794
+ );
648
795
  const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
649
796
  let isManualDiscount = false;
650
797
  if (flatItem.type === "main") {
651
- isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every((item) => {
652
- var _a2;
653
- return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
654
- }) && (!((_g = product.discount_list) == null ? void 0 : _g.length) || ((_i = (_h = product == null ? void 0 : product.discount_list) == null ? void 0 : _h.every) == null ? void 0 : _i.call(_h, (item) => item.type === "product")));
798
+ isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every(
799
+ (item) => {
800
+ var _a2;
801
+ return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
802
+ }
803
+ ) && (!((_g = product.discount_list) == null ? void 0 : _g.length) || ((_i = (_h = product == null ? void 0 : product.discount_list) == null ? void 0 : _h.every) == null ? void 0 : _i.call(
804
+ _h,
805
+ (item) => item.type === "product"
806
+ )));
807
+ if (product.inPromotion) {
808
+ isManualDiscount = false;
809
+ }
655
810
  } else {
656
811
  const parentProduct = flatItem.parentProduct;
657
812
  if (parentProduct) {
658
- isManualDiscount = typeof parentProduct.isManualDiscount === "boolean" ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every((item) => {
659
- var _a2;
660
- return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
661
- }) && (!((_j = parentProduct.discount_list) == null ? void 0 : _j.length) || ((_l = (_k = parentProduct == null ? void 0 : parentProduct.discount_list) == null ? void 0 : _k.every) == null ? void 0 : _l.call(_k, (item) => item.type === "product")));
813
+ isManualDiscount = typeof parentProduct.isManualDiscount === "boolean" ? parentProduct.isManualDiscount : parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(
814
+ (item) => {
815
+ var _a2;
816
+ return !((_a2 = item.discount_list || []) == null ? void 0 : _a2.length);
817
+ }
818
+ ) && (!((_j = parentProduct.discount_list) == null ? void 0 : _j.length) || ((_l = (_k = parentProduct == null ? void 0 : parentProduct.discount_list) == null ? void 0 : _k.every) == null ? void 0 : _l.call(
819
+ _k,
820
+ (item) => item.type === "product"
821
+ )));
662
822
  }
663
823
  }
664
824
  if (options == null ? void 0 : options.discountId) {
@@ -710,17 +870,17 @@ var RulesModule = class extends import_BaseModule.BaseModule {
710
870
  }
711
871
  if (applicableDiscounts.length === 0 || isManualDiscount || (0, import_lodash_es.isBoolean)(product.vouchersApplicable) && !product.vouchersApplicable) {
712
872
  if (flatItem.type === "main") {
873
+ const restoredOptions = restoreOptionPrices(product.options);
713
874
  if (product.isClient) {
714
- processedProductsMap.set(
715
- product._id,
716
- [this.hooks.setProduct(originProduct, {
875
+ processedProductsMap.set(product._id, [
876
+ this.hooks.setProduct(originProduct, {
717
877
  ...isManualDiscount ? {} : {
718
878
  origin_total: (0, import_utils2.getProductOriginTotalPrice)({
719
879
  product: {
720
880
  original_price: product.original_price
721
881
  },
722
882
  bundle: product.bundle,
723
- options: product.options
883
+ options: restoredOptions
724
884
  }),
725
885
  variant: originProduct._productInit.variant,
726
886
  original_price: originProduct._productInit.original_price,
@@ -729,14 +889,14 @@ var RulesModule = class extends import_BaseModule.BaseModule {
729
889
  price: product.price
730
890
  },
731
891
  bundle: product.bundle,
732
- options: product.options
892
+ options: restoredOptions
733
893
  }),
734
894
  price: product.price,
735
- options: product.options
895
+ options: restoredOptions
736
896
  },
737
897
  discount_list: this.filterDiscountListByType(product.discount_list, "promotion")
738
- })]
739
- );
898
+ })
899
+ ]);
740
900
  } else {
741
901
  let total = product.inPromotion ? ((_u = product == null ? void 0 : product._promotion) == null ? void 0 : _u.finalPrice) ?? product.origin_total ?? product.total : product.origin_total ?? product.total;
742
902
  let main_product_selling_price = product.price ?? product.main_product_selling_price;
@@ -746,19 +906,20 @@ var RulesModule = class extends import_BaseModule.BaseModule {
746
906
  }
747
907
  processedProductsMap.set(
748
908
  product._id,
749
- [this.hooks.setProduct(originProduct, {
750
- ...isManualDiscount ? {
751
- price: product.price
752
- } : {
753
- _id: product._id.split("___")[0] + "___" + index,
754
- origin_total: product.origin_total,
755
- total,
756
- original_price: product.original_price,
757
- price: product.price,
758
- main_product_selling_price
759
- },
760
- discount_list: this.filterDiscountListByType(product.discount_list, "promotion")
761
- })]
909
+ [
910
+ this.hooks.setProduct(originProduct, {
911
+ ...isManualDiscount ? {
912
+ price: product.price
913
+ } : {
914
+ _id: product._id.split("___")[0] + "___" + index,
915
+ total,
916
+ price: product.price,
917
+ main_product_selling_price,
918
+ options: restoredOptions
919
+ },
920
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion")
921
+ })
922
+ ]
762
923
  );
763
924
  }
764
925
  } else {
@@ -774,104 +935,166 @@ var RulesModule = class extends import_BaseModule.BaseModule {
774
935
  if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct) {
775
936
  return;
776
937
  }
777
- const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
938
+ const discountType = selectedDiscount.tag || selectedDiscount.type;
939
+ const isGoodPass = discountType === "good_pass";
940
+ const isDiscountCard = ["discount_card", "product_discount_card"].includes(discountType);
941
+ const applicableProductLimit = ((_w = selectedDiscount.config) == null ? void 0 : _w.applicableProductLimit) || 0;
942
+ const isNeedSplit = isGoodPass || isDiscountCard && applicableProductLimit > 0;
778
943
  const totalQuantity = product.quantity || product.num || 1;
779
- const availableGoodPassCount = applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length;
780
- const splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
944
+ const availableGoodPassCount = applicableDiscounts.filter(
945
+ (item) => (item.tag || item.type) === "good_pass"
946
+ ).length;
947
+ let maxUsageLimit;
948
+ if (isGoodPass) {
949
+ maxUsageLimit = availableGoodPassCount;
950
+ if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
951
+ maxUsageLimit = Math.min(
952
+ availableGoodPassCount,
953
+ selectedDiscount.config.maxUsagePerOrder
954
+ );
955
+ }
956
+ } else if (isDiscountCard && applicableProductLimit > 0) {
957
+ const usedLimitCount = usedDiscountCardLimitCounts.get(selectedDiscount.id) || 0;
958
+ maxUsageLimit = Math.max(0, applicableProductLimit - usedLimitCount);
959
+ } else {
960
+ maxUsageLimit = 1;
961
+ }
962
+ const splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
781
963
  const arr = [];
782
964
  if (flatItem.type === "main") {
783
965
  if (splitCount < totalQuantity && isNeedSplit) {
784
- arr.push(this.hooks.setProduct(originProduct, {
785
- discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
786
- quantity: totalQuantity - splitCount,
787
- _id: product._id.split("___")[0]
788
- }));
966
+ let total = product.origin_total ?? product.total;
967
+ if ((product.discount_list || []).some((item) => item.type === "promotion")) {
968
+ total = product.total ?? product.origin_total;
969
+ }
970
+ arr.push(
971
+ this.hooks.setProduct(originProduct, {
972
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
973
+ quantity: totalQuantity - splitCount,
974
+ _id: product._id.split("___")[0],
975
+ total
976
+ })
977
+ );
789
978
  }
790
979
  for (let i = 0; i < splitCount; i++) {
791
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
792
- usedDiscounts.set(selectedDiscount2.id, true);
793
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
980
+ const currentSelectedDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
981
+ usedDiscounts.set(currentSelectedDiscount.id, true);
982
+ if ((currentSelectedDiscount.tag || currentSelectedDiscount.type) === "good_pass") {
983
+ const currentCount = usedProductIdCounts.get(currentSelectedDiscount.product_id) || 0;
984
+ usedProductIdCounts.set(currentSelectedDiscount.product_id, currentCount + 1);
985
+ }
986
+ const currentDiscountTypeForCount = currentSelectedDiscount.tag || currentSelectedDiscount.type;
987
+ if (["discount_card", "product_discount_card"].includes(currentDiscountTypeForCount)) {
988
+ const currentLimitCount = usedDiscountCardLimitCounts.get(currentSelectedDiscount.id) || 0;
989
+ usedDiscountCardLimitCounts.set(currentSelectedDiscount.id, currentLimitCount + 1);
990
+ }
991
+ const appliedProducts = appliedDiscountProducts.get(currentSelectedDiscount.id) || [];
794
992
  let productOriginTotal = product.origin_total || product.total || 0;
795
993
  if (this.filterDiscountListByType(product.discount_list, "promotion").length && product.origin_total) {
796
994
  productOriginTotal = product.origin_total;
797
995
  }
798
- if (Number(((_w = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _w.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
996
+ if (Number(((_x = originProduct == null ? void 0 : originProduct._productInit) == null ? void 0 : _x.original_price) || 0) > 0 && product.origin_total && product.total && product.origin_total !== product.total) {
799
997
  productOriginTotal = product.total;
800
998
  }
801
- const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
802
- const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
999
+ const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount);
1000
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
803
1001
  const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
804
- let targetProductTotal;
1002
+ const isDeductOptionPrice = !!((_y = selectedDiscount.config) == null ? void 0 : _y.deductOptionPrice);
1003
+ let mainProductSellingPrice;
805
1004
  let amount;
806
1005
  let productDiscountDifference;
1006
+ let discountedOptions = product.options;
1007
+ let optionDiscountAmount = 0;
807
1008
  if (isOrderLevel && productAllocation) {
808
1009
  amount = productAllocation.discountAmount;
809
1010
  productDiscountDifference = productAllocation.difference;
810
- targetProductTotal = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
1011
+ mainProductSellingPrice = Math.max(new import_decimal.default(product.price).minus(amount).toNumber(), 0);
811
1012
  } else {
812
- targetProductTotal = (0, import_utils.getDiscountAmount)(selectedDiscount2, product.price, product.price);
813
- amount = new import_decimal.default(product.price).minus(new import_decimal.default(targetProductTotal)).toNumber();
1013
+ mainProductSellingPrice = (0, import_utils.getDiscountAmount)(
1014
+ currentSelectedDiscount,
1015
+ product.price,
1016
+ product.price
1017
+ );
1018
+ amount = new import_decimal.default(product.price).minus(new import_decimal.default(mainProductSellingPrice)).toNumber();
814
1019
  }
815
- const discountType = selectedDiscount2.tag || selectedDiscount2.type;
816
- const isGoodPass = discountType === "good_pass";
1020
+ if (isDeductOptionPrice && ((_z = product.options) == null ? void 0 : _z.length)) {
1021
+ const optionResult = applyDiscountToOptions(
1022
+ product.options,
1023
+ currentSelectedDiscount
1024
+ );
1025
+ discountedOptions = optionResult.discountedOptions;
1026
+ optionDiscountAmount = optionResult.optionDiscountAmount;
1027
+ }
1028
+ const optionsForLineTotal = isDeductOptionPrice && ((_A = product.options) == null ? void 0 : _A.length) ? discountedOptions : product.options;
1029
+ const optionsLineTotal = getOptionTotal(optionsForLineTotal || []);
1030
+ const total = new import_decimal.default(mainProductSellingPrice).plus(optionsLineTotal).toNumber();
1031
+ const mainProductDiscountAmount = amount;
1032
+ const lineDiscountAmount = new import_decimal.default(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1033
+ const currentDiscountType = currentSelectedDiscount.tag === "product_discount_card" ? "discount_card" : currentSelectedDiscount.tag;
1034
+ const discountType2 = selectedDiscount.tag || selectedDiscount.type;
1035
+ const currentIsGoodPass = currentDiscountType === "good_pass";
817
1036
  const discountDetail = {
818
- amount,
819
- type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
1037
+ amount: lineDiscountAmount,
1038
+ type: selectedDiscount.tag === "product_discount_card" ? "discount_card" : discountType2,
820
1039
  discount: {
821
- discount_card_type: (_x = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _x.discount_card_type,
822
- fixed_amount: amount,
823
- discount_calculation_mode: (_y = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _y.discount_calculation_mode,
824
- resource_id: selectedDiscount2.id,
825
- title: selectedDiscount2.format_title,
1040
+ discount_card_type: (_B = selectedDiscount == null ? void 0 : selectedDiscount.metadata) == null ? void 0 : _B.discount_card_type,
1041
+ fixed_amount: lineDiscountAmount,
1042
+ discount_calculation_mode: (_C = selectedDiscount == null ? void 0 : selectedDiscount.metadata) == null ? void 0 : _C.discount_calculation_mode,
1043
+ resource_id: selectedDiscount.id,
1044
+ title: selectedDiscount.format_title,
826
1045
  original_amount: product.price,
827
1046
  product_id: originProduct.id,
828
- percent: selectedDiscount2.par_value
1047
+ percent: currentSelectedDiscount.par_value,
1048
+ discount_product_id: currentSelectedDiscount.product_id
829
1049
  },
830
- // 前端使用的num数量,为了计算优惠金额
831
- _num: isGoodPass ? 1 : product.num,
1050
+ // 前端使用的num数量,为了计算优惠金额(拆分时为1)
1051
+ _num: isNeedSplit ? 1 : product.num,
1052
+ config: currentSelectedDiscount == null ? void 0 : currentSelectedDiscount.config,
832
1053
  metadata: {
833
1054
  num: 1,
834
- discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1055
+ discount_rule_uncheck_flag: selectedDiscount == null ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
835
1056
  // 🔥 order_level 分摊差值
836
- ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
1057
+ ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference },
1058
+ /** 仅主商品上的优惠金额(不含 option) */
1059
+ mainProductDiscountAmount,
1060
+ optionDiscountAmount
837
1061
  }
838
1062
  };
839
1063
  appliedProducts.push(discountDetail);
840
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
841
- let total = targetProductTotal;
842
- if (product.options) {
843
- total = product.options.reduce((accumulator, currentValue) => {
844
- const currentPrice = new import_decimal.default(currentValue.price || 0);
845
- const currentNum = new import_decimal.default(currentValue.num || 0);
846
- return accumulator.add(currentPrice.mul(currentNum));
847
- }, new import_decimal.default(total)).toNumber();
848
- }
1064
+ appliedDiscountProducts.set(currentSelectedDiscount.id, appliedProducts);
849
1065
  if (product.isClient) {
850
- arr.push(this.hooks.setProduct(originProduct, {
851
- discount_list: [discountDetail],
852
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
853
- quantity: isNeedSplit ? 1 : product.quantity,
854
- origin_total: (0, import_utils2.getProductOriginTotalPrice)({
855
- product: {
856
- original_price: product.original_price
857
- },
858
- bundle: product.bundle,
859
- options: product.options
860
- }),
861
- variant: originProduct._productInit.variant,
862
- original_price: new import_decimal.default(product.price || 0).toNumber(),
863
- total
864
- }));
1066
+ arr.push(
1067
+ this.hooks.setProduct(originProduct, {
1068
+ discount_list: [discountDetail],
1069
+ // good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1070
+ price: currentIsGoodPass ? mainProductSellingPrice : product.price,
1071
+ quantity: isNeedSplit ? 1 : product.quantity,
1072
+ origin_total: (0, import_utils2.getProductOriginTotalPrice)({
1073
+ product: {
1074
+ original_price: product.original_price
1075
+ },
1076
+ bundle: product.bundle,
1077
+ options: restoreOptionPrices(product.options)
1078
+ }),
1079
+ variant: originProduct._productInit.variant,
1080
+ original_price: new import_decimal.default(product.price || 0).toNumber(),
1081
+ total,
1082
+ options: discountedOptions
1083
+ })
1084
+ );
865
1085
  } else {
866
- arr.push(this.hooks.setProduct(originProduct, {
867
- discount_list: this.filterDiscountListByType(product.discount_list, "promotion").concat([discountDetail]),
868
- _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index,
869
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
870
- quantity: isNeedSplit ? 1 : product.quantity,
871
- total,
872
- origin_total: productOriginTotal,
873
- main_product_selling_price: targetProductTotal
874
- }));
1086
+ arr.push(
1087
+ this.hooks.setProduct(originProduct, {
1088
+ discount_list: this.filterDiscountListByType(product.discount_list, "promotion").concat([discountDetail]),
1089
+ _id: product._id.split("___")[0] + "___" + currentSelectedDiscount.id + "_" + i + "_" + index,
1090
+ price: currentIsGoodPass ? 0 : product.price,
1091
+ quantity: isNeedSplit ? 1 : product.quantity,
1092
+ total,
1093
+ origin_total: productOriginTotal,
1094
+ main_product_selling_price: mainProductSellingPrice,
1095
+ options: discountedOptions
1096
+ })
1097
+ );
875
1098
  }
876
1099
  }
877
1100
  processedProductsMap.set(product._id, arr);
@@ -881,62 +1104,298 @@ var RulesModule = class extends import_BaseModule.BaseModule {
881
1104
  const discountNum = splitCount;
882
1105
  const normalNum = totalQuantity - discountNum;
883
1106
  for (let i = 0; i < discountNum; i++) {
884
- const selectedDiscount2 = applicableDiscounts[i];
885
- usedDiscounts.set(selectedDiscount2.id, true);
1107
+ const currentBundleDiscount = isGoodPass ? selectedDiscountCard || applicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[0];
1108
+ usedDiscounts.set(currentBundleDiscount.id, true);
1109
+ if ((currentBundleDiscount.tag || currentBundleDiscount.type) === "good_pass") {
1110
+ const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
1111
+ usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
1112
+ }
1113
+ const bundleDiscountTypeForCount = currentBundleDiscount.tag || currentBundleDiscount.type;
1114
+ if (["discount_card", "product_discount_card"].includes(bundleDiscountTypeForCount)) {
1115
+ const currentBundleLimitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
1116
+ usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentBundleLimitCount + 1);
1117
+ }
886
1118
  const uniqueId = `${flatItem._id}_split_${i}`;
1119
+ const discountedPrice = (0, import_utils.getDiscountAmount)(
1120
+ currentBundleDiscount,
1121
+ product.origin_total,
1122
+ product.origin_total
1123
+ );
1124
+ const bundleDiscountAmount = new import_decimal.default(product.origin_total || 0).minus(discountedPrice).toNumber();
1125
+ const bundleDiscountType = currentBundleDiscount.tag === "product_discount_card" ? "discount_card" : currentBundleDiscount.tag;
887
1126
  const discountDetail = {
888
- amount: product.origin_total,
889
- type: "good_pass",
1127
+ amount: bundleDiscountAmount,
1128
+ type: bundleDiscountType,
890
1129
  discount: {
891
- fixed_amount: product.origin_total,
892
- discount_calculation_mode: (_z = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _z.discount_calculation_mode,
893
- resource_id: selectedDiscount2.id,
894
- title: selectedDiscount2.format_title,
1130
+ discount_card_type: (_D = currentBundleDiscount == null ? void 0 : currentBundleDiscount.metadata) == null ? void 0 : _D.discount_card_type,
1131
+ discount_calculation_mode: (_E = currentBundleDiscount == null ? void 0 : currentBundleDiscount.metadata) == null ? void 0 : _E.discount_calculation_mode,
1132
+ fixed_amount: bundleDiscountAmount,
1133
+ resource_id: currentBundleDiscount.id,
1134
+ title: currentBundleDiscount.format_title,
895
1135
  original_amount: product.origin_total,
896
- product_id: product.id
1136
+ product_id: product.id,
1137
+ percent: currentBundleDiscount.par_value,
1138
+ discount_product_id: currentBundleDiscount.product_id
897
1139
  },
898
1140
  metadata: {
899
1141
  // 🔥 使用拆分后的唯一 _id
900
1142
  custom_product_bundle_map_id: uniqueId,
901
- discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1143
+ discount_rule_uncheck_flag: selectedDiscount == null ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
902
1144
  num: 1
903
1145
  },
904
- _num: 1
1146
+ _num: 1,
1147
+ config: currentBundleDiscount == null ? void 0 : currentBundleDiscount.config
905
1148
  };
906
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1149
+ const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
907
1150
  appliedProducts.push(discountDetail);
908
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1151
+ appliedDiscountProducts.set(currentBundleDiscount.id, appliedProducts);
909
1152
  processedItems.push({
910
1153
  ...flatItem,
911
1154
  // 🔥 使用唯一的 _id
912
1155
  _id: uniqueId,
913
1156
  num: 1,
914
1157
  quantity: 1,
915
- price: 0,
916
- // 商品券价格为0
917
- total: 0,
1158
+ price: discountedPrice,
1159
+ // 折扣后的价格
1160
+ total: discountedPrice,
918
1161
  discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion").concat([discountDetail]),
919
1162
  processed: true,
920
- _discountId: selectedDiscount2.id
1163
+ _discountId: currentBundleDiscount.id
921
1164
  });
922
1165
  }
923
- if (normalNum > 0) {
924
- processedItems.push({
925
- ...flatItem,
926
- // 🔥 为剩余商品生成唯一的 _id
927
- _id: `${flatItem._id}_split_rest`,
928
- num: normalNum,
929
- quantity: normalNum,
930
- discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion"),
931
- processed: true
1166
+ let remainingNum = normalNum;
1167
+ let continueSplitIndex = discountNum;
1168
+ while (remainingNum > 0) {
1169
+ const nextApplicableDiscounts = sortedDiscountList.filter((nextDiscount) => {
1170
+ var _a2, _b2, _c2, _d2;
1171
+ const nextDiscountType = nextDiscount.tag || nextDiscount.type;
1172
+ if (["good_pass", "discount_card", "product_discount_card"].includes(nextDiscountType)) {
1173
+ if (nextDiscount.config === void 0 || !((_a2 = nextDiscount == null ? void 0 : nextDiscount.config) == null ? void 0 : _a2.isAvailable)) {
1174
+ return false;
1175
+ }
1176
+ }
1177
+ if ((Number(product.total) <= 0 || !product.total) && !((_b2 = product.discount_list) == null ? void 0 : _b2.find(
1178
+ (n) => {
1179
+ var _a3;
1180
+ return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === nextDiscount.id;
1181
+ }
1182
+ )) && nextDiscountType !== "good_pass")
1183
+ return false;
1184
+ if (usedDiscounts.get(nextDiscount.id) && nextDiscountType === "good_pass")
1185
+ return false;
1186
+ if (nextDiscountType === "good_pass") {
1187
+ const maxUsagePerOrder = (_c2 = nextDiscount.config) == null ? void 0 : _c2.maxUsagePerOrder;
1188
+ if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1189
+ const currentUsedCount = usedProductIdCounts.get(nextDiscount.product_id) || 0;
1190
+ if (currentUsedCount >= maxUsagePerOrder) {
1191
+ return false;
1192
+ }
1193
+ }
1194
+ }
1195
+ if (["discount_card", "product_discount_card"].includes(nextDiscountType)) {
1196
+ const limitConfig = ((_d2 = nextDiscount.config) == null ? void 0 : _d2.applicableProductLimit) || 0;
1197
+ if (limitConfig > 0) {
1198
+ const currentUsedLimitCount = usedDiscountCardLimitCounts.get(nextDiscount.id) || 0;
1199
+ if (currentUsedLimitCount >= limitConfig) {
1200
+ return false;
1201
+ }
1202
+ }
1203
+ }
1204
+ const limitedData = nextDiscount.limited_relation_product_data;
1205
+ if (limitedData.type === "product_all") {
1206
+ if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
1207
+ return false;
1208
+ }
1209
+ if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1210
+ return false;
1211
+ }
1212
+ return true;
1213
+ } else if (limitedData.product_ids && limitedData.product_ids.includes(product.id)) {
1214
+ if (!this.checkPackageSubItemUsageRules(nextDiscount, flatItem)) {
1215
+ return false;
1216
+ }
1217
+ return true;
1218
+ }
1219
+ return false;
932
1220
  });
1221
+ if (nextApplicableDiscounts.length === 0) {
1222
+ processedItems.push({
1223
+ ...flatItem,
1224
+ _id: `${flatItem._id}_split_rest`,
1225
+ num: remainingNum,
1226
+ quantity: remainingNum,
1227
+ discount_list: [],
1228
+ processed: true
1229
+ });
1230
+ break;
1231
+ }
1232
+ const nextSelectedDiscountCard = nextApplicableDiscounts.find(
1233
+ (n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass"
1234
+ );
1235
+ const nextSelectedDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1236
+ const nextDiscType = nextSelectedDiscount.tag || nextSelectedDiscount.type;
1237
+ const nextIsGoodPass = nextDiscType === "good_pass";
1238
+ const nextIsDiscountCard = ["discount_card", "product_discount_card"].includes(nextDiscType);
1239
+ const nextApplicableProductLimit = ((_F = nextSelectedDiscount.config) == null ? void 0 : _F.applicableProductLimit) || 0;
1240
+ const nextIsNeedSplit = nextIsGoodPass || nextIsDiscountCard && nextApplicableProductLimit > 0;
1241
+ if (!nextIsNeedSplit) {
1242
+ const nextBundleDiscount = nextSelectedDiscountCard || nextApplicableDiscounts[0];
1243
+ usedDiscounts.set(nextBundleDiscount.id, true);
1244
+ if ((nextBundleDiscount.tag || nextBundleDiscount.type) === "good_pass") {
1245
+ const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1246
+ usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1247
+ }
1248
+ const nextNoSplitType = nextBundleDiscount.tag || nextBundleDiscount.type;
1249
+ if (["discount_card", "product_discount_card"].includes(nextNoSplitType)) {
1250
+ const curCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1251
+ usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curCount + remainingNum);
1252
+ }
1253
+ const nextOriginTotal = product.original_price || product.price || 0;
1254
+ const nextTargetTotal = (0, import_utils.getDiscountAmount)(nextBundleDiscount, nextOriginTotal, nextOriginTotal);
1255
+ const nextDiscountAmount = new import_decimal.default(nextOriginTotal).minus(nextTargetTotal).toNumber();
1256
+ const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
1257
+ const nextBundleDiscType = nextBundleDiscount.tag === "product_discount_card" ? "discount_card" : nextBundleDiscount.tag;
1258
+ const nextDiscountDetail = {
1259
+ amount: nextDiscountAmount * remainingNum,
1260
+ type: nextBundleDiscType,
1261
+ discount: {
1262
+ discount_card_type: (_G = nextBundleDiscount == null ? void 0 : nextBundleDiscount.metadata) == null ? void 0 : _G.discount_card_type,
1263
+ fixed_amount: nextDiscountAmount,
1264
+ resource_id: nextBundleDiscount.id,
1265
+ title: nextBundleDiscount.format_title,
1266
+ original_amount: product.original_price,
1267
+ product_id: product.id,
1268
+ percent: nextBundleDiscount.par_value,
1269
+ discount_product_id: nextBundleDiscount.product_id
1270
+ },
1271
+ metadata: {
1272
+ custom_product_bundle_map_id: nextUniqueId,
1273
+ num: remainingNum
1274
+ },
1275
+ config: nextBundleDiscount == null ? void 0 : nextBundleDiscount.config,
1276
+ _num: remainingNum * (((_H = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _H.num) || 1)
1277
+ };
1278
+ const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1279
+ nextAppliedProducts.push(nextDiscountDetail);
1280
+ appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1281
+ processedItems.push({
1282
+ ...flatItem,
1283
+ _id: nextUniqueId,
1284
+ num: remainingNum,
1285
+ quantity: remainingNum,
1286
+ total: nextTargetTotal,
1287
+ price: new import_decimal.default(nextOriginTotal || 0).minus(nextDiscountDetail.discount.fixed_amount).toNumber(),
1288
+ discount_list: [nextDiscountDetail],
1289
+ processed: true
1290
+ });
1291
+ remainingNum = 0;
1292
+ break;
1293
+ }
1294
+ let nextMaxUsageLimit;
1295
+ if (nextIsGoodPass) {
1296
+ const nextGoodPassCount = nextApplicableDiscounts.filter(
1297
+ (item) => (item.tag || item.type) === "good_pass"
1298
+ ).length;
1299
+ nextMaxUsageLimit = nextGoodPassCount;
1300
+ if ((_I = nextSelectedDiscount.config) == null ? void 0 : _I.maxUsagePerOrder) {
1301
+ const usedCount = usedProductIdCounts.get(nextSelectedDiscount.product_id) || 0;
1302
+ nextMaxUsageLimit = Math.min(
1303
+ nextGoodPassCount,
1304
+ Math.max(0, nextSelectedDiscount.config.maxUsagePerOrder - usedCount)
1305
+ );
1306
+ }
1307
+ } else if (nextIsDiscountCard && nextApplicableProductLimit > 0) {
1308
+ const usedLimitCount = usedDiscountCardLimitCounts.get(nextSelectedDiscount.id) || 0;
1309
+ nextMaxUsageLimit = Math.max(0, nextApplicableProductLimit - usedLimitCount);
1310
+ } else {
1311
+ nextMaxUsageLimit = 1;
1312
+ }
1313
+ const nextSplitCount = Math.min(remainingNum, nextMaxUsageLimit);
1314
+ if (nextSplitCount === 0) {
1315
+ processedItems.push({
1316
+ ...flatItem,
1317
+ _id: `${flatItem._id}_split_rest`,
1318
+ num: remainingNum,
1319
+ quantity: remainingNum,
1320
+ discount_list: this.filterDiscountListByType(flatItem.discount_list, "promotion"),
1321
+ processed: true
1322
+ });
1323
+ break;
1324
+ }
1325
+ for (let j = 0; j < nextSplitCount; j++) {
1326
+ const nextBundleDiscount = nextIsGoodPass ? nextSelectedDiscountCard || nextApplicableDiscounts[j] : nextSelectedDiscountCard || nextApplicableDiscounts[0];
1327
+ usedDiscounts.set(nextBundleDiscount.id, true);
1328
+ if ((nextBundleDiscount.tag || nextBundleDiscount.type) === "good_pass") {
1329
+ const curCount = usedProductIdCounts.get(nextBundleDiscount.product_id) || 0;
1330
+ usedProductIdCounts.set(nextBundleDiscount.product_id, curCount + 1);
1331
+ }
1332
+ const nextBundleDiscTypeForCount = nextBundleDiscount.tag || nextBundleDiscount.type;
1333
+ if (["discount_card", "product_discount_card"].includes(nextBundleDiscTypeForCount)) {
1334
+ const curLimitCount = usedDiscountCardLimitCounts.get(nextBundleDiscount.id) || 0;
1335
+ usedDiscountCardLimitCounts.set(nextBundleDiscount.id, curLimitCount + 1);
1336
+ }
1337
+ const nextUniqueId = `${flatItem._id}_split_${continueSplitIndex}`;
1338
+ const nextDiscountedPrice = (0, import_utils.getDiscountAmount)(
1339
+ nextBundleDiscount,
1340
+ product.origin_total,
1341
+ product.origin_total
1342
+ );
1343
+ const nextBundleDiscAmount = new import_decimal.default(product.origin_total || 0).minus(nextDiscountedPrice).toNumber();
1344
+ const nextBundleDiscTypeStr = nextBundleDiscount.tag === "product_discount_card" ? "discount_card" : nextBundleDiscount.tag;
1345
+ const nextDiscountDetail = {
1346
+ amount: nextBundleDiscAmount,
1347
+ type: nextBundleDiscTypeStr,
1348
+ discount: {
1349
+ discount_card_type: (_J = nextBundleDiscount == null ? void 0 : nextBundleDiscount.metadata) == null ? void 0 : _J.discount_card_type,
1350
+ fixed_amount: nextBundleDiscAmount,
1351
+ resource_id: nextBundleDiscount.id,
1352
+ title: nextBundleDiscount.format_title,
1353
+ original_amount: product.origin_total,
1354
+ product_id: product.id,
1355
+ percent: nextBundleDiscount.par_value,
1356
+ discount_product_id: nextBundleDiscount.product_id
1357
+ },
1358
+ metadata: {
1359
+ custom_product_bundle_map_id: nextUniqueId,
1360
+ num: 1
1361
+ },
1362
+ _num: 1,
1363
+ config: nextBundleDiscount == null ? void 0 : nextBundleDiscount.config
1364
+ };
1365
+ const nextAppliedProducts = appliedDiscountProducts.get(nextBundleDiscount.id) || [];
1366
+ nextAppliedProducts.push(nextDiscountDetail);
1367
+ appliedDiscountProducts.set(nextBundleDiscount.id, nextAppliedProducts);
1368
+ processedItems.push({
1369
+ ...flatItem,
1370
+ _id: nextUniqueId,
1371
+ num: 1,
1372
+ quantity: 1,
1373
+ price: nextDiscountedPrice,
1374
+ total: nextDiscountedPrice,
1375
+ discount_list: [nextDiscountDetail],
1376
+ processed: true,
1377
+ _discountId: nextBundleDiscount.id
1378
+ });
1379
+ continueSplitIndex++;
1380
+ }
1381
+ remainingNum -= nextSplitCount;
933
1382
  }
934
1383
  } else {
935
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
936
- usedDiscounts.set(selectedDiscount2.id, true);
1384
+ const currentBundleDiscount = selectedDiscountCard || applicableDiscounts[0];
1385
+ usedDiscounts.set(currentBundleDiscount.id, true);
1386
+ if ((currentBundleDiscount.tag || currentBundleDiscount.type) === "good_pass") {
1387
+ const currentCount = usedProductIdCounts.get(currentBundleDiscount.product_id) || 0;
1388
+ usedProductIdCounts.set(currentBundleDiscount.product_id, currentCount + 1);
1389
+ }
1390
+ const noSplitDiscountType = currentBundleDiscount.tag || currentBundleDiscount.type;
1391
+ if (["discount_card", "product_discount_card"].includes(noSplitDiscountType)) {
1392
+ const bundleQuantity = product.num || 1;
1393
+ const currentNoSplitCount = usedDiscountCardLimitCounts.get(currentBundleDiscount.id) || 0;
1394
+ usedDiscountCardLimitCounts.set(currentBundleDiscount.id, currentNoSplitCount + bundleQuantity);
1395
+ }
937
1396
  const productOriginTotal = product.original_price || product.price || 0;
938
- const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
939
- const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
1397
+ const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount);
1398
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
940
1399
  const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
941
1400
  let targetProductTotal;
942
1401
  let fixedAmountPerItem;
@@ -947,39 +1406,42 @@ var RulesModule = class extends import_BaseModule.BaseModule {
947
1406
  targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
948
1407
  } else {
949
1408
  targetProductTotal = (0, import_utils.getDiscountAmount)(
950
- selectedDiscount2,
1409
+ currentBundleDiscount,
951
1410
  productOriginTotal,
952
1411
  productOriginTotal
953
1412
  );
954
1413
  fixedAmountPerItem = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
955
1414
  }
1415
+ const bundleActualDiscountAmount = new import_decimal.default(productOriginTotal).minus(targetProductTotal).toNumber();
956
1416
  const uniqueId = flatItem._id;
957
1417
  const discountDetail = {
958
- amount: fixedAmountPerItem * (product.num || 1),
959
- type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
1418
+ amount: bundleActualDiscountAmount * (product.num || 1),
1419
+ type: currentBundleDiscount.tag === "product_discount_card" ? "discount_card" : currentBundleDiscount.tag,
960
1420
  discount: {
961
- discount_card_type: (_A = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _A.discount_card_type,
962
- fixed_amount: fixedAmountPerItem,
963
- discount_calculation_mode: (_B = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _B.discount_calculation_mode,
964
- resource_id: selectedDiscount2.id,
965
- title: selectedDiscount2.format_title,
1421
+ discount_card_type: (_K = currentBundleDiscount == null ? void 0 : currentBundleDiscount.metadata) == null ? void 0 : _K.discount_card_type,
1422
+ fixed_amount: bundleActualDiscountAmount,
1423
+ discount_calculation_mode: (_L = currentBundleDiscount == null ? void 0 : currentBundleDiscount.metadata) == null ? void 0 : _L.discount_calculation_mode,
1424
+ resource_id: currentBundleDiscount.id,
1425
+ title: currentBundleDiscount.format_title,
966
1426
  original_amount: product.original_price,
967
1427
  product_id: product.id,
968
- percent: selectedDiscount2.par_value
1428
+ percent: currentBundleDiscount.par_value,
1429
+ discount_product_id: currentBundleDiscount.product_id
969
1430
  },
970
1431
  metadata: {
971
1432
  // 🔥 使用唯一的 _id
972
1433
  custom_product_bundle_map_id: uniqueId,
973
- discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1434
+ discount_rule_uncheck_flag: selectedDiscount == null ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
974
1435
  num: product.num || 1,
975
1436
  // 🔥 order_level 分摊差值
976
1437
  ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
977
1438
  },
978
- _num: (product.num || 1) * (((_C = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _C.num) || 1)
1439
+ config: currentBundleDiscount == null ? void 0 : currentBundleDiscount.config,
1440
+ _num: (product.num || 1) * (((_M = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _M.num) || 1)
979
1441
  };
980
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1442
+ const appliedProducts = appliedDiscountProducts.get(currentBundleDiscount.id) || [];
981
1443
  appliedProducts.push(discountDetail);
982
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1444
+ appliedDiscountProducts.set(currentBundleDiscount.id, appliedProducts);
983
1445
  processedItems.push({
984
1446
  ...flatItem,
985
1447
  total: targetProductTotal,
@@ -998,6 +1460,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
998
1460
  const mainProductArr = processedProductsMap2.get(product._id);
999
1461
  if (!mainProductArr || mainProductArr.length === 0) {
1000
1462
  const getDefaultProduct = () => {
1463
+ const restoredOptions = restoreOptionPrices(product.options);
1001
1464
  if (product.isClient) {
1002
1465
  return this.hooks.setProduct(originProduct, {
1003
1466
  discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
@@ -1007,7 +1470,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1007
1470
  original_price: product.original_price
1008
1471
  },
1009
1472
  bundle: product.bundle,
1010
- options: product.options
1473
+ options: restoredOptions
1011
1474
  }),
1012
1475
  variant: originProduct._productInit.variant,
1013
1476
  original_price: originProduct._productInit.original_price,
@@ -1016,15 +1479,17 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1016
1479
  price: product.price
1017
1480
  },
1018
1481
  bundle: product.bundle,
1019
- options: product.options
1020
- })
1482
+ options: restoredOptions
1483
+ }),
1484
+ options: restoredOptions
1021
1485
  });
1022
1486
  } else {
1023
1487
  return this.hooks.setProduct(originProduct, {
1024
1488
  discount_list: this.filterDiscountListByType(product.discount_list, "promotion"),
1025
1489
  total: product.total,
1026
1490
  origin_total: product.origin_total,
1027
- price: product.price
1491
+ price: product.price,
1492
+ options: restoreOptionPrices(product.options)
1028
1493
  });
1029
1494
  }
1030
1495
  };
@@ -1064,80 +1529,92 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1064
1529
  const mainProduct = mainProductArr[0];
1065
1530
  const mainProductData = this.hooks.getProduct(mainProduct);
1066
1531
  const newBundleWithDiscount = [];
1067
- (product.bundle || []).forEach((bundleItem, bundleIndex) => {
1068
- const processedItems = bundleProcessingInfo.get(bundleIndex) || [bundleItem];
1069
- if (processedItems.length > 1) {
1070
- processedItems.forEach((item) => {
1071
- const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1072
- var _a;
1073
- return {
1074
- ...discount,
1075
- metadata: {
1076
- ...discount.metadata,
1077
- num: item.num,
1078
- custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
1079
- }
1080
- // num: item.num, // 使用拆分后的 num
1081
- };
1082
- });
1083
- newBundleWithDiscount.push({
1084
- ...bundleItem,
1085
- _id: item._id,
1086
- product_id: bundleItem.product_id,
1087
- price: item.price,
1088
- num: item.num,
1089
- discount_list: updatedDiscountList2
1090
- });
1091
- });
1092
- } else {
1093
- const item = processedItems[0];
1094
- if (item.processed) {
1095
- const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1096
- var _a;
1097
- return {
1098
- ...discount,
1099
- metadata: {
1100
- ...discount.metadata,
1101
- num: item.num,
1102
- custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
1103
- }
1104
- // num: item.num, // 使用当前的 num
1105
- };
1106
- });
1107
- newBundleWithDiscount.push({
1108
- ...bundleItem,
1109
- _id: item._id,
1110
- product_id: bundleItem.product_id,
1111
- price: item.price,
1112
- num: item.num,
1113
- discount_list: updatedDiscountList2
1532
+ (product.bundle || []).forEach(
1533
+ (bundleItem, bundleIndex) => {
1534
+ const processedItems = bundleProcessingInfo.get(
1535
+ bundleIndex
1536
+ ) || [bundleItem];
1537
+ if (processedItems.length > 1) {
1538
+ processedItems.forEach((item) => {
1539
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1540
+ var _a;
1541
+ return {
1542
+ ...discount,
1543
+ metadata: {
1544
+ ...discount.metadata,
1545
+ num: item.num,
1546
+ custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
1547
+ }
1548
+ // num: item.num, // 使用拆分后的 num
1549
+ };
1550
+ });
1551
+ newBundleWithDiscount.push({
1552
+ ...bundleItem,
1553
+ _id: item._id,
1554
+ product_id: bundleItem.product_id,
1555
+ price: item.price,
1556
+ num: item.num,
1557
+ quantity: item.num,
1558
+ discount_list: updatedDiscountList2
1559
+ });
1114
1560
  });
1115
1561
  } else {
1116
- newBundleWithDiscount.push(item);
1562
+ const item = processedItems[0];
1563
+ if (item.processed) {
1564
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1565
+ var _a;
1566
+ return {
1567
+ ...discount,
1568
+ metadata: {
1569
+ ...discount.metadata,
1570
+ num: item.num,
1571
+ custom_product_bundle_map_id: (_a = item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id
1572
+ }
1573
+ // num: item.num, // 使用当前的 num
1574
+ };
1575
+ });
1576
+ newBundleWithDiscount.push({
1577
+ ...bundleItem,
1578
+ _id: item._id,
1579
+ product_id: bundleItem.product_id,
1580
+ price: item.price,
1581
+ num: item.num,
1582
+ quantity: item.num,
1583
+ discount_list: updatedDiscountList2
1584
+ });
1585
+ } else {
1586
+ newBundleWithDiscount.push(item);
1587
+ }
1117
1588
  }
1118
1589
  }
1119
- });
1590
+ );
1120
1591
  let newTotalWithDiscount = Number(mainProductData.price || 0);
1121
- let newOriginTotalWithDiscount = Number(mainProductData.original_price || mainProductData.price || 0);
1122
- const updatedMainDiscountList = mainProductData.discount_list.map((discount) => {
1123
- var _a, _b;
1124
- if ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.custom_product_bundle_map_id) {
1125
- return discount;
1126
- }
1127
- return {
1128
- ...discount,
1129
- // num: 1,
1130
- metadata: {
1131
- ...discount.metadata,
1132
- custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
1133
- num: 1
1592
+ let newOriginTotalWithDiscount = Number(
1593
+ mainProductData.original_price || mainProductData.price || 0
1594
+ );
1595
+ const updatedMainDiscountList = mainProductData.discount_list.map(
1596
+ (discount) => {
1597
+ var _a, _b;
1598
+ if ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.custom_product_bundle_map_id) {
1599
+ return discount;
1134
1600
  }
1135
- };
1136
- });
1137
- const mainDiscountList = updatedMainDiscountList.filter((item) => {
1138
- var _a;
1139
- return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
1140
- });
1601
+ return {
1602
+ ...discount,
1603
+ // num: 1,
1604
+ metadata: {
1605
+ ...discount.metadata,
1606
+ custom_product_bundle_map_id: (_b = discount == null ? void 0 : discount.metadata) == null ? void 0 : _b.custom_product_bundle_map_id,
1607
+ num: 1
1608
+ }
1609
+ };
1610
+ }
1611
+ );
1612
+ const mainDiscountList = updatedMainDiscountList.filter(
1613
+ (item) => {
1614
+ var _a;
1615
+ return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
1616
+ }
1617
+ );
1141
1618
  if (mainDiscountList && mainDiscountList.length > 0) {
1142
1619
  const allDiscountAmount = (0, import_utils.getDiscountListAmountTotal)(mainDiscountList);
1143
1620
  newTotalWithDiscount = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalWithDiscount;
@@ -1167,20 +1644,24 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1167
1644
  quantity: 1,
1168
1645
  discount_list: updatedMainDiscountList,
1169
1646
  bundle: newBundleWithDiscount,
1170
- total: new import_decimal.default(newTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber(),
1171
- origin_total: new import_decimal.default(newOriginTotalWithDiscount).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber()
1647
+ total: newTotalWithDiscount,
1648
+ origin_total: newOriginTotalWithDiscount
1172
1649
  })
1173
1650
  );
1174
1651
  if (mainProductQuantity > 1) {
1175
1652
  const newBundleOriginal = [];
1176
- (product.bundle || []).forEach((bundleItem, bundleIndex) => {
1177
- newBundleOriginal.push({
1178
- ...bundleItem,
1179
- discount_list: []
1180
- });
1181
- });
1653
+ (product.bundle || []).forEach(
1654
+ (bundleItem, bundleIndex) => {
1655
+ newBundleOriginal.push({
1656
+ ...bundleItem,
1657
+ discount_list: []
1658
+ });
1659
+ }
1660
+ );
1182
1661
  let newTotalOriginal = Number(mainProductData.price || 0);
1183
- let newOriginTotalOriginal = Number(mainProductData.original_price || mainProductData.price || 0);
1662
+ let newOriginTotalOriginal = Number(
1663
+ mainProductData.original_price || mainProductData.price || 0
1664
+ );
1184
1665
  const updatedMainDiscountListOriginal = mainProductData.discount_list.map((discount) => {
1185
1666
  var _a, _b;
1186
1667
  if ((_a = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a.custom_product_bundle_map_id) {
@@ -1196,12 +1677,16 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1196
1677
  // num: mainProductQuantity - 1,
1197
1678
  };
1198
1679
  });
1199
- const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter((item) => {
1200
- var _a;
1201
- return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
1202
- });
1680
+ const mainDiscountListOriginal = updatedMainDiscountListOriginal.filter(
1681
+ (item) => {
1682
+ var _a;
1683
+ return !((_a = item == null ? void 0 : item.metadata) == null ? void 0 : _a.custom_product_bundle_map_id);
1684
+ }
1685
+ );
1203
1686
  if (mainDiscountListOriginal && mainDiscountListOriginal.length > 0) {
1204
- const allDiscountAmount = (0, import_utils.getDiscountListAmount)(mainDiscountListOriginal);
1687
+ const allDiscountAmount = (0, import_utils.getDiscountListAmount)(
1688
+ mainDiscountListOriginal
1689
+ );
1205
1690
  newTotalOriginal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotalOriginal;
1206
1691
  newOriginTotalOriginal = mainProductData.origin_total ?? newOriginTotalOriginal;
1207
1692
  }
@@ -1238,59 +1723,68 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1238
1723
  const mainProductData = this.hooks.getProduct(mainProduct);
1239
1724
  const newBundle = [];
1240
1725
  if (product.bundle && Array.isArray(product.bundle)) {
1241
- product.bundle.forEach((bundleItem, bundleIndex) => {
1242
- const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
1243
- const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
1244
- if (!processedBundleItems || processedBundleItems.length === 0) {
1245
- newBundle.push(bundleItem);
1246
- } else {
1247
- processedBundleItems.forEach((item) => {
1248
- const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1249
- var _a2;
1250
- return {
1251
- ...discount,
1252
- metadata: {
1253
- ...discount.metadata,
1254
- num: item.num,
1255
- custom_product_bundle_map_id: (_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
1256
- }
1257
- // num: item.num, // 使用拆分后的 num
1258
- };
1726
+ product.bundle.forEach(
1727
+ (bundleItem, bundleIndex) => {
1728
+ const bundleItemId = `${product._id}_bundle_${bundleIndex}`;
1729
+ const processedBundleItems = processedFlatItemsMap2.get(bundleItemId);
1730
+ if (!processedBundleItems || processedBundleItems.length === 0) {
1731
+ newBundle.push(bundleItem);
1732
+ } else {
1733
+ processedBundleItems.forEach((item) => {
1734
+ const updatedDiscountList2 = (item.discount_list || []).map((discount) => {
1735
+ var _a2;
1736
+ return {
1737
+ ...discount,
1738
+ metadata: {
1739
+ ...discount.metadata,
1740
+ num: item.num,
1741
+ custom_product_bundle_map_id: (_a2 = discount == null ? void 0 : discount.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id
1742
+ }
1743
+ // num: item.num, // 使用拆分后的 num
1744
+ };
1745
+ });
1746
+ newBundle.push({
1747
+ ...bundleItem,
1748
+ _id: item._id,
1749
+ product_id: bundleItem.product_id,
1750
+ price: item.price,
1751
+ num: item.num,
1752
+ quantity: item.num,
1753
+ discount_list: updatedDiscountList2,
1754
+ bundle_selling_price: bundleItem.bundle_selling_price !== void 0 ? item.price : void 0
1755
+ });
1259
1756
  });
1260
- newBundle.push({
1261
- ...bundleItem,
1262
- _id: item._id,
1263
- product_id: bundleItem.product_id,
1264
- price: item.price,
1265
- num: item.num,
1266
- discount_list: updatedDiscountList2
1267
- });
1268
- });
1757
+ }
1269
1758
  }
1270
- });
1759
+ );
1271
1760
  }
1272
1761
  let newTotal = Number(mainProductData.price || 0);
1273
- let newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
1274
- const isManualDiscount = typeof mainProductData.isManualDiscount === "boolean" ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!((_a = mainProductData.discount_list) == null ? void 0 : _a.length) || ((_c = (_b = mainProductData == null ? void 0 : mainProductData.discount_list) == null ? void 0 : _b.every) == null ? void 0 : _c.call(_b, (item) => item.type === "product")));
1762
+ let newOriginTotal = Number(
1763
+ mainProductData.original_price || mainProductData.price || 0
1764
+ );
1765
+ const isManualDiscount = typeof mainProductData.isManualDiscount === "boolean" ? mainProductData.isManualDiscount : mainProductData.total != mainProductData.origin_total && (!((_a = mainProductData.discount_list) == null ? void 0 : _a.length) || ((_c = (_b = mainProductData == null ? void 0 : mainProductData.discount_list) == null ? void 0 : _b.every) == null ? void 0 : _c.call(
1766
+ _b,
1767
+ (item) => item.type === "product"
1768
+ )));
1275
1769
  if (isManualDiscount) {
1276
1770
  newTotal = mainProductData.total ?? newTotal;
1277
1771
  newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
1278
1772
  } else {
1279
- const mainDiscountList = mainProductData.discount_list.filter((item) => {
1280
- var _a2;
1281
- return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
1282
- });
1773
+ const mainDiscountList = mainProductData.discount_list.filter(
1774
+ (item) => {
1775
+ var _a2;
1776
+ return !((_a2 = item == null ? void 0 : item.metadata) == null ? void 0 : _a2.custom_product_bundle_map_id);
1777
+ }
1778
+ );
1283
1779
  if (mainDiscountList && mainDiscountList.length > 0) {
1284
1780
  const allDiscountAmount = (0, import_utils.getDiscountListAmount)(mainDiscountList);
1285
1781
  newTotal = new import_decimal.default(mainProductData.price || 0).minus(allDiscountAmount).toNumber() ?? newTotal;
1286
1782
  newOriginTotal = mainProductData.origin_total ?? newOriginTotal;
1287
1783
  }
1288
1784
  if (newBundle.length > 0) {
1289
- newBundle.forEach((item) => {
1290
- newTotal += Number(item.price) * Number(item.num);
1291
- });
1292
1785
  newBundle.forEach((item) => {
1293
1786
  var _a2, _b2, _c2;
1787
+ newTotal += Number(item.price) * Number(item.num);
1294
1788
  const originalPrice = ((_c2 = (_b2 = (_a2 = item.discount_list) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.discount) == null ? void 0 : _c2.original_amount) || item.price;
1295
1789
  newOriginTotal += Number(originalPrice) * Number(item.num);
1296
1790
  });
@@ -1303,8 +1797,6 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1303
1797
  return accumulator.add(currentPrice.mul(currentNum));
1304
1798
  }, new import_decimal.default(newTotal)).toNumber();
1305
1799
  }
1306
- newTotal = new import_decimal.default(newTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1307
- newOriginTotal = new import_decimal.default(newOriginTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
1308
1800
  result.push(
1309
1801
  this.hooks.setProduct(mainProduct, {
1310
1802
  ...mainProductData,
@@ -1421,14 +1913,14 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1421
1913
  const _isMarkupPrice = isMarkupPrice && rules.includes("markup_price");
1422
1914
  const isPriceValid = _isOriginalPrice || _isMarkupPrice;
1423
1915
  let isScopeValid = false;
1424
- if (scopeType === "all_packages" || scopeType === "product_all") {
1916
+ if (scopeType === "all_packages") {
1425
1917
  if (!filter) {
1426
1918
  isScopeValid = true;
1427
1919
  } else {
1428
1920
  isScopeValid = !exclude_bundle_product_ids.includes(Number(mainProductId));
1429
1921
  }
1430
1922
  }
1431
- if (scopeType === "specific_packages" || scopeType === "products") {
1923
+ if (scopeType === "specific_packages") {
1432
1924
  isScopeValid = include_bundle_product_ids.includes(Number(mainProductId));
1433
1925
  }
1434
1926
  if (isPriceValid && isScopeValid) {