@pisell/pisellos 0.10.41 → 0.10.43

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 (56) hide show
  1. package/dist/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +58 -19
  2. package/dist/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +24 -12
  3. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  4. package/dist/modules/Discount/entitlementPass.js +147 -0
  5. package/dist/modules/Discount/index.d.ts +2 -0
  6. package/dist/modules/Discount/index.js +39 -13
  7. package/dist/modules/Discount/types.d.ts +26 -5
  8. package/dist/modules/Order/index.d.ts +5 -0
  9. package/dist/modules/Order/index.js +283 -118
  10. package/dist/modules/Order/utils/orderCollectionIdentity.js +16 -12
  11. package/dist/modules/Order/utils.js +17 -1
  12. package/dist/modules/ResourcePlanner/planner.d.ts +2 -2
  13. package/dist/modules/ResourcePlanner/planner.js +163 -46
  14. package/dist/modules/ResourcePlanner/types.d.ts +17 -0
  15. package/dist/modules/Rules/index.js +312 -135
  16. package/dist/solution/BaseSales/index.d.ts +2 -0
  17. package/dist/solution/BaseSales/index.js +9 -1
  18. package/dist/solution/BaseSales/utils/cartPromotion.js +141 -126
  19. package/dist/solution/BookingTicket/types.d.ts +5 -1
  20. package/dist/solution/BookingTicket/utils/scan/applyGlobalScan.js +171 -96
  21. package/dist/solution/BookingTicket/utils/scan/cloudSearch.js +3 -1
  22. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +2 -0
  23. package/dist/solution/BookingTicket/utils/scan/formatGlobalScan.js +12 -3
  24. package/dist/solution/ShopDiscount/index.d.ts +1 -0
  25. package/dist/solution/ShopDiscount/index.js +41 -21
  26. package/dist/solution/ShopDiscount/utils.js +3 -2
  27. package/dist/solution/UnifiedBookingSales/index.js +94 -21
  28. package/lib/model/strategy/adapter/promotion/index.js +1 -46
  29. package/lib/modules/BookingContext/utils/buildCacheItemFromOrderLine.js +35 -6
  30. package/lib/modules/BookingContext/utils/buildNormalProductCacheItemFromOrderLine.js +13 -6
  31. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  32. package/lib/modules/Discount/entitlementPass.js +141 -0
  33. package/lib/modules/Discount/index.d.ts +2 -0
  34. package/lib/modules/Discount/index.js +25 -9
  35. package/lib/modules/Discount/types.d.ts +26 -5
  36. package/lib/modules/Order/index.d.ts +5 -0
  37. package/lib/modules/Order/index.js +172 -28
  38. package/lib/modules/Order/utils/orderCollectionIdentity.js +14 -11
  39. package/lib/modules/Order/utils.js +19 -1
  40. package/lib/modules/ResourcePlanner/planner.d.ts +2 -2
  41. package/lib/modules/ResourcePlanner/planner.js +137 -35
  42. package/lib/modules/ResourcePlanner/types.d.ts +17 -0
  43. package/lib/modules/Rules/index.js +232 -97
  44. package/lib/solution/BaseSales/index.d.ts +2 -0
  45. package/lib/solution/BaseSales/index.js +7 -1
  46. package/lib/solution/BaseSales/utils/cartPromotion.js +12 -4
  47. package/lib/solution/BookingTicket/types.d.ts +5 -1
  48. package/lib/solution/BookingTicket/utils/scan/applyGlobalScan.js +65 -18
  49. package/lib/solution/BookingTicket/utils/scan/cloudSearch.js +3 -1
  50. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.d.ts +2 -0
  51. package/lib/solution/BookingTicket/utils/scan/formatGlobalScan.js +5 -1
  52. package/lib/solution/ShopDiscount/index.d.ts +1 -0
  53. package/lib/solution/ShopDiscount/index.js +26 -6
  54. package/lib/solution/ShopDiscount/utils.js +3 -2
  55. package/lib/solution/UnifiedBookingSales/index.js +86 -22
  56. package/package.json +1 -1
@@ -2,6 +2,10 @@ var _excluded = ["_original_add_price"],
2
2
  _excluded2 = ["_original_price", "_original_add_price"];
3
3
  function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
4
4
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
5
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
6
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
8
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
5
9
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
10
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
11
  function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
@@ -39,6 +43,7 @@ import { isBoolean } from 'lodash-es';
39
43
  import dayjs from 'dayjs';
40
44
  import { isOrderLevelFixedAmountDiscount } from "../../solution/ShopDiscount/utils";
41
45
  import { calculateOrderLevelDiscountAllocation } from "../../solution/ShopDiscount/utils";
46
+ import { compareEntitlementPassPriority, getRemainingEntitlementUses, isEntitlementPass, isFullCoveragePass, resolveEntitlementQuota } from "../Discount/entitlementPass";
42
47
  export var RulesModule = /*#__PURE__*/function (_BaseModule) {
43
48
  _inherits(RulesModule, _BaseModule);
44
49
  var _super = _createSuper(RulesModule);
@@ -181,7 +186,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
181
186
  // 合并新旧折扣列表,并计算折扣结果,注意,如果旧折扣里有 isEditMode 为 true 的优惠券,则不合并
182
187
  // 保留之前扫码得到的商品券(isScan: true)
183
188
  var filteredOldDiscountList = oldDiscountList.filter(function (discount) {
184
- return !discount.isEditMode && (discount.tag !== 'good_pass' || discount.isScan);
189
+ return !discount.isEditMode && (!isFullCoveragePass(discount) || discount.isScan);
185
190
  });
186
191
  var mergedDiscountList = uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
187
192
  var result = this.calcDiscount({
@@ -378,8 +383,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
378
383
  if (!selectedDiscount) return false;
379
384
  var uid = getOriginProductUid(originProduct);
380
385
  if (!uid || !reapplyBookingDiscountProductUids.has(uid)) return false;
381
- var discountType = selectedDiscount.tag || selectedDiscount.type;
382
- return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
386
+ var discountType = selectedDiscount.tag || selectedDiscount.type || '';
387
+ return selectedDiscount.isEditMode === true && selectedDiscount.isSelected === true && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
383
388
  };
384
389
  var resolveReapplyBookingDiscountPercent = function resolveReapplyBookingDiscountPercent(originProduct, selectedDiscount) {
385
390
  var _discount2;
@@ -427,8 +432,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
427
432
  };
428
433
  }
429
434
  var canUseEditModeDiscountForReapply = function canUseEditModeDiscountForReapply(discount) {
430
- var discountType = discount.tag || discount.type;
431
- return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
435
+ var discountType = discount.tag || discount.type || '';
436
+ return reapplyBookingDiscountProductUids.size > 0 && discount.isEditMode === true && discount.isSelected === true && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
432
437
  };
433
438
 
434
439
  // 过滤掉手动取消false的优惠券,但仅用于应用优惠逻辑。
@@ -510,6 +515,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
510
515
  var isGoodPass = function isGoodPass(discount) {
511
516
  return discount.tag === 'good_pass';
512
517
  };
518
+ var isEntitlement = function isEntitlement(discount) {
519
+ return isEntitlementPass(discount);
520
+ };
513
521
 
514
522
  // 辅助函数:判断是否是订单级折扣卡
515
523
  var isOrderLevelDiscount = function isOrderLevelDiscount(discount) {
@@ -578,6 +586,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
578
586
  }
579
587
  return 0;
580
588
  }
589
+ var entitlementA = isEntitlement(a);
590
+ var entitlementB = isEntitlement(b);
591
+ if (entitlementA || entitlementB) {
592
+ if (entitlementA && entitlementB) {
593
+ return compareEntitlementPassPriority(a, b);
594
+ }
595
+ return entitlementA ? -1 : 1;
596
+ }
581
597
 
582
598
  // 1. 先按优先级排序
583
599
  var priorityA = getPriority(a);
@@ -650,15 +666,23 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
650
666
  var evaluator = this.getWalletPassEvaluator();
