Skip to content

Commit b75bb4a

Browse files
authored
refactor(core): 优化折扣分摊逻辑,提高计算精度并修正尾差处理。
2 parents 79f0648 + 53cf5b0 commit b75bb4a

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

src/Calculators/SequentialCalculator.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ public function calculate(Cart $cart, User $user, array $rules): array
1616
foreach ($rules as $rule) {
1717
$result = $rule->apply($cart, $user);
1818
if ($result->hasDiscount()) {
19-
$totalDiscount += $result->discount;
20-
$details[] = $result->description . " (-¥{$result->discount})";
19+
$discount = round($result->discount, 2);
20+
$totalDiscount += $discount;
21+
$details[] = $result->description . " (-¥{$discount})";
2122
if (method_exists($rule, 'getApplicableItems')) {
2223
$indexes = $rule->getApplicableItems($cart);
23-
$cart->applyDiscountToItems($indexes, $result->discount);
24+
$cart->applyDiscountToItems($indexes, $discount);
2425
}
2526
$totalDiscount = round($totalDiscount, 2); // 确保总折扣是两位小数
2627
}

src/Models/Cart.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,33 @@ public function updateItemPrice(int $index, float $newPrice): void
120120
*/
121121
public function applyDiscountToItems(array $indexes, float $totalDiscount): void
122122
{
123-
$totalPrice = 0;
123+
if (empty($indexes) || $totalDiscount <= 0) {
124+
return;
125+
}
126+
$totalPrice = 0.0;
124127
foreach ($indexes as $i) {
125128
$totalPrice += $this->items[$i]['price'] * $this->items[$i]['qty'];
126129
}
130+
if ($totalPrice <= 0) {
131+
return;
132+
}
133+
134+
$distributed = 0.0;
135+
$lastIndex = $indexes[array_key_last($indexes)];
127136
foreach ($indexes as $i) {
128137
$item = &$this->items[$i];
129-
$shop_name[] = $item['name'];
130-
$share = round(($item['price'] * $item['qty']) / $totalPrice, 4);
131-
$item['price'] -= round(($totalDiscount * $share) / $item['qty'], 2);
138+
$share = ($item['price'] * $item['qty']) / $totalPrice;
139+
$unitReduction = round(($totalDiscount * $share) / $item['qty'], 2);
140+
$distributed += $unitReduction * $item['qty'];
141+
$item['price'] = max(0, round($item['price'] - $unitReduction, 2));
142+
unset($item);
143+
}
144+
145+
// 尾差补偿,保证分摊总额与 totalDiscount 一致
146+
$remainder = round($totalDiscount - $distributed, 2);
147+
if (abs($remainder) > 0) {
148+
$qty = $this->items[$lastIndex]['qty'];
149+
$this->items[$lastIndex]['price'] = max(0, round($this->items[$lastIndex]['price'] - ($remainder / $qty), 2));
132150
}
133151
}
134152

0 commit comments

Comments
 (0)