@pisell/pisellos 2.1.52 → 2.1.54

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 (101) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/model/index.d.ts +1 -0
  4. package/dist/model/index.js +1 -0
  5. package/dist/model/strategy/adapter/index.d.ts +3 -0
  6. package/dist/model/strategy/adapter/index.js +4 -0
  7. package/dist/model/strategy/adapter/type.d.ts +28 -0
  8. package/dist/model/strategy/adapter/type.js +1 -0
  9. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
  10. package/dist/model/strategy/adapter/walletPass/evaluator.js +496 -0
  11. package/dist/model/strategy/adapter/walletPass/example.d.ts +4 -0
  12. package/dist/model/strategy/adapter/walletPass/example.js +258 -0
  13. package/dist/model/strategy/adapter/walletPass/index.d.ts +32 -0
  14. package/dist/model/strategy/adapter/walletPass/index.js +182 -0
  15. package/dist/model/strategy/adapter/walletPass/locales.d.ts +1 -0
  16. package/dist/model/strategy/adapter/walletPass/locales.js +23 -0
  17. package/dist/model/strategy/adapter/walletPass/type.d.ts +163 -0
  18. package/dist/model/strategy/adapter/walletPass/type.js +1 -0
  19. package/dist/model/strategy/adapter/walletPass/utils.d.ts +50 -0
  20. package/dist/model/strategy/adapter/walletPass/utils.js +965 -0
  21. package/dist/model/strategy/index.d.ts +94 -0
  22. package/dist/model/strategy/index.js +551 -0
  23. package/dist/model/strategy/strategy-example.d.ts +5 -0
  24. package/dist/model/strategy/strategy-example.js +331 -0
  25. package/dist/model/strategy/type.d.ts +228 -0
  26. package/dist/model/strategy/type.js +94 -0
  27. package/dist/modules/Cart/types.d.ts +2 -0
  28. package/dist/modules/Cart/utils/cartProduct.js +11 -0
  29. package/dist/modules/Discount/index.d.ts +1 -0
  30. package/dist/modules/Discount/index.js +1 -1
  31. package/dist/modules/Discount/types.d.ts +15 -0
  32. package/dist/modules/Payment/index.d.ts +2 -1
  33. package/dist/modules/Payment/index.js +10 -7
  34. package/dist/modules/Payment/utils.js +3 -0
  35. package/dist/modules/Payment/walletpass.d.ts +23 -0
  36. package/dist/modules/Payment/walletpass.js +191 -95
  37. package/dist/modules/Rules/index.d.ts +15 -3
  38. package/dist/modules/Rules/index.js +194 -28
  39. package/dist/modules/Rules/types.d.ts +5 -0
  40. package/dist/modules/Summary/types.d.ts +2 -0
  41. package/dist/modules/Summary/utils.d.ts +6 -0
  42. package/dist/modules/Summary/utils.js +21 -0
  43. package/dist/plugins/window.d.ts +2 -0
  44. package/dist/solution/BookingByStep/index.d.ts +1 -0
  45. package/dist/solution/BookingByStep/utils/capacity.js +1 -2
  46. package/dist/solution/Checkout/index.js +2 -0
  47. package/dist/solution/ShopDiscount/index.d.ts +4 -0
  48. package/dist/solution/ShopDiscount/index.js +26 -5
  49. package/dist/solution/ShopDiscount/types.d.ts +6 -0
  50. package/dist/solution/ShopDiscount/utils.js +26 -11
  51. package/lib/index.d.ts +1 -0
  52. package/lib/index.js +3 -1
  53. package/lib/model/index.d.ts +1 -0
  54. package/lib/model/index.js +23 -0
  55. package/lib/model/strategy/adapter/index.d.ts +3 -0
  56. package/lib/model/strategy/adapter/index.js +45 -0
  57. package/lib/model/strategy/adapter/type.d.ts +28 -0
  58. package/lib/model/strategy/adapter/type.js +17 -0
  59. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +84 -0
  60. package/lib/model/strategy/adapter/walletPass/evaluator.js +420 -0
  61. package/lib/model/strategy/adapter/walletPass/example.d.ts +4 -0
  62. package/lib/model/strategy/adapter/walletPass/example.js +207 -0
  63. package/lib/model/strategy/adapter/walletPass/index.d.ts +32 -0
  64. package/lib/model/strategy/adapter/walletPass/index.js +142 -0
  65. package/lib/model/strategy/adapter/walletPass/locales.d.ts +1 -0
  66. package/lib/model/strategy/adapter/walletPass/locales.js +51 -0
  67. package/lib/model/strategy/adapter/walletPass/type.d.ts +163 -0
  68. package/lib/model/strategy/adapter/walletPass/type.js +17 -0
  69. package/lib/model/strategy/adapter/walletPass/utils.d.ts +50 -0
  70. package/lib/model/strategy/adapter/walletPass/utils.js +660 -0
  71. package/lib/model/strategy/index.d.ts +94 -0
  72. package/lib/model/strategy/index.js +413 -0
  73. package/lib/model/strategy/strategy-example.d.ts +5 -0
  74. package/lib/model/strategy/strategy-example.js +318 -0
  75. package/lib/model/strategy/type.d.ts +228 -0
  76. package/lib/model/strategy/type.js +44 -0
  77. package/lib/modules/Cart/types.d.ts +2 -0
  78. package/lib/modules/Cart/utils/cartProduct.js +9 -0
  79. package/lib/modules/Discount/index.d.ts +1 -0
  80. package/lib/modules/Discount/index.js +1 -1
  81. package/lib/modules/Discount/types.d.ts +15 -0
  82. package/lib/modules/Payment/index.d.ts +2 -1
  83. package/lib/modules/Payment/index.js +1 -0
  84. package/lib/modules/Payment/utils.js +3 -0
  85. package/lib/modules/Payment/walletpass.d.ts +23 -0
  86. package/lib/modules/Payment/walletpass.js +94 -17
  87. package/lib/modules/Rules/index.d.ts +15 -3
  88. package/lib/modules/Rules/index.js +409 -195
  89. package/lib/modules/Rules/types.d.ts +5 -0
  90. package/lib/modules/Summary/types.d.ts +2 -0
  91. package/lib/modules/Summary/utils.d.ts +6 -0
  92. package/lib/modules/Summary/utils.js +15 -0
  93. package/lib/plugins/window.d.ts +2 -0
  94. package/lib/solution/BookingByStep/index.d.ts +1 -0
  95. package/lib/solution/BookingByStep/utils/capacity.js +1 -2
  96. package/lib/solution/Checkout/index.js +2 -0
  97. package/lib/solution/ShopDiscount/index.d.ts +4 -0
  98. package/lib/solution/ShopDiscount/index.js +18 -4
  99. package/lib/solution/ShopDiscount/types.d.ts +6 -0
  100. package/lib/solution/ShopDiscount/utils.js +10 -6
  101. package/package.json +1 -1