651
667
  if (evaluator) {
652
668
  addModeDiscount.forEach(function (discount) {
653
- var discountType = discount.tag || discount.type;
654
- // 只对 good_pass 和 discount_card 类型执行策略检查
655
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
669
+ var discountType = discount.tag || discount.type || '';
670
+ // 对两类全额抵扣卡和折扣卡执行附加策略检查。
671
+ if (['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType)) {
656
672
  var _discount$limited_rel, _discount$limited_rel2;
673
+ var entitlementQuota = isEntitlementPass(discount) ? resolveEntitlementQuota(discount) : null;
674
+ if (isEntitlementPass(discount) && !entitlementQuota) {
675
+ discount.config = {
676
+ isAvailable: false
677
+ };
678
+ return;
679
+ }
680
+
657
681
  // 转换 discount 为 Voucher 格式
658
682
  var voucher = {
659
683
  id: discount.id,
660
684
  amount: Number(discount.par_value || 0),
661
- balance: Number(discount.balance || 0),
685
+ balance: (entitlementQuota === null || entitlementQuota === void 0 ? void 0 : entitlementQuota.type) === 'unlimited' ? Number.MAX_SAFE_INTEGER : (entitlementQuota === null || entitlementQuota === void 0 ? void 0 : entitlementQuota.type) === 'limited' ? entitlementQuota.balance : Number(discount.balance || 0),
662
686
  type: discountType,
663
687
  product_id: discount.product_id,
664
688
  unified_available_status: 1,
@@ -716,11 +740,154 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
716
740
  });
717
741
  */
718
742
 
719
- // 标记已使用的优惠券
743
+ // good_pass / 折扣卡保持原有的一次性使用标记。
720
744
  var usedDiscounts = new Map();
721
745
 
746
+ // Entitlement Pass 单独记录本次重算新增分配的次数。
747
+ var entitlementUsageCounts = new Map();
748
+
722
749
  // 🔥 统计每个 product_id(商品券商品id)已使用的数量,用于 maxUsagePerOrder 限制
723
750
  var usedProductIdCounts = new Map();
751
+ var markDiscountUsed = function markDiscountUsed(discount) {
752
+ var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
753
+ if (isEntitlementPass(discount)) {
754
+ entitlementUsageCounts.set(discount.id, (entitlementUsageCounts.get(discount.id) || 0) + count);
755
+ return;
756
+ }
757
+ usedDiscounts.set(discount.id, true);
758
+ };
759
+ var isDiscountUsed = function isDiscountUsed(discount) {
760
+ if (isEntitlementPass(discount)) {
761
+ return (entitlementUsageCounts.get(discount.id) || 0) > 0;
762
+ }
763
+ return usedDiscounts.get(discount.id) === true;
764
+ };
765
+ var buildFullCoveragePassUsageGroups = function buildFullCoveragePassUsageGroups(discounts, requestedCount) {
766
+ var _firstGoodPass$config;
767
+ var groups = [];
768
+ var pendingUsedDiscounts = new Set(Array.from(usedDiscounts.entries()).filter(function (_ref6) {
769
+ var _ref7 = _slicedToArray(_ref6, 2),
770
+ used = _ref7[1];
771
+ return used;
772
+ }).map(function (_ref8) {
773
+ var _ref9 = _slicedToArray(_ref8, 1),
774
+ discountId = _ref9[0];
775
+ return discountId;
776
+ }));
777
+ var pendingEntitlementCounts = new Map(entitlementUsageCounts);
778
+ var pendingProductCounts = new Map(usedProductIdCounts);
779
+ var firstGoodPass = discounts.find(function (discount) {
780
+ return isFullCoveragePass(discount) && !isEntitlementPass(discount);
781
+ });
782
+ var legacyGoodPassPerLineLimit = firstGoodPass ? Number(((_firstGoodPass$config = firstGoodPass.config) === null || _firstGoodPass$config === void 0 ? void 0 : _firstGoodPass$config.maxUsagePerOrder) || 0) : 0;
783
+ var allocatedGoodPassCount = 0;
784
+ var remaining = Math.max(Math.floor(requestedCount), 0);
785
+ var _iterator5 = _createForOfIteratorHelper(discounts),
786
+ _step5;
787
+ try {
788
+ var _loop = function _loop() {
789
+ var _discount$config;
790
+ var discount = _step5.value;
791
+ if (remaining <= 0) return 0; // break
792
+ if (!isFullCoveragePass(discount)) return 1; // continue
793
+ var currentEntitlementCount = pendingEntitlementCounts.get(discount.id) || 0;
794
+ var availableCount = isEntitlementPass(discount) ? getRemainingEntitlementUses(discount, currentEntitlementCount, remaining) : pendingUsedDiscounts.has(discount.id) ? 0 : 1;
795
+ if (!isEntitlementPass(discount) && legacyGoodPassPerLineLimit > 0) {
796
+ availableCount = Math.min(availableCount, Math.max(Math.floor(legacyGoodPassPerLineLimit) - allocatedGoodPassCount, 0));
797
+ }
798
+ var maxUsagePerOrder = Number(((_discount$config = discount.config) === null || _discount$config === void 0 ? void 0 : _discount$config.maxUsagePerOrder) || 0);
799
+ if (isEntitlementPass(discount) && maxUsagePerOrder > 0) {
800
+ var currentProductCount = pendingProductCounts.get(discount.product_id) || 0;
801
+ availableCount = Math.min(availableCount, Math.max(Math.floor(maxUsagePerOrder) - currentProductCount, 0));
802
+ }
803
+ var allocatedCount = Math.min(availableCount, remaining);
804
+ if (allocatedCount <= 0) return 1; // continue
805
+ var existingGroup = groups.find(function (group) {
806
+ return String(group.discount.id) === String(discount.id);
807
+ });
808
+ if (existingGroup) {
809
+ existingGroup.count += allocatedCount;
810
+ } else {
811
+ groups.push({
812
+ discount: discount,
813
+ count: allocatedCount
814
+ });
815
+ }
816
+ if (isEntitlementPass(discount)) {
817
+ pendingEntitlementCounts.set(discount.id, currentEntitlementCount + allocatedCount);
818
+ } else {
819
+ pendingUsedDiscounts.add(discount.id);
820
+ allocatedGoodPassCount += allocatedCount;
821
+ }
822
+ pendingProductCounts.set(discount.product_id, (pendingProductCounts.get(discount.product_id) || 0) + allocatedCount);
823
+ remaining -= allocatedCount;
824
+ },
825
+ _ret;
826
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
827
+ _ret = _loop();
828
+ if (_ret === 0) break;
829
+ if (_ret === 1) continue;
830
+ }
831
+ } catch (err) {
832
+ _iterator5.e(err);
833
+ } finally {
834
+ _iterator5.f();
835
+ }
836
+ return groups;
837
+ };
838
+ var mergeEntitlementAppliedProductDetails = function mergeEntitlementAppliedProductDetails(details) {
839
+ var mergedDetails = [];
840
+ var mergedIndexByKey = new Map();
841
+ var toComparableNumber = function toComparableNumber(value) {
842
+ var numberValue = Number(value);
843
+ return Number.isFinite(numberValue) ? String(numberValue) : String(value !== null && value !== void 0 ? value : '');
844
+ };
845
+ var _iterator6 = _createForOfIteratorHelper(details || []),
846
+ _step6;
847
+ try {
848
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
849
+ var _detail$discount$reso, _detail$discount, _detail$discount$prod, _detail$discount2, _detail$metadata$cust, _detail$metadata, _detail$discount3, _ref10, _detail$metadata$num, _detail$metadata2, _ref11, _existed$metadata$num, _existed$metadata;
850
+ var detail = _step6.value;
851
+ if (!isEntitlementPass(detail)) {
852
+ mergedDetails.push(detail);
853
+ continue;
854
+ }
855
+ var resourceId = (_detail$discount$reso = detail === null || detail === void 0 || (_detail$discount = detail.discount) === null || _detail$discount === void 0 ? void 0 : _detail$discount.resource_id) !== null && _detail$discount$reso !== void 0 ? _detail$discount$reso : detail === null || detail === void 0 ? void 0 : detail.resource_id;
856
+ if (resourceId === undefined || resourceId === null) {
857
+ mergedDetails.push(detail);
858
+ continue;
859
+ }
860
+ var key = [resourceId, (_detail$discount$prod = detail === null || detail === void 0 || (_detail$discount2 = detail.discount) === null || _detail$discount2 === void 0 ? void 0 : _detail$discount2.product_id) !== null && _detail$discount$prod !== void 0 ? _detail$discount$prod : '', (_detail$metadata$cust = detail === null || detail === void 0 || (_detail$metadata = detail.metadata) === null || _detail$metadata === void 0 ? void 0 : _detail$metadata.custom_product_bundle_map_id) !== null && _detail$metadata$cust !== void 0 ? _detail$metadata$cust : '', toComparableNumber(detail === null || detail === void 0 ? void 0 : detail.amount), toComparableNumber(detail === null || detail === void 0 || (_detail$discount3 = detail.discount) === null || _detail$discount3 === void 0 ? void 0 : _detail$discount3.fixed_amount)].join('|');
861
+ var rawUsageCount = Number((_ref10 = (_detail$metadata$num = detail === null || detail === void 0 || (_detail$metadata2 = detail.metadata) === null || _detail$metadata2 === void 0 ? void 0 : _detail$metadata2.num) !== null && _detail$metadata$num !== void 0 ? _detail$metadata$num : detail === null || detail === void 0 ? void 0 : detail._num) !== null && _ref10 !== void 0 ? _ref10 : 1);
862
+ var usageCount = Number.isFinite(rawUsageCount) && rawUsageCount > 0 ? rawUsageCount : 1;
863
+ var mergedIndex = mergedIndexByKey.get(key);
864
+ if (mergedIndex === undefined) {
865
+ mergedIndexByKey.set(key, mergedDetails.length);
866
+ mergedDetails.push(_objectSpread(_objectSpread({}, detail), {}, {
867
+ metadata: _objectSpread(_objectSpread({}, (detail === null || detail === void 0 ? void 0 : detail.metadata) || {}), {}, {
868
+ num: usageCount
869
+ }),
870
+ _num: usageCount
871
+ }));
872
+ continue;
873
+ }
874
+ var existed = mergedDetails[mergedIndex];
875
+ var existedUsageCount = Number((_ref11 = (_existed$metadata$num = existed === null || existed === void 0 || (_existed$metadata = existed.metadata) === null || _existed$metadata === void 0 ? void 0 : _existed$metadata.num) !== null && _existed$metadata$num !== void 0 ? _existed$metadata$num : existed === null || existed === void 0 ? void 0 : existed._num) !== null && _ref11 !== void 0 ? _ref11 : 1);
876
+ var totalUsageCount = existedUsageCount + usageCount;
877
+ mergedDetails[mergedIndex] = _objectSpread(_objectSpread({}, existed), {}, {
878
+ metadata: _objectSpread(_objectSpread({}, (existed === null || existed === void 0 ? void 0 : existed.metadata) || {}), {}, {
879
+ num: totalUsageCount
880
+ }),
881
+ _num: totalUsageCount
882
+ });
883
+ }
884
+ } catch (err) {
885
+ _iterator6.e(err);
886
+ } finally {
887
+ _iterator6.f();
888
+ }
889
+ return mergedDetails;
890
+ };
724
891
 
725
892
  // 记录每个优惠券适用的商品ID
726
893
  var discountApplicability = new Map();
@@ -769,7 +936,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
769
936
 
770
937
  // 编辑的商品使用了优惠券不可用
771
938
  var isAvailableProduct = flatItem.type === 'main' ? !((_product = product) !== null && _product !== void 0 && _product.booking_id && (_product2 = product) !== null && _product2 !== void 0 && (_product2 = _product2.discount_list) !== null && _product2 !== void 0 && _product2.length && (_product3 = product) !== null && _product3 !== void 0 && (_product3 = _product3.discount_list) !== null && _product3 !== void 0 && _product3.every(function (d) {
772
- return d.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
939
+ return d.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(d.tag || d.type);
773
940
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem = flatItem.bundleItem) !== null && _flatItem$bundleItem !== void 0 && (_flatItem$bundleItem = _flatItem$bundleItem.discount_list) !== null && _flatItem$bundleItem !== void 0 && _flatItem$bundleItem.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem2 = flatItem.bundleItem) !== null && _flatItem$bundleItem2 !== void 0 && (_flatItem$bundleItem2 = _flatItem$bundleItem2.discount_list) !== null && _flatItem$bundleItem2 !== void 0 && _flatItem$bundleItem2.every(function (d) {
774
941
  return d.id;
775
942
  }));
@@ -869,7 +1036,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
869
1036
  // 收集该折扣卡适用的商品(排除被其他专属折扣卡占用的商品)
870
1037
  var applicableProducts = [];
871
1038
  sortedFlattenedList.forEach(function (flatItem) {
872
- var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref6, _flatItem$original_pr;
1039
+ var _flatItem$parentProdu2, _flatItem$parentProdu3, _product$price, _ref12, _flatItem$original_pr;
873
1040
  // 🔥 检查该商品是否被其他专属折扣卡占用
874
1041
  var occupyingDiscountId = occupiedItems.get(flatItem._id);
875
1042
  if (occupyingDiscountId !== undefined && occupyingDiscountId !== discount.id) {
@@ -897,7 +1064,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
897
1064
 
898
1065
  // 对于主商品:使用 price
899
1066
  // 对于子商品:优先使用 flatItem.original_price,否则使用 flatItem.price
900
- var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref6 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref6 !== void 0 ? _ref6 : 0);
1067
+ var originalAmount = flatItem.type === 'main' ? Number((_product$price = product.price) !== null && _product$price !== void 0 ? _product$price : 0) : Number((_ref12 = (_flatItem$original_pr = flatItem.original_price) !== null && _flatItem$original_pr !== void 0 ? _flatItem$original_pr : flatItem.price) !== null && _ref12 !== void 0 ? _ref12 : 0);
901
1068
 
902
1069
  // 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
903
1070
  var productData = {
@@ -954,7 +1121,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
954
1121
  }
955
1122
  var isItemRewardProductDiscount = _this4.isItemRewardProductDiscount(product);
956
1123
  addModeDiscount.forEach(function (discount) {
957
- var _product5, _product6, _product7, _product8, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config;
1124
+ var _product5, _product6, _product7, _product8, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config2;
958
1125
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
959
1126
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
960
1127
  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;
@@ -969,7 +1136,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
969
1136
 
970
1137
  // 编辑的商品 使用了优惠券不可用
971
1138
  var isAvailableProduct = flatItem.type === 'main' ? !((_product6 = product) !== null && _product6 !== void 0 && _product6.booking_id && (_product7 = product) !== null && _product7 !== void 0 && (_product7 = _product7.discount_list) !== null && _product7 !== void 0 && _product7.length && (_product8 = product) !== null && _product8 !== void 0 && (_product8 = _product8.discount_list) !== null && _product8 !== void 0 && _product8.every(function (discount) {
972
- return discount.id && ['good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
1139
+ return discount.id && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discount.tag || discount.type);
973
1140
  })) : !(flatItem !== null && flatItem !== void 0 && flatItem.booking_id && !!(flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem3 = flatItem.bundleItem) !== null && _flatItem$bundleItem3 !== void 0 && (_flatItem$bundleItem3 = _flatItem$bundleItem3.discount_list) !== null && _flatItem$bundleItem3 !== void 0 && _flatItem$bundleItem3.length) && flatItem !== null && flatItem !== void 0 && (_flatItem$bundleItem4 = flatItem.bundleItem) !== null && _flatItem$bundleItem4 !== void 0 && (_flatItem$bundleItem4 = _flatItem$bundleItem4.discount_list) !== null && _flatItem$bundleItem4 !== void 0 && _flatItem$bundleItem4.every(function (discount) {
974
1141
  return discount.id;
975
1142
  }));
@@ -978,7 +1145,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
978
1145
  var isBundleAvailable = _this4.checkPackageSubItemUsageRules(discount, flatItem);
979
1146
 
980
1147
  // 判断优惠券是否适用于该商品
981
- if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config = discount.config) !== null && _discount$config !== void 0 && _discount$config.isAvailable) {
1148
+ if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable && (!isEntitlementPass(discount) || getRemainingEntitlementUses(discount, 0, 1) > 0)) {
982
1149
  var _discountApplicabilit, _discount$metadata4, _discount$metadata5;
983
1150
  // 记录此优惠券适用的商品
984
1151
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -986,10 +1153,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
986
1153
  // 记录可抵扣的商品详情
987
1154
  var applicableProducts = discountApplicableProducts.get(discount.id) || [];
988
1155
  var discountType = discount.tag || discount.type;
989
- var isGoodPass = discountType === 'good_pass';
1156
+ var isFullCoverage = isFullCoveragePass(discount);
990
1157
 
991
1158
  // 使用数量
992
- var num = isGoodPass || (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'main' ? 1 : product.num;
1159
+ var num = isFullCoverage || (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'main' ? 1 : product.num;
993
1160
  var productData = {
994
1161
  amount: product.price * num,
995
1162
  type: discountType,
@@ -1027,13 +1194,13 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1027
1194
  };
1028
1195
  var optionDiscountAmount = 0;
1029
1196
  var discountedOptions = options.map(function (option) {
1030
- var _ref7, _ref8, _option$_original_pri, _ref9, _option$num, _rest$price, _option$_original_pri2;
1197
+ var _ref13, _ref14, _option$_original_pri, _ref15, _option$num, _rest$price, _option$_original_pri2;
1031
1198
  // 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
1032
- var rawUnit = (_ref7 = (_ref8 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref8 !== void 0 ? _ref8 : option.price) !== null && _ref7 !== void 0 ? _ref7 : option.add_price;
1199
+ var rawUnit = (_ref13 = (_ref14 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref14 !== void 0 ? _ref14 : option.price) !== null && _ref13 !== void 0 ? _ref13 : option.add_price;
1033
1200
  var baseUnitNum = Number(rawUnit !== null && rawUnit !== void 0 ? rawUnit : 0);
1034
1201
  if (baseUnitNum <= 0) return option;
1035
1202
  var discountedPrice = getDiscountAmount(discount, baseUnitNum, baseUnitNum);
1036
- var optQty = Number((_ref9 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref9 !== void 0 ? _ref9 : 1);
1203
+ var optQty = Number((_ref15 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref15 !== void 0 ? _ref15 : 1);
1037
1204
  optionDiscountAmount = new Decimal(optionDiscountAmount).plus(new Decimal(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
1038
1205
  var _original_add_price = option._original_add_price,
1039
1206
  rest = _objectWithoutProperties(option, _excluded);
@@ -1067,9 +1234,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1067
1234
  var getOptionTotal = function getOptionTotal(options) {
1068
1235
  if (!(options !== null && options !== void 0 && options.length)) return 0;
1069
1236
  return options.reduce(function (sum, opt) {
1070
- var _ref10, _opt$price, _ref11, _opt$num;
1071
- var unit = Number((_ref10 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref10 !== void 0 ? _ref10 : 0);
1072
- var n = Number((_ref11 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref11 !== void 0 ? _ref11 : 1);
1237
+ var _ref16, _opt$price, _ref17, _opt$num;
1238
+ var unit = Number((_ref16 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref16 !== void 0 ? _ref16 : 0);
1239
+ var n = Number((_ref17 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref17 !== void 0 ? _ref17 : 1);
1073
1240
  return new Decimal(sum).plus(new Decimal(unit).mul(n)).toNumber();
1074
1241
  }, 0);
1075
1242
  };
@@ -1106,7 +1273,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1106
1273
  var _discount$id, _discount$discount4;
1107
1274
  var discountIdentity = (_discount$id = discount.id) !== null && _discount$id !== void 0 ? _discount$id : (_discount$discount4 = discount.discount) === null || _discount$discount4 === void 0 ? void 0 : _discount$discount4.resource_id;
1108
1275
  var discountType = discount.tag || discount.type;
1109
- return Boolean(discountIdentity && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType));
1276
+ return Boolean(discountIdentity && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType));
1110
1277
  }));
1111
1278
 
1112
1279
  // 已持久化且已有钱包券/折扣卡的商品行跳过,保留后端历史折扣结果。
@@ -1124,8 +1291,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1124
1291
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
1125
1292
  var _product$discount_lis3, _product$discount_lis4;
1126
1293
  if (_this4.isItemRewardProductDiscount(product)) return false;
1127
- // 🔥 检查策略可用性(针对 good_pass 和折扣卡)
1128
- var discountType = discount.tag || discount.type;
1294
+ // 🔥 检查策略可用性(针对全额抵扣卡和折扣卡)
1295
+ var discountType = discount.tag || discount.type || '';
1129
1296
  var currentOriginUid = getOriginProductUid(originProduct);
1130
1297
  var isReapplyEditModeDiscountForProduct = discount.isEditMode && reapplyBookingDiscountProductUids.size > 0 && currentOriginUid && reapplyBookingDiscountProductUids.has(String(currentOriginUid)) && discount.isSelected === true;
1131
1298
  if (discount.isEditMode && reapplyBookingDiscountProductUids.size > 0) {
@@ -1133,31 +1300,36 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1133
1300
  if (!uid || !reapplyBookingDiscountProductUids.has(uid)) return false;
1134
1301
  if (!discount.isSelected) return false;
1135
1302
  }
1136
- if (['good_pass', 'discount_card', 'product_discount_card'].includes(discountType) && !isReapplyEditModeDiscountForProduct) {
1137
- var _discount$config2;
1303
+ if (['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType) && !isReapplyEditModeDiscountForProduct) {
1304
+ var _discount$config3;
1138
1305
  // 如果策略检查后没有config,说明不可用
1139
- if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config2 = discount.config) !== null && _discount$config2 !== void 0 && _discount$config2.isAvailable)) {
1306
+ if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config3 = discount.config) !== null && _discount$config3 !== void 0 && _discount$config3.isAvailable)) {
1140
1307
  return false;
1141
1308
  }
1142
1309
  }
1143
1310
 
1144
1311
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
1145
- // 商品券时主商品价格为0不可用
1146
- 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;
1312
+ // 全额抵扣卡在主商品价格为 0 时不可用。
1313
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && isFullCoveragePass(discount)) return false;
1147
1314
 
1148
1315
  // 折扣卡商品价格为0时不可用
1149
1316
  if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.find(function (n) {
1150
1317
  var _n$discount;
1151
1318
  return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
1152
- })) && (discount.tag || discount.type) !== 'good_pass') return false;
1153
- // 如果优惠券已被使用,则跳过
1154
- var targetUsedDiscounts = usedDiscounts.get(discount.id);
1155
- if (targetUsedDiscounts && (discount.tag || discount.type) === 'good_pass') return false;
1319
+ })) && !isFullCoveragePass(discount)) return false;
1320
+ // good_pass 保持一张实例只使用一次。
1321
+ if ((discount.tag || discount.type) === 'good_pass' && usedDiscounts.get(discount.id)) {
1322
+ return false;
1323
+ }
1324
+ // 有限次数卡按后端实时 balance 约束本次新增分配;无限卡不看余额。
1325
+ if (isEntitlementPass(discount) && getRemainingEntitlementUses(discount, entitlementUsageCounts.get(discount.id) || 0, 1) <= 0) {
1326
+ return false;
1327
+ }
1156
1328
 
1157
1329
  // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
1158
- if ((discount.tag || discount.type) === 'good_pass') {
1159
- var _discount$config3;
1160
- var maxUsagePerOrder = (_discount$config3 = discount.config) === null || _discount$config3 === void 0 ? void 0 : _discount$config3.maxUsagePerOrder;
1330
+ if (isFullCoveragePass(discount)) {
1331
+ var _discount$config4;
1332
+ var maxUsagePerOrder = (_discount$config4 = discount.config) === null || _discount$config4 === void 0 ? void 0 : _discount$config4.maxUsagePerOrder;
1161
1333
  if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1162
1334
  var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
1163
1335
  if (currentUsedCount >= maxUsagePerOrder) {
@@ -1204,38 +1376,40 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1204
1376
  // 用户显式点击某张卡券时,本次选择优先于自动排序和扫码默认选择。
1205
1377
  // 目标仍必须在当前商品的 applicableDiscounts 中,因此不会绕过 Holder、时间或商品范围校验。
1206
1378
  var explicitlySelectedDiscount = (options === null || options === void 0 ? void 0 : options.isSelected) === true && options.discountId !== undefined ? applicableDiscounts.find(function (discount) {
1207
- var discountType = discount.tag || discount.type;
1208
- return String(discount.id) === String(options.discountId) && ['good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
1379
+ var discountType = discount.tag || discount.type || '';
1380
+ return String(discount.id) === String(options.discountId) && ['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType);
1209
1381
  }) : undefined;
1210
1382
  // 折扣卡会复用于整条商品行;商品券必须继续按单张拆分,不能复用该分支。
1211
- var explicitlySelectedDiscountCard = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) !== 'good_pass' ? explicitlySelectedDiscount : undefined;
1383
+ var explicitlySelectedDiscountCard = explicitlySelectedDiscount && !isFullCoveragePass(explicitlySelectedDiscount) ? explicitlySelectedDiscount : undefined;
1212
1384
 
1213
1385
  // 商品数量等变化会触发无 discountId 的重算。只要当前行已应用的折扣卡仍在
1214
1386
  // applicableDiscounts 中,就应保留该行选择,避免被自动排序中力度更大的卡替换。
1215
1387
  var appliedDiscountCardIds = new Set((product.discount_list || []).filter(function (item) {
1216
1388
  return ['discount_card', 'product_discount_card'].includes((item === null || item === void 0 ? void 0 : item.tag) || (item === null || item === void 0 ? void 0 : item.type));
1217
1389
  }).map(function (item) {
1218
- var _ref12, _item$discount$resour, _item$discount;
1219
- return (_ref12 = (_item$discount$resour = item === null || item === void 0 || (_item$discount = item.discount) === null || _item$discount === void 0 ? void 0 : _item$discount.resource_id) !== null && _item$discount$resour !== void 0 ? _item$discount$resour : item === null || item === void 0 ? void 0 : item.resource_id) !== null && _ref12 !== void 0 ? _ref12 : item === null || item === void 0 ? void 0 : item.id;
1390
+ var _ref18, _item$discount$resour, _item$discount;
1391
+ return (_ref18 = (_item$discount$resour = item === null || item === void 0 || (_item$discount = item.discount) === null || _item$discount === void 0 ? void 0 : _item$discount.resource_id) !== null && _item$discount$resour !== void 0 ? _item$discount$resour : item === null || item === void 0 ? void 0 : item.resource_id) !== null && _ref18 !== void 0 ? _ref18 : item === null || item === void 0 ? void 0 : item.id;
1220
1392
  }).filter(function (id) {
1221
1393
  return id !== undefined && id !== null;
1222
1394
  }).map(String));
1223
1395
  var appliedDiscountCard = options !== null && options !== void 0 && options.scan ? undefined : applicableDiscounts.find(function (discount) {
1224
- var discountType = discount.tag || discount.type;
1396
+ var discountType = discount.tag || discount.type || '';
1225
1397
  return discount.isSelected === true && ['discount_card', 'product_discount_card'].includes(discountType) && appliedDiscountCardIds.has(String(discount.id));
1226
1398
  });
1227
1399
 
1228
- // 优先级:本次显式选择 > 当前行既有选择 > 扫码选择 > 自动排序第一项。
1400
+ // Entitlement Pass 始终按协议优先级使用;没有新卡时沿用原选择优先级。
1229
1401
  var scannedSelectedDiscountCard = applicableDiscounts.find(function (n) {
1230
- return n.isScan && n.isSelected && (n.tag || n.type) !== 'good_pass';
1402
+ return n.isScan && n.isSelected && !isFullCoveragePass(n);
1231
1403
  });
1232
1404
  var selectedDiscountCard = explicitlySelectedDiscountCard || appliedDiscountCard || scannedSelectedDiscountCard;
1233
- var selectedDiscount = explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1234
- var prioritizedApplicableDiscounts = explicitlySelectedDiscount && (explicitlySelectedDiscount.tag || explicitlySelectedDiscount.type) === 'good_pass' ? [explicitlySelectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (discount) {
1235
- var discountType = discount.tag || discount.type;
1236
- return discountType === 'good_pass' && String(discount.id) !== String(explicitlySelectedDiscount.id);
1405
+ var highestPriorityEntitlementPass = applicableDiscounts.find(function (discount) {
1406
+ return isEntitlementPass(discount);
1407
+ });
1408
+ var selectedDiscount = highestPriorityEntitlementPass || explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1409
+ var prioritizedApplicableDiscounts = !highestPriorityEntitlementPass && explicitlySelectedDiscount && isFullCoveragePass(explicitlySelectedDiscount) ? [explicitlySelectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (discount) {
1410
+ return isFullCoveragePass(discount) && String(discount.id) !== String(explicitlySelectedDiscount.id);
1237
1411
  })), _toConsumableArray(applicableDiscounts.filter(function (discount) {
1238
- return (discount.tag || discount.type) !== 'good_pass';
1412
+ return !isFullCoveragePass(discount);
1239
1413
  }))) : applicableDiscounts;
1240
1414
 
1241
1415
  // 如果是手动折扣,则不适用优惠券
@@ -1247,8 +1421,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1247
1421
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : ((_product$discount_lis5 = product.discount_list) === null || _product$discount_lis5 === void 0 ? void 0 : _product$discount_lis5.some(function (item) {
1248
1422
  return item.type === 'product';
1249
1423
  })) || product.total != product.origin_total && (product.bundle || []).every(function (item) {
1250
- var _ref13;
1251
- return !((_ref13 = item.discount_list || []) !== null && _ref13 !== void 0 && _ref13.length);
1424
+ var _ref19;
1425
+ return !((_ref19 = item.discount_list || []) !== null && _ref19 !== void 0 && _ref19.length);
1252
1426
  }) && (!((_product$discount_lis6 = product.discount_list) !== null && _product$discount_lis6 !== void 0 && _product$discount_lis6.length) || ((_product11 = product) === null || _product11 === void 0 || (_product11 = _product11.discount_list) === null || _product11 === void 0 || (_product11$every = _product11.every) === null || _product11$every === void 0 ? void 0 : _product11$every.call(_product11, function (item) {
1253
1427
  return item.type === 'product';
1254
1428
  })));
@@ -1264,8 +1438,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1264
1438
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : ((_parentProduct$discou = parentProduct.discount_list) === null || _parentProduct$discou === void 0 ? void 0 : _parentProduct$discou.some(function (item) {
1265
1439
  return item.type === 'product';
1266
1440
  })) || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
1267
- var _ref14;
1268
- return !((_ref14 = item.discount_list || []) !== null && _ref14 !== void 0 && _ref14.length);
1441
+ var _ref20;
1442
+ return !((_ref20 = item.discount_list || []) !== null && _ref20 !== void 0 && _ref20.length);
1269
1443
  }) && (!((_parentProduct$discou2 = parentProduct.discount_list) !== null && _parentProduct$discou2 !== void 0 && _parentProduct$discou2.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou3 = parentProduct.discount_list) === null || _parentProduct$discou3 === void 0 || (_parentProduct$discou4 = _parentProduct$discou3.every) === null || _parentProduct$discou4 === void 0 ? void 0 : _parentProduct$discou4.call(_parentProduct$discou3, function (item) {
1270
1444
  return item.type === 'product';
1271
1445
  })));
@@ -1358,8 +1532,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1358
1532
  discount_list: isManualDiscount ? _this4.resolveDiscountListForManualOverride(product.discount_list) : _this4.filterDiscountListByType(product.discount_list, 'promotion')
1359
1533
  }))]);
