@pisell/pisellos 0.0.392 → 0.0.394

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.
@@ -581,11 +581,20 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
581
581
  var _flatItem$parentProdu2;
582
582
  // 🔥 对于 bundle 子商品,quantity 需要乘以主商品的购买数量
583
583
  var quantity = flatItem.type === 'main' ? product.quantity || 1 : (product.num || 1) * (((_flatItem$parentProdu2 = flatItem.parentProduct) === null || _flatItem$parentProdu2 === void 0 ? void 0 : _flatItem$parentProdu2.quantity) || 1);
584
- applicableProducts.push({
584
+
585
+ // 🔥 传递 parentQuantity 用于差值处理时判断是否是真正的"数量为1"
586
+ var productData = {
585
587
  productId: flatItem._id,
586
588
  amount: Number(product.price || 0),
587
589
  quantity: quantity
588
- });
590
+ };
591
+
592
+ // 子商品需要传递主商品数量
593
+ if (flatItem.type === 'bundle') {
594
+ var _flatItem$parentProdu3;
595
+ productData.parentQuantity = ((_flatItem$parentProdu3 = flatItem.parentProduct) === null || _flatItem$parentProdu3 === void 0 ? void 0 : _flatItem$parentProdu3.quantity) || 1;
596
+ }
597
+ applicableProducts.push(productData);
589
598
  }
590
599
  });
591
600
 
@@ -611,10 +620,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
611
620
  product = flatItem.product;
612
621
  originProduct = flatItem.originProduct;
613
622
  } else {
614
- var _flatItem$parentProdu3;
623
+ var _flatItem$parentProdu4;
615
624
  // bundle子商品:构造虚拟商品对象
616
625
  product = {
617
- startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu3 = flatItem.parentProduct) === null || _flatItem$parentProdu3 === void 0 ? void 0 : _flatItem$parentProdu3.startDate,
626
+ startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu4 = flatItem.parentProduct) === null || _flatItem$parentProdu4 === void 0 ? void 0 : _flatItem$parentProdu4.startDate,
618
627
  _id: flatItem._id,
619
628
  id: flatItem.id,
620
629
  price: flatItem.price,
@@ -699,10 +708,10 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
699
708
  product = flatItem.product;
700
709
  originProduct = flatItem.originProduct;
701
710
  } else {
702
- var _flatItem$parentProdu4, _flatItem$bundleItem3, _flatItem$bundleItem4, _flatItem$bundleItem5;
711
+ var _flatItem$parentProdu5, _flatItem$bundleItem3, _flatItem$bundleItem4, _flatItem$bundleItem5;
703
712
  // bundle子商品
704
713
  product = {
705
- startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu4 = flatItem.parentProduct) === null || _flatItem$parentProdu4 === void 0 ? void 0 : _flatItem$parentProdu4.startDate,
714
+ startDate: flatItem === null || flatItem === void 0 || (_flatItem$parentProdu5 = flatItem.parentProduct) === null || _flatItem$parentProdu5 === void 0 ? void 0 : _flatItem$parentProdu5.startDate,
706
715
  _id: flatItem._id,
707
716
  id: flatItem.id,
708
717
  price: flatItem.price,
@@ -746,15 +755,12 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
746
755
 
747
756
  // 如果商品价格为 0,其实不需要使用任何优惠券,直接 return true
748
757
  // 商品券时主商品价格为0不可用
749
- if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.find(function (n) {
750
- var _n$discount;
751
- return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
752
- })) && (discount.tag || discount.type) === 'good_pass') return false;
758
+ if ((Number(product.price) <= 0 || !product.price) && !((_product$discount_lis3 = product.discount_list) !== null && _product$discount_lis3 !== void 0 && _product$discount_lis3.length) && (discount.tag || discount.type) === 'good_pass') return false;
753
759
 
754
760
  // 折扣卡商品价格为0时不可用
755
761
  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) {
756
- var _n$discount2;
757
- return ((_n$discount2 = n.discount) === null || _n$discount2 === void 0 ? void 0 : _n$discount2.resource_id) === discount.id;
762
+ var _n$discount;
763
+ return ((_n$discount = n.discount) === null || _n$discount === void 0 ? void 0 : _n$discount.resource_id) === discount.id;
758
764
  })) && (discount.tag || discount.type) !== 'good_pass') return false;
759
765
  // 如果优惠券已被使用,则跳过
760
766
  var targetUsedDiscounts = usedDiscounts.get(discount.id);
