@pisell/pisellos 0.10.49 → 0.10.50

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.
@@ -0,0 +1,9 @@
1
+ // 导出评估器
2
+ export { PromotionEvaluator } from "./evaluator";
3
+
4
+ // 导出适配器
5
+ export { PromotionAdapter } from "./adapter";
6
+ export { default } from "./adapter";
7
+
8
+ // 导出策略配置示例常量
9
+ export { X_ITEMS_FOR_Y_PRICE_STRATEGY, BUY_X_GET_Y_FREE_STRATEGY, ITEM_REWARD_STRATEGY } from "./examples";
@@ -44,6 +44,7 @@ interface ApplicableProductDetails {
44
44
  original_amount: string;
45
45
  num: number;
46
46
  metadata?: {
47
+ encoded?: string;
47
48
  product_discount_difference?: number;
48
49
  /** 月卡扣除本单新增使用后的剩余次数;不限次数时为 null。 */
49
50
  balance?: number | null;
@@ -135,6 +136,7 @@ export interface Discount {
135
136
  available_products_info?: any[];
136
137
  format_title: Formattitle;
137
138
  metadata?: {
139
+ encoded?: string;
138
140
  discount_card_type?: 'fixed_amount' | 'percent';
139
141
  custom_product_bundle_map_id?: string;
140
142
  validity_type?: 'custom_schedule_validity' | 'fixed_validity';
@@ -108,6 +108,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
108
108
  }>;
109
109
  applyDiscount(options?: {
110
110
  reapplyBookingDiscountProductUids?: string[];
111
+ preferredEntitlementPassIds?: number[];
111
112
  }): void;
112
113
  /**
113
114
  * 注入促销评估器。
@@ -210,7 +210,7 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
210
210
  _step2;
211
211
  try {
212
212
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
213
- var _item$type2, _ref, _ref2, _item$discount$resour, _item$discount, _item$discount$title, _item$discount2, _item$discount3, _item$discount$fixed_, _item$discount4, _item$discount5, _item$amount, _ref3, _item$discount$origin, _item$discount6, _ref4, _ref5, _item$metadata$num, _item$metadata, _item$discount$produc, _item$discount7, _ref6, _ref7, _item$metadata$num2, _item$metadata2, _ref8, _item$discount$discou, _item$discount8, _item$amount2, _item$amount3, _product$product_id, _product$is_charge_ta, _ref9, _product$original_pri, _ref10, _item$discount$discou2, _item$discount9, _item$discount$discou3, _item$discount10;
213
+ var _item$type2, _ref, _ref2, _item$discount$resour, _item$discount, _item$discount$title, _item$discount2, _item$metadata, _item$discount3, _item$discount4, _item$discount$fixed_, _item$discount5, _item$discount6, _item$amount, _ref3, _item$discount$origin, _item$discount7, _ref4, _ref5, _item$metadata$num, _item$metadata2, _item$discount$produc, _item$discount8, _ref6, _ref7, _item$metadata$num2, _item$metadata3, _item$discount9, _ref8, _item$discount$discou, _item$discount10, _item$amount2, _item$amount3, _product$product_id, _product$is_charge_ta, _ref9, _product$original_pri, _ref10, _item$discount$discou2, _item$discount11, _item$discount$discou3, _item$discount12;
214
214
  var item = _step2.value;
215
215
  var type = (_item$type2 = item === null || item === void 0 ? void 0 : item.type) !== null && _item$type2 !== void 0 ? _item$type2 : item === null || item === void 0 ? void 0 : item.tag;
216
216
  if (!type || type === 'product') continue;
@@ -221,24 +221,31 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
221
221
  var key = Number.isFinite(id) ? id : String(resourceId);
222
222
  var title = (_item$discount$title = item === null || item === void 0 || (_item$discount2 = item.discount) === null || _item$discount2 === void 0 ? void 0 : _item$discount2.title) !== null && _item$discount$title !== void 0 ? _item$discount$title : {};
223
223
  var amount = Number((item === null || item === void 0 ? void 0 : item.amount) || 0);
224
- var discountCardType = item === null || item === void 0 || (_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.discount_card_type;
225
- var parValue = isDiscountCard ? discountCardType === 'fixed_amount' ? (_item$discount$fixed_ = item === null || item === void 0 || (_item$discount4 = item.discount) === null || _item$discount4 === void 0 ? void 0 : _item$discount4.fixed_amount) !== null && _item$discount$fixed_ !== void 0 ? _item$discount$fixed_ : item === null || item === void 0 ? void 0 : item.amount : item === null || item === void 0 || (_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.percent : '0';
224
+ var encoded = (item === null || item === void 0 || (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.encoded) || (item === null || item === void 0 ? void 0 : item.encoded) || (item === null || item === void 0 || (_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.encoded) || '';
225
+ var discountCardType = item === null || item === void 0 || (_item$discount4 = item.discount) === null || _item$discount4 === void 0 ? void 0 : _item$discount4.discount_card_type;
226
+ var parValue = isDiscountCard ? discountCardType === 'fixed_amount' ? (_item$discount$fixed_ = item === null || item === void 0 || (_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.fixed_amount) !== null && _item$discount$fixed_ !== void 0 ? _item$discount$fixed_ : item === null || item === void 0 ? void 0 : item.amount : item === null || item === void 0 || (_item$discount6 = item.discount) === null || _item$discount6 === void 0 ? void 0 : _item$discount6.percent : '0';
226
227
  var detail = {
227
228
  amount: String((_item$amount = item === null || item === void 0 ? void 0 : item.amount) !== null && _item$amount !== void 0 ? _item$amount : '0'),
228
229
  type: type,
229
230
  resource_id: key,
230
231
  title: title,
231
- original_amount: String((_ref3 = (_item$discount$origin = item === null || item === void 0 || (_item$discount6 = item.discount) === null || _item$discount6 === void 0 ? void 0 : _item$discount6.original_amount) !== null && _item$discount$origin !== void 0 ? _item$discount$origin : item === null || item === void 0 ? void 0 : item.amount) !== null && _ref3 !== void 0 ? _ref3 : '0'),
232
- num: Number((_ref4 = (_ref5 = (_item$metadata$num = item === null || item === void 0 || (_item$metadata = item.metadata) === null || _item$metadata === void 0 ? void 0 : _item$metadata.num) !== null && _item$metadata$num !== void 0 ? _item$metadata$num : product === null || product === void 0 ? void 0 : product.num) !== null && _ref5 !== void 0 ? _ref5 : product === null || product === void 0 ? void 0 : product.product_quantity) !== null && _ref4 !== void 0 ? _ref4 : 1) || 1,
232
+ original_amount: String((_ref3 = (_item$discount$origin = item === null || item === void 0 || (_item$discount7 = item.discount) === null || _item$discount7 === void 0 ? void 0 : _item$discount7.original_amount) !== null && _item$discount$origin !== void 0 ? _item$discount$origin : item === null || item === void 0 ? void 0 : item.amount) !== null && _ref3 !== void 0 ? _ref3 : '0'),
233
+ num: Number((_ref4 = (_ref5 = (_item$metadata$num = item === null || item === void 0 || (_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.num) !== null && _item$metadata$num !== void 0 ? _item$metadata$num : product === null || product === void 0 ? void 0 : product.num) !== null && _ref5 !== void 0 ? _ref5 : product === null || product === void 0 ? void 0 : product.product_quantity) !== null && _ref4 !== void 0 ? _ref4 : 1) || 1,
233
234
  metadata: item === null || item === void 0 ? void 0 : item.metadata,
234
235
  discount: _objectSpread(_objectSpread({}, (item === null || item === void 0 ? void 0 : item.discount) || {}), {}, {
235
- product_id: (_item$discount$produc = item === null || item === void 0 || (_item$discount7 = item.discount) === null || _item$discount7 === void 0 ? void 0 : _item$discount7.product_id) !== null && _item$discount$produc !== void 0 ? _item$discount$produc : product === null || product === void 0 ? void 0 : product.product_id
236
+ product_id: (_item$discount$produc = item === null || item === void 0 || (_item$discount8 = item.discount) === null || _item$discount8 === void 0 ? void 0 : _item$discount8.product_id) !== null && _item$discount$produc !== void 0 ? _item$discount$produc : product === null || product === void 0 ? void 0 : product.product_id
236
237
  }),
237
- _num: Number((_ref6 = (_ref7 = (_item$metadata$num2 = item === null || item === void 0 || (_item$metadata2 = item.metadata) === null || _item$metadata2 === void 0 ? void 0 : _item$metadata2.num) !== null && _item$metadata$num2 !== void 0 ? _item$metadata$num2 : product === null || product === void 0 ? void 0 : product.num) !== null && _ref7 !== void 0 ? _ref7 : product === null || product === void 0 ? void 0 : product.product_quantity) !== null && _ref6 !== void 0 ? _ref6 : 1) || 1
238
+ _num: Number((_ref6 = (_ref7 = (_item$metadata$num2 = item === null || item === void 0 || (_item$metadata3 = item.metadata) === null || _item$metadata3 === void 0 ? void 0 : _item$metadata3.num) !== null && _item$metadata$num2 !== void 0 ? _item$metadata$num2 : product === null || product === void 0 ? void 0 : product.num) !== null && _ref7 !== void 0 ? _ref7 : product === null || product === void 0 ? void 0 : product.product_quantity) !== null && _ref6 !== void 0 ? _ref6 : 1) || 1
238
239
  };
239
240
  var existed = discountMap.get(key);
240
241
  if (existed) {
241
242
  var _existed$limited_rela;
243
+ if (!existed.encoded && encoded) {
244
+ existed.encoded = encoded;
245
+ existed.metadata = _objectSpread(_objectSpread({}, existed.metadata), {}, {
246
+ encoded: encoded
247
+ });
248
+ }
242
249
  existed.amount = Number(existed.amount || 0) + amount;
243
250
  existed.used_par_value = String(Number(existed.used_par_value || 0) + amount);
244
251
  if (!isDiscountCard) {
@@ -257,10 +264,13 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
257
264
  discountMap.set(key, {
258
265
  id: key,
259
266
  product_name: '',
260
- encoded: '',
261
- code: '',
267
+ encoded: encoded,
268
+ code: (item === null || item === void 0 ? void 0 : item.code) || (item === null || item === void 0 || (_item$discount9 = item.discount) === null || _item$discount9 === void 0 ? void 0 : _item$discount9.code) || '',
269
+ metadata: {
270
+ encoded: encoded
271
+ },
262
272
  tag: type,
263
- product_id: (_ref8 = (_item$discount$discou = item === null || item === void 0 || (_item$discount8 = item.discount) === null || _item$discount8 === void 0 ? void 0 : _item$discount8.discount_product_id) !== null && _item$discount$discou !== void 0 ? _item$discount$discou : product === null || product === void 0 ? void 0 : product.product_id) !== null && _ref8 !== void 0 ? _ref8 : 0,
273
+ product_id: (_ref8 = (_item$discount$discou = item === null || item === void 0 || (_item$discount10 = item.discount) === null || _item$discount10 === void 0 ? void 0 : _item$discount10.discount_product_id) !== null && _item$discount$discou !== void 0 ? _item$discount$discou : product === null || product === void 0 ? void 0 : product.product_id) !== null && _ref8 !== void 0 ? _ref8 : 0,
264
274
  relation_type: '',
265
275
  par_value: String(parValue !== null && parValue !== void 0 ? parValue : '0'),
266
276
  used_par_value: String((_item$amount2 = item === null || item === void 0 ? void 0 : item.amount) !== null && _item$amount2 !== void 0 ? _item$amount2 : '0'),
@@ -293,8 +303,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
293
303
  amount: amount,
294
304
  discount: _objectSpread(_objectSpread({}, (item === null || item === void 0 ? void 0 : item.discount) || {}), {}, {
295
305
  resource_id: key,
296
- discount_product_id: (_ref10 = (_item$discount$discou2 = item === null || item === void 0 || (_item$discount9 = item.discount) === null || _item$discount9 === void 0 ? void 0 : _item$discount9.discount_product_id) !== null && _item$discount$discou2 !== void 0 ? _item$discount$discou2 : product === null || product === void 0 ? void 0 : product.product_id) !== null && _ref10 !== void 0 ? _ref10 : 0,
297
- discount_calculation_mode: (_item$discount$discou3 = item === null || item === void 0 || (_item$discount10 = item.discount) === null || _item$discount10 === void 0 ? void 0 : _item$discount10.discount_calculation_mode) !== null && _item$discount$discou3 !== void 0 ? _item$discount$discou3 : 'item_level'
306
+ discount_product_id: (_ref10 = (_item$discount$discou2 = item === null || item === void 0 || (_item$discount11 = item.discount) === null || _item$discount11 === void 0 ? void 0 : _item$discount11.discount_product_id) !== null && _item$discount$discou2 !== void 0 ? _item$discount$discou2 : product === null || product === void 0 ? void 0 : product.product_id) !== null && _ref10 !== void 0 ? _ref10 : 0,
307
+ discount_calculation_mode: (_item$discount$discou3 = item === null || item === void 0 || (_item$discount12 = item.discount) === null || _item$discount12 === void 0 ? void 0 : _item$discount12.discount_calculation_mode) !== null && _item$discount$discou3 !== void 0 ? _item$discount$discou3 : 'item_level'
298
308
  }),
299
309
  applicableProductDetails: [detail],
300
310
  appliedProductDetails: [detail]
@@ -1004,7 +1014,14 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1004
1014
  _context6.next = 31;
1005
1015
  return (_this$store$discount12 = this.store.discount) === null || _this$store$discount12 === void 0 ? void 0 : _this$store$discount12.setDiscountList(normalizedNewDiscountList);
1006
1016
  case 31:
1007
- this.applyDiscount();
1017
+ // 实际写回商品时沿用扫码试算的优先级,避免旧商品行的选卡覆盖本次扫码。
1018
+ this.applyDiscount({
1019
+ preferredEntitlementPassIds: withScanList.filter(function (discount) {
1020
+ return isEntitlementPass(discount);
1021
+ }).map(function (discount) {
1022
+ return discount.id;
1023
+ })
1024
+ });
1008
1025
  _context6.next = 34;
1009
1026
  return this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
1010
1027
  case 34:
@@ -1093,7 +1110,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
1093
1110
  },
1094
1111
  orderTotalAmount: Number(((_this$store$summary2 = this.store.summary) === null || _this$store$summary2 === void 0 ? void 0 : _this$store$summary2.total_amount) || 0)
1095
1112
  }, {
1096
- reapplyBookingDiscountProductUids: options === null || options === void 0 ? void 0 : options.reapplyBookingDiscountProductUids
1113
+ reapplyBookingDiscountProductUids: options === null || options === void 0 ? void 0 : options.reapplyBookingDiscountProductUids,
1114
+ preferredEntitlementPassIds: options === null || options === void 0 ? void 0 : options.preferredEntitlementPassIds
1097
1115
  });
1098
1116
  if (result !== null && result !== void 0 && result.productList) {
1099
1117
  var previousProductsByUid = indexOrderProductsByUid(tempOrder.products);
@@ -5397,8 +5415,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5397
5415
  if (unique_identification_number !== undefined) {
5398
5416
  var targetUid = String(unique_identification_number);
5399
5417
  productIndex = tempOrder.products.findIndex(function (item) {
5400
- var _item$metadata3;
5401
- return String(((_item$metadata3 = item.metadata) === null || _item$metadata3 === void 0 ? void 0 : _item$metadata3.unique_identification_number) || item.unique_identification_number || '') === targetUid;
5418
+ var _item$metadata4;
5419
+ return String(((_item$metadata4 = item.metadata) === null || _item$metadata4 === void 0 ? void 0 : _item$metadata4.unique_identification_number) || item.unique_identification_number || '') === targetUid;
5402
5420
  });
5403
5421
  }
5404
5422
  if (productIndex === -1) {
@@ -5663,8 +5681,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5663
5681
  if (unique_identification_number !== undefined) {
5664
5682
  targetUid = String(unique_identification_number);
5665
5683
  productIndex = tempOrder.products.findIndex(function (item) {
5666
- var _item$metadata4;
5667
- return String(((_item$metadata4 = item.metadata) === null || _item$metadata4 === void 0 ? void 0 : _item$metadata4.unique_identification_number) || item.unique_identification_number || '') === targetUid;
5684
+ var _item$metadata5;
5685
+ return String(((_item$metadata5 = item.metadata) === null || _item$metadata5 === void 0 ? void 0 : _item$metadata5.unique_identification_number) || item.unique_identification_number || '') === targetUid;
5668
5686
  });
5669
5687
  }
5670
5688
  if (productIndex === -1) {
@@ -5853,8 +5871,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5853
5871
  bookingsBeforeRemove = tempOrder.bookings || [];
5854
5872
  preserveDisplayPosition = options === null || options === void 0 ? void 0 : options.preserveDisplayPosition;
5855
5873
  anchorIndex = preserveDisplayPosition ? productsBeforeRemove.findIndex(function (item) {
5856
- var _item$metadata5;
5857
- var uid = ((_item$metadata5 = item.metadata) === null || _item$metadata5 === void 0 ? void 0 : _item$metadata5.unique_identification_number) || item.unique_identification_number;
5874
+ var _item$metadata6;
5875
+ var uid = ((_item$metadata6 = item.metadata) === null || _item$metadata6 === void 0 ? void 0 : _item$metadata6.unique_identification_number) || item.unique_identification_number;
5858
5876
  return uid !== undefined && uid !== null && String(uid) === String(preserveDisplayPosition.anchorProductUid);
5859
5877
  }) : -1;
5860
5878
  productsAfterAnchor = anchorIndex >= 0 ? productsBeforeRemove.slice(anchorIndex + 1) : [];
@@ -5950,8 +5968,8 @@ export var OrderModule = /*#__PURE__*/function (_BaseModule) {
5950
5968
  }
5951
5969
  if (preserveDisplayPosition && anchorIndex >= 0) {
5952
5970
  remainingProductIndex = tempOrder.products.findIndex(function (item) {
5953
- var _item$metadata6;
5954
- var uid = ((_item$metadata6 = item.metadata) === null || _item$metadata6 === void 0 ? void 0 : _item$metadata6.unique_identification_number) || item.unique_identification_number;
5971
+ var _item$metadata7;
5972
+ var uid = ((_item$metadata7 = item.metadata) === null || _item$metadata7 === void 0 ? void 0 : _item$metadata7.unique_identification_number) || item.unique_identification_number;
5955
5973
  return uid !== undefined && uid !== null && String(uid) === String(preserveDisplayPosition.remainingProductUid);
5956
5974
  });
5957
5975
  if (remainingProductIndex >= 0) {
@@ -191,11 +191,17 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
191
191
  unavailableReason: UnavailableReason.AlreadyUsed
192
192
  };
193
193
  }
194
+ var scannedEntitlementPassIds = newDiscountList.filter(function (discount) {
195
+ return isEntitlementPass(discount);
196
+ }).map(function (discount) {
197
+ return discount.id;
198
+ });
199
+ var scannedEntitlementPassIdSet = new Set(scannedEntitlementPassIds.map(String));
194
200
 
195
- // 合并新旧折扣列表,并计算折扣结果,注意,如果旧折扣里有 isEditMode 为 true 的优惠券,则不合并
196
- // 保留之前扫码得到的商品券(isScan: true)
201
+ // 客户次卡必须保留在完整列表中;同一实例以本次扫码数据更新。
202
+ // 历史折扣不参与试算,商品券继续沿用仅保留扫码来源的规则。
197
203
  var filteredOldDiscountList = oldDiscountList.filter(function (discount) {
198
- return !discount.isEditMode && (!isFullCoveragePass(discount) || discount.isScan);
204
+ return !discount.isEditMode && (!isFullCoveragePass(discount) || isEntitlementPass(discount) || discount.isScan) && !scannedEntitlementPassIdSet.has(String(discount.id));
199
205
  });
200
206
  var mergedDiscountList = uniqueById([].concat(_toConsumableArray(filteredOldDiscountList), _toConsumableArray(newDiscountList)));
201
207
  var result = this.calcDiscount({
@@ -205,7 +211,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
205
211
  holders: holders,
206
212
  isFormSubject: isFormSubject
207
213
  }, {
208
- scan: true
214
+ scan: true,
215
+ preferredEntitlementPassIds: scannedEntitlementPassIds
209
216
  });
210
217
 
211
218
  // 检查是否有产品使用了新折扣
@@ -368,6 +375,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
368
375
  holders = _ref8.holders,
369
376
  isFormSubject = _ref8.isFormSubject,
370
377
  orderTotalAmount = _ref8.orderTotalAmount;
378
+ var preferredEntitlementPassIds = new Set(((options === null || options === void 0 ? void 0 : options.preferredEntitlementPassIds) || []).map(String));
371
379
  var resolveIsFormSubject = function resolveIsFormSubject(product) {
372
380
  return typeof isFormSubject === 'function' ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
373
381
  };
@@ -1179,7 +1187,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1179
1187
 
1180
1188
  // 判断优惠券是否适用于该商品
1181
1189
  if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config3 = discount.config) !== null && _discount$config3 !== void 0 && _discount$config3.isAvailable && (!isEntitlementPass(discount) || getRemainingEntitlementUses(discount, 0, 1) > 0)) {
1182
- var _discountApplicabilit, _discount$metadata4, _discount$metadata5;
1190
+ var _discountApplicabilit, _discount$metadata4, _discount$metadata5, _discount$metadata6;
1183
1191
  // 记录此优惠券适用的商品
1184
1192
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
1185
1193
 
@@ -1206,6 +1214,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1206
1214
  discount_product_id: discount.product_id
1207
1215
  },
1208
1216
  metadata: {
1217
+ encoded: ((_discount$metadata6 = discount.metadata) === null || _discount$metadata6 === void 0 ? void 0 : _discount$metadata6.encoded) || discount.encoded,
1209
1218
  num: num,
1210
1219
  discount_rule_uncheck_flag: discount === null || discount === void 0 ? void 0 : discount.discount_rule_uncheck_flag
1211
1220
  }
@@ -1406,7 +1415,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1406
1415
  return false;
1407
1416
  });