1360
1534
  } else {
1361
- var _ref15, _product$_promotion$f, _product12, _product$origin_total;
1362
- var total = product.inPromotion ? (_ref15 = (_product$_promotion$f = (_product12 = product) === null || _product12 === void 0 || (_product12 = _product12._promotion) === null || _product12 === void 0 ? void 0 : _product12.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref15 !== void 0 ? _ref15 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1535
+ var _ref21, _product$_promotion$f, _product12, _product$origin_total;
1536
+ var total = product.inPromotion ? (_ref21 = (_product$_promotion$f = (_product12 = product) === null || _product12 === void 0 || (_product12 = _product12._promotion) === null || _product12 === void 0 ? void 0 : _product12.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref21 !== void 0 ? _ref21 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1363
1537
  var main_product_selling_price = product.price;
1364
1538
  if ((product.discount_list || []).some(function (item) {
1365
1539
  return item.type === 'promotion';
@@ -1400,21 +1574,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1400
1574
  return;
1401
1575
  }
1402
1576
 
1403
- // 是否需要拆分(商品券需要拆分)
1404
- var isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === 'good_pass';
1577
+ // good_pass 与 Entitlement Pass 都沿用全额抵扣卡的商品行拆分机制。
1578
+ var isNeedSplit = isFullCoveragePass(selectedDiscount);
1405
1579
 
1406
1580
  // 需要拆分出来的数量
1407
1581
  var totalQuantity = product.quantity || product.num || 1;
1408
- var availableGoodPassCount = applicableDiscounts.filter(function (item) {
1409
- return (item.tag || item.type) === 'good_pass';
1410
- }).length;
1411
-
1412
- // 🔥 如果selectedDiscount有config配置,则使用config.maxUsagePerOrder限制使用次数
1413
- var maxUsageLimit = availableGoodPassCount;
1414
- if (selectedDiscount.config && selectedDiscount.config.maxUsagePerOrder) {
1415
- maxUsageLimit = Math.min(availableGoodPassCount, selectedDiscount.config.maxUsagePerOrder);
1416
- }
1417
- var splitCount = isNeedSplit ? Math.min(product.quantity || product.num || 1, maxUsageLimit) : 1;
1582
+ var fullCoveragePassUsageGroups = isNeedSplit ? buildFullCoveragePassUsageGroups(prioritizedApplicableDiscounts, totalQuantity) : [];
1583
+ var splitCount = isNeedSplit ? fullCoveragePassUsageGroups.reduce(function (total, group) {
1584
+ return total + group.count;
1585
+ }, 0) : 1;
1418
1586
  var arr = [];
1419
1587
 
1420
1588
  // 🔥 主商品和bundle子商品分别处理
@@ -1423,8 +1591,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1423
1591
  if (splitCount < totalQuantity && isNeedSplit) {
1424
1592
  var _product$origin_total2, _product$main_product2;
1425
1593
  var remainingQuantity = totalQuantity - splitCount;
1426
- var applicableNonGoodPassById = new Map(applicableDiscounts.filter(function (discount) {
1427
- return (discount.tag || discount.type) !== 'good_pass';
1594
+ var applicableNonFullCoveragePassById = new Map(applicableDiscounts.filter(function (discount) {
1595
+ return !isFullCoveragePass(discount);
1428
1596
  }).map(function (discount) {
1429
1597
  return [String(discount.id), discount];
1430
1598
  }));
@@ -1432,19 +1600,19 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1432
1600
  var _discount$discount$re, _discount$discount5;
1433
1601
  var discountType = discount.tag || discount.type;
1434
1602
  if (discountType === 'promotion') return true;
1435
- if (discountType === 'good_pass') return false;
1603
+ if (isFullCoveragePass(discount)) return false;
1436
1604
  var resourceId = (_discount$discount$re = (_discount$discount5 = discount.discount) === null || _discount$discount5 === void 0 ? void 0 : _discount$discount5.resource_id) !== null && _discount$discount$re !== void 0 ? _discount$discount$re : discount.id;
1437
- return resourceId !== undefined && resourceId !== null && applicableNonGoodPassById.has(String(resourceId));
1605
+ return resourceId !== undefined && resourceId !== null && applicableNonFullCoveragePassById.has(String(resourceId));
1438
1606
  }).map(function (discount) {
1439
1607
  var _discount$discount$re2, _discount$discount6;
1440
1608
  if ((discount.tag || discount.type) === 'promotion') return discount;
1441
1609
  var resourceId = (_discount$discount$re2 = (_discount$discount6 = discount.discount) === null || _discount$discount6 === void 0 ? void 0 : _discount$discount6.resource_id) !== null && _discount$discount$re2 !== void 0 ? _discount$discount$re2 : discount.id;
1442
- var matchedDiscount = applicableNonGoodPassById.get(String(resourceId));
1610
+ var matchedDiscount = applicableNonFullCoveragePassById.get(String(resourceId));
1443
1611
  if (matchedDiscount) {
1444
1612
  // 实际场景:3 件折扣卡商品中拆出 1 件改用商品券后,
1445
1613
  // 剩余 2 件仍在使用原折扣卡;必须同步登记折扣卡的使用状态,
1446
1614
  // 否则 updatedDiscountList 会把它改成未选中并清空 savedAmount。
1447
- usedDiscounts.set(matchedDiscount.id, true);
1615
+ markDiscountUsed(matchedDiscount);
1448
1616
  var appliedProducts = appliedDiscountProducts.get(matchedDiscount.id) || [];
1449
1617
  appliedProducts.push(_objectSpread(_objectSpread({}, discount), {}, {
1450
1618
  _num: remainingQuantity
@@ -1457,7 +1625,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1457
1625
  });
1458
1626
  });
1459
1627
  var hasRetainedWalletDiscount = remainderDiscountList.some(function (discount) {
1460
- return !['promotion', 'good_pass'].includes(discount.tag || discount.type);
1628
+ return (discount.tag || discount.type) !== 'promotion' && !isFullCoveragePass(discount);
1461
1629
  });
1462
1630
  var _total = (_product$origin_total2 = product.origin_total) !== null && _product$origin_total2 !== void 0 ? _product$origin_total2 : product.total;
1463
1631
  if ((product.discount_list || []).some(function (item) {
@@ -1468,7 +1636,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1468
1636
  }
1469
1637
  arr.push(_this4.hooks.setProduct(originProduct, _objectSpread({
1470
1638
  // 商品券只替换被拆出的 splitCount 件。余量行原本仍有效的折扣卡
1471
- // 不能随 good_pass 拆分一起清除;已取消或已失效的折扣不会进入此列表。
1639
+ // 不能随全额抵扣卡拆分一起清除;已取消或已失效的折扣不会进入此列表。
1472
1640
  discount_list: remainderDiscountList,
1473
1641
  quantity: remainingQuantity,
1474
1642
  _id: product._id.split('___')[0],
@@ -1477,15 +1645,21 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1477
1645
  main_product_selling_price: (_product$main_product2 = product.main_product_selling_price) !== null && _product$main_product2 !== void 0 ? _product$main_product2 : product.price
1478
1646
  } : {})));
1479
1647
  }
1480
- for (var i = 0; i < splitCount; i++) {
1648
+ var discountUsageGroups = isNeedSplit ? fullCoveragePassUsageGroups : [{
1649
+ discount: selectedDiscount,
1650
+ count: 1
1651
+ }];
1652
+ for (var i = 0; i < discountUsageGroups.length; i++) {
1481
1653
  var _originProduct4, _selectedDiscount$con, _product$options, _product$options2, _selectedDiscount$met, _selectedDiscount$met2, _reapplyDiscountPerce;
1482
- var _selectedDiscount = isNeedSplit ? prioritizedApplicableDiscounts[i] : selectedDiscountCard || applicableDiscounts[i];
1654
+ var _discountUsageGroups$ = discountUsageGroups[i],
1655
+ _selectedDiscount = _discountUsageGroups$.discount,
1656
+ appliedUseCount = _discountUsageGroups$.count;
1483
1657
  // 标记优惠券为已使用
1484
- usedDiscounts.set(_selectedDiscount.id, true);
1658
+ markDiscountUsed(_selectedDiscount, appliedUseCount);
1485
1659
  // 🔥 更新 product_id 使用计数
1486
- if ((_selectedDiscount.tag || _selectedDiscount.type) === 'good_pass') {
1660
+ if (isFullCoveragePass(_selectedDiscount)) {
1487
1661
  var currentCount = usedProductIdCounts.get(_selectedDiscount.product_id) || 0;
1488
- usedProductIdCounts.set(_selectedDiscount.product_id, currentCount + 1);
1662
+ usedProductIdCounts.set(_selectedDiscount.product_id, currentCount + appliedUseCount);
1489
1663
  }
1490
1664
 
1491
1665
  // 记录实际应用了优惠券的商品信息
@@ -1547,7 +1721,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1547
1721
  var mainProductDiscountAmount = amount;
1548
1722
  var lineDiscountAmount = new Decimal(mainProductDiscountAmount).plus(optionDiscountAmount).toNumber();
1549
1723
  var discountType = _selectedDiscount.tag || _selectedDiscount.type;
1550
- var isGoodPass = discountType === 'good_pass';
1724
+ var isFullCoverage = isFullCoveragePass(_selectedDiscount);
1551
1725
  var discountDetail = {
1552
1726
  amount: lineDiscountAmount,
1553
1727
  type: _selectedDiscount.tag === 'product_discount_card' ? 'discount_card' : discountType,
@@ -1563,10 +1737,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1563
1737
  discount_product_id: _selectedDiscount.product_id
1564
1738
  },
1565
1739
  // 前端使用的num数量,为了计算优惠金额
1566
- _num: isGoodPass ? 1 : product.num,
1740
+ _num: isFullCoverage ? appliedUseCount : product.num,
1567
1741
  config: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.config,
1568
1742
  metadata: _objectSpread(_objectSpread({
1569
- num: 1,
1743
+ num: isFullCoverage ? appliedUseCount : 1,
1570
1744
  discount_rule_uncheck_flag: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.discount_rule_uncheck_flag
1571
1745
  }, productDiscountDifference !== undefined && {
1572
1746
  product_discount_difference: productDiscountDifference
@@ -1584,9 +1758,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1584
1758
  if (product.isClient) {
1585
1759
  arr.push(_this4.hooks.setProduct(originProduct, {
1586
1760
  discount_list: [discountDetail],
1587
- // good_pass:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1588
- price: isGoodPass ? mainProductSellingPrice : product.price,
1589
- quantity: isNeedSplit ? 1 : product.quantity,
1761
+ // 全额抵扣卡:主商品价以折后价为准;勿用 product.price - amount(amount 含 option 优惠时会算错)
1762
+ price: isFullCoverage ? mainProductSellingPrice : product.price,
1763
+ quantity: isNeedSplit ? appliedUseCount : product.quantity,
1590
1764
  origin_total: getProductOriginTotalPrice({
1591
1765
  product: {
1592
1766
  original_price: product.original_price
@@ -1603,8 +1777,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1603
1777
  arr.push(_this4.hooks.setProduct(originProduct, {
1604
1778
  discount_list: _this4.filterDiscountListByType(product.discount_list, 'promotion').concat([discountDetail]),
1605
1779
  _id: product._id.split('___')[0] + '___' + _selectedDiscount.id + index,
1606
- price: _selectedDiscount.tag === 'good_pass' ? 0 : product.price,
1607
- quantity: isNeedSplit ? 1 : product.quantity,
1780
+ price: isFullCoverage ? 0 : product.price,
1781
+ quantity: isNeedSplit ? appliedUseCount : product.quantity,
1608
1782
  total: _total2,
1609
1783
  origin_total: productOriginTotal,
1610
1784
  main_product_selling_price: mainProductSellingPrice,
@@ -1621,15 +1795,17 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1621
1795
  var discountNum = splitCount;
1622
1796
  var normalNum = totalQuantity - discountNum;
1623
1797
 
1624
- // 生成有折扣的商品(每张商品券对应 num: 1)
1625
- for (var _i = 0; _i < discountNum; _i++) {
1798
+ // 同一卡实例的本次新增使用合并为一条,metadata.num 记录实际次数。
1799
+ for (var _i = 0; _i < fullCoveragePassUsageGroups.length; _i++) {
1626
1800
  var _selectedDiscount2$me;
1627
- var _selectedDiscount2 = prioritizedApplicableDiscounts[_i];
1628
- usedDiscounts.set(_selectedDiscount2.id, true);
1801
+ var _fullCoveragePassUsag = fullCoveragePassUsageGroups[_i],
1802
+ _selectedDiscount2 = _fullCoveragePassUsag.discount,
1803
+ _appliedUseCount = _fullCoveragePassUsag.count;
1804
+ markDiscountUsed(_selectedDiscount2, _appliedUseCount);
1629
1805
  // 🔥 更新 product_id 使用计数
1630
- if ((_selectedDiscount2.tag || _selectedDiscount2.type) === 'good_pass') {
1806
+ if (isFullCoveragePass(_selectedDiscount2)) {
1631
1807
  var _currentCount = usedProductIdCounts.get(_selectedDiscount2.product_id) || 0;
1632
- usedProductIdCounts.set(_selectedDiscount2.product_id, _currentCount + 1);
1808
+ usedProductIdCounts.set(_selectedDiscount2.product_id, _currentCount + _appliedUseCount);
1633
1809
  }
1634
1810
 
1635
1811
  // 🔥 生成唯一的 _id
@@ -1637,11 +1813,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1637
1813
 
1638
1814
  // 计算折扣后的价格(使用 getDiscountAmount,内部已处理 maxDeductionAmount)
1639
1815
  var discountedPrice = getDiscountAmount(_selectedDiscount2, product.origin_total, product.origin_total);
1640
- var bundleDiscountAmount = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
1816
+ var bundleDiscountAmountPerItem = new Decimal(product.origin_total || 0).minus(discountedPrice).toNumber();
1817
+ var bundleDiscountAmount = new Decimal(bundleDiscountAmountPerItem).mul(_appliedUseCount).toNumber();
1641
1818
  debugger;
1642
1819
  var _discountDetail = {
1643
1820
  amount: bundleDiscountAmount,
1644
- type: 'good_pass',
1821
+ type: _selectedDiscount2.tag || _selectedDiscount2.type,
1645
1822
  discount: {
1646
1823
  fixed_amount: product.origin_total,
1647
1824
  discount_calculation_mode: _selectedDiscount2 === null || _selectedDiscount2 === void 0 || (_selectedDiscount2$me = _selectedDiscount2.metadata) === null || _selectedDiscount2$me === void 0 ? void 0 : _selectedDiscount2$me.discount_calculation_mode,
@@ -1655,9 +1832,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1655
1832
  // 🔥 使用拆分后的唯一 _id
1656
1833
  custom_product_bundle_map_id: uniqueId,
1657
1834
  discount_rule_uncheck_flag: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.discount_rule_uncheck_flag,
1658
- num: 1
1835
+ num: _appliedUseCount
1659
1836
  },
1660
- _num: 1,
1837
+ _num: _appliedUseCount,
1661
1838
  config: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.config
1662
1839
  };
1663
1840
 
@@ -1668,11 +1845,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1668
1845
  processedItems.push(_objectSpread(_objectSpread({}, flatItem), {}, {
1669
1846
  // 🔥 使用唯一的 _id
1670
1847
  _id: uniqueId,
1671
- num: 1,
1672
- quantity: 1,
1848
+ num: _appliedUseCount,
1849
+ quantity: _appliedUseCount,
1673
1850
  price: discountedPrice,
1674
1851
  // 折扣后的价格
1675
- total: discountedPrice,
1852
+ total: new Decimal(discountedPrice).mul(_appliedUseCount).toNumber(),
1676
1853
  discount_list: [_discountDetail],
1677
1854
  processed: true,
1678
1855
  _discountId: _selectedDiscount2.id
@@ -1694,9 +1871,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1694
1871
  var _selectedDiscount3$me, _selectedDiscount3$me2, _reapplyDiscountPerce2, _flatItem$parentProdu9;
1695
1872
  // 折扣卡:不拆分数量,直接应用
1696
1873
  var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
1697
- usedDiscounts.set(_selectedDiscount3.id, true);
1874
+ markDiscountUsed(_selectedDiscount3);
1698
1875
  // 🔥 更新 product_id 使用计数(虽然此处主要是折扣卡,但保持一致性)
1699
- if ((_selectedDiscount3.tag || _selectedDiscount3.type) === 'good_pass') {
1876
+ if (isFullCoveragePass(_selectedDiscount3)) {
1700
1877
  var _currentCount2 = usedProductIdCounts.get(_selectedDiscount3.product_id) || 0;
1701
1878
  usedProductIdCounts.set(_selectedDiscount3.product_id, _currentCount2 + 1);
1702
1879
  }
@@ -1826,11 +2003,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1826
2003
  // 没有bundle,直接使用主商品处理结果
1827
2004
  result.push.apply(result, _toConsumableArray(mainProductArr));
1828
2005
  } else {
1829
- // 🔥 有bundle,需要检查子商品是否应用了商品券
2006
+ // 🔥 有 bundle,需要检查子商品是否应用了全额抵扣卡
1830
2007
  // 1. 先收集所有bundle子商品的处理结果
1831
2008
  var bundleProcessingInfo = new Map();
1832
- var hasGoodPassApplied = false; // 标记是否有子商品应用了商品券
1833
-
2009
+ var hasFullCoveragePassApplied = false;
1834
2010
  if (product.bundle && Array.isArray(product.bundle)) {
1835
2011
  product.bundle.forEach(function (bundleItem, bundleIndex) {
1836
2012
  var bundleItemId = "".concat(product._id, "_bundle_").concat(bundleIndex);
@@ -1841,15 +2017,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1841
2017
  } else {
1842
2018
  // 处理过的bundle item
1843
2019
  bundleProcessingInfo.set(bundleIndex, processedBundleItems);
1844
- // 🔥 检查是否应用了商品券(good_pass)
1845
- var hasGoodPass = processedBundleItems.some(function (item) {
2020
+ var hasFullCoveragePass = processedBundleItems.some(function (item) {
1846
2021
  var _item$discount_list;
1847
2022
  return (_item$discount_list = item.discount_list) === null || _item$discount_list === void 0 ? void 0 : _item$discount_list.some(function (discount) {
1848
- return discount.type === 'good_pass' || discount.tag === 'good_pass';
2023
+ return isFullCoveragePass(discount);
1849
2024
  });
1850
2025
  });
1851
- if (hasGoodPass) {
1852
- hasGoodPassApplied = true;
2026
+ if (hasFullCoveragePass) {
2027
+ hasFullCoveragePassApplied = true;
1853
2028
  }
1854
2029
  }
1855
2030
  });
@@ -1857,7 +2032,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1857
2032
 
1858
2033
  // 🔥 2. 如果有子商品应用了商品券,且主商品数量大于1,需要拆分主商品
1859
2034
  var mainProductQuantity = mainProductArr[0] ? _this4.hooks.getProduct(mainProductArr[0]).quantity : 1;
1860
- if (hasGoodPassApplied && mainProductArr.length === 1 && mainProductQuantity > 1) {
2035
+ if (hasFullCoveragePassApplied && mainProductArr.length === 1 && mainProductQuantity > 1) {
1861
2036
  var mainProduct = mainProductArr[0];
1862
2037
  var mainProductData = _this4.hooks.getProduct(mainProduct);
1863
2038
 
@@ -2058,7 +2233,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2058
2233
  } else {
2059
2234
  // 🔥 没有子商品被拆分,使用原有逻辑
2060
2235
  mainProductArr.forEach(function (mainProduct) {
2061
- var _ref17, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2236
+ var _ref23, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2062
2237
  var mainProductData = _this4.hooks.getProduct(mainProduct);
2063
2238
 
2064
2239
  // 重组bundle
@@ -2073,9 +2248,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2073
2248
  } else {
2074
2249
  // 🔥 关键:拆分后的bundle item
2075
2250
  processedBundleItems.forEach(function (item) {
2076
- var _item$price, _ref16, _item$bundle_selling_;
2251
+ var _item$price, _ref22, _item$bundle_selling_;
2077
2252
  var nextBundlePrice = (_item$price = item.price) !== null && _item$price !== void 0 ? _item$price : bundleItem.price;
2078
- var nextBundleSellingPrice = (_ref16 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref16 !== void 0 ? _ref16 : bundleItem.bundle_selling_price;
2253
+ var nextBundleSellingPrice = (_ref22 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref22 !== void 0 ? _ref22 : bundleItem.bundle_selling_price;
2079
2254
  // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
2080
2255
  var updatedDiscountList = (item.discount_list || []).map(function (discount) {
2081
2256
  var _discount$metadata10;
@@ -2102,7 +2277,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2102
2277
 
2103
2278
  // 主商品已经在前面的 setProduct 中应用过折扣;这里只替换 bundle,
2104
2279
  // 避免把主商品 discount_list 再扣一次。
2105
- var mainSellingPrice = (_ref17 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref17 !== void 0 ? _ref17 : 0;
2280
+ var mainSellingPrice = (_ref23 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref23 !== void 0 ? _ref23 : 0;
2106
2281
  var newTotal = Number(mainSellingPrice || 0);
2107
2282
  var newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
2108
2283
 
@@ -2171,6 +2346,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2171
2346
 
2172
2347
  // 获取此优惠券实际应用的商品详情
2173
2348
  var appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
2349
+ var committedAppliedProductDetails = isEntitlementPass(discount) ? mergeEntitlementAppliedProductDetails(discount.committedAppliedProductDetails || []) : [];
2350
+ var allAppliedProductDetails = isEntitlementPass(discount) ? mergeEntitlementAppliedProductDetails([].concat(_toConsumableArray(committedAppliedProductDetails), _toConsumableArray(appliedProductDetails))) : appliedProductDetails;
2174
2351
 
2175
2352
  // 根据是否有适用商品决定isAvailable
2176
2353
  var isAvailable = applicableProducts.length > 0;
@@ -2184,11 +2361,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2184
2361
  applicableProductIds: applicableProducts,
2185
2362
  // 添加可抵扣的商品详情
2186
2363
  applicableProductDetails: applicableProductDetails,
2187
- // 添加实际抵扣的商品详情(对于未选中的优惠券,为空数组)
2188
- appliedProductDetails: []
2364
+ // 已提交的历史使用不可撤销;只取消本次新增分配。
2365
+ appliedProductDetails: committedAppliedProductDetails
2189
2366
  });
2190
2367
  }
2191
- if (usedDiscounts.get(discount.id)) {
2368
+ if (isDiscountUsed(discount)) {
2192
2369
  return _objectSpread(_objectSpread({}, discount), {}, {
2193
2370
  isSelected: true,
2194
2371
  isManualSelect: options !== null && options !== void 0 && options.scan ? false : discount.isManualSelect,
@@ -2199,7 +2376,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2199
2376
  // 添加可抵扣的商品详情
2200
2377
  applicableProductDetails: applicableProductDetails,
2201
2378
  // 添加实际抵扣的商品详情
2202
- appliedProductDetails: appliedProductDetails
2379
+ appliedProductDetails: allAppliedProductDetails
2203
2380
  });
2204
2381
  }
2205
2382
  var isSelected = typeof discount.isSelected === 'boolean' ? discount.isSelected : undefined;
@@ -2207,7 +2384,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2207
2384
  // 如果是可用的 并且没有手动标记 则设置为选中
2208
2385
  if (isAvailable && appliedProductDetails.length && !discount.isManualSelect) {
2209
2386
  isSelected = true;
2210
- } else if (!appliedProductDetails.length) {
2387
+ } else if (!appliedProductDetails.length && !committedAppliedProductDetails.length) {
2211
2388
  isSelected = false;
2212
2389
  }
2213
2390
  return _objectSpread(_objectSpread({}, discount), {}, {
@@ -2220,8 +2397,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2220
2397
  applicableProductIds: applicableProducts,
2221
2398
  // 添加可抵扣的商品详情
2222
2399
  applicableProductDetails: applicableProductDetails,
2223
- // 添加实际抵扣的商品详情(对于未使用的优惠券,为空数组)
2224
- appliedProductDetails: []
2400
+ // 编辑订单的历史使用继续保留,本次没有新增使用。
2401
+ appliedProductDetails: committedAppliedProductDetails
2225
2402
  });
2226
2403
  });
2227
2404
  return {
@@ -2251,15 +2428,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2251
2428
  var ruleType = usageRules.type;
2252
2429
  // 套餐适用范围配置
2253
2430
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
2254
- var _ref18 = packageScope || {},
2255
- _ref18$type = _ref18.type,
2256
- scopeType = _ref18$type === void 0 ? 'product_all' : _ref18$type,
2257
- _ref18$exclude_bundle = _ref18.exclude_bundle_product_ids,
2258
- exclude_bundle_product_ids = _ref18$exclude_bundle === void 0 ? [] : _ref18$exclude_bundle,
2259
- _ref18$include_bundle = _ref18.include_bundle_product_ids,
2260
- include_bundle_product_ids = _ref18$include_bundle === void 0 ? [] : _ref18$include_bundle,
2261
- _ref18$filter = _ref18.filter,
2262
- filter = _ref18$filter === void 0 ? 0 : _ref18$filter;
2431
+ var _ref24 = packageScope || {},
2432
+ _ref24$type = _ref24.type,
2433
+ scopeType = _ref24$type === void 0 ? 'product_all' : _ref24$type,
2434
+ _ref24$exclude_bundle = _ref24.exclude_bundle_product_ids,
2435
+ exclude_bundle_product_ids = _ref24$exclude_bundle === void 0 ? [] : _ref24$exclude_bundle,
2436
+ _ref24$include_bundle = _ref24.include_bundle_product_ids,
2437
+ include_bundle_product_ids = _ref24$include_bundle === void 0 ? [] : _ref24$include_bundle,
2438
+ _ref24$filter = _ref24.filter,
2439
+ filter = _ref24$filter === void 0 ? 0 : _ref24$filter;
2263
2440
  var isMainProduct = flatItem.type === 'main'; // 单独购买
2264
2441
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2265
2442
  var bundleMainProductId = (_flatItem$product = flatItem.product) === null || _flatItem$product === void 0 ? void 0 : _flatItem$product.product_id;