@@ -851,11 +857,11 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
851
857
  }
852
858
  // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
853
859
  if (flatItem.type === 'bundle') {
854
- var _product$discount_lis7, _flatItem$parentProdu5;
860
+ var _product$discount_lis7, _flatItem$parentProdu6;
855
861
  if ((_product$discount_lis7 = product.discount_list) !== null && _product$discount_lis7 !== void 0 && _product$discount_lis7.some(function (item) {
856
862
  var _item$discount2;
857
863
  return ((_item$discount2 = item.discount) === null || _item$discount2 === void 0 ? void 0 : _item$discount2.resource_id) === options.discountId;
858
- }) || (_flatItem$parentProdu5 = flatItem.parentProduct) !== null && _flatItem$parentProdu5 !== void 0 && (_flatItem$parentProdu5 = _flatItem$parentProdu5.discount_list) !== null && _flatItem$parentProdu5 !== void 0 && _flatItem$parentProdu5.some(function (item) {
864
+ }) || (_flatItem$parentProdu6 = flatItem.parentProduct) !== null && _flatItem$parentProdu6 !== void 0 && (_flatItem$parentProdu6 = _flatItem$parentProdu6.discount_list) !== null && _flatItem$parentProdu6 !== void 0 && _flatItem$parentProdu6.some(function (item) {
859
865
  var _item$discount3;
860
866
  return ((_item$discount3 = item.discount) === null || _item$discount3 === void 0 ? void 0 : _item$discount3.resource_id) === options.discountId;
861
867
  })) {
@@ -877,14 +883,14 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
877
883
  }
878
884
  // bundle子商品:检查自己的 discount_list 或父主商品的 discount_list
879
885
  if (flatItem.type === 'bundle') {
880
- var _product$discount_lis9, _flatItem$parentProdu6;
886
+ var _product$discount_lis9, _flatItem$parentProdu7;
881
887
  if ((_product$discount_lis9 = product.discount_list) !== null && _product$discount_lis9 !== void 0 && _product$discount_lis9.some(function (item) {
882
888
  var _options$selectedList2;
883
889
  return options === null || options === void 0 || (_options$selectedList2 = options.selectedList) === null || _options$selectedList2 === void 0 ? void 0 : _options$selectedList2.some(function (n) {
884
890
  var _item$discount5;
885
891
  return n.discountId === ((_item$discount5 = item.discount) === null || _item$discount5 === void 0 ? void 0 : _item$discount5.resource_id);
886
892
  });
887
- }) || (_flatItem$parentProdu6 = flatItem.parentProduct) !== null && _flatItem$parentProdu6 !== void 0 && (_flatItem$parentProdu6 = _flatItem$parentProdu6.discount_list) !== null && _flatItem$parentProdu6 !== void 0 && _flatItem$parentProdu6.some(function (item) {
893
+ }) || (_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) {
888
894
  var _options$selectedList3;
889
895
  return options === null || options === void 0 || (_options$selectedList3 = options.selectedList) === null || _options$selectedList3 === void 0 ? void 0 : _options$selectedList3.some(function (n) {
890
896
  var _item$discount6;
@@ -1165,7 +1171,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1165
1171
  }));
1166
1172
  }
1167
1173
  } else {
1168
- var _selectedDiscount3$me, _flatItem$parentProdu7;
1174
+ var _selectedDiscount3$me, _flatItem$parentProdu8;
1169
1175
  // 折扣卡:不拆分数量,直接应用
1170
1176
  var _selectedDiscount3 = selectedDiscountCard || applicableDiscounts[0];
1171
1177
  usedDiscounts.set(_selectedDiscount3.id, true);
@@ -1217,7 +1223,7 @@ export var RulesModule = /*#__PURE__*/function (_BaseModule) {
1217
1223
  product_discount_difference: _productDiscountDifference
1218
1224
  }),
1219
1225
  config: _selectedDiscount3 === null || _selectedDiscount3 === void 0 ? void 0 : _selectedDiscount3.config,
1220
- _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu7 = flatItem.parentProduct) === null || _flatItem$parentProdu7 === void 0 ? void 0 : _flatItem$parentProdu7.num) || 1)
1226
+ _num: (product.num || 1) * ((flatItem === null || flatItem === void 0 || (_flatItem$parentProdu8 = flatItem.parentProduct) === null || _flatItem$parentProdu8 === void 0 ? void 0 : _flatItem$parentProdu8.num) || 1)
1221
1227
  };