@@ -24,11 +24,13 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
24
24
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
25
25
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
26
26
  import { BaseModule } from "../BaseModule";
27
- import { uniqueById, getDiscountAmount, filterDiscountListByBookingTime, getDiscountListAmountTotal, getDiscountListAmount } from "../../solution/ShopDiscount/utils";
27
+ import { uniqueById, getDiscountAmount, getDiscountListAmountTotal, getDiscountListAmount, filterDiscountListByBookingTime } from "../../solution/ShopDiscount/utils";
28
28
  import { getProductOriginTotalPrice, getProductTotalPrice } from "../Cart/utils";
29
29
  import Decimal from 'decimal.js';
30
30
  import { isBoolean } from 'lodash-es';
31
31
  import dayjs from 'dayjs';
32
+ // 临时变量
33
+ var flatItem;
32
34
  export var RulesModule = /*#__PURE__*/function (_BaseModule) {
33
35
  _inherits(RulesModule, _BaseModule);
34
36
  var _super = _createSuper(RulesModule);
@@ -39,6 +41,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
39
41
  _defineProperty(_assertThisInitialized(_this), "defaultName", 'rules');
40
42
  _defineProperty(_assertThisInitialized(_this), "defaultVersion", '1.0.0');
41
43
  _defineProperty(_assertThisInitialized(_this), "store", void 0);
44
+ _defineProperty(_assertThisInitialized(_this), "window", void 0);
45
+ // WindowPlugin 实例
42
46
  _defineProperty(_assertThisInitialized(_this), "hooks", void 0);
43
47
  _this.hooks = {};
44
48
  return _this;
@@ -53,7 +57,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
53
57
  this.core = core;
54
58
  this.hooks = options === null || options === void 0 ? void 0 : options.hooks;
55
59
  this.store = options === null || options === void 0 ? void 0 : options.store;
56
- case 3:
60
+ this.window = core.getPlugin('window');
61
+ case 4:
57
62
  case "end":
58
63
  return _context.stop();
59
64
  }
@@ -90,6 +95,31 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
90
95
  value: function getRulesList() {
91
96
  return this.store.rulesList;
92
97
  }
