@pisell/pisellos 2.2.76 → 2.2.77

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.
@@ -908,11 +908,74 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
908
908
  // 更新已处理数量
909
909
  processedQuantityMap.set(_key, _processedQty + _availableQty);
910
910
  }
911
+
912
+ // 8. 尾差调整:确保促销商品的 finalPrice × quantity 之和精确等于 groupPrice × groupCount
911
913
  } catch (err) {
912
914
  _iterator13.e(err);
913
915
  } finally {
914
916
  _iterator13.f();
915
917
  }
918
+ if (groupCount > 0) {
919
+ var expectedPromoTotal = new Decimal(groupPrice).mul(groupCount);
920
+ var promoItems = result.filter(function (p) {
921
+ return p.inPromotion;
922
+ });
923
+ var actualPromoTotal = new Decimal(0);
924
+ var _iterator14 = _createForOfIteratorHelper(promoItems),
925
+ _step14;
926
+ try {
927
+ for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
928
+ var _p = _step14.value;
929
+ actualPromoTotal = actualPromoTotal.plus(new Decimal(_p.finalPrice).mul(_p.quantity));
930
+ }
931
+ } catch (err) {
932
+ _iterator14.e(err);
933
+ } finally {
934
+ _iterator14.f();
935
+ }
936
+ var roundingDiff = actualPromoTotal.minus(expectedPromoTotal);
937
+ if (!roundingDiff.eq(0)) {
938
+ // 优先找 quantity=1 的促销商品调整(差额直接加减到单价上)
939
+ var adjustTarget = promoItems.find(function (p) {
940
+ return p.quantity === 1;
941
+ });
942
+ if (adjustTarget) {
943
+ adjustTarget.finalPrice = this.formatPrice(new Decimal(adjustTarget.finalPrice).minus(roundingDiff));
944
+ } else if (promoItems.length > 0) {
945
+ // 没有 quantity=1 的促销商品,从最后一个促销商品中拆出1件做尾差调整
946
+ var lastPromo = promoItems[promoItems.length - 1];
947
+ var adjustedUnitPrice = this.formatPrice(new Decimal(lastPromo.finalPrice).minus(roundingDiff));
948
+
949
+ // 原商品减少1件
950
+ lastPromo.quantity -= 1;
951
+ lastPromo.isSplit = true;
952
+
953
+ // 拆出1件用调整后的价格
954
+ result.push(_objectSpread(_objectSpread({}, lastPromo), {}, {
955
+ id: this.generateRandomId(),
956
+ originalId: lastPromo.originalId || lastPromo.id,
957
+ quantity: 1,
958
+ finalPrice: adjustedUnitPrice,
959
+ isSplit: true
960
+ }));
961
+ }
962
+
963
+ // 重新计算 finalAmount
964
+ finalAmount = new Decimal(0);
965
+ var _iterator15 = _createForOfIteratorHelper(result),
966
+ _step15;
967
+ try {
968
+ for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
969
+ var p = _step15.value;
970
+ finalAmount = finalAmount.plus(new Decimal(p.finalPrice).mul(p.quantity));
971
+ }
972
+ } catch (err) {
973
+ _iterator15.e(err);
974
+ } finally {
975
+ _iterator15.f();
976
+ }
977
+ }
978
+ }
916
979
  return {
917
980
  products: result,
918
981
  originalAmount: originalAmount.toNumber(),
@@ -947,11 +1010,11 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
947
1010
  // 对于 bundle 子商品匹配,促销数量 = 主商品数量 × bundle子商品数量
948
1011
  var totalPromoQty = 0;
949
1012
  var productInfoMap = new Map();
950
- var _iterator14 = _createForOfIteratorHelper(groupProducts),
951
- _step14;
1013
+ var _iterator16 = _createForOfIteratorHelper(groupProducts),
1014
+ _step16;
952
1015
  try {
953
- for (_iterator14.s(); !(_step14 = _iterator14.n()).done;) {
954
- var product = _step14.value;
1016
+ for (_iterator16.s(); !(_step16 = _iterator16.n()).done;) {
1017
+ var product = _step16.value;
955
1018
  var key = this.getProductKey(product);
956
1019
  var processedQty = processedQuantityMap.get(key) || 0;
957
1020
  var availableQty = product.quantity - processedQty;
@@ -977,18 +1040,18 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
977
1040
 
978
1041
  // 2. 判断是否满足促销条件
979
1042
  } catch (err) {
980
- _iterator14.e(err);
1043
+ _iterator16.e(err);
981
1044
  } finally {
982
- _iterator14.f();
1045
+ _iterator16.f();
983
1046
  }
984
1047
  var isFulfilled = totalPromoQty >= buyQuantity;
985
1048
 
986
1049
  // 3. 生成商品结果(第二次遍历)
987
- var _iterator15 = _createForOfIteratorHelper(groupProducts),
988
- _step15;
1050
+ var _iterator17 = _createForOfIteratorHelper(groupProducts),
1051
+ _step17;
989
1052
  try {
990
- for (_iterator15.s(); !(_step15 = _iterator15.n()).done;) {
991
- var _product2 = _step15.value;
1053
+ for (_iterator17.s(); !(_step17 = _iterator17.n()).done;) {
1054
+ var _product2 = _step17.value;
992
1055
  var _key2 = this.getProductKey(_product2);
993
1056
  var info = productInfoMap.get(_key2);
994
1057
  if (!info || info.availableQty <= 0) continue;
@@ -1016,9 +1079,9 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
1016
1079
 
1017
1080
  // 4. 计算赠品数量(使用促销数量)
1018
1081
  } catch (err) {
1019
- _iterator15.e(err);
1082
+ _iterator17.e(err);
1020
1083
  } finally {
1021
- _iterator15.f();
1084
+ _iterator17.f();
1022
1085
  }
1023
1086
  var giftCount = 0;
1024
1087
  if (isFulfilled) {
@@ -1047,11 +1110,11 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
1047
1110
  key: "getRemainingProducts",
1048
1111
  value: function getRemainingProducts(allProducts, processedQuantityMap) {
1049
1112
  var result = [];
1050
- var _iterator16 = _createForOfIteratorHelper(allProducts),
1051
- _step16;
1113
+ var _iterator18 = _createForOfIteratorHelper(allProducts),
1114
+ _step18;
1052
1115
  try {
1053
- for (_iterator16.s(); !(_step16 = _iterator16.n()).done;) {
1054
- var product = _step16.value;
1116
+ for (_iterator18.s(); !(_step18 = _iterator18.n()).done;) {
1117
+ var product = _step18.value;
1055
1118
  var key = this.getProductKey(product);
1056
1119
  var processedQty = processedQuantityMap.get(key) || 0;
1057
1120
  var remainingQty = product.quantity - processedQty;
@@ -1066,9 +1129,9 @@ export var PromotionEvaluator = /*#__PURE__*/function () {
1066
1129
  }
1067
1130
  }
1068
1131
  } catch (err) {
1069
- _iterator16.e(err);
1132
+ _iterator18.e(err);
1070
1133
  } finally {
1071
- _iterator16.f();
1134
+ _iterator18.f();
1072
1135
  }
1073
1136
  return result;
1074
1137
  }
@@ -645,6 +645,46 @@ var PromotionEvaluator = class {
645
645
  }
646
646
  processedQuantityMap.set(key, processedQty + availableQty);
647
647
  }
648
+ if (groupCount > 0) {
649
+ const expectedPromoTotal = new import_decimal.default(groupPrice).mul(groupCount);
650
+ const promoItems = result.filter((p) => p.inPromotion);
651
+ let actualPromoTotal = new import_decimal.default(0);
652
+ for (const p of promoItems) {
653
+ actualPromoTotal = actualPromoTotal.plus(
654
+ new import_decimal.default(p.finalPrice).mul(p.quantity)
655
+ );
656
+ }
657
+ const roundingDiff = actualPromoTotal.minus(expectedPromoTotal);
658
+ if (!roundingDiff.eq(0)) {
659
+ const adjustTarget = promoItems.find((p) => p.quantity === 1);
660
+ if (adjustTarget) {
661
+ adjustTarget.finalPrice = this.formatPrice(
662
+ new import_decimal.default(adjustTarget.finalPrice).minus(roundingDiff)
663
+ );
664
+ } else if (promoItems.length > 0) {
665
+ const lastPromo = promoItems[promoItems.length - 1];
666
+ const adjustedUnitPrice = this.formatPrice(
667
+ new import_decimal.default(lastPromo.finalPrice).minus(roundingDiff)
668
+ );
669
+ lastPromo.quantity -= 1;
670
+ lastPromo.isSplit = true;
671
+ result.push({
672
+ ...lastPromo,
673
+ id: this.generateRandomId(),
674
+ originalId: lastPromo.originalId || lastPromo.id,
675
+ quantity: 1,
676
+ finalPrice: adjustedUnitPrice,
677
+ isSplit: true
678
+ });
679
+ }
680
+ finalAmount = new import_decimal.default(0);
681
+ for (const p of result) {
682
+ finalAmount = finalAmount.plus(
683
+ new import_decimal.default(p.finalPrice).mul(p.quantity)
684
+ );
685
+ }
686
+ }
687
+ }
648
688
  return {
649
689
  products: result,
650
690
  originalAmount: originalAmount.toNumber(),
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "private": false,
3
3
  "name": "@pisell/pisellos",
4
- "version": "2.2.76",
4
+ "version": "2.2.77",
5
5
  "description": "一个可扩展的前端模块化SDK框架,支持插件系统",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",