Skip to content

Commit e76c516

Browse files
authored
Merge pull request #40 from bizexcel/main
Fix PDF invoice crash when item price is zero
2 parents b8122ab + 5932bce commit e76c516

File tree

2 files changed

+18
-11
lines changed

2 files changed

+18
-11
lines changed

src/Pdf/PdfInvoice.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,38 +133,41 @@ public function subTotalDiscountedAmount(): Money
133133
*/
134134
public function totalTaxAmount(): Money
135135
{
136-
if (empty($this->items)) {
137-
return Money::of(0, $this->getCurrency());
138-
}
139-
140136
$totalDiscount = $this->totalDiscountAmount();
141137

142138
/**
143-
* Taxes must be calculated on the discounted subtotal.
144-
* Since discounts apply at the invoice level and taxes at the item level,
145-
* we allocate the discount across items before computing taxes.
139+
* Taxes must be calculated based on the discounted subtotal.
140+
* Since discounts are applied at the invoice level, but taxes are calculated at the item level,
141+
* we allocate the total discount proportionally across individual items before computing taxes.
146142
*/
147-
$allocatedDiscounts = $totalDiscount->allocate(...array_map(
143+
$ratios = array_map(
148144
fn ($item) => $item->subTotalAmount()->abs()->getMinorAmount()->toInt(),
149145
$this->items
150-
));
146+
);
147+
148+
if (array_sum($ratios) === 0) {
149+
return Money::of(0, $this->getCurrency());
150+
}
151+
152+
$allocatedDiscounts = $totalDiscount->allocate(...$ratios);
151153

152154
$totalTaxAmount = Money::of(0, $this->getCurrency());
153155

154156
foreach ($this->items as $index => $item) {
155157

156158
if ($item->unit_tax) {
157159
/**
158-
* When unit_tax is defined, the amount is considered right
159-
* and the discount is not apply
160+
* When unit_tax is defined, the amount is considered correct
160161
*/
161162
$itemTaxAmount = $item->unit_tax->multipliedBy($item->quantity);
162163
} elseif ($item->tax_percentage) {
164+
163165
$itemDiscount = $allocatedDiscounts[$index];
164166

165167
$itemTaxAmount = $item->subTotalAmount()
166168
->minus($itemDiscount)
167169
->multipliedBy($item->tax_percentage / 100.0, roundingMode: RoundingMode::HALF_EVEN);
170+
168171
} else {
169172
$itemTaxAmount = Money::of(0, $totalTaxAmount->getCurrency());
170173
}

tests/Feature/PdfInvoiceTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
expect($pdfInvoice->totalTaxAmount()->getAmount()->toFloat())->toEqual($totalTaxAmount);
4646
expect($pdfInvoice->totalAmount()->getAmount()->toFloat())->toEqual($totalAmount);
4747
})->with([
48+
[[], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
49+
[[['unit_price' => 0.0]], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
50+
[[['unit_price' => 0.0]], 10.0, 0.0, 0.0, 0.0, 0.0, 0.0],
51+
[[['unit_price' => 0.0]], 10.0, 10.0, 0.0, 0.0, 0.0, 0.0],
4852
[[['unit_price' => 100.0]], 0.0, 0.0, 100.0, 0.0, 0.0, 100.0],
4953
[[['unit_price' => 100.0, 'quantity' => 2]], 0.0, 0.0, 200.0, 0.0, 0.0, 200.0],
5054
[[['unit_price' => 100.0, 'quantity' => 0.1]], 0.0, 0.0, 10.0, 0.0, 0.0, 10.0],

0 commit comments

Comments
 (0)