98
+ }, {
99
+ key: "getWalletPassEvaluator",
100
+ value: function getWalletPassEvaluator() {
101
+ var _this$window$getWalle, _this$window;
102
+ return (_this$window$getWalle = (_this$window = this.window).getWalletPassEvaluator) === null || _this$window$getWalle === void 0 ? void 0 : _this$window$getWalle.call(_this$window);
103
+ }
104
+
105
+ // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
106
+ }, {
107
+ key: "checkHolderMatch",
108
+ value: function checkHolderMatch(discount, product, holders) {
109
+ var _discount$holder;
110
+ // 非表单类型 holder 视为匹配
111
+ if (((_discount$holder = discount.holder) === null || _discount$holder === void 0 ? void 0 : _discount$holder.holder_type) !== 'form') return true;
112
+ // 主预约holder, 目前(20251124)默认只考虑单个holder的情况
113
+ var orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id : undefined;
114
+ var productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
115
+ // 商品不需要选holder,则不对比holder,直接返回true,
116
+ if (!product.isNeedHolder) return true;
117
+ // 商品需要holder,但父预约及商品都无holder,返回false
118
+ if (!orderHolderId && !productHolderId) return false;
119
+
120
+ // 最终直接匹配 holder 是否相同
121
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
122
+ }
93
123
 
94
124
  // 判断discountList 是否可以对当前productList生效
95
125
  }, {
@@ -98,7 +128,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
98
128
  var _this2 = this;
99
129
  var oldDiscountList = _ref.oldDiscountList,
100
130
  newDiscountList = _ref.newDiscountList,
101
- productList = _ref.productList;
131
+ productList = _ref.productList,
132
+ holders = _ref.holders,
133
+ orderTotalAmount = _ref.orderTotalAmount;
102
134
  // 首先检查是否有新的优惠券可应用
103
135
  if (!newDiscountList || newDiscountList.length === 0) {
104
136
  return {
@@ -128,7 +160,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
128
160
  var mergedDiscountList = uniqueById(uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList))), 'product_id');
129
161
  var result = this.calcDiscount({
130
162
  discountList: mergedDiscountList,
131
- productList: _toConsumableArray(productList)
163
+ productList: _toConsumableArray(productList),
164
+ holders: holders,
165
+ orderTotalAmount: orderTotalAmount
132
166
  }, {
133
167
  scan: true
134
168
  });