1222
1228
 
1223
1229
  // 记录实际应用的折扣
@@ -308,7 +308,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
308
308
  date: string;
309
309
  status: string;
310
310
  week: string;
311
- weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
311
+ weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
312
312
  }[]>;
313
313
  submitTimeSlot(timeSlots: TimeSliceItem): void;
314
314
  private getScheduleDataByIds;
@@ -74,16 +74,17 @@ export declare const isOrderLevelFixedAmountDiscount: (discount: Discount) => bo
74
74
  /**
75
75
  * 计算订单级别固定金额折扣卡的分摊结果
76
76
  * @param discount 折扣卡
77
- * @param applicableProducts 适用商品列表 { productId, amount, quantity }
77
+ * @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
78
78
  * @returns 分摊结果 Map<productId, { discountAmount, difference }>
79
79
  * 注意:
80
80
  * - discountAmount 是单价折扣金额(不是总折扣金额)
81
- * - difference(总差值)只会放在最后一个商品上,用于后端补齐金额
81
+ * - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
82
82
  */
83
83
  export declare const calculateOrderLevelDiscountAllocation: (discount: Discount, applicableProducts: Array<{
84
84
  productId: string | number;
85
85
  amount: number;
86
86
  quantity: number;
87
+ parentQuantity?: number;
87
88
  }>) => Map<string | number, {
88
89
  discountAmount: number;
89
90
  difference: number;
@@ -498,11 +498,11 @@ export var isOrderLevelFixedAmountDiscount = function isOrderLevelFixedAmountDis
498
498
  /**
499
499
  * 计算订单级别固定金额折扣卡的分摊结果
500
500
  * @param discount 折扣卡
501
- * @param applicableProducts 适用商品列表 { productId, amount, quantity }
501
+ * @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
502
502
  * @returns 分摊结果 Map<productId, { discountAmount, difference }>
503
503
  * 注意:
504
504
  * - discountAmount 是单价折扣金额(不是总折扣金额)
505
- * - difference(总差值)只会放在最后一个商品上,用于后端补齐金额
505
+ * - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
506
506
  */
507
507
  export var calculateOrderLevelDiscountAllocation = function calculateOrderLevelDiscountAllocation(discount, applicableProducts) {
508
508
  var result = new Map();
@@ -543,16 +543,71 @@ export var calculateOrderLevelDiscountAllocation = function calculateOrderLevelD
543
543
  allocatedTotal = allocatedTotal.plus(new Decimal(discountAmountPerItem).mul(product.quantity));
544
544
  });
545
545
 
546
- // 🔥 计算总差值,只放在最后一个商品上
546
+ // 🔥 计算总差值
547
547
  // 总差值 = 固定金额 - 所有商品的 (单价折扣 × 数量) 之和
548
548
  var totalDifference = new Decimal(actualDiscountTotal).minus(allocatedTotal).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
