@pisell/pisellos 2.1.62 → 2.1.64

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 +497 -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.js +1 -1
  30. package/dist/modules/Discount/types.d.ts +15 -0
  31. package/dist/modules/Payment/index.d.ts +2 -1
  32. package/dist/modules/Payment/index.js +10 -7
  33. package/dist/modules/Payment/utils.js +3 -0
  34. package/dist/modules/Payment/walletpass.d.ts +23 -0
  35. package/dist/modules/Payment/walletpass.js +191 -95
  36. package/dist/modules/Rules/index.d.ts +8 -3
  37. package/dist/modules/Rules/index.js +164 -34
  38. package/dist/modules/Rules/types.d.ts +1 -0
  39. package/dist/modules/Summary/types.d.ts +2 -0
  40. package/dist/modules/Summary/utils.d.ts +6 -0
  41. package/dist/modules/Summary/utils.js +21 -0
  42. package/dist/plugins/window.d.ts +2 -0
  43. package/dist/solution/BookingByStep/index.d.ts +2 -0
  44. package/dist/solution/BookingByStep/index.js +12 -1
  45. package/dist/solution/BookingTicket/index.d.ts +1 -1
  46. package/dist/solution/Checkout/index.js +2 -0
  47. package/dist/solution/ShopDiscount/index.d.ts +1 -0
  48. package/dist/solution/ShopDiscount/index.js +11 -1
  49. package/dist/solution/ShopDiscount/types.d.ts +1 -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 +421 -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.js +1 -1
  80. package/lib/modules/Discount/types.d.ts +15 -0
  81. package/lib/modules/Payment/index.d.ts +2 -1
  82. package/lib/modules/Payment/index.js +1 -0
  83. package/lib/modules/Payment/utils.js +3 -0
  84. package/lib/modules/Payment/walletpass.d.ts +23 -0
  85. package/lib/modules/Payment/walletpass.js +94 -17
  86. package/lib/modules/Rules/index.d.ts +8 -3
  87. package/lib/modules/Rules/index.js +381 -199
  88. package/lib/modules/Rules/types.d.ts +1 -0
  89. package/lib/modules/Summary/types.d.ts +2 -0
  90. package/lib/modules/Summary/utils.d.ts +6 -0
  91. package/lib/modules/Summary/utils.js +15 -0
  92. package/lib/plugins/window.d.ts +2 -0
  93. package/lib/solution/BookingByStep/index.d.ts +2 -0
  94. package/lib/solution/BookingByStep/index.js +12 -1
  95. package/lib/solution/BookingTicket/index.d.ts +1 -1
  96. package/lib/solution/Checkout/index.js +2 -0
  97. package/lib/solution/ShopDiscount/index.d.ts +1 -0
  98. package/lib/solution/ShopDiscount/index.js +6 -0
  99. package/lib/solution/ShopDiscount/types.d.ts +1 -0
  100. package/lib/solution/ShopDiscount/utils.js +10 -6
  101. package/package.json +1 -1
@@ -24,12 +24,11 @@ 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
32
  // 临时变量
34
33
  var flatItem;
35
34
  export var RulesModule = /*#__PURE__*/function (_BaseModule) {
@@ -42,6 +41,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
42
41
  _defineProperty(_assertThisInitialized(_this), "defaultName", 'rules');
43
42
  _defineProperty(_assertThisInitialized(_this), "defaultVersion", '1.0.0');
44
43
  _defineProperty(_assertThisInitialized(_this), "store", void 0);
44
+ _defineProperty(_assertThisInitialized(_this), "window", void 0);
45
+ // WindowPlugin 实例
45
46
  _defineProperty(_assertThisInitialized(_this), "hooks", void 0);
46
47
  _this.hooks = {};
47
48
  return _this;
@@ -56,7 +57,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
56
57
  this.core = core;
57
58
  this.hooks = options === null || options === void 0 ? void 0 : options.hooks;
58
59
  this.store = options === null || options === void 0 ? void 0 : options.store;
59
- case 3:
60
+ this.window = core.getPlugin('window');
61
+ case 4:
60
62
  case "end":
61
63
  return _context.stop();
62
64
  }