@@ -170,7 +204,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
170
204
  value: function calcDiscount(_ref2, options) {
171
205
  var _this3 = this;
172
206
  var discountList = _ref2.discountList,
173
- productList = _ref2.productList;
207
+ productList = _ref2.productList,
208
+ holders = _ref2.holders,
209
+ orderTotalAmount = _ref2.orderTotalAmount;
174
210
  // 识别出来是不是在编辑的界面里又新增了商品
175
211
  // 这种情况下,如果有可用的优惠券,也会自动勾选上
176
212
  var isEditModeAddNewProduct = productList.find(function (n) {
@@ -344,6 +380,57 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
344
380
  return priceB.minus(priceA).toNumber();
345
381
  });
346
382
 
383
+ // 🔥 为每个折扣卡/商品券执行策略检查并附加config
384
+ var evaluator = this.getWalletPassEvaluator();
385
+ if (evaluator) {
386
+ addModeDiscount.forEach(function (discount) {
387
+ var discountType = discount.tag || discount.type;
388
+ // 只对 good_pass 和 discount_card 类型执行策略检查
389
+ if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
390
+ var _discount$limited_rel, _discount$limited_rel2;
391
+ // 转换 discount 为 Voucher 格式
392
+ var voucher = {
393
+ id: discount.id,
394
+ amount: Number(discount.par_value || 0),
395
+ balance: Number(discount.balance || 0),
396
+ type: discountType,
397
+ product_id: discount.product_id,
398
+ unified_available_status: 1,
399
+ available_product_type: (_discount$limited_rel = discount.limited_relation_product_data) === null || _discount$limited_rel === void 0 ? void 0 : _discount$limited_rel.type,
400
+ available_product_ids: (_discount$limited_rel2 = discount.limited_relation_product_data) === null || _discount$limited_rel2 === void 0 ? void 0 : _discount$limited_rel2.product_ids
401
+ };
402
+
403
+ // 转换 sortedFlattenedList 为 Product 格式
404
+ var productsForEvaluate = sortedFlattenedList.map(function (item) {
405
+ return {
406
+ product_id: item.id,
407
+ price: item.price || 0,
408
+ quantity: item.quantity || item.num || 1,
409
+ selling_price: item.price || 0
410
+ };
411
+ });
412
+
413
+ // 调用策略检查
414
+ var result = evaluator.checkVoucherAvailability({
415
+ orderTotalAmount: orderTotalAmount,
416
+ products: productsForEvaluate,
417
+ vouchers: [voucher]
418
+ });
419
+
420
+ // 将 config 附加到 discount 对象
421
+ if (result.isAvailable) {
422
+ discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
423
+ isAvailable: true
424
+ });
425
+ } else {
426
+ discount.config = {
427
+ isAvailable: false
428
+ };
429
+ }
430
+ }
431
+ });
432
+ }
433
+
347
434
  /**
348
435
  // 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
349
436
  const sortedProductList = [...productList].sort((a, b) => {
@@ -364,6 +451,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
364
451
  // 标记已使用的优惠券
365
452
  var usedDiscounts = new Map();
366
453
 
454
+ // 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
455
+ var usedProductIdCounts = new Map();
456
+
367
457
  // 记录每个优惠券适用的商品ID
368
458
  var discountApplicability = new Map();
369
459
 
@@ -406,12 +496,18 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
406
496
  originProduct = flatItem.originProduct;
407
497
  }
408
498
  addModeDiscount.forEach(function (discount) {
409
- var _product, _product2, _product3, _product4, _flatItem$bundleItem;
499
+ var _product, _product2, _product3, _product4, _flatItem$bundleItem, _discount$config;
410
500
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
501
+ // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
502
+ var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
503
+ var isHolderMatch = _this3.checkHolderMatch(discount, {
504
+ isNeedHolder: _tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.isNeedHolder,
505
+ holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
506
+ }, holders);
411
507
  var timeLimit = true;
412
508
  timeLimit = !!filterDiscountListByBookingTime([discount], (((_product = product) === null || _product === void 0 ? void 0 : _product.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
413
509
  // 是符合折扣的商品
414
- var isLimitedProduct = limitedData.type === 'product_all' || limitedData.product_ids && limitedData.product_ids.includes(product.id);
510
+ var 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;
415
511
 
416
512
  // 编辑的商品 使用了优惠券不可用
417
513
  var isAvailableProduct = flatItem.type === 'main' ? !((_product2 = product) !== null && _product2 !== void 0 && _product2.booking_id && (_product3 = product) !== null && _product3 !== void 0 && (_product3 = _product3.discount_list) !== null && _product3 !== void 0 && _product3.length && (_product4 = product) !== null && _product4 !== void 0 && (_product4 = _product4.discount_list) !== null && _product4 !== void 0 && _product4.every(function (discount) {
@@ -422,7 +518,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
422
518
  var isBundleAvailable = _this3.checkPackageSubItemUsageRules(discount, flatItem);
423
519
 
424
520
  // 判断优惠券是否适用于该商品
425
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
521
+ if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config = discount.config) !== null && _discount$config !== void 0 && _discount$config.isAvailable) {
426
522
  var _discountApplicabilit, _discount$metadata;
427
523
  // 记录此优惠券适用的商品
428
524
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -445,7 +541,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
445
541
  title: discount.format_title,
446
542
  original_amount: product.price || product.origin_total,
447
543
  pre_value: discount.par_value,
448
- product_id: originProduct.id
544
+ product_id: originProduct.id,
545
+ discount_product_id: discount.product_id
449
546
  },
450
547
  metadata: {
451
548
  num: num
@@ -504,6 +601,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
504
601
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
505
602
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
506
603
  var _product$discount_lis3, _product$discount_lis4;
604
+ // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
605
+ var discountType = discount.tag || discount.type;
606
+ if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
607
+ var _discount$config2;
608
+ // 如果策略检查后没有config,说明不可用
609
+ if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable)) {
610
+ return false;
611
+ }
612
+ }
613
+
507
614
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
508
615
  // 商品券时主商品价格为0不可用
509
616
  if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.find(function (n) {
@@ -519,7 +626,28 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
519
626
  // 如果优惠券已被使用,则跳过
520
627
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
521
628
  if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
629
+
630
+ // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
631
+ if ((discount.tag || discount.type) === 'good_pass') {
632
+ var _discount$config3;
633
+ var maxUsagePerOrder = (_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.maxUsagePerOrder;
634
+ if (maxUsagePerOrder && maxUsagePerOrder > 0) {
635
+ var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
636
+ if (currentUsedCount >= maxUsagePerOrder) {
637
+ return false;
638
+ }
639
+ }
640
+ }
522
641
  var limitedData = discount.limited_relation_product_data;
642
+
643
+ // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
644
+ var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
645
+ var isHolderMatch = _this3.checkHolderMatch(discount, {
646
+ isNeedHolder: _tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.isNeedHolder,
647
+ holder_id: (_tempVar === null || _tempVar === void 0 ? void 0 : _tempVar.holder_id) || product.holder_id
648
+ }, holders);
649
+ // 如果 holder 不匹配,则不适用
650
+ if (!isHolderMatch) return false;
523
651
  var timeLimit = true;
524
652
  timeLimit = !!filterDiscountListByBookingTime([discount], (product.startDate || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
525
653
  if (!timeLimit) {
@@ -528,6 +656,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
528
656
 
529
657
  // 判断优惠券是否适用于该商品
530
658
  if (limitedData.type === 'product_all') {
659
+ if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
660
+ return false;
661
+ }
531
662
  // 检查 package_sub_item_usage_rules
532
663
  if (!_this3.checkPackageSubItemUsageRules(discount, flatItem)) {
533
664
  return false;
@@ -694,7 +825,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
694
825
  var availableGoodPassCount = applicableDiscounts.filter(function (item) {
695
826
  return (item.tag || item.type) === 'good_pass';
696
827
  }).length;
697
- var splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
828
+
829
+ // 🔥 如果selectedDiscount有config配置,则使用config.maxUsagePerOrder限制使用次数
830
+ var maxUsageLimit = availableGoodPassCount;
831
+ if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
832
+ maxUsageLimit = Math.min(availableGoodPassCount, selectedDiscount.config.maxUsagePerOrder);
833
+ }
834
+ var splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
698
835
  var arr = [];
699
836
 
700
837
  // 🔥 主商品和bundle子商品分别处理
@@ -704,7 +841,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
704
841
  arr.push(_this3.hooks.setProduct(originProduct, {
705
842
  discount_list: [],
706
843
  quantity: totalQuantity - splitCount,
707
- _id: product._id.split('___')[0]
844
+ _id: product._id.split('___')[0],
845
+ total: product.origin_total || product.total
708
846
  }));
709
847
  }
710
848
  for (var i = 0; i < splitCount; i++) {
@@ -713,6 +851,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
713
851
  var _selectedDiscount = selectedDiscountCard || applicableDiscounts[i];
714
852
  // 标记优惠券为已使用
715
853
  usedDiscounts.set(_selectedDiscount.id, true);
854
+ // 🔥 更新 product_id 使用计数
855
+ if ((_selectedDiscount.tag || _selectedDiscount.type) === 'good_pass') {
856
+ var currentCount = usedProductIdCounts.get(_selectedDiscount.product_id) || 0;
857
+ usedProductIdCounts.set(_selectedDiscount.product_id, currentCount + 1);
858
+ }
716
859
 
717
860
  // 记录实际应用了优惠券的商品信息
718
861
  var appliedProducts = appliedDiscountProducts.get(_selectedDiscount.id) || [];
@@ -730,23 +873,27 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
730
873
 
731
874
  // 计算使用折扣卡/商品券以后,单个商品的总 total
732
875
  var targetProductTotal = getDiscountAmount(_selectedDiscount, product.price, product.price);
733
- var discountType = _selectedDiscount.tag || _selectedDiscount.type;
876
+ var discountType = _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount.tag;
877
+
878
+ // 计算实际折扣金额
879
+ var actualDiscountAmount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
734
880
  var isGoodPass = discountType === 'good_pass';
735
- var amount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
736
881
  var discountDetail = {
737
- amount: amount,
738
- type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
882
+ amount: actualDiscountAmount,
883
+ type: discountType,
739
884
  discount: {
740
885
  discount_card_type: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met = _selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
741
- fixed_amount: amount,
886
+ fixed_amount: actualDiscountAmount,
742
887
  resource_id: _selectedDiscount.id,
743
888
  title: _selectedDiscount.format_title,
744
889
  original_amount: product.price,
745
890
  product_id: originProduct.id,
746
- percent: _selectedDiscount.par_value
891
+ percent: _selectedDiscount.par_value,
892
+ discount_product_id: _selectedDiscount.product_id
747
893
  },
748
894
  // 前端使用的num数量,为了计算优惠金额
749
895
  _num: isGoodPass ? 1 : product.num,
896
+ config: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.config,
750
897
  metadata: {
751
898
  num: 1
752
899
  }
@@ -765,7 +912,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
765
912
  // 记录应用了优惠券的商品
766
913
  // 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
767
914
  if (product.isClient) {
768
- debugger;
769
915
  arr.push(_this3.hooks.setProduct(originProduct, {
770
916
  discount_list: [discountDetail],
771
917
  price: _selectedDiscount.tag === 'good_pass' ? 0 : product.price,
@@ -806,25 +952,36 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
806
952
  for (var _i = 0; _i < discountNum; _i++) {
807
953
  var _selectedDiscount2 = applicableDiscounts[_i];
808
954
  usedDiscounts.set(_selectedDiscount2.id, true);
955
+ // 🔥 更新 product_id 使用计数
956
+ if ((_selectedDiscount2.tag || _selectedDiscount2.type) === 'good_pass') {
957
+ var _currentCount = usedProductIdCounts.get(_selectedDiscount2.product_id) || 0;
958
+ usedProductIdCounts.set(_selectedDiscount2.product_id, _currentCount + 1);
959
+ }
809
960
 
810
961
  // 🔥 生成唯一的 _id
811
962
  var uniqueId = "".concat(flatItem._id, "_split_").concat(_i);
963
+
964
+ // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
965
+ var discountedPrice = getDiscountAmount(_selectedDiscount2, product.origin_total, product.origin_total);
966
+ var bundleDiscountAmount = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
812
967
  var _discountDetail = {
813
- amount: product.origin_total,
968
+ amount: bundleDiscountAmount,
814
969
  type: 'good_pass',
815
970
  discount: {
816
971
  fixed_amount: product.origin_total,
817
972
  resource_id: _selectedDiscount2.id,
818
973
  title: _selectedDiscount2.format_title,
819
974
  original_amount: product.origin_total,
820
- product_id: product.id
975
+ product_id: product.id,
976
+ discount_product_id: _selectedDiscount2.product_id
821
977
  },
822
978
  metadata: {
823
979
  // 🔥 使用拆分后的唯一 _id
824
980
  custom_product_bundle_map_id: uniqueId,
825
981
  num: 1
826
982
  },
827
- _num: 1
983
+ _num: 1,
984
+ config: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.config
828
985
  };
829
986
 
830
987
  // 记录实际应用的折扣
@@ -836,9 +993,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
836
993
  _id: uniqueId,
837
994
  num: 1,
838
995
  quantity: 1,
839
- price: 0,
840
- // 商品券价格为0
841
- total: 0,
996
+ price: discountedPrice,
997
+ // 折扣后的价格
998
+ total: discountedPrice,
842
999
  discount_list: [_discountDetail],
843
1000
  processed: true,
844
1001
  _discountId: _selectedDiscount2.id
@@ -861,28 +1018,38 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
861
1018
  // 折扣卡:不拆分数量,直接应用
862
1019
  var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
863
1020
  usedDiscounts.set(_selectedDiscount3.id, true);
1021
+ // 🔥 更新 product_id 使用计数(虽然此处主要是折扣卡,但保持一致性)
1022
+ if ((_selectedDiscount3.tag || _selectedDiscount3.type) === 'good_pass') {
1023
+ var _currentCount2 = usedProductIdCounts.get(_selectedDiscount3.product_id) || 0;
1024
+ usedProductIdCounts.set(_selectedDiscount3.product_id, _currentCount2 + 1);
1025
+ }
864
1026
  var _productOriginTotal = product.original_price || product.price || 0;
865
1027
  var _targetProductTotal = getDiscountAmount(_selectedDiscount3, _productOriginTotal, _productOriginTotal);
866
1028
 
1029
+ // 计算实际折扣金额
1030
+ var bundleActualDiscountAmount = new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber();
1031
+
867
1032
  // 🔥 使用当前的 _id 作为唯一标识
868
1033
  var _uniqueId = flatItem._id;
869
1034
  var _discountDetail2 = {
870
- amount: new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber() * (product.num || 1),
1035
+ amount: bundleActualDiscountAmount * (product.num || 1),
871
1036
  type: _selectedDiscount3.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount3.tag,
872
1037
  discount: {
873
1038
  discount_card_type: _selectedDiscount3 === null || _selectedDiscount3 === void 0 || (_selectedDiscount3$me = _selectedDiscount3.metadata) === null || _selectedDiscount3$me === void 0 ? void 0 : _selectedDiscount3$me.discount_card_type,
874
- fixed_amount: new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber(),
1039
+ fixed_amount: bundleActualDiscountAmount,
875
1040
  resource_id: _selectedDiscount3.id,
876
1041
  title: _selectedDiscount3.format_title,
877
1042
  original_amount: product.original_price,
878
1043
  product_id: product.id,
879
- percent: _selectedDiscount3.par_value
1044
+ percent: _selectedDiscount3.par_value,
1045
+ discount_product_id: _selectedDiscount3.product_id
880
1046
  },
881
1047
  metadata: {
882
1048
  // 🔥 使用唯一的 _id
883
1049
  custom_product_bundle_map_id: _uniqueId,
884
1050
  num: product.num || 1
885
1051
  },
1052
+ config: _selectedDiscount3 === null || _selectedDiscount3 === void 0 ? void 0 : _selectedDiscount3.config,
886
1053
  _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu3 = flatItem.parentProduct) === null || _flatItem$parentProdu3 === void 0 ? void 0 : _flatItem$parentProdu3.num) || 1)
887
1054
  };
888
1055
 
@@ -948,7 +1115,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
948
1115
 
949
1116
  // 检查是否有bundle子商品需要重组
950
1117
  var hasBundle = product.bundle && Array.isArray(product.bundle) && product.bundle.length > 0;
951
- debugger;
952
1118
  if (!hasBundle) {
953
1119
  // 没有bundle,直接使用主商品处理结果
954
1120
  result.push.apply(result, _toConsumableArray(mainProductArr));
@@ -22,6 +22,10 @@ export interface RulesModuleAPI {
22
22
  calcDiscount: (params: {
23
23
  discountList: any[];
24
24
  productList: any[];
25
+ holders: {
26
+ form_record_id: number;
27
+ }[];
28
+ orderTotalAmount: number;
25
29
  }) => DiscountResult;
26
30
  }
27
31
  type ProductDetail = {
@@ -39,6 +43,7 @@ type ProductDetail = {
39
43
  original_price?: number | string;
40
44
  num?: number;
41
45
  quantity: number;
46
+ holder_id?: number | string;
42
47
  vouchersApplicable?: boolean;
43
48
  startDate?: any;
44
49
  };
@@ -5,6 +5,8 @@ export interface ISummaryState {
5
5
  subtotal: string | number;
6
6
  /** 最终总价 */