549
549
  if (totalDifference > 0) {
550
- var lastProduct = applicableProducts[applicableProducts.length - 1];
551
- var lastProductAllocation = result.get(lastProduct.productId);
552
- if (lastProductAllocation) {
553
- result.set(lastProduct.productId, _objectSpread(_objectSpread({}, lastProductAllocation), {}, {
554
- difference: totalDifference
555
- }));
550
+ // 🔥 判断商品是否是真正的"数量为1"
551
+ // 主商品:quantity === 1
552
+ // 子商品:quantity === 1 且 parentQuantity === 1
553
+ var isSingleQuantity = function isSingleQuantity(product) {
554
+ if (product.parentQuantity !== undefined) {
555
+ // 子商品:需要同时满足自身数量为1且主商品数量为1
556
+ return product.quantity === 1 && product.parentQuantity === 1;
557
+ }
558
+ // 主商品:只需要自身数量为1
559
+ return product.quantity === 1;
560
+ };
561
+
562
+ // 🔥 筛选出数量为1的商品
563
+ var singleQuantityProducts = applicableProducts.filter(isSingleQuantity);
564
+ if (singleQuantityProducts.length > 0) {
565
+ // 🔥 优先级1:找到有足够剩余空间且金额最大的商品
566
+ // 剩余空间 = 商品价格 - 当前折扣金额 >= 差值
567
+ var productsWithEnoughSpace = singleQuantityProducts.filter(function (product) {
568
+ var allocation = result.get(product.productId);
569
+ if (!allocation) return false;
570
+ var remainingSpace = new Decimal(product.amount).minus(allocation.discountAmount).toNumber();
571
+ return remainingSpace >= totalDifference;
572
+ });
573
+ if (productsWithEnoughSpace.length > 0) {
574
+ // 按金额降序排序,选择金额最大的
575
+ productsWithEnoughSpace.sort(function (a, b) {
576
+ return b.amount - a.amount;
577
+ });
578
+ var targetProduct = productsWithEnoughSpace[0];
579
+ var targetAllocation = result.get(targetProduct.productId);
580
+ if (targetAllocation) {
581
+ // 差值直接加到折扣金额上
582
+ result.set(targetProduct.productId, {
583
+ discountAmount: new Decimal(targetAllocation.discountAmount).plus(totalDifference).toNumber(),
584
+ difference: 0 // 不需要存储差值
585
+ });
586
+ }
587
+ } else {
588
+ // 🔥 优先级2:所有数量为1的商品都没有足够剩余空间
589
+ // 选择金额最大的商品,差值存储在metadata中
590
+ singleQuantityProducts.sort(function (a, b) {
591
+ return b.amount - a.amount;
592
+ });
593
+ var _targetProduct = singleQuantityProducts[0];
594
+ var _targetAllocation = result.get(_targetProduct.productId);
595
+ if (_targetAllocation) {
596
+ result.set(_targetProduct.productId, _objectSpread(_objectSpread({}, _targetAllocation), {}, {
597
+ difference: totalDifference
598
+ }));
599
+ }
600
+ }
601
+ } else {
602
+ // 🔥 优先级3:没有数量为1的商品,走原有逻辑
603
+ // 差值存储在最后一个商品的metadata中
604
+ var lastProduct = applicableProducts[applicableProducts.length - 1];
605
+ var lastProductAllocation = result.get(lastProduct.productId);
606
+ if (lastProductAllocation) {
607
+ result.set(lastProduct.productId, _objectSpread(_objectSpread({}, lastProductAllocation), {}, {
608
+ difference: totalDifference
609
+ }));
610
+ }
556
611
  }
557
612
  }
558
613
  return result;
@@ -369,7 +369,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
369
369
  }
370
370
  const applicableProducts = [];
371
371
  sortedFlattenedList.forEach((flatItem) => {
372
- var _a, _b, _c, _d, _e, _f;
372
+ var _a, _b, _c, _d, _e, _f, _g;
373
373
  let product;
374
374
  if (flatItem.type === "main") {
375
375
  product = flatItem.product;
@@ -401,11 +401,15 @@ var RulesModule = class extends import_BaseModule.BaseModule {
401
401
  const isBundleAvailable = this.checkPackageSubItemUsageRules(discount, flatItem);
402
402
  if (isLimitedProduct && isBundleAvailable) {
403
403
  const quantity = flatItem.type === "main" ? product.quantity || 1 : (product.num || 1) * (((_f = flatItem.parentProduct) == null ? void 0 : _f.quantity) || 1);
404
- applicableProducts.push({
404
+ const productData = {
405
405
  productId: flatItem._id,
406
406
  amount: Number(product.price || 0),
407
407
  quantity
408
- });
408
+ };
409
+ if (flatItem.type === "bundle") {
410
+ productData.parentQuantity = ((_g = flatItem.parentProduct) == null ? void 0 : _g.quantity) || 1;
411
+ }
412
+ applicableProducts.push(productData);
409
413
  }
410
414
  });
411
415
  if (applicableProducts.length > 0) {
@@ -538,10 +542,7 @@ var RulesModule = class extends import_BaseModule.BaseModule {
538
542
  return false;
539
543
  }
540
544
  }
541
- if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.find((n) => {
542
- var _a3;
543
- return ((_a3 = n.discount) == null ? void 0 : _a3.resource_id) === discount.id;
544
- })) && (discount.tag || discount.type) === "good_pass")
545
+ if ((Number(product.price) <= 0 || !product.price) && !((_b2 = product.discount_list) == null ? void 0 : _b2.length) && (discount.tag || discount.type) === "good_pass")
545
546
  return false;