@@ -93,6 +95,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
93
95
  value: function getRulesList() {
94
96
  return this.store.rulesList;
95
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
+ }
96
104
 
97
105
  // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
98
106
  }, {
@@ -122,6 +130,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
122
130
  newDiscountList = _ref.newDiscountList,
123
131
  productList = _ref.productList,
124
132
  holders = _ref.holders,
133
+ orderTotalAmount = _ref.orderTotalAmount,
125
134
  isFormSubject = _ref.isFormSubject;
126
135
  // 首先检查是否有新的优惠券可应用
127
136
  if (!newDiscountList || newDiscountList.length === 0) {
@@ -154,6 +163,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
154
163
  discountList: mergedDiscountList,
155
164
  productList: _toConsumableArray(productList),
156
165
  holders: holders,
166
+ orderTotalAmount: orderTotalAmount,
157
167
  isFormSubject: isFormSubject
158
168
  }, {
159
169
  scan: true
@@ -198,6 +208,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
198
208
  var discountList = _ref2.discountList,
199
209
  productList = _ref2.productList,
200
210
  holders = _ref2.holders,
211
+ orderTotalAmount = _ref2.orderTotalAmount,
201
212
  isFormSubject = _ref2.isFormSubject;
202
213
  // 识别出来是不是在编辑的界面里又新增了商品
203
214
  // 这种情况下,如果有可用的优惠券,也会自动勾选上
@@ -374,6 +385,57 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
374
385
  return priceB.minus(priceA).toNumber();
375
386
  });
376
387
 