7
7
  total: string | number;
8
+ /** 最终原始价格 不包含折扣卡商品券折扣 */
9
+ originTotal: string | number;
8
10
  /** 税率标题 */
9
11
  taxTitle?: string;
10
12
  /** 商品总费率 */
@@ -8,6 +8,12 @@ export declare const calculatePriceDetails: (shopInfo: any, items: CartItem[]) =
8
8
  * @returns 商品总价字符串,保留2位小数
9
9
  */
10
10
  export declare const calculateSubtotal: (items: CartItem[]) => string;
11
+ /**
12
+ * 计算商品小计(不含其他费用 不包含折扣卡商品券抵扣金额)
13
+ * @param items - 购物车商品数组
14
+ * @returns 商品总价字符串,保留2位小数
15
+ */
16
+ export declare const calculateOriginSubtotal: (items: CartItem[]) => string;
11
17
  /**
12
18
  * @title: 单个商品的税费
13
19
  * @description:
@@ -1,16 +1,21 @@
1
1
  import Decimal from 'decimal.js';
2
2
  export var calculatePriceDetails = function calculatePriceDetails(shopInfo, items) {
3
3
  var subtotal = new Decimal(calculateSubtotal(items));
4
+ var subOriginTotal = new Decimal(calculateOriginSubtotal(items));
4
5
  var totalTaxFee = new Decimal(calculateTaxFee(shopInfo, items));
5
6
 
6
7
  // 计算总价
7
8
  var total = shopInfo !== null && shopInfo !== void 0 && shopInfo.is_price_include_tax ? subtotal : subtotal.plus(totalTaxFee);
8
9
 
10
+ // 计算总价 不包含折扣卡商品券折扣信息价格
11
+ var originTotal = shopInfo !== null && shopInfo !== void 0 && shopInfo.is_price_include_tax ? subOriginTotal : subOriginTotal.plus(totalTaxFee);
12
+
9
13
  // 计算定金
10
14
  var deposit = calculateDeposit(items);
11
15
  return {
12
16
  subtotal: subtotal.toFixed(2),
13
17
  total: total.toFixed(2),
18
+ originTotal: originTotal.toFixed(2),
14
19
  taxTitle: shopInfo === null || shopInfo === void 0 ? void 0 : shopInfo.tax_title,
15
20
  totalTaxFee: totalTaxFee.toFixed(2),
16
21
  isPriceIncludeTax: shopInfo === null || shopInfo === void 0 ? void 0 : shopInfo.is_price_include_tax,
@@ -34,6 +39,22 @@ export var calculateSubtotal = function calculateSubtotal(items) {
34
39
  return subtotal.toFixed(2);
35
40
  };
36
41
 
42
+ /**
43
+ * 计算商品小计(不含其他费用 不包含折扣卡商品券抵扣金额)
44
+ * @param items - 购物车商品数组
45
+ * @returns 商品总价字符串,保留2位小数
46
+ */
47
+ export var calculateOriginSubtotal = function calculateOriginSubtotal(items) {
48
+ if (!(items !== null && items !== void 0 && items.length)) {
49
+ return '0.00';
50
+ }
51
+ var subtotal = items.reduce(function (sum, item) {
52
+ var cartItemTotalPrice = new Decimal(item.summaryOriginTotal || 0);
53
+ return sum.plus(cartItemTotalPrice);
54
+ }, new Decimal(0));
55
+ return subtotal.toFixed(2);
56
+ };
57
+
37
58
  /**
38
59
  * @title: 单个商品的税费
39
60
  * @description:
@@ -1,3 +1,4 @@
1
+ import { WalletPassEvaluator } from '../model';
1
2
  import { Plugin } from '../types';
2
3
  /**
3
4
  * WindowPlugin 接口定义
@@ -14,6 +15,7 @@ export interface WindowPlugin extends Plugin {
14
15
  document: Partial<Document>;
15
16
  history: History;
16
17
  interaction?: any;
18
+ getWalletPassEvaluator?: () => WalletPassEvaluator;
17
19
  }
18
20
  /**
19
21
  * 简单的 Storage 接口实现
@@ -144,6 +144,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
144
144
  getSummary(): Promise<{
145
145
  subtotal: string | number;
146
146
  total: string | number;
147
+ originTotal: string | number;
147
148
  taxTitle?: string | undefined;
148
149
  totalTaxFee?: string | number | undefined;
149
150
  isPriceIncludeTax?: 0 | 1 | undefined;
@@ -344,8 +344,7 @@ export function checkTimeSlotCapacity(timeSlotStart, timeSlotEnd, cartItems, all
344
344
  resourcesInType.forEach(function (resource) {
345
345
  // 过滤出在时间段内的资源时间片
346
346
  var availableTimes = resource.times.filter(function (time) {
347
- var _time$event_list;
348
- return !dayjs(time.start_at).isAfter(dayjs(timeSlotStart), 'minute') && !dayjs(time.end_at).isBefore(dayjs(timeSlotEnd), 'minute') || dayjs(time.start_at).isBefore(dayjs(timeSlotEnd), 'minute') && dayjs(time.end_at).isAfter(dayjs(timeSlotStart), 'minute') && ((_time$event_list = time.event_list) === null || _time$event_list === void 0 ? void 0 : _time$event_list.length) === 0;
347
+ return !dayjs(time.start_at).isAfter(dayjs(timeSlotStart), 'minute') && !dayjs(time.end_at).isBefore(dayjs(timeSlotEnd), 'minute') || dayjs(time.start_at).isBefore(dayjs(timeSlotEnd), 'minute') && dayjs(time.end_at).isAfter(dayjs(timeSlotStart), 'minute');
349
348
  });
350
349
  if (availableTimes.length > 0) {
351
350
  availableResourceCount++;
@@ -403,6 +403,7 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
403
403
  product_id: item.product_id,
404
404
  product_variant_id: item.product_variant_id,
405
405
  quantity: item.num,
406
+ is_price_include_tax: item.is_price_include_tax,
406
407
  // 商品是否含税:1;0
407
408
  is_charge_tax: (_item$is_charge_tax = item.is_charge_tax) !== null && _item$is_charge_tax !== void 0 ? _item$is_charge_tax : 0,
408
409
  // 若商品不含税,计算得到的税费,单位(元)
@@ -427,6 +428,7 @@ export var CheckoutImpl = /*#__PURE__*/function (_BaseModule) {
427
428
  },
