@pisell/pisellos 2.1.173 → 2.1.174

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 (93) hide show
  1. package/dist/model/strategy/adapter/promotion/index.js +9 -0
  2. package/dist/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  3. package/dist/model/strategy/adapter/walletPass/evaluator.js +4 -2
  4. package/dist/modules/Discount/availability.d.ts +7 -0
  5. package/dist/modules/Discount/availability.js +52 -0
  6. package/dist/modules/Discount/entitlementPass.d.ts +34 -0
  7. package/dist/modules/Discount/entitlementPass.js +147 -0
  8. package/dist/modules/Discount/entitlementState.d.ts +8 -0
  9. package/dist/modules/Discount/entitlementState.js +205 -0
  10. package/dist/modules/Discount/index.d.ts +6 -3
  11. package/dist/modules/Discount/index.js +125 -23
  12. package/dist/modules/Discount/types.d.ts +34 -5
  13. package/dist/modules/Holder/index.d.ts +48 -0
  14. package/dist/modules/Holder/index.js +640 -0
  15. package/dist/modules/Holder/types.d.ts +123 -0
  16. package/dist/modules/Holder/types.js +1 -0
  17. package/dist/modules/Holder/utils.d.ts +13 -0
  18. package/dist/modules/Holder/utils.js +34 -0
  19. package/dist/modules/Order/index.d.ts +1 -0
  20. package/dist/modules/Order/index.js +18 -1
  21. package/dist/modules/Order/types.d.ts +2 -0
  22. package/dist/modules/Order/utils.d.ts +10 -0
  23. package/dist/modules/Order/utils.js +35 -3
  24. package/dist/modules/Product/types.d.ts +7 -0
  25. package/dist/modules/Rules/entitlementLines.d.ts +8 -0
  26. package/dist/modules/Rules/entitlementLines.js +157 -0
  27. package/dist/modules/Rules/index.d.ts +12 -2
  28. package/dist/modules/Rules/index.js +377 -112
  29. package/dist/modules/Rules/types.d.ts +2 -2
  30. package/dist/modules/index.d.ts +1 -0
  31. package/dist/modules/index.js +2 -1
  32. package/dist/plugins/window.d.ts +3 -0
  33. package/dist/solution/BookingByStep/index.d.ts +17 -2
  34. package/dist/solution/BookingByStep/index.js +276 -204
  35. package/dist/solution/BookingByStep/types.d.ts +2 -1
  36. package/dist/solution/BookingByStep/types.js +3 -1
  37. package/dist/solution/ScanOrder/index.js +1 -1
  38. package/dist/solution/ScanOrder/types.d.ts +1 -0
  39. package/dist/solution/ShopDiscount/index.d.ts +3 -0
  40. package/dist/solution/ShopDiscount/index.js +161 -78
  41. package/dist/solution/ShopDiscount/utils.d.ts +1 -0
  42. package/dist/solution/ShopDiscount/utils.js +40 -1
  43. package/dist/solution/VenueBooking/index.d.ts +19 -0
  44. package/dist/solution/VenueBooking/index.js +978 -748
  45. package/dist/solution/VenueBooking/types.d.ts +2 -0
  46. package/dist/types/index.d.ts +1 -0
  47. package/lib/model/strategy/adapter/promotion/index.js +49 -0
  48. package/lib/model/strategy/adapter/walletPass/evaluator.d.ts +2 -0
  49. package/lib/model/strategy/adapter/walletPass/evaluator.js +4 -2
  50. package/lib/modules/Discount/availability.d.ts +7 -0
  51. package/lib/modules/Discount/availability.js +91 -0
  52. package/lib/modules/Discount/entitlementPass.d.ts +34 -0
  53. package/lib/modules/Discount/entitlementPass.js +184 -0
  54. package/lib/modules/Discount/entitlementState.d.ts +8 -0
  55. package/lib/modules/Discount/entitlementState.js +206 -0
  56. package/lib/modules/Discount/index.d.ts +6 -3
  57. package/lib/modules/Discount/index.js +66 -16
  58. package/lib/modules/Discount/types.d.ts +34 -5
  59. package/lib/modules/Holder/index.d.ts +48 -0
  60. package/lib/modules/Holder/index.js +402 -0
  61. package/lib/modules/Holder/types.d.ts +123 -0
  62. package/lib/modules/Holder/types.js +17 -0
  63. package/lib/modules/Holder/utils.d.ts +13 -0
  64. package/lib/modules/Holder/utils.js +71 -0
  65. package/lib/modules/Order/index.d.ts +1 -0
  66. package/lib/modules/Order/index.js +14 -0
  67. package/lib/modules/Order/types.d.ts +2 -0
  68. package/lib/modules/Order/utils.d.ts +10 -0
  69. package/lib/modules/Order/utils.js +36 -5
  70. package/lib/modules/Product/types.d.ts +7 -0
  71. package/lib/modules/Rules/entitlementLines.d.ts +8 -0
  72. package/lib/modules/Rules/entitlementLines.js +158 -0
  73. package/lib/modules/Rules/index.d.ts +12 -2
  74. package/lib/modules/Rules/index.js +304 -70
  75. package/lib/modules/Rules/types.d.ts +2 -2
  76. package/lib/modules/index.d.ts +1 -0
  77. package/lib/modules/index.js +3 -1
  78. package/lib/plugins/window.d.ts +3 -0
  79. package/lib/solution/BookingByStep/index.d.ts +17 -2
  80. package/lib/solution/BookingByStep/index.js +39 -0
  81. package/lib/solution/BookingByStep/types.d.ts +2 -1
  82. package/lib/solution/BookingByStep/types.js +5 -0
  83. package/lib/solution/ScanOrder/index.js +1 -1
  84. package/lib/solution/ScanOrder/types.d.ts +1 -0
  85. package/lib/solution/ShopDiscount/index.d.ts +3 -0
  86. package/lib/solution/ShopDiscount/index.js +78 -28
  87. package/lib/solution/ShopDiscount/utils.d.ts +1 -0
  88. package/lib/solution/ShopDiscount/utils.js +42 -1
  89. package/lib/solution/VenueBooking/index.d.ts +19 -0
  90. package/lib/solution/VenueBooking/index.js +134 -16
  91. package/lib/solution/VenueBooking/types.d.ts +2 -0
  92. package/lib/types/index.d.ts +1 -0
  93. package/package.json +1 -1
@@ -39,13 +39,28 @@ var import_utils2 = require("../Cart/utils");
39
39
  var import_decimal = __toESM(require("decimal.js"));
40
40
  var import_lodash_es = require("lodash-es");
41
41
  var import_dayjs = __toESM(require("dayjs"));