388
+ // 🔥 为每个折扣卡/商品券执行策略检查并附加config
389
+ var evaluator = this.getWalletPassEvaluator();
390
+ if (evaluator) {
391
+ addModeDiscount.forEach(function (discount) {
392
+ var discountType = discount.tag || discount.type;
393
+ // 只对 good_pass 和 discount_card 类型执行策略检查
394
+ if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
395
+ var _discount$limited_rel, _discount$limited_rel2;
396
+ // 转换 discount 为 Voucher 格式
397
+ var voucher = {
398
+ id: discount.id,
399
+ amount: Number(discount.par_value || 0),
400
+ balance: Number(discount.balance || 0),
401
+ type: discountType,
402
+ product_id: discount.product_id,
403
+ unified_available_status: 1,
404
+ available_product_type: (_discount$limited_rel = discount.limited_relation_product_data) === null || _discount$limited_rel === void 0 ? void 0 : _discount$limited_rel.type,
405
+ available_product_ids: (_discount$limited_rel2 = discount.limited_relation_product_data) === null || _discount$limited_rel2 === void 0 ? void 0 : _discount$limited_rel2.product_ids
406
+ };
407
+
408
+ // 转换 sortedFlattenedList 为 Product 格式
409
+ var productsForEvaluate = sortedFlattenedList.map(function (item) {
410
+ return {
411
+ product_id: item.id,
412
+ price: item.price || 0,
413
+ quantity: item.quantity || item.num || 1,
414
+ selling_price: item.price || 0
415
+ };
416
+ });
417
+
418
+ // 调用策略检查
419
+ var result = evaluator.checkVoucherAvailability({
420
+ orderTotalAmount: orderTotalAmount,
421
+ products: productsForEvaluate,
422
+ vouchers: [voucher]
423
+ });
424
+
425
+ // 将 config 附加到 discount 对象
426
+ if (result.isAvailable) {
427
+ discount.config = _objectSpread(_objectSpread({}, result.config), {}, {
428
+ isAvailable: true
429
+ });
430
+ } else {
431
+ discount.config = {
432
+ isAvailable: false
433
+ };
434
+ }
435
+ }
436
+ });
437
+ }
438
+
377
439
  /**
378
440
  // 对productList按价格降序排序(用于应用优惠券时优先选择高价商品) 价格相同时使用quantity 排序
379
441
  const sortedProductList = [...productList].sort((a, b) => {
@@ -394,6 +456,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
394
456
  // 标记已使用的优惠券
395
457
  var usedDiscounts = new Map();
396
458
 
459
+ // 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
460
+ var usedProductIdCounts = new Map();
461
+
397
462
  // 记录每个优惠券适用的商品ID
398
463
  var discountApplicability = new Map();
399
464
 
@@ -421,6 +486,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
421
486
  product = flatItem.product;
422
487
  originProduct = flatItem.originProduct;
423
488
  } else {
489
+ var _flatItem$parentProdu;
424
490
  // bundle子商品:构造虚拟商品对象
425
491
  product = {
426
492
  _id: flatItem._id,
@@ -431,12 +497,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
431
497
  total: flatItem.total,
432
498
  origin_total: flatItem.origin_total,
433
499
  booking_id: flatItem.booking_id,
434
- discount_list: flatItem.discount_list || []
500
+ discount_list: flatItem.discount_list || [],
501
+ startDate: (_flatItem$parentProdu = flatItem.parentProduct) === null || _flatItem$parentProdu === void 0 ? void 0 : _flatItem$parentProdu.startDate
435
502
  };
436
503
  originProduct = flatItem.originProduct;
437
504
  }
438
505
  addModeDiscount.forEach(function (discount) {
439
- var _product, _product2, _product3, _product4, _flatItem$bundleItem;
506
+ var _product, _product2, _product3, _product4, _flatItem$bundleItem, _discount$config;
440
507
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
441
508
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
442
509
  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;
@@ -447,7 +514,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
447
514
  var timeLimit = true;
448
515
  timeLimit = !!filterDiscountListByBookingTime([discount], (((_product = product) === null || _product === void 0 ? void 0 : _product.startDate) || dayjs()).format('YYYY-MM-DD HH:mm:ss')).length;
449
516
  // 是符合折扣的商品
450
- var isLimitedProduct = (limitedData.type === 'product_all' || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
517
+ 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;
451
518
 
452
519
  // 编辑的商品 使用了优惠券不可用
453
520
  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) {
@@ -458,7 +525,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
458
525
  var isBundleAvailable = _this3.checkPackageSubItemUsageRules(discount, flatItem);
459
526
 
460
527
  // 判断优惠券是否适用于该商品
461
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
528
+ if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config = discount.config) !== null && _discount$config !== void 0 && _discount$config.isAvailable) {
462
529
  var _discountApplicabilit, _discount$metadata;
463
530
  // 记录此优惠券适用的商品
464
531
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -481,7 +548,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
481
548
  title: discount.format_title,
482
549
  original_amount: product.price || product.origin_total,
483
550
  pre_value: discount.par_value,
484
- product_id: originProduct.id
551
+ product_id: originProduct.id,
552
+ discount_product_id: discount.product_id
485
553
  },
486
554
  metadata: {
487
555
  num: num
@@ -506,7 +574,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
506
574
  product = flatItem.product;
507
575
  originProduct = flatItem.originProduct;
508
576
  } else {
509
- var _flatItem$bundleItem2, _flatItem$bundleItem3, _flatItem$bundleItem4;
577
+ var _flatItem$bundleItem2, _flatItem$bundleItem3, _flatItem$bundleItem4, _flatItem$parentProdu2;
510
578
  // bundle子商品
511
579
  product = {
512
580
  _id: flatItem._id,
@@ -518,7 +586,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
518
586
  original_price: flatItem === null || flatItem === void 0 || (_flatItem$bundleItem2 = flatItem.bundleItem) === null || _flatItem$bundleItem2 === void 0 ? void 0 : _flatItem$bundleItem2.original_price,
519
587
  origin_total: flatItem === null || flatItem === void 0 || (_flatItem$bundleItem3 = flatItem.bundleItem) === null || _flatItem$bundleItem3 === void 0 ? void 0 : _flatItem$bundleItem3.original_price,
520
588
  booking_id: flatItem.booking_id,
521
- discount_list: (flatItem === null || flatItem === void 0 || (_flatItem$bundleItem4 = flatItem.bundleItem) === null || _flatItem$bundleItem4 === void 0 ? void 0 : _flatItem$bundleItem4.discount_list) || []
589
+ discount_list: (flatItem === null || flatItem === void 0 || (_flatItem$bundleItem4 = flatItem.bundleItem) === null || _flatItem$bundleItem4 === void 0 ? void 0 : _flatItem$bundleItem4.discount_list) || [],
590
+ startDate: (_flatItem$parentProdu2 = flatItem.parentProduct) === null || _flatItem$parentProdu2 === void 0 ? void 0 : _flatItem$parentProdu2.startDate
522
591
  };
523
592
  originProduct = flatItem.originProduct;
524
593
  }
@@ -540,6 +609,16 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
540
609
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
541
610
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
542
611
  var _product$discount_lis3, _product$discount_lis4;
612
+ // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
613
+ var discountType = discount.tag || discount.type;
614
+ if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
615
+ var _discount$config2;
616
+ // 如果策略检查后没有config,说明不可用
617
+ if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable)) {
618
+ return false;
619
+ }
620
+ }
621
+
543
622
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
544
623
  // 商品券时主商品价格为0不可用
545
624
  if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && (discount.tag || discount.type) === 'good_pass') return false;
@@ -552,6 +631,18 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
552
631
  // 如果优惠券已被使用,则跳过
553
632
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
554
633
  if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
634
+
635
+ // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
636
+ if ((discount.tag || discount.type) === 'good_pass') {
637
+ var _discount$config3;
638
+ var maxUsagePerOrder = (_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.maxUsagePerOrder;
639
+ if (maxUsagePerOrder && maxUsagePerOrder > 0) {
640
+ var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
641
+ if (currentUsedCount >= maxUsagePerOrder) {
642
+ return false;
643
+ }
644
+ }
645
+ }
555
646
  var limitedData = discount.limited_relation_product_data;
556
647
 
557
648
  // 拿到discount配置的holder信息 product信息 product.holder 不可用return false
@@ -570,6 +661,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
570
661
 
571
662
  // 判断优惠券是否适用于该商品
572
663
  if (limitedData.type === 'product_all') {
664
+ if (limitedData.filter === 1 && limitedData.exclude_product_ids.includes(product.id)) {
665
+ return false;
666
+ }
573
667
  // 检查 package_sub_item_usage_rules
574
668
  if (!_this3.checkPackageSubItemUsageRules(discount, flatItem)) {
575
669
  return false;
@@ -630,11 +724,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
630
724
  }
631
725
  // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
632
726
  if (flatItem.type === 'bundle') {
633
- var _product$discount_lis7, _flatItem$parentProdu;
727
+ var _product$discount_lis7, _flatItem$parentProdu3;
634
728
  if ((_product$discount_lis7 = product.discount_list) !== null && _product$discount_lis7 !== void 0 && _product$discount_lis7.some(function (item) {
635
729
  var _item$discount2;
636
730
  return ((_item$discount2 = item.discount) === null || _item$discount2 === void 0 ? void 0 : _item$discount2.resource_id) === options.discountId;
637
- }) || (_flatItem$parentProdu = flatItem.parentProduct) !== null && _flatItem$parentProdu !== void 0 && (_flatItem$parentProdu = _flatItem$parentProdu.discount_list) !== null && _flatItem$parentProdu !== void 0 && _flatItem$parentProdu.some(function (item) {
731
+ }) || (_flatItem$parentProdu3 = flatItem.parentProduct) !== null && _flatItem$parentProdu3 !== void 0 && (_flatItem$parentProdu3 = _flatItem$parentProdu3.discount_list) !== null && _flatItem$parentProdu3 !== void 0 && _flatItem$parentProdu3.some(function (item) {
638
732
  var _item$discount3;
639
733
  return ((_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.resource_id) === options.discountId;
640
734
  })) {
@@ -656,14 +750,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
656
750
  }
657
751
  // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
658
752
  if (flatItem.type === 'bundle') {
659
- var _product$discount_lis9, _flatItem$parentProdu2;
753
+ var _product$discount_lis9, _flatItem$parentProdu4;
660
754
  if ((_product$discount_lis9 = product.discount_list) !== null && _product$discount_lis9 !== void 0 && _product$discount_lis9.some(function (item) {
661
755
  var _options$selectedList2;
662
756
  return options === null || options === void 0 || (_options$selectedList2 = options.selectedList) === null || _options$selectedList2 === void 0 ? void 0 : _options$selectedList2.some(function (n) {
663
757
  var _item$discount5;
664
758
  return n.discountId === ((_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.resource_id);
665
759
  });
666
- }) || (_flatItem$parentProdu2 = flatItem.parentProduct) !== null && _flatItem$parentProdu2 !== void 0 && (_flatItem$parentProdu2 = _flatItem$parentProdu2.discount_list) !== null && _flatItem$parentProdu2 !== void 0 && _flatItem$parentProdu2.some(function (item) {
760
+ }) || (_flatItem$parentProdu4 = flatItem.parentProduct) !== null && _flatItem$parentProdu4 !== void 0 && (_flatItem$parentProdu4 = _flatItem$parentProdu4.discount_list) !== null && _flatItem$parentProdu4 !== void 0 && _flatItem$parentProdu4.some(function (item) {
667
761
  var _options$selectedList3;
668
762
  return options === null || options === void 0 || (_options$selectedList3 = options.selectedList) === null || _options$selectedList3 === void 0 ? void 0 : _options$selectedList3.some(function (n) {
669
763
  var _item$discount6;
@@ -736,7 +830,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
736
830
  var availableGoodPassCount = applicableDiscounts.filter(function (item) {
737
831
  return (item.tag || item.type) === 'good_pass';
738
832
  }).length;
739
- var splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
833
+
834
+ // 🔥 如果selectedDiscount有config配置,则使用config.maxUsagePerOrder限制使用次数
835
+ var maxUsageLimit = availableGoodPassCount;
836
+ if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
837
+ maxUsageLimit = Math.min(availableGoodPassCount, selectedDiscount.config.maxUsagePerOrder);
838
+ }
839
+ var splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
740
840
  var arr = [];
741
841
 
742
842
  // 🔥 主商品和bundle子商品分别处理
@@ -746,7 +846,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
746
846
  arr.push(_this3.hooks.setProduct(originProduct, {
747
847
  discount_list: [],
748
848
  quantity: totalQuantity - splitCount,
749
- _id: product._id.split('___')[0]
849
+ _id: product._id.split('___')[0],
850
+ total: product.origin_total || product.total
750
851
  }));
751
852
  }
752
853
  for (var i = 0; i < splitCount; i++) {
@@ -755,6 +856,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
755
856
  var _selectedDiscount = selectedDiscountCard || applicableDiscounts[i];
756
857
  // 标记优惠券为已使用
757
858
  usedDiscounts.set(_selectedDiscount.id, true);
859
+ // 🔥 更新 product_id 使用计数
860
+ if ((_selectedDiscount.tag || _selectedDiscount.type) === 'good_pass') {
861
+ var currentCount = usedProductIdCounts.get(_selectedDiscount.product_id) || 0;
862
+ usedProductIdCounts.set(_selectedDiscount.product_id, currentCount + 1);
863
+ }
758
864
 
759
865
  // 记录实际应用了优惠券的商品信息
760
866
  var appliedProducts = appliedDiscountProducts.get(_selectedDiscount.id) || [];
@@ -772,23 +878,27 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
772
878
 
773
879
  // 计算使用折扣卡/商品券以后,单个商品的总 total
774
880
  var targetProductTotal = getDiscountAmount(_selectedDiscount, product.price, product.price);
775
- var discountType = _selectedDiscount.tag || _selectedDiscount.type;
881
+ var discountType = _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount.tag;
882
+
883
+ // 计算实际折扣金额
884
+ var actualDiscountAmount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
776
885
  var isGoodPass = discountType === 'good_pass';
777
- var amount = new Decimal(product.price).minus(new Decimal(targetProductTotal)).toNumber();
778
886
  var discountDetail = {
779
- amount: amount,
780
- type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
887
+ amount: actualDiscountAmount,
888
+ type: discountType,
781
889
  discount: {
782
890
  discount_card_type: _selectedDiscount === null || _selectedDiscount === void 0 || (_selectedDiscount$met = _selectedDiscount.metadata) === null || _selectedDiscount$met === void 0 ? void 0 : _selectedDiscount$met.discount_card_type,
783
- fixed_amount: amount,
891
+ fixed_amount: actualDiscountAmount,
784
892
  resource_id: _selectedDiscount.id,
785
893
  title: _selectedDiscount.format_title,
786
894
  original_amount: product.price,
787
895
  product_id: originProduct.id,
788
- percent: _selectedDiscount.par_value
896
+ percent: _selectedDiscount.par_value,
897
+ discount_product_id: _selectedDiscount.product_id
789
898
  },
790
899
  // 前端使用的num数量,为了计算优惠金额
791
900
  _num: isGoodPass ? 1 : product.num,
901
+ config: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.config,
792
902
  metadata: {
793
903
  num: 1
794
904
  }
@@ -807,7 +917,6 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
807
917
  // 记录应用了优惠券的商品
808
918
  // 后续更新价格改为 getProductTotalPrice getProductOriginTotalPrice逻辑
809
919
  if (product.isClient) {
810
- debugger;
811
920
  arr.push(_this3.hooks.setProduct(originProduct, {
812
921
  discount_list: [discountDetail],
813
922
  price: _selectedDiscount.tag === 'good_pass' ? 0 : product.price,
@@ -848,25 +957,36 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
848
957
  for (var _i = 0; _i < discountNum; _i++) {
849
958
  var _selectedDiscount2 = applicableDiscounts[_i];
850
959
  usedDiscounts.set(_selectedDiscount2.id, true);
960
+ // 🔥 更新 product_id 使用计数
961
+ if ((_selectedDiscount2.tag || _selectedDiscount2.type) === 'good_pass') {
962
+ var _currentCount = usedProductIdCounts.get(_selectedDiscount2.product_id) || 0;
963
+ usedProductIdCounts.set(_selectedDiscount2.product_id, _currentCount + 1);
964
+ }
851
965
 
852
966
  // 🔥 生成唯一的 _id
853
967
  var uniqueId = "".concat(flatItem._id, "_split_").concat(_i);
968
+
969
+ // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
970
+ var discountedPrice = getDiscountAmount(_selectedDiscount2, product.origin_total, product.origin_total);
971
+ var bundleDiscountAmount = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
854
972
  var _discountDetail = {
855
- amount: product.origin_total,
973
+ amount: bundleDiscountAmount,
856
974
  type: 'good_pass',
857
975
  discount: {
858
976
  fixed_amount: product.origin_total,
859
977
  resource_id: _selectedDiscount2.id,
860
978
  title: _selectedDiscount2.format_title,
861
979
  original_amount: product.origin_total,
862
- product_id: product.id
980
+ product_id: product.id,
981
+ discount_product_id: _selectedDiscount2.product_id
863
982
  },
864
983
  metadata: {
865
984
  // 🔥 使用拆分后的唯一 _id
866
985
  custom_product_bundle_map_id: uniqueId,
867
986
  num: 1
868
987
  },
869
- _num: 1
988
+ _num: 1,
989
+ config: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.config
870
990
  };
871
991
 
872
992
  // 记录实际应用的折扣
@@ -878,9 +998,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
878
998
  _id: uniqueId,
879
999
  num: 1,
880
1000
  quantity: 1,
881
- price: 0,
882
- // 商品券价格为0
883
- total: 0,
1001
+ price: discountedPrice,
1002
+ // 折扣后的价格
1003
+ total: discountedPrice,
884
1004
  discount_list: [_discountDetail],
885
1005
  processed: true,
886
1006
  _discountId: _selectedDiscount2.id
@@ -899,33 +1019,43 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
899
1019
  }));
900
1020
  }
901
1021
  } else {
902
- var _selectedDiscount3$me, _flatItem$parentProdu3;
1022
+ var _selectedDiscount3$me, _flatItem$parentProdu5;
903
1023
  // 折扣卡:不拆分数量,直接应用
904
1024
  var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
905
1025
  usedDiscounts.set(_selectedDiscount3.id, true);
1026
+ // 🔥 更新 product_id 使用计数(虽然此处主要是折扣卡,但保持一致性)
1027
+ if ((_selectedDiscount3.tag || _selectedDiscount3.type) === 'good_pass') {
1028
+ var _currentCount2 = usedProductIdCounts.get(_selectedDiscount3.product_id) || 0;
1029
+ usedProductIdCounts.set(_selectedDiscount3.product_id, _currentCount2 + 1);
1030
+ }
906
1031
  var _productOriginTotal = product.original_price || product.price || 0;
907
1032
  var _targetProductTotal = getDiscountAmount(_selectedDiscount3, _productOriginTotal, _productOriginTotal);
908
1033
 
1034
+ // 计算实际折扣金额
1035
+ var bundleActualDiscountAmount = new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber();
1036
+
909
1037
  // 🔥 使用当前的 _id 作为唯一标识
910
1038
  var _uniqueId = flatItem._id;
911
1039
  var _discountDetail2 = {
912
- amount: new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber() * (product.num || 1),
1040
+ amount: bundleActualDiscountAmount * (product.num || 1),
913
1041
  type: _selectedDiscount3.tag === 'product_discount_card' ? 'discount_card' : _selectedDiscount3.tag,
914
1042
  discount: {
915
1043
  discount_card_type: _selectedDiscount3 === null || _selectedDiscount3 === void 0 || (_selectedDiscount3$me = _selectedDiscount3.metadata) === null || _selectedDiscount3$me === void 0 ? void 0 : _selectedDiscount3$me.discount_card_type,
916
- fixed_amount: new Decimal(_productOriginTotal).minus(_targetProductTotal).toNumber(),
1044
+ fixed_amount: bundleActualDiscountAmount,
917
1045
  resource_id: _selectedDiscount3.id,
918
1046
  title: _selectedDiscount3.format_title,
919
1047
  original_amount: product.original_price,
920
1048
  product_id: product.id,
921
- percent: _selectedDiscount3.par_value
1049
+ percent: _selectedDiscount3.par_value,
1050
+ discount_product_id: _selectedDiscount3.product_id
922
1051
  },
923
1052
  metadata: {
924
1053
  // 🔥 使用唯一的 _id
925
1054
  custom_product_bundle_map_id: _uniqueId,
926
1055
  num: product.num || 1
927
1056
  },
928
- _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu3 = flatItem.parentProduct) === null || _flatItem$parentProdu3 === void 0 ? void 0 : _flatItem$parentProdu3.num) || 1)
1057
+ config: _selectedDiscount3 === null || _selectedDiscount3 === void 0 ? void 0 : _selectedDiscount3.config,
1058
+ _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu5 = flatItem.parentProduct) === null || _flatItem$parentProdu5 === void 0 ? void 0 : _flatItem$parentProdu5.num) || 1)
929
1059
  };
930
1060
 
931
1061
  // 记录实际应用的折扣
@@ -25,6 +25,7 @@ export interface RulesModuleAPI {
25
25
  holders: {
26
26
  form_record_id: number;
27
27
  }[];
28
+ orderTotalAmount: number;
28
29
  isFormSubject: boolean;
29
30
  }) => DiscountResult;
30
31
  }
@@ -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;
@@ -315,6 +316,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
315
316
  end_at: dayjs.Dayjs;
316
317
  count: number;
317
318
  left: number;
319
+ summaryCount: number;
318
320
  }[];
319
321
  /**
320
322
  * 找到多个资源的公共可用时间段
@@ -2470,10 +2470,12 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2470
2470
  var resourcesUseableMap = {};
2471
2471
  var count = 0;
2472
2472
  var bookingLeft = 0;
2473
+ var summaryCount = 0;
2473
2474
  // 遍历所有资源
2474
2475
  allProductResources === null || allProductResources === void 0 || allProductResources.forEach(function (m) {
2475
2476
  // 遍历所有资源的上工时间片
2476
2477
  var currentResourcesCount = 0;
2478
+ var currentResourcesSummaryCount = 0;
2477
2479
  var currentResourcesTimeSlotCanUsedArr = [];
2478
2480
  // m.times 需要做个过滤,假设 timeSlice.start_at 是 09:30 timeSlice.end_at 是 11:30
2479
2481
  // time 是 time.start_at = 2025-05-26 10:30, time.end_at = 2025-05-26 12:30
@@ -2511,6 +2513,9 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2511
2513
  if (res.usable && res.remainingCapacity >= count && !m.onlyComputed) {
2512
2514
  currentResourcesCount = res.remainingCapacity;
2513
2515
  }
2516
+ if (res.usable && !m.onlyComputed && res.remainingCapacity >= currentResourcesSummaryCount) {
2517
+ currentResourcesSummaryCount = res.remainingCapacity;
2518
+ }
2514
2519
  currentResourcesTimeSlotCanUsedArr.push(res.usable);
2515
2520
  });
2516
2521
  // 在已经选定时间的情况下,只要canUseTime如果有一个 false 那就不可用
@@ -2524,6 +2529,7 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2524
2529
  }
2525
2530
  if (!m.onlyComputed) {
2526
2531
  bookingLeft += 1;
2532
+ summaryCount += currentResourcesSummaryCount;
2527
2533
  }
2528
2534
  }
2529
2535
  });
@@ -2543,6 +2549,7 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2543
2549
  if (sameCartItems.length > 0 && sameCartItems.length >= currentResourcesSet.size || sameCartItems.length > bookingLeft) {
2544
2550
  bookingLeft = 0;
2545
2551
  count = 0;
2552
+ summaryCount = 0;
2546
2553
  }
2547
2554
  // 规则 2
2548
2555
  var otherCartItems = cartItems.filter(function (m) {
@@ -2577,6 +2584,7 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2577
2584
  if (currentResourcesSet.size > 0 && otherCartItems.length + sameCartItems.length >= currentResourcesSet.size) {
2578
2585
  bookingLeft = 0;
2579
2586
  count = 0;
2587
+ summaryCount = 0;
2580
2588
  }
2581
2589
  } else {
2582
2590
  // 多个预约的检测规则:
@@ -2594,6 +2602,7 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2594
2602
  if (sameCartNeedCapacity >= currentProductResourcesCapacity) {
2595
2603
  bookingLeft = 0;
2596
2604
  count = 0;
2605
+ summaryCount = 0;
2597
2606
  }
2598
2607
  // 规则2、不管是不是跟我一样的商品,只需要跟我当前商品有同一种类型的资源的同一时间的,把所有购物车的 capacity 之和 和 所有当前类型资源的 capacity 之和比较,如果超过了resourcesCapacity,则不可用
2599
2608
  // const otherCartItems = cartItems.filter((m) => m._productOrigin?.id?.toString() !== targetProductData?.id?.toString() && m.start_time === item.start && m.end_time === item.end);
@@ -2656,6 +2665,7 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2656
2665
  if (otherCartNeedCapacity + usedCapacity >= currentTypeResourcesCapacity) {
2657
2666
  bookingLeft = 0;
2658
2667
  count = 0;
2668
+ summaryCount = 0;
2659
2669
  }
2660
2670
  }
2661
2671
  });
@@ -2667,7 +2677,8 @@ export var BookingByStepImpl = /*#__PURE__*/function (_BaseModule) {
2667
2677
  start_at: startDayJs,
2668
2678
  end_at: endDayJs,
2669
2679
  count: count,
2670
- left: bookingLeft
2680
+ left: bookingLeft,
2681
+ summaryCount: summaryCount
2671
2682
  };
2672
2683
  });
2673
2684
  return formatScheduleTimeSlots;
@@ -115,7 +115,7 @@ export declare class BookingTicketImpl extends BaseModule implements Module {
115
115
  * 获取当前的客户搜索条件
116
116
  * @returns 当前搜索条件
117
117
  */
118
- getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "skip" | "num">;
118
+ getCurrentCustomerSearchParams(): Omit<import("../../modules").ShopGetCustomerListParams, "num" | "skip">;
119
119
  /**
120
120
  * 获取客户列表状态(包含滚动加载相关状态)
121
121
  * @returns 客户状态