@pisell/pisellos 2.3.148 → 2.3.150

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.
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
49
49
  getCategories(): ProductCategory[];
50
50
  setOtherParams(key: string, value: any): void;
51
51
  getOtherParams(): any;
52
- getProductType(): "normal" | "duration" | "session";
52
+ getProductType(): "duration" | "normal" | "session";
53
53
  }
@@ -1129,6 +1129,30 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1129
1129
  // 记录已应用优惠券的商品信息
1130
1130
  var appliedDiscountProducts = new Map();
1131
1131
 
1132
+ // 可用性和实际应用共用金额判断;零基础价商品可按策略抵扣收费 option。
1133
+ var isDiscountCardPriceAvailable = function isDiscountCardPriceAvailable(flatItem, discount) {
1134
+ var _product$discount_lis2, _discount$config3;
1135
+ var product = flatItem.type === 'main' ? flatItem.product : flatItem.bundleItem;
1136
+ if (!(Number(flatItem.price) <= 0 || !flatItem.price) || (_product$discount_lis2 = product.discount_list) !== null && _product$discount_lis2 !== void 0 && _product$discount_lis2.some(function (item) {
1137
+ var _item$discount;
1138
+ return ((_item$discount = item.discount) === null || _item$discount === void 0 ? void 0 : _item$discount.resource_id) === discount.id;
1139
+ })) {
1140
+ return true;
1141
+ }
1142
+ if (flatItem.type !== 'main' || Number(flatItem.price) !== 0 || !['discount_card', 'product_discount_card'].includes(discount.tag || discount.type || '') || !((_discount$config3 = discount.config) !== null && _discount$config3 !== void 0 && _discount$config3.deductOptionPrice) || isOrderLevelFixedAmountDiscount(discount)) {
1143
+ return false;
1144
+ }
1145
+ return (product.options || []).reduce(function (total, option) {
1146
+ var _ref19, _ref20, _ref21, _option$_original_pri, _ref22, _option$num;
1147
+ var unitPrice = Number((_ref19 = (_ref20 = (_ref21 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref21 !== void 0 ? _ref21 : option.price) !== null && _ref20 !== void 0 ? _ref20 : option.add_price) !== null && _ref19 !== void 0 ? _ref19 : 0);
1148
+ var quantity = Number((_ref22 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref22 !== void 0 ? _ref22 : 1);
1149
+ if (!Number.isFinite(unitPrice) || !Number.isFinite(quantity) || quantity <= 0) {
1150
+ return total;
1151
+ }
1152
+ return total.plus(new Decimal(unitPrice).mul(quantity));
1153
+ }, new Decimal(0)).greaterThan(0);
1154
+ };
1155
+
1132
1156
  // 首先遍历所有商品和所有优惠券,确定每个优惠券的适用范围,包括isSelected为false的优惠券
1133
1157
  // 🔥 使用扁平化后的列表,包含主商品和bundle子商品
1134
1158
  sortedFlattenedList.forEach(function (flatItem) {
@@ -1156,7 +1180,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1156
1180
  }
1157
1181
  var isItemRewardProductDiscount = _this4.isItemRewardProductDiscount(product);
1158
1182
  addModeDiscount.forEach(function (discount) {
1159
- var _product5, _product6, _product7, _product8, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config3;
1183
+ var _product5, _product6, _product7, _product8, _flatItem$bundleItem3, _flatItem$bundleItem4, _discount$config4;
1160
1184
  var limitedData = discount === null || discount === void 0 ? void 0 : discount.limited_relation_product_data;
1161
1185
  // 拿到discount配置的holder信息 product信息 product.holder 加在 isLimitedProduct
1162
1186
  var _tempVar = (flatItem === null || flatItem === void 0 ? void 0 : flatItem.type) === 'bundle' ? flatItem === null || flatItem === void 0 ? void 0 : flatItem.parentProduct : flatItem === null || flatItem === void 0 ? void 0 : flatItem.product;
@@ -1187,7 +1211,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1187
1211
  }
1188
1212
 
1189
1213
  // 判断优惠券是否适用于该商品
1190
- 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)) {
1214
+ if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && (_discount$config4 = discount.config) !== null && _discount$config4 !== void 0 && _discount$config4.isAvailable && (isFullCoveragePass(discount) || isDiscountCardPriceAvailable(flatItem, discount)) && (!isEntitlementPass(discount) || getRemainingEntitlementUses(discount, 0, 1) > 0)) {
1191
1215
  var _discountApplicabilit, _discount$metadata4, _discount$metadata5, _discount$metadata6;
1192
1216
  // 记录此优惠券适用的商品
1193
1217
  (_discountApplicabilit = discountApplicability.get(discount.id)) === null || _discountApplicabilit === void 0 || _discountApplicabilit.push(product.id);
@@ -1237,20 +1261,20 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1237
1261
  };
1238
1262
  var optionDiscountAmount = 0;
1239
1263
  var discountedOptions = options.map(function (option) {
1240
- var _ref19, _ref20, _option$_original_pri, _ref21, _option$num, _rest$price, _option$_original_pri2;
1264
+ var _ref23, _ref24, _option$_original_pri2, _ref25, _option$num2, _rest$price, _option$_original_pri3;
1241
1265
  // 折前单价:优先 price,缺失再 add_price;已写回折后价时用 _original_price(或旧字段 _original_add_price)
1242
- var rawUnit = (_ref19 = (_ref20 = (_option$_original_pri = option._original_price) !== null && _option$_original_pri !== void 0 ? _option$_original_pri : option._original_add_price) !== null && _ref20 !== void 0 ? _ref20 : option.price) !== null && _ref19 !== void 0 ? _ref19 : option.add_price;
1266
+ var rawUnit = (_ref23 = (_ref24 = (_option$_original_pri2 = option._original_price) !== null && _option$_original_pri2 !== void 0 ? _option$_original_pri2 : option._original_add_price) !== null && _ref24 !== void 0 ? _ref24 : option.price) !== null && _ref23 !== void 0 ? _ref23 : option.add_price;
1243
1267
  var baseUnitNum = Number(rawUnit !== null && rawUnit !== void 0 ? rawUnit : 0);
1244
1268
  if (baseUnitNum <= 0) return option;
1245
1269
  var discountedPrice = getDiscountAmount(discount, baseUnitNum, baseUnitNum);
1246
- var optQty = Number((_ref21 = (_option$num = option.num) !== null && _option$num !== void 0 ? _option$num : option.quantity) !== null && _ref21 !== void 0 ? _ref21 : 1);
1270
+ var optQty = Number((_ref25 = (_option$num2 = option.num) !== null && _option$num2 !== void 0 ? _option$num2 : option.quantity) !== null && _ref25 !== void 0 ? _ref25 : 1);
1247
1271
  optionDiscountAmount = new Decimal(optionDiscountAmount).plus(new Decimal(baseUnitNum).minus(discountedPrice).mul(optQty)).toNumber();
1248
1272
  var _original_add_price = option._original_add_price,
1249
1273
  rest = _objectWithoutProperties(option, _excluded);
1250
1274
  var tmpl = (_rest$price = rest.price) !== null && _rest$price !== void 0 ? _rest$price : rest.add_price;
1251
1275
  var nextPrice = typeof tmpl === 'string' ? String(discountedPrice) : discountedPrice;
1252
1276
  return _objectSpread(_objectSpread({}, rest), {}, {
1253
- _original_price: (_option$_original_pri2 = option._original_price) !== null && _option$_original_pri2 !== void 0 ? _option$_original_pri2 : _original_add_price !== undefined ? _original_add_price : rawUnit,
1277
+ _original_price: (_option$_original_pri3 = option._original_price) !== null && _option$_original_pri3 !== void 0 ? _option$_original_pri3 : _original_add_price !== undefined ? _original_add_price : rawUnit,
1254
1278
  price: nextPrice
1255
1279
  });
1256
1280
  });
@@ -1277,9 +1301,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1277
1301
  var getOptionTotal = function getOptionTotal(options) {
1278
1302
  if (!(options !== null && options !== void 0 && options.length)) return 0;
1279
1303
  return options.reduce(function (sum, opt) {
1280
- var _ref22, _opt$price, _ref23, _opt$num;
1281
- var unit = Number((_ref22 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref22 !== void 0 ? _ref22 : 0);
1282
- var n = Number((_ref23 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref23 !== void 0 ? _ref23 : 1);
1304
+ var _ref26, _opt$price, _ref27, _opt$num;
1305
+ var unit = Number((_ref26 = (_opt$price = opt.price) !== null && _opt$price !== void 0 ? _opt$price : opt.add_price) !== null && _ref26 !== void 0 ? _ref26 : 0);
1306
+ var n = Number((_ref27 = (_opt$num = opt.num) !== null && _opt$num !== void 0 ? _opt$num : opt.quantity) !== null && _ref27 !== void 0 ? _ref27 : 1);
1283
1307
  return new Decimal(sum).plus(new Decimal(unit).mul(n)).toNumber();
1284
1308
  }, 0);
1285
1309
  };
@@ -1287,7 +1311,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1287
1311
  // 然后再处理应用哪些优惠券,此时只考虑filteredDiscountList中的优惠券
1288
1312
  // 🔥 使用扁平化后的列表进行处理
1289
1313
  sortedFlattenedList.forEach(function (flatItem, index) {
1290
- var _product9, _originProduct, _originProduct2, _originProduct3, _product$discount_lis2, _product10;
1314
+ var _product9, _originProduct, _originProduct2, _originProduct3, _product$discount_lis3, _product10;
1291
1315
  // 获取商品数据
1292
1316
  var product, originProduct;
1293
1317
  if (flatItem.type === 'main') {
@@ -1312,7 +1336,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1312
1336
  originProduct = flatItem.originProduct;
1313
1337
  }
1314
1338
  var isPersistedProduct = ((_product9 = product) === null || _product9 === void 0 ? void 0 : _product9.booking_id) || ((_originProduct = originProduct) === null || _originProduct === void 0 ? void 0 : _originProduct.order_detail_id) || ((_originProduct2 = originProduct) === null || _originProduct2 === void 0 ? void 0 : _originProduct2.orderDetailId) || ((_originProduct3 = originProduct) === null || _originProduct3 === void 0 ? void 0 : _originProduct3.booking_id);
1315
- var hasExistingWalletDiscount = ((_product$discount_lis2 = product.discount_list) === null || _product$discount_lis2 === void 0 ? void 0 : _product$discount_lis2.length) && ((_product10 = product) === null || _product10 === void 0 || (_product10 = _product10.discount_list) === null || _product10 === void 0 ? void 0 : _product10.every(function (discount) {
1339
+ var hasExistingWalletDiscount = ((_product$discount_lis3 = product.discount_list) === null || _product$discount_lis3 === void 0 ? void 0 : _product$discount_lis3.length) && ((_product10 = product) === null || _product10 === void 0 || (_product10 = _product10.discount_list) === null || _product10 === void 0 ? void 0 : _product10.every(function (discount) {
1316
1340
  var _discount$id, _discount$discount4;
1317
1341
  var discountIdentity = (_discount$id = discount.id) !== null && _discount$id !== void 0 ? _discount$id : (_discount$discount4 = discount.discount) === null || _discount$discount4 === void 0 ? void 0 : _discount$discount4.resource_id;
1318
1342
  var discountType = discount.tag || discount.type;
@@ -1333,7 +1357,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1333
1357
 
1334
1358
  // 找到适用于此商品的所有优惠券,仅考虑isSelected不为false的优惠券
1335
1359
  var applicableDiscounts = sortedDiscountList.filter(function (discount) {
1336
- var _product$discount_lis3, _product$discount_lis4;
1360
+ var _product$discount_lis4;
1337
1361
  if (_this4.isItemRewardProductDiscount(product)) return false;
1338
1362
  // 🔥 检查策略可用性(针对全额抵扣卡和折扣卡)
1339
1363
  var discountType = discount.tag || discount.type;
@@ -1345,22 +1369,19 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1345
1369
  if (!discount.isSelected) return false;
1346
1370
  }
1347
1371
  if (['entitlement_pass', 'good_pass', 'discount_card', 'product_discount_card'].includes(discountType !== null && discountType !== void 0 ? discountType : '') && !isReapplyEditModeDiscountForProduct) {
1348
- var _discount$config4;
1372
+ var _discount$config5;
1349
1373
  // 如果策略检查后没有config,说明不可用
1350
- if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config4 = discount.config) !== null && _discount$config4 !== void 0 && _discount$config4.isAvailable)) {
1374
+ if (discount.config === undefined || !(discount !== null && discount !== void 0 && (_discount$config5 = discount.config) !== null && _discount$config5 !== void 0 && _discount$config5.isAvailable)) {
1351
1375
  return false;
1352
1376
  }
1353
1377
  }
1354
1378
 
1355
1379
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
1356
1380
  // 全额抵扣卡在主商品价格为 0 时不可用。
1357
- if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && isFullCoveragePass(discount)) return false;
1381
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.length) && isFullCoveragePass(discount)) return false;
1358
1382
 
1359
- // 折扣卡商品价格为0时不可用
1360
- if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis4 = product.discount_list) !== null && _product$discount_lis4 !== void 0 && _product$discount_lis4.find(function (n) {
1361
- var _n$discount;
1362
- return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
1363
- })) && !isFullCoveragePass(discount)) return false;
1383
+ // 基础价和策略允许抵扣的 option 都无金额时,折扣卡不可用。
1384
+ if (!isFullCoveragePass(discount) && !isDiscountCardPriceAvailable(flatItem, discount)) return false;
1364
1385
  // good_pass 保持一张实例只使用一次。
1365
1386
  if ((discount.tag || discount.type) === 'good_pass' && usedDiscounts.get(discount.id)) {
1366
1387
  return false;
@@ -1372,8 +1393,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1372
1393
 
1373
1394
  // 🔥 检查 maxUsagePerOrder 限制:同一 product_id 的商品券使用数量不能超过配置值
1374
1395
  if (isFullCoveragePass(discount)) {
1375
- var _discount$config5;
1376
- var maxUsagePerOrder = (_discount$config5 = discount.config) === null || _discount$config5 === void 0 ? void 0 : _discount$config5.maxUsagePerOrder;
1396
+ var _discount$config6;
1397
+ var maxUsagePerOrder = (_discount$config6 = discount.config) === null || _discount$config6 === void 0 ? void 0 : _discount$config6.maxUsagePerOrder;
1377
1398
  if (maxUsagePerOrder && maxUsagePerOrder > 0) {
1378
1399
  var currentUsedCount = usedProductIdCounts.get(discount.product_id) || 0;
1379
1400
  if (currentUsedCount >= maxUsagePerOrder) {
@@ -1431,8 +1452,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1431
1452
  var appliedWalletDiscountIds = new Set((product.discount_list || []).filter(function (item) {
1432
1453
  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));
1433
1454
  }).map(function (item) {
1434
- var _ref24, _item$discount$resour, _item$discount;
1435
- 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;
1455
+ var _ref28, _item$discount$resour, _item$discount2;
1456
+ return (_ref28 = (_item$discount$resour = item === null || item === void 0 || (_item$discount2 = item.discount) === null || _item$discount2 === void 0 ? void 0 : _item$discount2.resource_id) !== null && _item$discount$resour !== void 0 ? _item$discount$resour : item === null || item === void 0 ? void 0 : item.resource_id) !== null && _ref28 !== void 0 ? _ref28 : item === null || item === void 0 ? void 0 : item.id;
1436
1457
  }).filter(function (id) {
1437
1458
  return id !== undefined && id !== null;
1438
1459
  }).map(String));
@@ -1472,8 +1493,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1472
1493
  isManualDiscount = typeof product.isManualDiscount === 'boolean' ? product.isManualDiscount : ((_product$discount_lis5 = product.discount_list) === null || _product$discount_lis5 === void 0 ? void 0 : _product$discount_lis5.some(function (item) {
1473
1494
  return item.type === 'product';
1474
1495
  })) || product.total != product.origin_total && (product.bundle || []).every(function (item) {
1475
- var _ref25;
1476
- return !((_ref25 = item.discount_list || []) !== null && _ref25 !== void 0 && _ref25.length);
1496
+ var _ref29;
1497
+ return !((_ref29 = item.discount_list || []) !== null && _ref29 !== void 0 && _ref29.length);
1477
1498
  }) && (!((_product$discount_lis6 = product.discount_list) !== null && _product$discount_lis6 !== void 0 && _product$discount_lis6.length) || ((_product11 = product) === null || _product11 === void 0 || (_product11 = _product11.discount_list) === null || _product11 === void 0 || (_product11$every = _product11.every) === null || _product11$every === void 0 ? void 0 : _product11$every.call(_product11, function (item) {
1478
1499
  return item.type === 'product';
1479
1500
  })));
@@ -1489,8 +1510,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1489
1510
  isManualDiscount = typeof parentProduct.isManualDiscount === 'boolean' ? parentProduct.isManualDiscount : ((_parentProduct$discou = parentProduct.discount_list) === null || _parentProduct$discou === void 0 ? void 0 : _parentProduct$discou.some(function (item) {
1490
1511
  return item.type === 'product';
1491
1512
  })) || parentProduct.total != parentProduct.origin_total && (parentProduct.bundle || []).every(function (item) {
1492
- var _ref26;
1493
- return !((_ref26 = item.discount_list || []) !== null && _ref26 !== void 0 && _ref26.length);
1513
+ var _ref30;
1514
+ return !((_ref30 = item.discount_list || []) !== null && _ref30 !== void 0 && _ref30.length);
1494
1515
  }) && (!((_parentProduct$discou2 = parentProduct.discount_list) !== null && _parentProduct$discou2 !== void 0 && _parentProduct$discou2.length) || (parentProduct === null || parentProduct === void 0 || (_parentProduct$discou3 = parentProduct.discount_list) === null || _parentProduct$discou3 === void 0 || (_parentProduct$discou4 = _parentProduct$discou3.every) === null || _parentProduct$discou4 === void 0 ? void 0 : _parentProduct$discou4.call(_parentProduct$discou3, function (item) {
1495
1516
  return item.type === 'product';
1496
1517
  })));
@@ -1502,8 +1523,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1502
1523
  var _product$discount_lis7;
1503
1524
  // 主商品:检查自己的 discount_list
1504
1525
  if (flatItem.type === 'main' && (_product$discount_lis7 = product.discount_list) !== null && _product$discount_lis7 !== void 0 && _product$discount_lis7.some(function (item) {
1505
- var _item$discount2;
1506
- return ((_item$discount2 = item.discount) === null || _item$discount2 === void 0 ? void 0 : _item$discount2.resource_id) === options.discountId;
1526
+ var _item$discount3;
1527
+ return ((_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.resource_id) === options.discountId;
1507
1528
  })) {
1508
1529
  isManualDiscount = false;
1509
1530
  }
@@ -1511,11 +1532,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1511
1532
  if (flatItem.type === 'bundle') {
1512
1533
  var _product$discount_lis8, _flatItem$parentProdu7;
1513
1534
  if ((_product$discount_lis8 = product.discount_list) !== null && _product$discount_lis8 !== void 0 && _product$discount_lis8.some(function (item) {
1514
- var _item$discount3;
1515
- return ((_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.resource_id) === options.discountId;
1516
- }) || (_flatItem$parentProdu7 = flatItem.parentProduct) !== null && _flatItem$parentProdu7 !== void 0 && (_flatItem$parentProdu7 = _flatItem$parentProdu7.discount_list) !== null && _flatItem$parentProdu7 !== void 0 && _flatItem$parentProdu7.some(function (item) {
1517
1535
  var _item$discount4;
1518
1536
  return ((_item$discount4 = item.discount) === null || _item$discount4 === void 0 ? void 0 : _item$discount4.resource_id) === options.discountId;
1537
+ }) || (_flatItem$parentProdu7 = flatItem.parentProduct) !== null && _flatItem$parentProdu7 !== void 0 && (_flatItem$parentProdu7 = _flatItem$parentProdu7.discount_list) !== null && _flatItem$parentProdu7 !== void 0 && _flatItem$parentProdu7.some(function (item) {
1538
+ var _item$discount5;
1539
+ return ((_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.resource_id) === options.discountId;
1519
1540
  })) {
1520
1541
  isManualDiscount = false;
1521
1542
  }
@@ -1527,8 +1548,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1527
1548
  if (flatItem.type === 'main' && (_product$discount_lis9 = product.discount_list) !== null && _product$discount_lis9 !== void 0 && _product$discount_lis9.some(function (item) {
1528
1549
  var _options$selectedList2;
1529
1550
  return options === null || options === void 0 || (_options$selectedList2 = options.selectedList) === null || _options$selectedList2 === void 0 ? void 0 : _options$selectedList2.some(function (n) {
1530
- var _item$discount5;
1531
- return n.discountId === ((_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.resource_id);
1551
+ var _item$discount6;
1552
+ return n.discountId === ((_item$discount6 = item.discount) === null || _item$discount6 === void 0 ? void 0 : _item$discount6.resource_id);
1532
1553
  });
1533
1554
  })) {
1534
1555
  isManualDiscount = false;
@@ -1539,14 +1560,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1539
1560
  if ((_product$discount_lis10 = product.discount_list) !== null && _product$discount_lis10 !== void 0 && _product$discount_lis10.some(function (item) {
1540
1561
  var _options$selectedList3;
1541
1562
  return options === null || options === void 0 || (_options$selectedList3 = options.selectedList) === null || _options$selectedList3 === void 0 ? void 0 : _options$selectedList3.some(function (n) {
1542
- var _item$discount6;
1543
- return n.discountId === ((_item$discount6 = item.discount) === null || _item$discount6 === void 0 ? void 0 : _item$discount6.resource_id);
1563
+ var _item$discount7;
1564
+ return n.discountId === ((_item$discount7 = item.discount) === null || _item$discount7 === void 0 ? void 0 : _item$discount7.resource_id);
1544
1565
  });
1545
1566
  }) || (_flatItem$parentProdu8 = flatItem.parentProduct) !== null && _flatItem$parentProdu8 !== void 0 && (_flatItem$parentProdu8 = _flatItem$parentProdu8.discount_list) !== null && _flatItem$parentProdu8 !== void 0 && _flatItem$parentProdu8.some(function (item) {
1546
1567
  var _options$selectedList4;
1547
1568
  return options === null || options === void 0 || (_options$selectedList4 = options.selectedList) === null || _options$selectedList4 === void 0 ? void 0 : _options$selectedList4.some(function (n) {
1548
- var _item$discount7;
1549
- return n.discountId === ((_item$discount7 = item.discount) === null || _item$discount7 === void 0 ? void 0 : _item$discount7.resource_id);
1569
+ var _item$discount8;
1570
+ return n.discountId === ((_item$discount8 = item.discount) === null || _item$discount8 === void 0 ? void 0 : _item$discount8.resource_id);
1550
1571
  });
1551
1572
  })) {
1552
1573
  isManualDiscount = false;
@@ -1583,8 +1604,8 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1583
1604
  discount_list: isManualDiscount ? _this4.resolveDiscountListForManualOverride(product.discount_list) : _this4.filterDiscountListByType(product.discount_list, 'promotion')
1584
1605
  }))]);
1585
1606
  } else {
1586
- var _ref27, _product$_promotion$f, _product12, _product$origin_total;
1587
- var total = product.inPromotion ? (_ref27 = (_product$_promotion$f = (_product12 = product) === null || _product12 === void 0 || (_product12 = _product12._promotion) === null || _product12 === void 0 ? void 0 : _product12.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref27 !== void 0 ? _ref27 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1607
+ var _ref31, _product$_promotion$f, _product12, _product$origin_total;
1608
+ var total = product.inPromotion ? (_ref31 = (_product$_promotion$f = (_product12 = product) === null || _product12 === void 0 || (_product12 = _product12._promotion) === null || _product12 === void 0 ? void 0 : _product12.finalPrice) !== null && _product$_promotion$f !== void 0 ? _product$_promotion$f : product.origin_total) !== null && _ref31 !== void 0 ? _ref31 : product.total : (_product$origin_total = product.origin_total) !== null && _product$origin_total !== void 0 ? _product$origin_total : product.total;
1588
1609
  var main_product_selling_price = product.price;
1589
1610
  if ((product.discount_list || []).some(function (item) {
1590
1611
  return item.type === 'promotion';
@@ -2287,7 +2308,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2287
2308
  } else {
2288
2309
  // 🔥 没有子商品被拆分,使用原有逻辑
2289
2310
  mainProductArr.forEach(function (mainProduct) {
2290
- var _ref29, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2311
+ var _ref33, _mainProductData$main, _mainProductData$disc, _mainProductData$disc2, _mainProductData$disc3;
2291
2312
  var mainProductData = _this4.hooks.getProduct(mainProduct);
2292
2313
 
2293
2314
  // 重组bundle
@@ -2302,9 +2323,9 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2302
2323
  } else {
2303
2324
  // 🔥 关键:拆分后的bundle item
2304
2325
  processedBundleItems.forEach(function (item) {
2305
- var _item$price, _ref28, _item$bundle_selling_;
2326
+ var _item$price, _ref32, _item$bundle_selling_;
2306
2327
  var nextBundlePrice = (_item$price = item.price) !== null && _item$price !== void 0 ? _item$price : bundleItem.price;
2307
- 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;
2328
+ var nextBundleSellingPrice = (_ref32 = (_item$bundle_selling_ = item.bundle_selling_price) !== null && _item$bundle_selling_ !== void 0 ? _item$bundle_selling_ : item.price) !== null && _ref32 !== void 0 ? _ref32 : bundleItem.bundle_selling_price;
2308
2329
  // 🔥 更新 discount_list 中的 num,使其与拆分后的 item.num 一致
2309
2330
  var updatedDiscountList = (item.discount_list || []).map(function (discount) {
2310
2331
  var _discount$metadata11;
@@ -2331,7 +2352,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2331
2352
 
2332
2353
  // 主商品已经在前面的 setProduct 中应用过折扣;这里只替换 bundle,
2333
2354
  // 避免把主商品 discount_list 再扣一次。
2334
- var mainSellingPrice = (_ref29 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref29 !== void 0 ? _ref29 : 0;
2355
+ var mainSellingPrice = (_ref33 = (_mainProductData$main = mainProductData.main_product_selling_price) !== null && _mainProductData$main !== void 0 ? _mainProductData$main : mainProductData.price) !== null && _ref33 !== void 0 ? _ref33 : 0;
2335
2356
  var newTotal = Number(mainSellingPrice || 0);
2336
2357
  var newOriginTotal = Number(mainProductData.original_price || mainProductData.price || 0);
2337
2358
 
@@ -2547,15 +2568,15 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
2547
2568
  var ruleType = usageRules.type;
2548
2569
  // 套餐适用范围配置
2549
2570
  var packageScope = usageRules === null || usageRules === void 0 ? void 0 : usageRules.package_scope;
2550
- var _ref30 = packageScope || {},
2551
- _ref30$type = _ref30.type,
2552
- scopeType = _ref30$type === void 0 ? 'product_all' : _ref30$type,
2553
- _ref30$exclude_bundle = _ref30.exclude_bundle_product_ids,
2554
- exclude_bundle_product_ids = _ref30$exclude_bundle === void 0 ? [] : _ref30$exclude_bundle,
2555
- _ref30$include_bundle = _ref30.include_bundle_product_ids,
2556
- include_bundle_product_ids = _ref30$include_bundle === void 0 ? [] : _ref30$include_bundle,
2557
- _ref30$filter = _ref30.filter,
2558
- filter = _ref30$filter === void 0 ? 0 : _ref30$filter;
2571
+ var _ref34 = packageScope || {},
2572
+ _ref34$type = _ref34.type,
2573
+ scopeType = _ref34$type === void 0 ? 'product_all' : _ref34$type,
2574
+ _ref34$exclude_bundle = _ref34.exclude_bundle_product_ids,
2575
+ exclude_bundle_product_ids = _ref34$exclude_bundle === void 0 ? [] : _ref34$exclude_bundle,
2576
+ _ref34$include_bundle = _ref34.include_bundle_product_ids,
2577
+ include_bundle_product_ids = _ref34$include_bundle === void 0 ? [] : _ref34$include_bundle,
2578
+ _ref34$filter = _ref34.filter,
2579
+ filter = _ref34$filter === void 0 ? 0 : _ref34$filter;
2559
2580
  var isMainProduct = flatItem.type === 'main'; // 单独购买
2560
2581
  var isBundleItem = flatItem.type === 'bundle'; // 套餐中购买
2561
2582
  var bundleMainProductId = (_flatItem$product = flatItem.product) === null || _flatItem$product === void 0 ? void 0 : _flatItem$product.product_id;
@@ -1250,7 +1250,7 @@ function buildFees(params) {
1250
1250
  customer_paid_amount: formatMoney(financials.customerPaidAmount, currencySymbol),
1251
1251
  net_payment_applied: formatMoney(financials.netPaymentApplied, currencySymbol)
1252
1252
  }, isPresentId(roundingAmount) ? {
1253
- rounding_amount: formatMoney(roundingAmount, currencySymbol)
1253
+ rounding_amount: formatCalculatedMoney(roundingAmount, currencySymbol)
1254
1254
  } : {}), isNonZero(totalSavingsAmount) ? {
1255
1255
  order_total_discount: formatMoney(totalSavingsAmount, currencySymbol)
1256
1256
  } : {}), financials.hasPayProcessingFee ? {
@@ -328,7 +328,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
328
328
  date: string;
329
329
  status: string;
330
330
  week: string;
331
- weekNum: 0 | 1 | 2 | 3 | 5 | 4 | 6;
331
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
332
332
  }[]>;
333
333
  submitTimeSlot(timeSlots: TimeSliceItem): void;
334
334
  private getScheduleDataByIds;
@@ -347,7 +347,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
347
347
  count: number;
348
348
  left: number;
349
349
  summaryCount: number;
350
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
350
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
351
351
  }[];
352
352
  /**
353
353
  * 找到多个资源的公共可用时间段
@@ -375,7 +375,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
375
375
  };
376
376
  setOtherData(key: string, value: any): void;
377
377
  getOtherData(key: string): any;
378
- getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
378
+ getProductTypeById(id: number): Promise<"duration" | "normal" | "session">;
379
379
  /**
380
380
  * 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
381
381
  *
@@ -49,5 +49,5 @@ export declare class Product extends BaseModule implements Module {
49
49
  getCategories(): ProductCategory[];
50
50
  setOtherParams(key: string, value: any): void;
51
51
  getOtherParams(): any;
52
- getProductType(): "normal" | "duration" | "session";
52
+ getProductType(): "duration" | "normal" | "session";
53
53
  }
@@ -895,6 +895,25 @@ class RulesModule extends _BaseModule.BaseModule {
895
895
  // 记录已应用优惠券的商品信息
896
896
  const appliedDiscountProducts = new Map();
897
897
 
898
+ // 可用性和实际应用共用金额判断;零基础价商品可按策略抵扣收费 option。
899
+ const isDiscountCardPriceAvailable = (flatItem, discount) => {
900
+ const product = flatItem.type === 'main' ? flatItem.product : flatItem.bundleItem;
901
+ if (!(Number(flatItem.price) <= 0 || !flatItem.price) || product.discount_list?.some(item => item.discount?.resource_id === discount.id)) {
902
+ return true;
903
+ }
904
+ if (flatItem.type !== 'main' || Number(flatItem.price) !== 0 || !['discount_card', 'product_discount_card'].includes(discount.tag || discount.type || '') || !discount.config?.deductOptionPrice || (0, _utils.isOrderLevelFixedAmountDiscount)(discount)) {
905
+ return false;
906
+ }
907
+ return (product.options || []).reduce((total, option) => {
908
+ const unitPrice = Number(option._original_price ?? option._original_add_price ?? option.price ?? option.add_price ?? 0);
909
+ const quantity = Number(option.num ?? option.quantity ?? 1);
910
+ if (!Number.isFinite(unitPrice) || !Number.isFinite(quantity) || quantity <= 0) {
911
+ return total;
912
+ }
913
+ return total.plus(new _decimal.default(unitPrice).mul(quantity));
914
+ }, new _decimal.default(0)).greaterThan(0);
915
+ };
916
+
898
917
  // 首先遍历所有商品和所有优惠券,确定每个优惠券的适用范围,包括isSelected为false的优惠券
899
918
  // 🔥 使用扁平化后的列表,包含主商品和bundle子商品
900
919
  sortedFlattenedList.forEach(flatItem => {
@@ -947,7 +966,7 @@ class RulesModule extends _BaseModule.BaseModule {
947
966
  }
948
967
 
949
968
  // 判断优惠券是否适用于该商品
950
- if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && discount.config?.isAvailable && (!(0, _entitlementPass.isEntitlementPass)(discount) || (0, _entitlementPass.getRemainingEntitlementUses)(discount, 0, 1) > 0)) {
969
+ if (isAvailableProduct && !isItemRewardProductDiscount && isLimitedProduct && timeLimit && isBundleAvailable && discount.config?.isAvailable && ((0, _entitlementPass.isFullCoveragePass)(discount) || isDiscountCardPriceAvailable(flatItem, discount)) && (!(0, _entitlementPass.isEntitlementPass)(discount) || (0, _entitlementPass.getRemainingEntitlementUses)(discount, 0, 1) > 0)) {
951
970
  // 记录此优惠券适用的商品
952
971
  discountApplicability.get(discount.id)?.push(product.id);
953
972
 
@@ -1114,8 +1133,8 @@ class RulesModule extends _BaseModule.BaseModule {
1114
1133
  // 全额抵扣卡在主商品价格为 0 时不可用。
1115
1134
  if ((Number(product.price) <= 0 || !product.price) && !product.discount_list?.length && (0, _entitlementPass.isFullCoveragePass)(discount)) return false;
1116
1135
 
1117
- // 折扣卡商品价格为0时不可用
1118
- if ((Number(product.price) <= 0 || !product.price) && !product.discount_list?.find(n => n.discount?.resource_id === discount.id) && !(0, _entitlementPass.isFullCoveragePass)(discount)) return false;
1136
+ // 基础价和策略允许抵扣的 option 都无金额时,折扣卡不可用。
1137
+ if (!(0, _entitlementPass.isFullCoveragePass)(discount) && !isDiscountCardPriceAvailable(flatItem, discount)) return false;
1119
1138
  // good_pass 保持一张实例只使用一次。
1120
1139
  if ((discount.tag || discount.type) === 'good_pass' && usedDiscounts.get(discount.id)) {
1121
1140
  return false;
@@ -1192,7 +1192,7 @@ function buildFees(params) {
1192
1192
  customer_paid_amount: formatMoney(financials.customerPaidAmount, currencySymbol),
1193
1193
  net_payment_applied: formatMoney(financials.netPaymentApplied, currencySymbol),
1194
1194
  ...(isPresentId(roundingAmount) ? {
1195
- rounding_amount: formatMoney(roundingAmount, currencySymbol)
1195
+ rounding_amount: formatCalculatedMoney(roundingAmount, currencySymbol)
1196
1196
  } : {}),
1197
1197
  ...(isNonZero(totalSavingsAmount) ? {
1198
1198
  order_total_discount: formatMoney(totalSavingsAmount, currencySymbol)
@@ -328,7 +328,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
328
328
  date: string;
329
329
  status: string;
330
330
  week: string;
331
- weekNum: 0 | 1 | 2 | 3 | 5 | 4 | 6;
331
+ weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
332
332
  }[]>;
333
333
  submitTimeSlot(timeSlots: TimeSliceItem): void;
334
334
  private getScheduleDataByIds;
@@ -347,7 +347,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
347
347
  count: number;
348
348
  left: number;
349
349
  summaryCount: number;
350
- status: "sold_out" | "lots_of_space" | "filling_up_fast";
350
+ status: "lots_of_space" | "filling_up_fast" | "sold_out";
351
351
  }[];
352
352
  /**
353
353
  * 找到多个资源的公共可用时间段
@@ -375,7 +375,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
375
375
  };
376
376
  setOtherData(key: string, value: any): void;
377
377
  getOtherData(key: string): any;
378
- getProductTypeById(id: number): Promise<"normal" | "duration" | "session">;
378
+ getProductTypeById(id: number): Promise<"duration" | "normal" | "session">;
379
379
  /**
380
380
  * 提供给 UI 的方法,减轻 UI 层的计算压力,UI 层只需要传递 cartItemId 和 resourceCode 即返回对应的 renderList
381
381
  *
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.3.148",
4
+ "version": "2.3.150",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",