546
547
  if ((Number(product.price) <= 0 || !product.price) && !((_c2 = product.discount_list) == null ? void 0 : _c2.find((n) => {
547
548
  var _a3;
@@ -308,7 +308,7 @@ export declare class BookingByStepImpl extends BaseModule implements Module {
308
308
  date: string;
309
309
  status: string;
310
310
  week: string;
311
- weekNum: 0 | 2 | 1 | 3 | 4 | 5 | 6;
311
+ weekNum: 0 | 1 | 2 | 3 | 4 | 5 | 6;
312
312
  }[]>;
313
313
  submitTimeSlot(timeSlots: TimeSliceItem): void;
314
314
  private getScheduleDataByIds;
@@ -74,16 +74,17 @@ export declare const isOrderLevelFixedAmountDiscount: (discount: Discount) => bo
74
74
  /**
75
75
  * 计算订单级别固定金额折扣卡的分摊结果
76
76
  * @param discount 折扣卡
77
- * @param applicableProducts 适用商品列表 { productId, amount, quantity }
77
+ * @param applicableProducts 适用商品列表 { productId, amount, quantity, parentQuantity }
78
78
  * @returns 分摊结果 Map<productId, { discountAmount, difference }>
79
79
  * 注意:
80
80
  * - discountAmount 是单价折扣金额(不是总折扣金额)
81
- * - difference(总差值)只会放在最后一个商品上,用于后端补齐金额
81
+ * - difference(总差值)优先直接加到数量为1的单商品折扣上,如果没有则存储在metadata中
82
82
  */
83
83
  export declare const calculateOrderLevelDiscountAllocation: (discount: Discount, applicableProducts: Array<{
84
84
  productId: string | number;
85
85
  amount: number;
86
86
  quantity: number;
87
+ parentQuantity?: number;
87
88
  }>) => Map<string | number, {
88
89
  discountAmount: number;
89
90
  difference: number;
@@ -345,13 +345,52 @@ var calculateOrderLevelDiscountAllocation = (discount, applicableProducts) => {
345
345
  });
346
346
  const totalDifference = new import_decimal.default(actualDiscountTotal).minus(allocatedTotal).toDecimalPlaces(2, import_decimal.default.ROUND_HALF_UP).toNumber();
347
347
  if (totalDifference > 0) {
348
- const lastProduct = applicableProducts[applicableProducts.length - 1];
349
- const lastProductAllocation = result.get(lastProduct.productId);
350
- if (lastProductAllocation) {
351
- result.set(lastProduct.productId, {
352
- ...lastProductAllocation,
353
- difference: totalDifference
348
+ const isSingleQuantity = (product) => {
349
+ if (product.parentQuantity !== void 0) {
350
+ return product.quantity === 1 && product.parentQuantity === 1;
351
+ }
352
+ return product.quantity === 1;
353
+ };
354
+ const singleQuantityProducts = applicableProducts.filter(isSingleQuantity);
355
+ if (singleQuantityProducts.length > 0) {
356
+ const productsWithEnoughSpace = singleQuantityProducts.filter((product) => {
357
+ const allocation = result.get(product.productId);
358
+ if (!allocation)
359
+ return false;
360
+ const remainingSpace = new import_decimal.default(product.amount).minus(allocation.discountAmount).toNumber();
361
+ return remainingSpace >= totalDifference;
354
362
  });
363
+ if (productsWithEnoughSpace.length > 0) {
364
+ productsWithEnoughSpace.sort((a, b) => b.amount - a.amount);
365
+ const targetProduct = productsWithEnoughSpace[0];
366
+ const targetAllocation = result.get(targetProduct.productId);
367
+ if (targetAllocation) {
368
+ result.set(targetProduct.productId, {
369
+ discountAmount: new import_decimal.default(targetAllocation.discountAmount).plus(totalDifference).toNumber(),
370
+ difference: 0
371
+ // 不需要存储差值
372
+ });
373
+ }
374
+ } else {
375
+ singleQuantityProducts.sort((a, b) => b.amount - a.amount);
376
+ const targetProduct = singleQuantityProducts[0];
377
+ const targetAllocation = result.get(targetProduct.productId);
378
+ if (targetAllocation) {
379
+ result.set(targetProduct.productId, {
380
+ ...targetAllocation,
381
+ difference: totalDifference
382
+ });
383
+ }
384
+ }
385
+ } else {
386
+ const lastProduct = applicableProducts[applicableProducts.length - 1];
387
+ const lastProductAllocation = result.get(lastProduct.productId);
388
+ if (lastProductAllocation) {
389
+ result.set(lastProduct.productId, {
390
+ ...lastProductAllocation,
391
+ difference: totalDifference
392
+ });
393
+ }
355
394
  }
356
395
  }
357
396
  return result;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "0.0.392",
4
+ "version": "0.0.394",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",