42
+ var import_evaluator = require("../../model/strategy/adapter/walletPass/evaluator");
43
+ var import_entitlementPass = require("../Discount/entitlementPass");
44
+ var import_availability = require("../Discount/availability");
45
+ var import_entitlementState = require("../Discount/entitlementState");
46
+ var import_utils3 = require("../../solution/ShopDiscount/utils");
47
+ var import_lodash_es2 = require("lodash-es");
48
+ var import_entitlementLines = require("./entitlementLines");
42
49
  var RulesModule = class extends import_BaseModule.BaseModule {
43
50
  constructor(name, version) {
44
51
  super(name, version);
45
52
  this.defaultName = "rules";
46
53
  this.defaultVersion = "1.0.0";
54
+ this.entitlementPassEnabled = false;
47
55
  this.hooks = {};
48
56
  }
57
+ setEntitlementPassEnabled(enabled) {
58
+ this.entitlementPassEnabled = enabled;
59
+ }
60
+ getWalletPassEvaluator() {
61
+ var _a, _b, _c;
62
+ return ((_c = (_b = (_a = this.core) == null ? void 0 : _a.getPlugin("window")) == null ? void 0 : _b.getWalletPassEvaluator) == null ? void 0 : _c.call(_b)) || (this.defaultWalletPassEvaluator ?? (this.defaultWalletPassEvaluator = new import_evaluator.WalletPassEvaluator()));
63
+ }
49
64
  async initialize(core, options) {
50
65
  this.core = core;
51
66
  this.hooks = options == null ? void 0 : options.hooks;
@@ -58,18 +73,58 @@ var RulesModule = class extends import_BaseModule.BaseModule {
58
73
  getRulesList() {
59
74
  return this.store.rulesList;
60
75
  }
61
- // 商品不需要holder,则不需要判断,直接返回true,商品需要holder但是还没填写,那么暂时不使用带有holder的券,直到填写才去匹配
62
- checkHolderMatch(discount, product, holders) {
63
- var _a;
76
+ normalizeHolderRecordIds(value) {
77
+ const records = Array.isArray(value) ? value : [value];
78
+ return Array.from(
79
+ new Set(
80
+ records.map((record) => {
81
+ if (record && typeof record === "object") {
82
+ return record.form_record_id;
83
+ }
84
+ return record;
85
+ }).filter(
86
+ (record) => record !== void 0 && record !== null && record !== "" && record !== 0 && record !== "0"
87
+ ).map(String)
88
+ )
89
+ );
90
+ }
91
+ /**
92
+ * 商品未开启 Holder 选择时跳过匹配;已开启时,特定 form Holder 卡
93
+ * 只适用于同一 Holder Record,是否必填不影响匹配规则。
94
+ */
95
+ checkHolderMatch(discount, product, holderSource, holders) {
96
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
64
97
  if (((_a = discount.holder) == null ? void 0 : _a.holder_type) !== "form")
65
98
  return true;
66
- const orderHolderId = Array.isArray(holders) && holders.length > 0 ? holders[0].form_record_id : void 0;
67
- const productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
68
- if (!product.isNeedHolder)
99
+ if (!(0, import_entitlementPass.isEntitlementPass)(discount)) {
100
+ if (!product.isNeedHolder)
101
+ return true;
102
+ const holder = holders == null ? void 0 : holders[0];
103
+ const orderHolderId = holder && typeof holder === "object" ? holder.form_record_id : holder;
104
+ const productHolderId = Array.isArray(product.holder_id) ? product.holder_id[0] : product.holder_id;
105
+ if (!orderHolderId && !productHolderId)
106
+ return false;
107
+ return (productHolderId || orderHolderId) === discount.holder.holder_id;
108
+ }
109
+ const holderConfig = (holderSource == null ? void 0 : holderSource.holder_config) ?? ((_b = holderSource == null ? void 0 : holderSource.metadata) == null ? void 0 : _b.holder_config) ?? ((_c = holderSource == null ? void 0 : holderSource.origin) == null ? void 0 : _c.holder_config) ?? ((_e = (_d = holderSource == null ? void 0 : holderSource.metadata) == null ? void 0 : _d.origin) == null ? void 0 : _e.holder_config) ?? ((_f = holderSource == null ? void 0 : holderSource._origin) == null ? void 0 : _f.holder_config) ?? ((_h = (_g = holderSource == null ? void 0 : holderSource._origin) == null ? void 0 : _g.product) == null ? void 0 : _h.holder_config) ?? ((_j = (_i = holderSource == null ? void 0 : holderSource._originData) == null ? void 0 : _i.product) == null ? void 0 : _j.holder_config) ?? ((_k = holderSource == null ? void 0 : holderSource._productInit) == null ? void 0 : _k.holder_config) ?? ((_l = holderSource == null ? void 0 : holderSource._productOrigin) == null ? void 0 : _l.holder_config) ?? ((_m = holderSource == null ? void 0 : holderSource._extend) == null ? void 0 : _m.holder_config) ?? ((_o = (_n = holderSource == null ? void 0 : holderSource._extend) == null ? void 0 : _n.product) == null ? void 0 : _o.holder_config) ?? ((_r = (_q = (_p = holderSource == null ? void 0 : holderSource._extend) == null ? void 0 : _p.product) == null ? void 0 : _q.metadata) == null ? void 0 : _r.holder_config);
110
+ const holderStatus = holderConfig == null ? void 0 : holderConfig.status;
111
+ const holderEnabled = holderStatus == null || holderStatus === "" || holderStatus === true || ["enable", "1"].includes(String(holderStatus).trim().toLowerCase());
112
+ if (!holderEnabled || !(holderConfig == null ? void 0 : holderConfig.resource_id)) {
69
113
  return true;
70
- if (!orderHolderId && !productHolderId)
114
+ }
115
+ const discountHolderIds = this.normalizeHolderRecordIds(
116
+ discount.holder.holder_id
117
+ );
118
+ if (!discountHolderIds.length)
71
119
  return false;
72
- return (productHolderId || orderHolderId) === discount.holder.holder_id;
120
+ const productHolderIds = this.normalizeHolderRecordIds(product.holder_id);
121
+ const candidateHolderIds = productHolderIds.length || Array.isArray(product.holder_id) ? productHolderIds : this.normalizeHolderRecordIds(holders);
122
+ if (!candidateHolderIds.length)
123
+ return false;
124
+ const discountHolderIdSet = new Set(discountHolderIds);
125
+ return candidateHolderIds.every(
126
+ (holderId) => discountHolderIdSet.has(holderId)
127
+ );
73
128
  }
74
129
  // 判断discountList 是否可以对当前productList生效
75
130
  isDiscountListAvailable({
@@ -86,7 +141,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
86
141
  productList
87
142
  };
88
143
  }
89
- if (productList.every((item) => {
144
+ if (!newDiscountList.some(import_entitlementPass.isEntitlementPass) && productList.length > 0 && productList.every((item) => {
90
145
  var _a;
91
146
  const product = this.hooks.getProduct(item);
92
147
  return product.booking_id && (((_a = product.discount_list) == null ? void 0 : _a.length) || product.total == 0);
@@ -102,21 +157,25 @@ var RulesModule = class extends import_BaseModule.BaseModule {
102
157
  (discount) => !discount.isEditMode && (discount.tag !== "good_pass" || discount.isScan)
103
158
  );
104
159
  const mergedDiscountList = (0, import_utils.uniqueById)([
160
+ ...newDiscountList.filter(import_entitlementPass.isEntitlementPass),
105
161
  ...filteredOldDiscountList,
106
162
  ...newDiscountList
107
163
  ]);
108
164
  const result = this.calcDiscount({
109
165
  discountList: mergedDiscountList,
110
- productList: [...productList],
166
+ productList: this.entitlementPassEnabled ? (0, import_lodash_es2.cloneDeep)(productList) : [...productList],
111
167
  holders,
112
168
  isFormSubject
113
169
  }, {
114
170
  scan: true
115
171
  });
116
172
  let hasApplicableDiscount = false;
117
- const newDiscountIds = newDiscountList.map((discount) => discount.id);
173
+ const newDiscountIds = new Set(newDiscountList.map((discount) => String(discount.id)));
118
174
  result.productList.forEach((product) => {
119
- const { discount_list, bundle } = this.hooks.getProduct(product);
175
+ const mappedProduct = this.hooks.getProduct(product);
176
+ if ((0, import_entitlementState.isPersistedEntitlementLine)(product, mappedProduct))
177
+ return;
178
+ const { discount_list, bundle } = mappedProduct;
120
179
  const allDiscountList = [...discount_list || []];
121
180
  (bundle || []).forEach((item) => {
122
181
  allDiscountList.push(...(item == null ? void 0 : item.discount_list) || []);
@@ -125,7 +184,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
125
184
  const usedNewDiscount = allDiscountList.some(
126
185
  (discount) => {
127
186
  var _a;
128
- return newDiscountIds.includes((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id);
187
+ return newDiscountIds.has(String((_a = discount == null ? void 0 : discount.discount) == null ? void 0 : _a.resource_id));
129
188
  }
130
189
  );
131
190
  if (usedNewDiscount) {
@@ -139,6 +198,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
139
198
  }
140
199
  return {
141
200
  isAvailable: hasApplicableDiscount,
201
+ evaluatedDiscountList: result.discountList,
142
202
  discountList: hasApplicableDiscount ? result.discountList : oldDiscountList,
143
203
  productList: hasApplicableDiscount ? result.productList : productList,
144
204
  unavailableReason
@@ -153,7 +213,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
153
213
  for (const discount of discountList) {
154
214
  for (const item of productList) {
155
215
  const product = this.hooks.getProduct(item);
156
- const bookingTime = ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss");
216
+ const bookingTime = (0, import_dayjs.default)((product == null ? void 0 : product.startDate) || void 0).format("YYYY-MM-DD HH:mm:ss");
157
217
  const filteredList = (0, import_utils.filterDiscountListByBookingTime)([discount], bookingTime);
158
218
  if (filteredList.length === 0) {
159
219
  return import_types.UnavailableReason.TimeLimit;
@@ -162,6 +222,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
162
222
  }
163
223
  for (const discount of discountList) {
164
224
  const limitedData = discount.limited_relation_product_data;
225
+ if (!limitedData)
226
+ return import_types.UnavailableReason.ProductNotApplicable;
165
227
  let hasApplicableProduct = false;
166
228
  for (const item of productList) {
167
229
  const product = this.hooks.getProduct(item);
@@ -185,13 +247,43 @@ var RulesModule = class extends import_BaseModule.BaseModule {
185
247
  holders,
186
248
  isFormSubject
187
249
  }, options) {
250
+ discountList = this.entitlementPassEnabled ? (0, import_entitlementState.withCommittedEntitlementDetails)(discountList, productList, this.hooks.getProduct) : discountList.filter((item) => !(0, import_entitlementPass.isEntitlementPass)(item));
251
+ const usableEntitlements = discountList.filter(
252
+ (discount) => (0, import_entitlementPass.isEntitlementPass)(discount) && !discount.isEditMode && !discount.isManualSelect && !(0, import_availability.getDiscountUsageBlockReason)(discount)
253
+ );
254
+ const canUseEntitlement = (originProduct) => {
255
+ const product = this.hooks.getProduct(originProduct);
256
+ const holderProducts = Array.isArray(product.holder_id) && product.holder_id.length > 1 ? product.holder_id.map((holder_id) => ({ ...product, holder_id })) : [product];
257
+ const items = [
258
+ { type: "main", id: product.id, price: product.original_price ?? product.price },
259
+ ...(product.bundle || []).map((bundleItem) => ({
260
+ type: "bundle",
261
+ id: bundleItem._bundle_product_id ?? bundleItem.bundle_product_id ?? bundleItem.product_id,
262
+ price: bundleItem.original_price ?? bundleItem.price,
263
+ bundleItem
264
+ }))
265
+ ];
266
+ return usableEntitlements.some((discount) => {
267
+ const scope = discount.limited_relation_product_data;
268
+ if (!scope || !holderProducts.some((item) => this.checkHolderMatch(discount, item, originProduct, holders)) || !(0, import_utils.filterDiscountListByBookingTime)([discount], (0, import_dayjs.default)(product.startDate || void 0).format("YYYY-MM-DD HH:mm:ss")).length)
269
+ return false;
270
+ return items.some(
271
+ (item) => {
272
+ var _a, _b;
273
+ return Number(item.price) > 0 && (scope.type === "product_all" ? !(scope.filter === 1 && ((_a = scope.exclude_product_ids) == null ? void 0 : _a.some((id) => String(id) === String(item.id)))) : !!((_b = scope.product_ids) == null ? void 0 : _b.includes(item.id))) && this.checkPackageSubItemUsageRules(discount, { ...item, originProduct, parentProduct: product });
274
+ }
275
+ );
276
+ });
277
+ };
278
+ if (this.entitlementPassEnabled)
279
+ productList = (0, import_entitlementLines.prepareEntitlementLines)(productList, this.hooks, canUseEntitlement);
188
280
  const editModeDiscount = [];
189
281
  const addModeDiscount = [];
190
282
  discountList.forEach((discount) => {
191
283
  if (discount.isEditMode) {
192
284
  editModeDiscount.push(discount);
193
285
  } else {
194
- addModeDiscount.push(discount);
286
+ addModeDiscount.push((0, import_entitlementPass.isEntitlementPass)(discount) ? { ...discount, config: void 0, reason: void 0, reasonCode: void 0 } : discount);
195
287
  }
196
288
  });
197
289
  const editModeOrderLevelProductIds = /* @__PURE__ */ new Set();
@@ -237,8 +329,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
237
329
  bundleIndex,
238
330
  // 虚拟商品属性
239
331
  price: Number(bundleItem.price || 0),
240
- id: bundleItem._bundle_product_id,
241
- // 🔥 使用 _bundle_product_id
332
+ id: bundleItem._bundle_product_id ?? bundleItem.bundle_product_id ?? bundleItem.product_id,
242
333
  _id: `${product._id}_bundle_${bundleIndex}`,
243
334
  parentId: product._id,
244
335
  num: bundleItem.num || 1,
@@ -320,6 +411,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
320
411
  }
321
412
  return 0;
322
413
  }
414
+ if ((0, import_entitlementPass.isEntitlementPass)(a) || (0, import_entitlementPass.isEntitlementPass)(b)) {
415
+ return (0, import_entitlementPass.isEntitlementPass)(a) && (0, import_entitlementPass.isEntitlementPass)(b) ? (0, import_entitlementPass.compareEntitlementPassPriority)(a, b) : (0, import_entitlementPass.isEntitlementPass)(a) ? -1 : 1;
416
+ }
323
417
  const priorityA = getPriority(a);
324
418
  const priorityB = getPriority(b);
325
419
  if (priorityA !== priorityB) {
@@ -368,6 +462,79 @@ var RulesModule = class extends import_BaseModule.BaseModule {
368
462
  return !isExcluded;
369
463
  };
370
464
  const usedDiscounts = /* @__PURE__ */ new Map();
465
+ const entitlementUsageCounts = /* @__PURE__ */ new Map();
466
+ const usedProductIdCounts = /* @__PURE__ */ new Map();
467
+ const markDiscountUsed = (discount) => {
468
+ if ((0, import_entitlementPass.isEntitlementPass)(discount)) {
469
+ entitlementUsageCounts.set(discount.id, (entitlementUsageCounts.get(discount.id) || 0) + 1);
470
+ } else {
471
+ usedDiscounts.set(discount.id, true);
472
+ }
473
+ usedProductIdCounts.set(discount.product_id, (usedProductIdCounts.get(discount.product_id) || 0) + 1);
474
+ };
475
+ const getFullCoveragePasses = (discounts, quantity) => {
476
+ var _a;
477
+ const allocated = [];
478
+ const productCounts = new Map(usedProductIdCounts);
479
+ for (const discount of discounts) {
480
+ if (!(0, import_entitlementPass.isFullCoveragePass)(discount) || allocated.length >= quantity)
481
+ continue;
482
+ let count = (0, import_entitlementPass.isEntitlementPass)(discount) ? (0, import_entitlementPass.getRemainingEntitlementUses)(discount, entitlementUsageCounts.get(discount.id) || 0, quantity - allocated.length) : usedDiscounts.get(discount.id) ? 0 : 1;
483
+ const limit = Number(((_a = discount.config) == null ? void 0 : _a.maxUsagePerOrder) || 0);
484
+ if ((0, import_entitlementPass.isEntitlementPass)(discount) && limit > 0) {
485
+ count = Math.min(count, Math.max(0, Math.floor(limit) - (productCounts.get(discount.product_id) || 0)));
486
+ }
487
+ for (let i = 0; i < count; i++)
488
+ allocated.push(discount);
489
+ productCounts.set(discount.product_id, (productCounts.get(discount.product_id) || 0) + count);
490
+ }
491
+ return allocated;
492
+ };
493
+ let evaluator;
494
+ addModeDiscount.filter(import_entitlementPass.isEntitlementPass).forEach((discount) => {
495
+ var _a, _b;
496
+ discount.usageLimitFailKey = (0, import_availability.getDiscountUsageLimitFailKey)(discount);
497
+ discount.reasonCode = (0, import_availability.getDiscountUsageBlockReason)(discount);
498
+ const quota = (0, import_entitlementPass.resolveEntitlementQuota)(discount);
499
+ if (discount.reasonCode || !quota) {
500
+ discount.config = { isAvailable: false };
501
+ return;
502
+ }
503
+ evaluator ?? (evaluator = this.getWalletPassEvaluator());
504
+ const result = evaluator.checkVoucherAvailability({
505
+ orderTotalAmount: productList.reduce((sum, item) => {
506
+ const product = this.hooks.getProduct(item);
507
+ return sum.plus(new import_decimal.default(product.origin_total || 0).times(product.quantity || product.num || 1));
508
+ }, new import_decimal.default(0)).toNumber(),
509
+ // 策略按统一商品结构读主价与数量,套餐次数还需乘父商品份数。
510
+ products: sortedFlattenedList.map((item) => {
511
+ var _a2, _b2, _c;
512
+ return {
513
+ product_id: item.id,
514
+ price: item.price || 0,
515
+ main_product_selling_price: item.price || 0,
516
+ quantity: (item.quantity || item.num || 1) * (item.type === "bundle" ? ((_a2 = item.parentProduct) == null ? void 0 : _a2.quantity) || ((_b2 = item.parentProduct) == null ? void 0 : _b2.num) || 1 : 1),
517
+ product_options: item.type === "main" ? (_c = item.product) == null ? void 0 : _c.options : void 0
518
+ };
519
+ }),
520
+ vouchers: [{
521
+ ...discount,
522
+ amount: Number(discount.par_value || 0),
523
+ balance: quota.type === "unlimited" ? Number.MAX_SAFE_INTEGER : quota.balance,
524
+ type: "entitlement_pass",
525
+ unified_available_status: discount.unified_available_status ?? 1,
526
+ available_product_type: (_a = discount.limited_relation_product_data) == null ? void 0 : _a.type,
527
+ available_product_ids: (_b = discount.limited_relation_product_data) == null ? void 0 : _b.product_ids
528
+ }]
529
+ });
530
+ discount.config = { ...result.config, isAvailable: result.isAvailable };
531
+ if (!result.isAvailable) {
532
+ discount.reason = result.reason;
533
+ discount.reasonCode = result.reasonCode || "not_meet_the_required_conditions";
534
+ }
535
+ });
536
+ const entitlementTimeReasons = /* @__PURE__ */ new Map();
537
+ const entitlementHolderMismatch = /* @__PURE__ */ new Set();
371
538
  const discountApplicability = /* @__PURE__ */ new Map();
372
539
  const discountApplicableProducts = /* @__PURE__ */ new Map();
373
540
  addModeDiscount.forEach((discount) => {
@@ -394,7 +561,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
394
561
  startDate: (_a = flatItem.parentProduct) == null ? void 0 : _a.startDate
395
562
  };
396
563
  }
397
- const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
564
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.length) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.every((d) => d.id && ["entitlement_pass", "good_pass", "discount_card", "product_discount_card"].includes(d.tag || d.type)))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_e = (_d = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _d.discount_list) == null ? void 0 : _e.length) && ((_g = (_f = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _f.discount_list) == null ? void 0 : _g.every((d) => d.id)));
398
565
  if (!isAvailableProduct) {
399
566
  return false;
400
567
  }
@@ -405,7 +572,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
405
572
  return false;
406
573
  }
407
574
  const limitedData = discount.limited_relation_product_data;
408
- const timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
575
+ const timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (0, import_dayjs.default)((product == null ? void 0 : product.startDate) || void 0).format("YYYY-MM-DD HH:mm:ss")).length;
409
576
  if (!timeLimit) {
410
577
  return false;
411
578
  }
@@ -521,8 +688,10 @@ var RulesModule = class extends import_BaseModule.BaseModule {
521
688
  originProduct = flatItem.originProduct;
522
689
  }
523
690
  addModeDiscount.forEach((discount) => {
524
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i;
691
+ var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
525
692
  const limitedData = discount == null ? void 0 : discount.limited_relation_product_data;
693
+ if (!limitedData || (0, import_entitlementPass.isEntitlementPass)(discount) && ((_a2 = discount.config) == null ? void 0 : _a2.isAvailable) === false)
694
+ return;
526
695
  const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
527
696
  const isHolderMatch = this.checkHolderMatch(
528
697
  discount,
@@ -530,38 +699,49 @@ var RulesModule = class extends import_BaseModule.BaseModule {
530
699
  isNeedHolder: isFormSubject && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
531
700
  holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
532
701
  },
702
+ flatItem.originProduct,
533
703
  holders
534
704
  );
535
705
  let timeLimit = true;
536
- timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], ((product == null ? void 0 : product.startDate) || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
537
- const isLimitedProduct = (limitedData.type === "product_all" || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
538
- const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_a2 = product == null ? void 0 : product.discount_list) == null ? void 0 : _a2.length) && ((_b = product == null ? void 0 : product.discount_list) == null ? void 0 : _b.every(
706
+ const useTime = (0, import_dayjs.default)((product == null ? void 0 : product.startDate) || void 0).format("YYYY-MM-DD HH:mm:ss");
707
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], useTime).length;
708
+ if ((0, import_entitlementPass.isEntitlementPass)(discount)) {
709
+ const reason = (0, import_utils3.getDiscountTimeUnavailableReason)(discount, useTime);
710
+ const reasons = entitlementTimeReasons.get(discount.id) || [];
711
+ reasons.push(reason);
712
+ entitlementTimeReasons.set(discount.id, reasons);
713
+ if (!isHolderMatch)
714
+ entitlementHolderMismatch.add(discount.id);
715
+ }
716
+ const isLimitedProduct = (limitedData.type === "product_all" && !(limitedData.filter === 1 && ((_b = limitedData.exclude_product_ids) == null ? void 0 : _b.includes(product.id))) || limitedData.product_ids && limitedData.product_ids.includes(product.id)) && isHolderMatch;
717
+ const isAvailableProduct = flatItem.type === "main" ? !((product == null ? void 0 : product.booking_id) && ((_c = product == null ? void 0 : product.discount_list) == null ? void 0 : _c.length) && ((_d = product == null ? void 0 : product.discount_list) == null ? void 0 : _d.every(
539
718
  (discount2) => discount2.id && [
719
+ "entitlement_pass",
540
720
  "good_pass",
541
721
  "discount_card",
542
722
  "product_discount_card"
543
723
  ].includes(discount2.tag || discount2.type)
544
- ))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_d = (_c = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _c.discount_list) == null ? void 0 : _d.length) && ((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.every((discount2) => discount2.id)));
724
+ ))) : !((flatItem == null ? void 0 : flatItem.booking_id) && !!((_f = (_e = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _e.discount_list) == null ? void 0 : _f.length) && ((_h = (_g = flatItem == null ? void 0 : flatItem.bundleItem) == null ? void 0 : _g.discount_list) == null ? void 0 : _h.every((discount2) => discount2.id)));
545
725
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
546
- if (isAvailableProduct && isLimitedProduct && timeLimit && isBundleAvailable) {
547
- (_g = discountApplicability.get(discount.id)) == null ? void 0 : _g.push(product.id);
726
+ if (isAvailableProduct && !(0, import_entitlementState.isPersistedEntitlementLine)(originProduct, flatItem.type === "main" ? flatItem.product : flatItem.parentProduct) && isLimitedProduct && isBundleAvailable && timeLimit) {
727
+ (_i = discountApplicability.get(discount.id)) == null ? void 0 : _i.push(product.id);
548
728
  const applicableProducts = discountApplicableProducts.get(discount.id) || [];
549
729
  const discountType = discount.tag || discount.type;
550
- const isGoodPass = discountType === "good_pass";
730
+ const isGoodPass = (0, import_entitlementPass.isFullCoveragePass)(discount);
551
731
  const num = isGoodPass || (flatItem == null ? void 0 : flatItem.type) === "main" ? 1 : product.num;
552
732
  const productData = {
553
733
  amount: product.price * num,
554
734
  type: discountType,
555
735
  tag: discountType,
556
736
  discount: {
557
- discount_card_type: (_h = discount == null ? void 0 : discount.metadata) == null ? void 0 : _h.discount_card_type,
737
+ discount_card_type: (_j = discount == null ? void 0 : discount.metadata) == null ? void 0 : _j.discount_card_type,
558
738
  fixed_amount: product.price,
559
- discount_calculation_mode: (_i = discount == null ? void 0 : discount.metadata) == null ? void 0 : _i.discount_calculation_mode,
739
+ discount_calculation_mode: (_k = discount == null ? void 0 : discount.metadata) == null ? void 0 : _k.discount_calculation_mode,
560
740
  resource_id: discount.id,
561
741
  title: discount.format_title,
562
742
  original_amount: product.price || product.origin_total,
563
743
  pre_value: discount.par_value,
564
- product_id: originProduct.id
744
+ product_id: product.id
565
745
  },
566
746
  metadata: {
567
747
  num,
@@ -596,7 +776,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
596
776
  };
597
777
  originProduct = flatItem.originProduct;
598
778
  }
599
- if ((product == null ? void 0 : product.booking_id) && ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every((discount) => discount.id && ["good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
779
+ if ((0, import_entitlementState.isPersistedEntitlementLine)(originProduct, flatItem.type === "main" ? flatItem.product : flatItem.parentProduct) || (product == null ? void 0 : product.booking_id) && ((_e = product.discount_list) == null ? void 0 : _e.length) && ((_f = product == null ? void 0 : product.discount_list) == null ? void 0 : _f.every((discount) => discount.id && ["entitlement_pass", "good_pass", "discount_card", "product_discount_card"].includes(discount.tag || discount.type)))) {
600
780
  if (flatItem.type === "main") {
601
781
  processedProductsMap.set(product._id, [originProduct]);
602
782
  } else {
@@ -608,18 +788,22 @@ var RulesModule = class extends import_BaseModule.BaseModule {
608
788
  return;
609
789
  }
610
790
  const applicableDiscounts = sortedDiscountList.filter((discount) => {
611
- var _a2, _b2;
612
- if ((Number(product.price) <= 0 || !product.price) && !((_a2 = product.discount_list) == null ? void 0 : _a2.length) && (discount.tag || discount.type) === "good_pass")
791
+ var _a2, _b2, _c2, _d2, _e2;
792
+ if ((0, import_entitlementPass.isEntitlementPass)(discount) && (((_a2 = discount.config) == null ? void 0 : _a2.isAvailable) === false || (0, import_entitlementPass.getRemainingEntitlementUses)(discount, entitlementUsageCounts.get(discount.id) || 0, 1) <= 0 || Number((_b2 = discount.config) == null ? void 0 : _b2.maxUsagePerOrder) > 0 && (usedProductIdCounts.get(discount.product_id) || 0) >= Number((_c2 = discount.config) == null ? void 0 : _c2.maxUsagePerOrder)))
793
+ return false;
794
+ if ((Number(product.price) <= 0 || !product.price) && !((_d2 = product.discount_list) == null ? void 0 : _d2.length) && (0, import_entitlementPass.isFullCoveragePass)(discount))
613
795
  return false;
614
- if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.find((n) => {
796
+ if ((Number(product.price) <= 0 || !product.price) && !((_e2 = product.discount_list) == null ? void 0 : _e2.find((n) => {
615
797
  var _a3;
616
798
  return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
617
- })) && (discount.tag || discount.type) !== "good_pass")
799
+ })) && !(0, import_entitlementPass.isFullCoveragePass)(discount))
618
800
  return false;
619
801
  const targetUsedDiscounts = usedDiscounts.get(discount.id);
620
802
  if (targetUsedDiscounts && (discount.tag || discount.type) === "good_pass")
621
803
  return false;
622
804
  const limitedData = discount.limited_relation_product_data;
805
+ if (!limitedData)
806
+ return false;
623
807
  const _tempVar = (flatItem == null ? void 0 : flatItem.type) === "bundle" ? flatItem == null ? void 0 : flatItem.parentProduct : flatItem == null ? void 0 : flatItem.product;
624
808
  const isHolderMatch = this.checkHolderMatch(
625
809
  discount,
@@ -627,12 +811,13 @@ var RulesModule = class extends import_BaseModule.BaseModule {
627
811
  isNeedHolder: isFormSubject && !(_tempVar == null ? void 0 : _tempVar.isNormalProduct),
628
812
  holder_id: (_tempVar == null ? void 0 : _tempVar.holder_id) || product.holder_id
629
813
  },
814
+ flatItem.originProduct,
630
815
  holders
631
816
  );
632
817
  if (!isHolderMatch)
633
818
  return false;
634
819
  let timeLimit = true;
635
- timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (product.startDate || (0, import_dayjs.default)()).format("YYYY-MM-DD HH:mm:ss")).length;
820
+ timeLimit = !!(0, import_utils.filterDiscountListByBookingTime)([discount], (0, import_dayjs.default)(product.startDate || void 0).format("YYYY-MM-DD HH:mm:ss")).length;
636
821
  if (!timeLimit) {
637
822
  return false;
638
823
  }
@@ -652,8 +837,9 @@ var RulesModule = class extends import_BaseModule.BaseModule {
652
837
  }
653
838
  return false;
654
839
  });
655
- const selectedDiscountCard = applicableDiscounts.find((n) => n.isScan && n.isSelected && (n.tag || n.type) !== "good_pass");
656
- const selectedDiscount = selectedDiscountCard || applicableDiscounts[0];
840
+ const selectedDiscountCard = applicableDiscounts.find((n) => n.isScan && n.isSelected && !(0, import_entitlementPass.isFullCoveragePass)(n));
841
+ const explicitlySelected = (options == null ? void 0 : options.isSelected) === true ? applicableDiscounts.find((item) => (0, import_entitlementPass.isEntitlementPass)(item) && String(item.id) === String(options.discountId)) : void 0;
842
+ const selectedDiscount = explicitlySelected || selectedDiscountCard || applicableDiscounts[0];
657
843
  let isManualDiscount = false;
658
844
  if (flatItem.type === "main") {
659
845
  isManualDiscount = typeof product.isManualDiscount === "boolean" ? product.isManualDiscount : product.total != product.origin_total && (product.bundle || []).every((item) => {
@@ -782,10 +968,11 @@ var RulesModule = class extends import_BaseModule.BaseModule {
782
968
  if (applicableDiscounts.length && product.booking_id && typeof selectedDiscount.isManualSelect === "undefined" && !(options == null ? void 0 : options.scan) && !isEditModeAddNewProduct) {
783
969
  return;
784
970
  }
785
- const isNeedSplit = (selectedDiscount.tag || selectedDiscount.type) === "good_pass";
971
+ const isNeedSplit = (0, import_entitlementPass.isFullCoveragePass)(selectedDiscount);
786
972
  const totalQuantity = product.quantity || product.num || 1;
787
- const availableGoodPassCount = applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length;
788
- const splitCount = isNeedSplit ? Math.min(totalQuantity, availableGoodPassCount) : 1;
973
+ const prioritizedDiscounts = [selectedDiscount, ...applicableDiscounts.filter((item) => item !== selectedDiscount)];
974
+ const allocatedPasses = isNeedSplit ? applicableDiscounts.some(import_entitlementPass.isEntitlementPass) ? getFullCoveragePasses(prioritizedDiscounts, totalQuantity) : applicableDiscounts.slice(0, Math.min(totalQuantity, applicableDiscounts.filter((item) => (item.tag || item.type) === "good_pass").length)) : [selectedDiscount];
975
+ const splitCount = allocatedPasses.length;
789
976
  const arr = [];
790
977
  if (flatItem.type === "main") {
791
978
  if (splitCount < totalQuantity && isNeedSplit) {
@@ -796,8 +983,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
796
983
  }));
797
984
  }
798
985
  for (let i = 0; i < splitCount; i++) {
799
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[i];
800
- usedDiscounts.set(selectedDiscount2.id, true);
986
+ const selectedDiscount2 = allocatedPasses[i];
987
+ markDiscountUsed(selectedDiscount2);
801
988
  const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
802
989
  let productOriginTotal = product.origin_total || product.total || 0;
803
990
  if (this.filterDiscountListByType(product.discount_list, "promotion").length && product.origin_total) {
@@ -821,7 +1008,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
821
1008
  amount = new import_decimal.default(product.price).minus(new import_decimal.default(targetProductTotal)).toNumber();
822
1009
  }
823
1010
  const discountType = selectedDiscount2.tag || selectedDiscount2.type;
824
- const isGoodPass = discountType === "good_pass";
1011
+ const isGoodPass = (0, import_entitlementPass.isFullCoveragePass)(selectedDiscount2);
825
1012
  const discountDetail = {
826
1013
  amount,
827
1014
  type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : discountType,
@@ -832,7 +1019,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
832
1019
  resource_id: selectedDiscount2.id,
833
1020
  title: selectedDiscount2.format_title,
834
1021
  original_amount: product.price,
835
- product_id: originProduct.id,
1022
+ product_id: product.id,
836
1023
  percent: selectedDiscount2.par_value
837
1024
  },
838
1025
  // 前端使用的num数量,为了计算优惠金额
@@ -857,7 +1044,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
857
1044
  if (product.isClient) {
858
1045
  arr.push(this.hooks.setProduct(originProduct, {
859
1046
  discount_list: [discountDetail],
860
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
1047
+ price: isGoodPass ? 0 : product.price,
861
1048
  quantity: isNeedSplit ? 1 : product.quantity,
862
1049
  origin_total: (0, import_utils2.getProductOriginTotalPrice)({
863
1050
  product: {
@@ -873,8 +1060,8 @@ var RulesModule = class extends import_BaseModule.BaseModule {
873
1060
  } else {
874
1061
  arr.push(this.hooks.setProduct(originProduct, {
875
1062
  discount_list: this.filterDiscountListByType(product.discount_list, "promotion").concat([discountDetail]),
876
- _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index,
877
- price: selectedDiscount2.tag === "good_pass" ? 0 : product.price,
1063
+ _id: product._id.split("___")[0] + "___" + selectedDiscount2.id + index + ((0, import_entitlementPass.isEntitlementPass)(selectedDiscount2) ? `_${i}` : ""),
1064
+ price: isGoodPass ? 0 : product.price,
878
1065
  quantity: isNeedSplit ? 1 : product.quantity,
879
1066
  total,
880
1067
  origin_total: productOriginTotal,
@@ -889,14 +1076,14 @@ var RulesModule = class extends import_BaseModule.BaseModule {
889
1076
  const discountNum = splitCount;
890
1077
  const normalNum = totalQuantity - discountNum;
891
1078
  for (let i = 0; i < discountNum; i++) {
892
- const selectedDiscount2 = applicableDiscounts[i];
893
- usedDiscounts.set(selectedDiscount2.id, true);
1079
+ const selectedDiscount2 = allocatedPasses[i];
1080
+ markDiscountUsed(selectedDiscount2);
894
1081
  const uniqueId = `${flatItem._id}_split_${i}`;
895
1082
  const discountDetail = {
896
- amount: product.origin_total,
897
- type: "good_pass",
1083
+ amount: product.origin_total || product.price || 0,
1084
+ type: selectedDiscount2.tag || selectedDiscount2.type,
898
1085
  discount: {
899
- fixed_amount: product.origin_total,
1086
+ fixed_amount: product.origin_total || product.price || 0,
900
1087
  discount_calculation_mode: (_z = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _z.discount_calculation_mode,
901
1088
  resource_id: selectedDiscount2.id,
902
1089
  title: selectedDiscount2.format_title,
@@ -940,11 +1127,10 @@ var RulesModule = class extends import_BaseModule.BaseModule {
940
1127
  });
941
1128
  }
942
1129
  } else {
943
- const selectedDiscount2 = selectedDiscountCard || applicableDiscounts[0];
944
- usedDiscounts.set(selectedDiscount2.id, true);
1130
+ usedDiscounts.set(selectedDiscount.id, true);
945
1131
  const productOriginTotal = product.original_price || product.price || 0;
946
- const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount2);
947
- const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount2.id) : null;
1132
+ const isOrderLevel = (0, import_utils.isOrderLevelFixedAmountDiscount)(selectedDiscount);
1133
+ const orderLevelAllocation = isOrderLevel ? orderLevelDiscountAllocations.get(selectedDiscount.id) : null;
948
1134
  const productAllocation = orderLevelAllocation == null ? void 0 : orderLevelAllocation.get(flatItem._id);
949
1135
  let targetProductTotal;
950
1136
  let fixedAmountPerItem;
@@ -955,7 +1141,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
955
1141
  targetProductTotal = Math.max(new import_decimal.default(productOriginTotal).minus(fixedAmountPerItem).toNumber(), 0);
956
1142
  } else {
957
1143
  targetProductTotal = (0, import_utils.getDiscountAmount)(
958
- selectedDiscount2,
1144
+ selectedDiscount,
959
1145
  productOriginTotal,
960
1146
  productOriginTotal
961
1147
  );
@@ -964,30 +1150,30 @@ var RulesModule = class extends import_BaseModule.BaseModule {
964
1150
  const uniqueId = flatItem._id;
965
1151
  const discountDetail = {
966
1152
  amount: fixedAmountPerItem * (product.num || 1),
967
- type: selectedDiscount2.tag === "product_discount_card" ? "discount_card" : selectedDiscount2.tag,
1153
+ type: selectedDiscount.tag === "product_discount_card" ? "discount_card" : selectedDiscount.tag,
968
1154
  discount: {
969
- discount_card_type: (_A = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _A.discount_card_type,
1155
+ discount_card_type: (_A = selectedDiscount == null ? void 0 : selectedDiscount.metadata) == null ? void 0 : _A.discount_card_type,
970
1156
  fixed_amount: fixedAmountPerItem,
971
- discount_calculation_mode: (_B = selectedDiscount2 == null ? void 0 : selectedDiscount2.metadata) == null ? void 0 : _B.discount_calculation_mode,
972
- resource_id: selectedDiscount2.id,
973
- title: selectedDiscount2.format_title,
1157
+ discount_calculation_mode: (_B = selectedDiscount == null ? void 0 : selectedDiscount.metadata) == null ? void 0 : _B.discount_calculation_mode,
1158
+ resource_id: selectedDiscount.id,
1159
+ title: selectedDiscount.format_title,
974
1160
  original_amount: product.original_price,
975
1161
  product_id: product.id,
976
- percent: selectedDiscount2.par_value
1162
+ percent: selectedDiscount.par_value
977
1163
  },
978
1164
  metadata: {
979
1165
  // 🔥 使用唯一的 _id
980
1166
  custom_product_bundle_map_id: uniqueId,
981
- discount_rule_uncheck_flag: selectedDiscount2 == null ? void 0 : selectedDiscount2.discount_rule_uncheck_flag,
1167
+ discount_rule_uncheck_flag: selectedDiscount == null ? void 0 : selectedDiscount.discount_rule_uncheck_flag,
982
1168
  num: product.num || 1,
983
1169
  // 🔥 order_level 分摊差值
984
1170
  ...productDiscountDifference !== void 0 && { product_discount_difference: productDiscountDifference }
985
1171
  },
986
1172
  _num: (product.num || 1) * (((_C = flatItem == null ? void 0 : flatItem.parentProduct) == null ? void 0 : _C.num) || 1)
987
1173
  };
988
- const appliedProducts = appliedDiscountProducts.get(selectedDiscount2.id) || [];
1174
+ const appliedProducts = appliedDiscountProducts.get(selectedDiscount.id) || [];
989
1175
  appliedProducts.push(discountDetail);
990
- appliedDiscountProducts.set(selectedDiscount2.id, appliedProducts);
1176
+ appliedDiscountProducts.set(selectedDiscount.id, appliedProducts);
991
1177
  processedItems.push({
992
1178
  ...flatItem,
993
1179
  total: targetProductTotal,
@@ -1003,7 +1189,31 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1003
1189
  const result = [];
1004
1190
  originalProductList.forEach((originProduct) => {
1005
1191
  const product = this.hooks.getProduct(originProduct);
1192
+ if ((0, import_entitlementState.isPersistedEntitlementLine)(originProduct, product)) {
1193
+ result.push(originProduct);
1194
+ return;
1195
+ }
1006
1196
  const mainProductArr = processedProductsMap2.get(product._id);
1197
+ if ((0, import_entitlementLines.isEntitlementRuntimeLine)(originProduct, product) && !product.isManualDiscount && (mainProductArr == null ? void 0 : mainProductArr.length)) {
1198
+ const bundle = (product.bundle || []).flatMap((item, index) => {
1199
+ const processed = processedFlatItemsMap2.get(`${product._id}_bundle_${index}`);
1200
+ if (!(processed == null ? void 0 : processed.length))
1201
+ return [item];
1202
+ return processed.map((child) => ({
1203
+ ...item,
1204
+ _id: child._id,
1205
+ price: child.price,
1206
+ bundle_selling_price: child.price,
1207
+ num: child.num,
1208
+ discount_list: (child.discount_list || []).map((detail) => ({
1209
+ ...detail,
1210
+ metadata: { ...detail.metadata, num: child.num, custom_product_bundle_map_id: child._id }
1211
+ }))
1212
+ }));
1213
+ });
1214
+ result.push(...mainProductArr.map((item) => (0, import_entitlementLines.rebuildEntitlementLine)(item, bundle, this.hooks)));
1215
+ return;
1216
+ }
1007
1217
  if (!mainProductArr || mainProductArr.length === 0) {
1008
1218
  const getDefaultProduct = () => {
1009
1219
  if (product.isClient) {
@@ -1057,7 +1267,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1057
1267
  (item) => {
1058
1268
  var _a;
1059
1269
  return (_a = item.discount_list) == null ? void 0 : _a.some(
1060
- (discount) => discount.type === "good_pass" || discount.tag === "good_pass"
1270
+ (discount) => (0, import_entitlementPass.isFullCoveragePass)(discount)
1061
1271
  );
1062
1272
  }
1063
1273
  );
@@ -1336,6 +1546,30 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1336
1546
  const applicableProducts = discountApplicability.get(discount.id) || [];
1337
1547
  const applicableProductDetails = discountApplicableProducts.get(discount.id) || [];
1338
1548
  const appliedProductDetails = appliedDiscountProducts.get(discount.id) || [];
1549
+ if ((0, import_entitlementPass.isEntitlementPass)(discount)) {
1550
+ const committed = discount.committedAppliedProductDetails || [];
1551
+ const details = [...committed, ...appliedProductDetails];
1552
+ const isAvailable2 = applicableProducts.length > 0;
1553
+ const timeReasons = entitlementTimeReasons.get(discount.id) || [];
1554
+ const timeReason = timeReasons.length ? timeReasons.every(Boolean) ? timeReasons[0] : void 0 : (0, import_utils3.getDiscountTimeUnavailableReason)(discount, (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss"));
1555
+ const reasonCode = isAvailable2 ? void 0 : discount.reasonCode || timeReason || (entitlementHolderMismatch.has(discount.id) ? "holder_not_matched" : "product_not_applicable");
1556
+ return {
1557
+ ...discount,
1558
+ isAvailable: isAvailable2 || committed.length > 0,
1559
+ isSelected: details.length > 0,
1560
+ isUsed: details.length > 0,
1561
+ reasonCode,
1562
+ reason: reasonCode === discount.reasonCode ? discount.reason : void 0,
1563
+ isManualSelect: (options == null ? void 0 : options.scan) ? false : discount.isManualSelect,
1564
+ applicableProductIds: applicableProducts,
1565
+ applicableProductDetails,
1566
+ appliedProductDetails: details,
1567
+ savedAmount: details.reduce((sum, detail) => {
1568
+ var _a;
1569
+ return new import_decimal.default(sum).plus(new import_decimal.default(((_a = detail.discount) == null ? void 0 : _a.fixed_amount) || 0).mul(detail._num || 1)).toNumber();
1570
+ }, 0)
1571
+ };
1572
+ }
1339
1573
  const isAvailable = applicableProducts.length > 0;
1340
1574
  if (typeof discount.isSelected === "boolean" && discount.isSelected === false && discount.isManualSelect) {
1341
1575
  return {
@@ -1388,7 +1622,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1388
1622
  });
1389
1623
  console.log(processedProductList, "processedProductList");
1390
1624
  return {
1391
- productList: processedProductList,
1625
+ productList: this.entitlementPassEnabled ? (0, import_entitlementLines.finalizeEntitlementLines)(processedProductList, this.hooks) : processedProductList,
1392
1626
  discountList: [...editModeDiscount, ...updatedDiscountList]
1393
1627
  };
1394
1628
  }
@@ -1408,7 +1642,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
1408
1642
  }
1409
1643
  const ruleType = usageRules.type;
1410
1644
  const packageScope = usageRules == null ? void 0 : usageRules.package_scope;
1411
- const { type: scopeType, exclude_bundle_product_ids = [], include_bundle_product_ids = [], filter = 0 } = packageScope || {};
1645
+ const { type: scopeType = "product_all", exclude_bundle_product_ids = [], include_bundle_product_ids = [], filter = 0 } = packageScope || {};
1412
1646
  const isMainProduct = flatItem.type === "main";
1413
1647
  const isBundleItem = flatItem.type === "bundle";
1414
1648
  if (isMainProduct) {