428
429
  product_bundle: item.product_bundle.map(function (bundle) {
429
430
  return {
431
+ is_price_include_tax: item.is_price_include_tax,
430
432
  bundle_id: bundle.bundle_id,
431
433
  bundle_product_id: bundle.bundle_product_id,
432
434
  bundle_variant_id: bundle.bundle_variant_id,
@@ -21,6 +21,10 @@ export declare class ShopDiscountImpl extends BaseModule implements Module {
21
21
  getCurrentBookingTime(): string | null;
22
22
  private filterDiscountListByBookingTime;
23
23
  setCustomer(customer: Customer): Promise<void>;
24
+ setOriginTotalAmount(amount: number): void;
25
+ setHolders(holders: {
26
+ form_record_id: number;
27
+ }[]): void;
24
28
  calcDiscount(productList: Record<string, any>[], options?: SetDiscountSelectedParams): {
25
29
  productList: Record<string, any>[];
26
30
  discountList: Discount[];
@@ -51,9 +51,11 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
51
51
  productList: [],
52
52
  discount: null,
53
53
  rules: null,
54
+ holders: [],
54
55
  originalDiscountList: [],
55
56
  currentBookingTime: "",
56
- filteredDiscountList: []
57
+ filteredDiscountList: [],
58
+ orderTotalAmount: 0
57
59
  };
58
60
  return _this;
59
61
  }
@@ -285,7 +287,21 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
285
287
  return _setCustomer.apply(this, arguments);
286
288
  }
287
289
  return setCustomer;
288
- }() // 计算优惠券
290
+ }()
291
+ }, {
292
+ key: "setOriginTotalAmount",
293
+ value: function setOriginTotalAmount(amount) {
294
+ this.store.orderTotalAmount = amount;
295
+ }
296
+
297
+ // 设置holders
298
+ }, {
299
+ key: "setHolders",
300
+ value: function setHolders(holders) {
301
+ this.store.holders = holders;
302
+ }
303
+
304
+ // 计算优惠券
289
305
  }, {
290
306
  key: "calcDiscount",
291
307
  value: function calcDiscount(productList, options) {
@@ -299,7 +315,9 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
299
315
  }
300
316
  var _ref = rulesModule.calcDiscount({
301
317
  productList: productList,
302
- discountList: this.getDiscountList()
318
+ discountList: this.getDiscountList(),
319
+ holders: this.store.holders || [],
320
+ orderTotalAmount: this.store.orderTotalAmount || 0
303
321
  }, options) || {
304
322
  productList: productList,
305
323
  discountList: this.getDiscountList()
@@ -437,7 +455,9 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
437
455
  _ref2 = rulesModule.isDiscountListAvailable({
438
456
  productList: this.store.productList || [],
439
457
  oldDiscountList: this.getDiscountList(),
440
- newDiscountList: withScanList
458
+ newDiscountList: withScanList,
459
+ holders: this.store.holders || [],
460
+ orderTotalAmount: this.store.orderTotalAmount || 0
441
461
  }) || {
442
462
  isAvailable: false,
443
463
  productList: this.store.productList || [],
@@ -720,7 +740,8 @@ export var ShopDiscountImpl = /*#__PURE__*/function (_BaseModule) {
720
740
  customer_id: customerId,
721
741
  action: 'create',
722
742
  with_good_pass: 1,
723
- with_discount_card: 1
743
+ with_discount_card: 1,
744
+ with_wallet_pass_holder: 1
724
745
  });
725
746
  case 4:
726
747
  goodPassList = _context9.sent;