1408
1417
 
1409
- // 用户显式点击某张卡券时,本次选择优先于自动排序和扫码默认选择。
1418
+ // 识别用户本次显式选择的卡券,供次卡和折扣卡各自的优先级使用。
1410
1419
  // 目标仍必须在当前商品的 applicableDiscounts 中,因此不会绕过 Holder、时间或商品范围校验。
1411
1420
  var explicitlySelectedDiscount = (options === null || options === void 0 ? void 0 : options.isSelected) === true && options.discountId !== undefined ? applicableDiscounts.find(function (discount) {
1412
1421
  var discountType = discount.tag || discount.type || '';
@@ -1415,10 +1424,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1415
1424
  // 折扣卡会复用于整条商品行;商品券必须继续按单张拆分,不能复用该分支。
1416
1425
  var explicitlySelectedDiscountCard = explicitlySelectedDiscount && !isFullCoveragePass(explicitlySelectedDiscount) ? explicitlySelectedDiscount : undefined;
1417
1426
 
1418
- // 商品数量等变化会触发无 discountId 的重算。只要当前行已应用的折扣卡仍在
1427
+ // 商品数量等变化会触发无 discountId 的重算。只要当前行已应用的卡仍在
1419
1428
  // applicableDiscounts 中,就应保留该行选择,避免被自动排序中力度更大的卡替换。
1420
- var appliedDiscountCardIds = new Set((product.discount_list || []).filter(function (item) {
1421
- 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));
1429
+ var appliedWalletDiscountIds = new Set((product.discount_list || []).filter(function (item) {
1430
+ return ['entitlement_pass', 'discount_card', 'product_discount_card'].includes((item === null || item === void 0 ? void 0 : item.tag) || (item === null || item === void 0 ? void 0 : item.type));
1422
1431
  }).map(function (item) {
1423
1432
  var _ref24, _item$discount$resour, _item$discount;
1424
1433
  return (_ref24 = (_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 && _ref24 !== void 0 ? _ref24 : item === null || item === void 0 ? void 0 : item.id;
@@ -1427,20 +1436,26 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1427
1436
  }).map(String));
1428
1437
  var appliedDiscountCard = options !== null && options !== void 0 && options.scan ? undefined : applicableDiscounts.find(function (discount) {
1429
1438
  var discountType = discount.tag || discount.type || '';
1430
- return discount.isSelected === true && ['discount_card', 'product_discount_card'].includes(discountType) && appliedDiscountCardIds.has(String(discount.id));
1439
+ return discount.isSelected === true && ['discount_card', 'product_discount_card'].includes(discountType) && appliedWalletDiscountIds.has(String(discount.id));
1440
+ });
1441
+ var appliedEntitlementPass = options !== null && options !== void 0 && options.scan || (options === null || options === void 0 ? void 0 : options.preserveEntitlementSelection) === false ? undefined : applicableDiscounts.find(function (discount) {
1442
+ return isEntitlementPass(discount) && discount.isSelected === true && appliedWalletDiscountIds.has(String(discount.id));
1431
1443
  });
1432
1444
 
1433
- // Entitlement Pass 始终按协议优先级使用;没有新卡时沿用原选择优先级。
1445
+ // 次卡内部按本次手选/扫码、当前行已应用、默认排序选择;仍保留次卡相对其他券的优先级。
1434
1446
  var scannedSelectedDiscountCard = applicableDiscounts.find(function (n) {
1435
1447
  return n.isScan && n.isSelected && !isFullCoveragePass(n);
1436
1448
  });
1437
1449
  var selectedDiscountCard = explicitlySelectedDiscountCard || appliedDiscountCard || scannedSelectedDiscountCard;
1438
- var highestPriorityEntitlementPass = applicableDiscounts.find(function (discount) {
1450
+ var selectedEntitlementPass = (explicitlySelectedDiscount && isEntitlementPass(explicitlySelectedDiscount) ? explicitlySelectedDiscount : undefined) || applicableDiscounts.find(function (discount) {
1451
+ return isEntitlementPass(discount) && preferredEntitlementPassIds.has(String(discount.id));
1452
+ }) || appliedEntitlementPass || applicableDiscounts.find(function (discount) {
1439
1453
  return isEntitlementPass(discount);
1440
1454
  });
1441
- var selectedDiscount = highestPriorityEntitlementPass || explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1442
- var prioritizedApplicableDiscounts = !highestPriorityEntitlementPass && explicitlySelectedDiscount && isFullCoveragePass(explicitlySelectedDiscount) ? [explicitlySelectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (discount) {
1443
- return isFullCoveragePass(discount) && String(discount.id) !== String(explicitlySelectedDiscount.id);
1455
+ var selectedDiscount = selectedEntitlementPass || explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1456
+ // 实际次数分配必须使用同一顺序,避免选中状态切换后仍将次数分配给默认卡。
1457
+ var prioritizedApplicableDiscounts = selectedDiscount && isFullCoveragePass(selectedDiscount) ? [selectedDiscount].concat(_toConsumableArray(applicableDiscounts.filter(function (discount) {
1458
+ return isFullCoveragePass(discount) && String(discount.id) !== String(selectedDiscount.id);
1444
1459
  })), _toConsumableArray(applicableDiscounts.filter(function (discount) {
1445
1460
  return !isFullCoveragePass(discount);
1446
1461
  }))) : applicableDiscounts;
@@ -1683,7 +1698,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1683
1698
  count: 1
1684
1699
  }];
1685
1700
  for (var i = 0; i < discountUsageGroups.length; i++) {
1686
- var _originProduct4, _selectedDiscount$con, _product$options, _product$options2, _selectedDiscount$met, _selectedDiscount$met2, _reapplyDiscountPerce;
1701
+ var _originProduct4, _selectedDiscount$con, _product$options, _product$options2, _selectedDiscount$met, _selectedDiscount$met2, _reapplyDiscountPerce, _selectedDiscount$met3;
1687
1702
  var _discountUsageGroups$ = discountUsageGroups[i],
1688
1703
  _selectedDiscount = _discountUsageGroups$.discount,
1689
1704
  appliedUseCount = _discountUsageGroups$.count;
@@ -1773,6 +1788,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1773
1788
  _num: isFullCoverage ? appliedUseCount : product.num,
1774
1789
  config: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.config,
1775
1790
  metadata: _objectSpread(_objectSpread({
1791
+ encoded: ((_selectedDiscount$met3 = _selectedDiscount.metadata) === null || _selectedDiscount$met3 === void 0 ? void 0 : _selectedDiscount$met3.encoded) || _selectedDiscount.encoded,
1776
1792
  num: isFullCoverage ? appliedUseCount : 1,
1777
1793
  discount_rule_uncheck_flag: _selectedDiscount === null || _selectedDiscount === void 0 ? void 0 : _selectedDiscount.discount_rule_uncheck_flag
1778
1794
  }, productDiscountDifference !== undefined && {
@@ -1830,7 +1846,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1830
1846
 
1831
1847
  // 同一卡实例的本次新增使用合并为一条,metadata.num 记录实际次数。
1832
1848
  for (var _i = 0; _i < fullCoveragePassUsageGroups.length; _i++) {
1833
- var _selectedDiscount2$me;
1849
+ var _selectedDiscount2$me, _selectedDiscount2$me2;
1834
1850
  var _fullCoveragePassUsag = fullCoveragePassUsageGroups[_i],
1835
1851
  _selectedDiscount2 = _fullCoveragePassUsag.discount,
1836
1852
  _appliedUseCount = _fullCoveragePassUsag.count;
@@ -1862,6 +1878,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1862
1878
  discount_product_id: _selectedDiscount2.product_id
1863
1879
  },
1864
1880
  metadata: {
1881
+ encoded: ((_selectedDiscount2$me2 = _selectedDiscount2.metadata) === null || _selectedDiscount2$me2 === void 0 ? void 0 : _selectedDiscount2$me2.encoded) || _selectedDiscount2.encoded,
1865
1882
  // 🔥 使用拆分后的唯一 _id
1866
1883
  custom_product_bundle_map_id: uniqueId,
1867
1884
  discount_rule_uncheck_flag: _selectedDiscount2 === null || _selectedDiscount2 === void 0 ? void 0 : _selectedDiscount2.discount_rule_uncheck_flag,
@@ -1901,7 +1918,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1901
1918
  }));
1902
1919
  }
1903
1920
  } else {
1904
- var _selectedDiscount3$me, _selectedDiscount3$me2, _reapplyDiscountPerce2, _flatItem$parentProdu9;
1921
+ var _selectedDiscount3$me, _selectedDiscount3$me2, _reapplyDiscountPerce2, _selectedDiscount3$me3, _flatItem$parentProdu9;
1905
1922
  // 折扣卡:不拆分数量,直接应用
1906
1923
  var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
1907
1924
  markDiscountUsed(_selectedDiscount3);
@@ -1956,6 +1973,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1956
1973
  discount_product_id: _selectedDiscount3.product_id
1957
1974
  },
1958
1975
  metadata: _objectSpread({
1976
+ encoded: ((_selectedDiscount3$me3 = _selectedDiscount3.metadata) === null || _selectedDiscount3$me3 === void 0 ? void 0 : _selectedDiscount3$me3.encoded) || _selectedDiscount3.encoded,
1959
1977
  // 🔥 使用唯一的 _id
1960
1978
  custom_product_bundle_map_id: _uniqueId,
1961
1979
  discount_rule_uncheck_flag: _selectedDiscount3 === null || _selectedDiscount3 === void 0 ? void 0 : _selectedDiscount3.discount_rule_uncheck_flag,
@@ -2133,8 +2151,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2133
2151
 
2134
2152
  // 🔥 更新主商品自己的 discount_list 中的 num(quantity=1)
2135
2153
  var updatedMainDiscountList = mainProductData.discount_list.map(function (discount) {
2136
- var _discount$metadata6, _discount$metadata7;
2137
- if (discount !== null && discount !== void 0 && (_discount$metadata6 = discount.metadata) !== null && _discount$metadata6 !== void 0 && _discount$metadata6.custom_product_bundle_map_id) {
2154
+ var _discount$metadata7, _discount$metadata8;
2155
+ if (discount !== null && discount !== void 0 && (_discount$metadata7 = discount.metadata) !== null && _discount$metadata7 !== void 0 && _discount$metadata7.custom_product_bundle_map_id) {
2138
2156
  // bundle的discount_list保持不变
2139
2157
  return discount;
2140
2158
  }
@@ -2142,7 +2160,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2142
2160
  return _objectSpread(_objectSpread({}, discount), {}, {
2143
2161
  // num: 1,
2144
2162
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2145
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata7 = discount.metadata) === null || _discount$metadata7 === void 0 ? void 0 : _discount$metadata7.custom_product_bundle_map_id,
2163
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata8 = discount.metadata) === null || _discount$metadata8 === void 0 ? void 0 : _discount$metadata8.custom_product_bundle_map_id,
2146
2164
  num: 1
2147
2165
  })
2148
2166
  });
@@ -2207,8 +2225,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2207
2225
 
2208
2226
  // 🔥 更新主商品自己的 discount_list 中的 num(quantity=原quantity-1)
2209
2227
  var updatedMainDiscountListOriginal = mainProductData.discount_list.map(function (discount) {
2210
- var _discount$metadata8, _discount$metadata9;
2211
- if (discount !== null && discount !== void 0 && (_discount$metadata8 = discount.metadata) !== null && _discount$metadata8 !== void 0 && _discount$metadata8.custom_product_bundle_map_id) {
2228
+ var _discount$metadata9, _discount$metadata10;
2229
+ if (discount !== null && discount !== void 0 && (_discount$metadata9 = discount.metadata) !== null && _discount$metadata9 !== void 0 && _discount$metadata9.custom_product_bundle_map_id) {
2212
2230
  // bundle的discount_list保持不变
2213
2231
  return discount;
2214
2232
  }
@@ -2216,7 +2234,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2216
2234
  return _objectSpread(_objectSpread({}, discount), {}, {
2217
2235
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2218
2236
  num: mainProductQuantity - 1,
2219
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata9 = discount.metadata) === null || _discount$metadata9 === void 0 ? void 0 : _discount$metadata9.custom_product_bundle_map_id
2237
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata10 = discount.metadata) === null || _discount$metadata10 === void 0 ? void 0 : _discount$metadata10.custom_product_bundle_map_id
2220
2238
  })
2221
2239
  // num: mainProductQuantity - 1,
2222
2240
  });
@@ -2286,11 +2304,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2286
2304
  var nextBundleSellingPrice = (_ref28 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref28 !== void 0 ? _ref28 : bundleItem.bundle_selling_price;
2287
2305
  // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
2288
2306
  var updatedDiscountList = (item.discount_list || []).map(function (discount) {
2289
- var _discount$metadata10;
2307
+ var _discount$metadata11;
2290
2308
  return _objectSpread(_objectSpread({}, discount), {}, {
2291
2309
  metadata: _objectSpread(_objectSpread({}, discount.metadata), {}, {
2292
2310
  num: item.num,
2293
- custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata10 = discount.metadata) === null || _discount$metadata10 === void 0 ? void 0 : _discount$metadata10.custom_product_bundle_map_id
2311
+ custom_product_bundle_map_id: discount === null || discount === void 0 || (_discount$metadata11 = discount.metadata) === null || _discount$metadata11 === void 0 ? void 0 : _discount$metadata11.custom_product_bundle_map_id
2294
2312
  })
2295
2313
  // num: item.num, // 使用拆分后的 num
2296
2314
  });
@@ -29,6 +29,10 @@ export interface RulesCalcDiscountOptions {
29
29
  discountId?: number;
30
30
  selectedList?: SetDiscountSelectedParams[];
31
31
  scan?: boolean;
32
+ /** 本次扫码优先使用的次卡实例;普通重算不传,继续保留商品行当前选择。 */
33
+ preferredEntitlementPassIds?: number[];
34
+ /** 普通重算保留商品行已应用的次卡;最优选择传 false 恢复自动排序。 */
35
+ preserveEntitlementSelection?: boolean;
32
36
  /** Change time 重报价目标行:允许已选编辑态折扣卡重新应用到这些 booking 商品。 */
33
37
  reapplyBookingDiscountProductUids?: string[];
34
38
  }
@@ -554,7 +554,8 @@ function normalizeProductDiscounts(params) {
554
554
  var title = resolveDiscountTitleWithPercent(discount, locale);
555
555
  var amount = (_ref15 = (_discount$amount2 = discount.amount) !== null && _discount$amount2 !== void 0 ? _discount$amount2 : discount.value) !== null && _ref15 !== void 0 ? _ref15 : discount.discount_amount;
556
556
  var isMarkup = isManualMarkup(discount);
557
- var totalAmount = new Decimal(toMoneyNumber(amount)).mul(quantity);
557
+ var isAggregatedBundleEntitlement = getProductWalletDiscountType(discount) === 'entitlement_pass' && Boolean(getReceiptDiscountBundleMapId(discount));
558
+ var totalAmount = new Decimal(toMoneyNumber(amount)).mul(isAggregatedBundleEntitlement ? 1 : quantity);
558
559
  var formattedAmount = isMarkup ? formatMoney(totalAmount.abs(), currencySymbol) : formatNegativeMoney(totalAmount, currencySymbol);
559
560
  return {
560
561
  item: title,
@@ -654,6 +655,9 @@ function buildProductQuantityPriceText(params) {
654
655
  function resolveDiscountTitleWithPercent(discount, locale) {
655
656
  var _discount$discount2, _discount$discount$di, _discount$discount3;
656
657
  var title = resolveDiscountTitle(discount, locale);
658
+ if (getProductWalletDiscountType(discount) === 'entitlement_pass') {
659
+ return title;
660
+ }
657
661
  var percentRaw = (_discount$discount2 = discount.discount) === null || _discount$discount2 === void 0 ? void 0 : _discount$discount2.percent;
658
662
  var cardType = (_discount$discount$di = (_discount$discount3 = discount.discount) === null || _discount$discount3 === void 0 ? void 0 : _discount$discount3.discount_card_type) !== null && _discount$discount$di !== void 0 ? _discount$discount$di : 'percent';
659
663
  var percent = percentRaw !== undefined && percentRaw !== null ? Math.trunc(Number(percentRaw)) : NaN;
@@ -1738,9 +1742,8 @@ function getProductEntitlementBalance(asset) {
1738
1742
  _step6;
1739
1743
  try {
1740
1744
  for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
1741
- var _record$metadata, _record$discount10, _record$discount11;
1742
1745
  var record = _step6.value;
1743
- var balance = getEntitlementBalance((_record$metadata = record.metadata) === null || _record$metadata === void 0 ? void 0 : _record$metadata.balance, record.balance, (_record$discount10 = record.discount) === null || _record$discount10 === void 0 || (_record$discount10 = _record$discount10.metadata) === null || _record$discount10 === void 0 ? void 0 : _record$discount10.balance, (_record$discount11 = record.discount) === null || _record$discount11 === void 0 ? void 0 : _record$discount11.balance);
1746
+ var balance = getProductDiscountEntitlementBalance(record);
1744
1747
  if (balance) return balance;
1745
1748
  }
1746
1749
  } catch (err) {
@@ -1750,6 +1753,10 @@ function getProductEntitlementBalance(asset) {
1750
1753
  }
1751
1754
  return null;
1752
1755
  }
1756
+ function getProductDiscountEntitlementBalance(record) {
1757
+ var _record$metadata, _record$discount10, _record$discount11;
1758
+ return getEntitlementBalance((_record$metadata = record.metadata) === null || _record$metadata === void 0 ? void 0 : _record$metadata.balance, record.balance, (_record$discount10 = record.discount) === null || _record$discount10 === void 0 || (_record$discount10 = _record$discount10.metadata) === null || _record$discount10 === void 0 ? void 0 : _record$discount10.balance, (_record$discount11 = record.discount) === null || _record$discount11 === void 0 ? void 0 : _record$discount11.balance);
1759
+ }
1753
1760
  function getEntitlementBalance() {
1754
1761
  for (var _len3 = arguments.length, values = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
1755
1762
  values[_key3] = arguments[_key3];
@@ -3302,6 +3302,8 @@ export var BaseSalesImpl = /*#__PURE__*/function (_BaseModule) {
3302
3302
  return resolveIsFormSubject(tempOrder, product);
3303
3303
  },
3304
3304
  orderTotalAmount: orderTotalAmount
3305
+ }, {
3306
+ preserveEntitlementSelection: false
3305
3307
  }) || result;
3306
3308
  if (result.productList) {
3307
3309
  tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
@@ -44,6 +44,7 @@ interface ApplicableProductDetails {
44
44
  original_amount: string;
45
45
  num: number;
46
46
  metadata?: {
47
+ encoded?: string;
47
48
  product_discount_difference?: number;
48
49
  /** 月卡扣除本单新增使用后的剩余次数;不限次数时为 null。 */
49
50
  balance?: number | null;
@@ -135,6 +136,7 @@ export interface Discount {
135
136
  available_products_info?: any[];
136
137
  format_title: Formattitle;
137
138
  metadata?: {
139
+ encoded?: string;
138
140
  discount_card_type?: 'fixed_amount' | 'percent';
139
141
  custom_product_bundle_map_id?: string;
140
142
  validity_type?: 'custom_schedule_validity' | 'fixed_validity';
@@ -108,6 +108,7 @@ export declare class OrderModule extends BaseModule implements Module, OrderModu
108
108
  }>;
109
109
  applyDiscount(options?: {
110
110
  reapplyBookingDiscountProductUids?: string[];
111
+ preferredEntitlementPassIds?: number[];
111
112
  }): void;
112
113
  /**
113
114
  * 注入促销评估器。
@@ -168,6 +168,7 @@ class OrderModule extends _BaseModule.BaseModule {
168
168
  const key = Number.isFinite(id) ? id : String(resourceId);
169
169
  const title = item?.discount?.title ?? {};
170
170
  const amount = Number(item?.amount || 0);
171
+ const encoded = item?.metadata?.encoded || item?.encoded || item?.discount?.encoded || '';
171
172
  const discountCardType = item?.discount?.discount_card_type;
172
173
  const parValue = isDiscountCard ? discountCardType === 'fixed_amount' ? item?.discount?.fixed_amount ?? item?.amount : item?.discount?.percent : '0';
173
174
  const detail = {
@@ -186,6 +187,13 @@ class OrderModule extends _BaseModule.BaseModule {
186
187
  };
187
188
  const existed = discountMap.get(key);
188
189
  if (existed) {
190
+ if (!existed.encoded && encoded) {
191
+ existed.encoded = encoded;
192
+ existed.metadata = {
193
+ ...existed.metadata,
194
+ encoded
195
+ };
196
+ }
189
197
  existed.amount = Number(existed.amount || 0) + amount;
190
198
  existed.used_par_value = String(Number(existed.used_par_value || 0) + amount);
191
199
  if (!isDiscountCard) {
@@ -205,8 +213,11 @@ class OrderModule extends _BaseModule.BaseModule {
205
213
  discountMap.set(key, {
206
214
  id: key,
207
215
  product_name: '',
208
- encoded: '',
209
- code: '',
216
+ encoded,
217
+ code: item?.code || item?.discount?.code || '',
218
+ metadata: {
219
+ encoded
220
+ },
210
221
  tag: type,
211
222
  product_id: item?.discount?.discount_product_id ?? product?.product_id ?? 0,
212
223
  relation_type: '',
@@ -728,7 +739,10 @@ class OrderModule extends _BaseModule.BaseModule {
728
739
  let resolvedDiscountList = normalizedNewDiscountList || this.getDiscountList();
729
740
  if (isAvailable && normalizedNewDiscountList) {
730
741
  await this.store.discount?.setDiscountList(normalizedNewDiscountList);
731
- this.applyDiscount();
742
+ // 实际写回商品时沿用扫码试算的优先级,避免旧商品行的选卡覆盖本次扫码。
743
+ this.applyDiscount({
744
+ preferredEntitlementPassIds: withScanList.filter(discount => (0, _entitlementPass.isEntitlementPass)(discount)).map(discount => discount.id)
745
+ });
732
746
  await this.syncScannedDiscountsToOriginalDiscountList(this.getDiscountList());
733
747
  resolvedDiscountList = this.getDiscountList();
734
748
  } else if (shouldRetainForLater) {
@@ -786,7 +800,8 @@ class OrderModule extends _BaseModule.BaseModule {
786
800
  isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
787
801
  orderTotalAmount: Number(this.store.summary?.total_amount || 0)
788
802
  }, {
789
- reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids
803
+ reapplyBookingDiscountProductUids: options?.reapplyBookingDiscountProductUids,
804
+ preferredEntitlementPassIds: options?.preferredEntitlementPassIds
790
805
  });
791
806
  if (result?.productList) {
792
807
  const previousProductsByUid = (0, _utils.indexOrderProductsByUid)(tempOrder.products);
@@ -104,10 +104,12 @@ class RulesModule extends _BaseModule.BaseModule {
104
104
  unavailableReason: _types.UnavailableReason.AlreadyUsed
105
105
  };
106
106
  }
107
+ const scannedEntitlementPassIds = newDiscountList.filter(discount => (0, _entitlementPass.isEntitlementPass)(discount)).map(discount => discount.id);
108
+ const scannedEntitlementPassIdSet = new Set(scannedEntitlementPassIds.map(String));
107
109
 
108
- // 合并新旧折扣列表,并计算折扣结果,注意,如果旧折扣里有 isEditMode 为 true 的优惠券,则不合并
109
- // 保留之前扫码得到的商品券(isScan: true)
110
- const filteredOldDiscountList = oldDiscountList.filter(discount => !discount.isEditMode && (!(0, _entitlementPass.isFullCoveragePass)(discount) || discount.isScan));
110
+ // 客户次卡必须保留在完整列表中;同一实例以本次扫码数据更新。
111
+ // 历史折扣不参与试算,商品券继续沿用仅保留扫码来源的规则。
112
+ const filteredOldDiscountList = oldDiscountList.filter(discount => !discount.isEditMode && (!(0, _entitlementPass.isFullCoveragePass)(discount) || (0, _entitlementPass.isEntitlementPass)(discount) || discount.isScan) && !scannedEntitlementPassIdSet.has(String(discount.id)));
111
113
  const mergedDiscountList = (0, _utils.uniqueById)([...filteredOldDiscountList, ...newDiscountList]);
112
114
  const result = this.calcDiscount({
113
115
  discountList: mergedDiscountList,
@@ -116,7 +118,8 @@ class RulesModule extends _BaseModule.BaseModule {
116
118
  holders,
117
119
  isFormSubject
118
120
  }, {
119
- scan: true
121
+ scan: true,
122
+ preferredEntitlementPassIds: scannedEntitlementPassIds
120
123
  });
121
124
 
122
125
  // 检查是否有产品使用了新折扣
@@ -216,6 +219,7 @@ class RulesModule extends _BaseModule.BaseModule {
216
219
  isFormSubject,
217
220
  orderTotalAmount
218
221
  }, options) {
222
+ const preferredEntitlementPassIds = new Set((options?.preferredEntitlementPassIds || []).map(String));
219
223
  const resolveIsFormSubject = product => typeof isFormSubject === 'function' ? Boolean(isFormSubject(product)) : Boolean(isFormSubject);
220
224
 
221
225
  // 识别出来是不是在编辑的界面里又新增了商品
@@ -969,6 +973,7 @@ class RulesModule extends _BaseModule.BaseModule {
969
973
  discount_product_id: discount.product_id
970
974
  },
971
975
  metadata: {
976
+ encoded: discount.metadata?.encoded || discount.encoded,
972
977
  num: num,
973
978
  discount_rule_uncheck_flag: discount?.discount_rule_uncheck_flag
974
979
  }
@@ -1164,7 +1169,7 @@ class RulesModule extends _BaseModule.BaseModule {
1164
1169
  return false;
1165
1170
  });
1166
1171
 
1167
- // 用户显式点击某张卡券时,本次选择优先于自动排序和扫码默认选择。
1172
+ // 识别用户本次显式选择的卡券,供次卡和折扣卡各自的优先级使用。
1168
1173
  // 目标仍必须在当前商品的 applicableDiscounts 中,因此不会绕过 Holder、时间或商品范围校验。
1169
1174
  const explicitlySelectedDiscount = options?.isSelected === true && options.discountId !== undefined ? applicableDiscounts.find(discount => {
1170
1175
  const discountType = discount.tag || discount.type || '';
@@ -1173,21 +1178,23 @@ class RulesModule extends _BaseModule.BaseModule {
1173
1178
  // 折扣卡会复用于整条商品行;商品券必须继续按单张拆分,不能复用该分支。
1174
1179
  const explicitlySelectedDiscountCard = explicitlySelectedDiscount && !(0, _entitlementPass.isFullCoveragePass)(explicitlySelectedDiscount) ? explicitlySelectedDiscount : undefined;
1175
1180
 
1176
- // 商品数量等变化会触发无 discountId 的重算。只要当前行已应用的折扣卡仍在
1181
+ // 商品数量等变化会触发无 discountId 的重算。只要当前行已应用的卡仍在
1177
1182
  // applicableDiscounts 中,就应保留该行选择,避免被自动排序中力度更大的卡替换。
1178
- const appliedDiscountCardIds = new Set((product.discount_list || []).filter(item => ['discount_card', 'product_discount_card'].includes(item?.tag || item?.type)).map(item => item?.discount?.resource_id ?? item?.resource_id ?? item?.id).filter(id => id !== undefined && id !== null).map(String));
1183
+ const appliedWalletDiscountIds = new Set((product.discount_list || []).filter(item => ['entitlement_pass', 'discount_card', 'product_discount_card'].includes(item?.tag || item?.type)).map(item => item?.discount?.resource_id ?? item?.resource_id ?? item?.id).filter(id => id !== undefined && id !== null).map(String));
1179
1184
  const appliedDiscountCard = options?.scan ? undefined : applicableDiscounts.find(discount => {
1180
1185
  const discountType = discount.tag || discount.type || '';
1181
- return discount.isSelected === true && ['discount_card', 'product_discount_card'].includes(discountType) && appliedDiscountCardIds.has(String(discount.id));
1186
+ return discount.isSelected === true && ['discount_card', 'product_discount_card'].includes(discountType) && appliedWalletDiscountIds.has(String(discount.id));
1182
1187
  });
1188
+ const appliedEntitlementPass = options?.scan || options?.preserveEntitlementSelection === false ? undefined : applicableDiscounts.find(discount => (0, _entitlementPass.isEntitlementPass)(discount) && discount.isSelected === true && appliedWalletDiscountIds.has(String(discount.id)));
1183
1189
 
1184
- // Entitlement Pass 始终按协议优先级使用;没有新卡时沿用原选择优先级。
1190
+ // 次卡内部按本次手选/扫码、当前行已应用、默认排序选择;仍保留次卡相对其他券的优先级。
1185
1191
  const scannedSelectedDiscountCard = applicableDiscounts.find(n => n.isScan && n.isSelected && !(0, _entitlementPass.isFullCoveragePass)(n));
1186
1192
  const selectedDiscountCard = explicitlySelectedDiscountCard || appliedDiscountCard || scannedSelectedDiscountCard;
1187
- const highestPriorityEntitlementPass = applicableDiscounts.find(discount => (0, _entitlementPass.isEntitlementPass)(discount));
1188
- const selectedDiscount = highestPriorityEntitlementPass || explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1189
- const prioritizedApplicableDiscounts = !highestPriorityEntitlementPass && explicitlySelectedDiscount && (0, _entitlementPass.isFullCoveragePass)(explicitlySelectedDiscount) ? [explicitlySelectedDiscount, ...applicableDiscounts.filter(discount => {
1190
- return (0, _entitlementPass.isFullCoveragePass)(discount) && String(discount.id) !== String(explicitlySelectedDiscount.id);
1193
+ const selectedEntitlementPass = (explicitlySelectedDiscount && (0, _entitlementPass.isEntitlementPass)(explicitlySelectedDiscount) ? explicitlySelectedDiscount : undefined) || applicableDiscounts.find(discount => (0, _entitlementPass.isEntitlementPass)(discount) && preferredEntitlementPassIds.has(String(discount.id))) || appliedEntitlementPass || applicableDiscounts.find(discount => (0, _entitlementPass.isEntitlementPass)(discount));
1194
+ const selectedDiscount = selectedEntitlementPass || explicitlySelectedDiscount || selectedDiscountCard || applicableDiscounts[0];
1195
+ // 实际次数分配必须使用同一顺序,避免选中状态切换后仍将次数分配给默认卡。
1196
+ const prioritizedApplicableDiscounts = selectedDiscount && (0, _entitlementPass.isFullCoveragePass)(selectedDiscount) ? [selectedDiscount, ...applicableDiscounts.filter(discount => {
1197
+ return (0, _entitlementPass.isFullCoveragePass)(discount) && String(discount.id) !== String(selectedDiscount.id);
1191
1198
  }), ...applicableDiscounts.filter(discount => !(0, _entitlementPass.isFullCoveragePass)(discount))] : applicableDiscounts;
1192
1199
 
1193
1200
  // 如果是手动折扣,则不适用优惠券
@@ -1461,6 +1468,7 @@ class RulesModule extends _BaseModule.BaseModule {
1461
1468
  _num: isFullCoverage ? appliedUseCount : product.num,
1462
1469
  config: selectedDiscount?.config,
1463
1470
  metadata: {
1471
+ encoded: selectedDiscount.metadata?.encoded || selectedDiscount.encoded,
1464
1472
  num: isFullCoverage ? appliedUseCount : 1,
1465
1473
  discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
1466
1474
  // 🔥 order_level 分摊差值
@@ -1551,6 +1559,7 @@ class RulesModule extends _BaseModule.BaseModule {
1551
1559
  discount_product_id: selectedDiscount.product_id
1552
1560
  },
1553
1561
  metadata: {
1562
+ encoded: selectedDiscount.metadata?.encoded || selectedDiscount.encoded,
1554
1563
  // 🔥 使用拆分后的唯一 _id
1555
1564
  custom_product_bundle_map_id: uniqueId,
1556
1565
  discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
@@ -1646,6 +1655,7 @@ class RulesModule extends _BaseModule.BaseModule {
1646
1655
  discount_product_id: selectedDiscount.product_id
1647
1656
  },
1648
1657
  metadata: {
1658
+ encoded: selectedDiscount.metadata?.encoded || selectedDiscount.encoded,
1649
1659
  // 🔥 使用唯一的 _id
1650
1660
  custom_product_bundle_map_id: uniqueId,
1651
1661
  discount_rule_uncheck_flag: selectedDiscount?.discount_rule_uncheck_flag,
@@ -29,6 +29,10 @@ export interface RulesCalcDiscountOptions {
29
29
  discountId?: number;
30
30
  selectedList?: SetDiscountSelectedParams[];
31
31
  scan?: boolean;
32
+ /** 本次扫码优先使用的次卡实例;普通重算不传,继续保留商品行当前选择。 */
33
+ preferredEntitlementPassIds?: number[];
34
+ /** 普通重算保留商品行已应用的次卡;最优选择传 false 恢复自动排序。 */
35
+ preserveEntitlementSelection?: boolean;
32
36
  /** Change time 重报价目标行:允许已选编辑态折扣卡重新应用到这些 booking 商品。 */
33
37
  reapplyBookingDiscountProductUids?: string[];
34
38
  }
@@ -527,7 +527,8 @@ function normalizeProductDiscounts(params) {
527
527
  const title = resolveDiscountTitleWithPercent(discount, locale);
528
528
  const amount = discount.amount ?? discount.value ?? discount.discount_amount;
529
529
  const isMarkup = isManualMarkup(discount);
530
- const totalAmount = new _decimal.default(toMoneyNumber(amount)).mul(quantity);
530
+ const isAggregatedBundleEntitlement = getProductWalletDiscountType(discount) === 'entitlement_pass' && Boolean(getReceiptDiscountBundleMapId(discount));
531
+ const totalAmount = new _decimal.default(toMoneyNumber(amount)).mul(isAggregatedBundleEntitlement ? 1 : quantity);
531
532
  const formattedAmount = isMarkup ? formatMoney(totalAmount.abs(), currencySymbol) : formatNegativeMoney(totalAmount, currencySymbol);
532
533
  return {
533
534
  item: title,
@@ -620,6 +621,9 @@ function buildProductQuantityPriceText(params) {
620
621
  }
621
622
  function resolveDiscountTitleWithPercent(discount, locale) {
622
623
  const title = resolveDiscountTitle(discount, locale);
624
+ if (getProductWalletDiscountType(discount) === 'entitlement_pass') {
625
+ return title;
626
+ }
623
627
  const percentRaw = discount.discount?.percent;
624
628
  const cardType = discount.discount?.discount_card_type ?? 'percent';
625
629
  const percent = percentRaw !== undefined && percentRaw !== null ? Math.trunc(Number(percentRaw)) : NaN;
@@ -1591,11 +1595,14 @@ function getProductWalletDiscountTime(asset) {
1591
1595
  }
1592
1596
  function getProductEntitlementBalance(asset) {
1593
1597
  for (const record of asset.records) {
1594
- const balance = getEntitlementBalance(record.metadata?.balance, record.balance, record.discount?.metadata?.balance, record.discount?.balance);
1598
+ const balance = getProductDiscountEntitlementBalance(record);
1595
1599
  if (balance) return balance;
1596
1600
  }
1597
1601
  return null;
1598
1602
  }
1603
+ function getProductDiscountEntitlementBalance(record) {
1604
+ return getEntitlementBalance(record.metadata?.balance, record.balance, record.discount?.metadata?.balance, record.discount?.balance);
1605
+ }
1599
1606
  function getEntitlementBalance(...values) {
1600
1607
  for (const value of values) {
1601
1608
  if (!isNumericAmount(value)) continue;
@@ -2111,6 +2111,8 @@ class BaseSalesImpl extends _BaseModule.BaseModule {
2111
2111
  holders: [],
2112
2112
  isFormSubject: product => (0, _utils.resolveIsFormSubject)(tempOrder, product),
2113
2113
  orderTotalAmount
2114
+ }, {
2115
+ preserveEntitlementSelection: false
2114
2116
  }) || result;
2115
2117
  if (result.productList) {
2116
2118
  tempOrder.products = preserveManualProductDiscountProducts(tempOrder.products, result.productList);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.10.49",
4
+ "version": "0.10.50",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",