@@ -133,50 +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 */
147143 $ ratios = array_map (
148144 fn ($ item ) => $ item ->subTotalAmount ()->abs ()->getMinorAmount ()->toInt (),
149145 $ this ->items
150146 );
151- // Check if all ratios are zero
152- $ hasNonZeroRatios = collect ($ ratios )->filter (fn ($ ratio ) => $ ratio > 0 )->isNotEmpty ();
153-
154- if ($ hasNonZeroRatios ) {
155- // Normal allocation when we have non-zero ratios
156- $ allocatedDiscounts = $ totalDiscount ->allocate (...$ ratios );
157- } else {
158- // All items have zero price - return zero amounts for each item
159- $ allocatedDiscounts = collect ($ ratios )->map (function () use ($ totalDiscount ) {
160- return Money::of ('0.00 ' , $ totalDiscount ->getCurrency ());
161- })->toArray ();
147+
148+ if (array_sum ($ ratios ) === 0 ) {
149+ return Money::of (0 , $ this ->getCurrency ());
162150 }
163151
152+ $ allocatedDiscounts = $ totalDiscount ->allocate (...$ ratios );
153+
164154 $ totalTaxAmount = Money::of (0 , $ this ->getCurrency ());
165155
166156 foreach ($ this ->items as $ index => $ item ) {
167157
168158 if ($ item ->unit_tax ) {
169159 /**
170- * When unit_tax is defined, the amount is considered right
171- * and the discount is not apply
160+ * When unit_tax is defined, the amount is considered correct
172161 */
173162 $ itemTaxAmount = $ item ->unit_tax ->multipliedBy ($ item ->quantity );
174163 } elseif ($ item ->tax_percentage ) {
164+
175165 $ itemDiscount = $ allocatedDiscounts [$ index ];
176166
177167 $ itemTaxAmount = $ item ->subTotalAmount ()
178168 ->minus ($ itemDiscount )
179169 ->multipliedBy ($ item ->tax_percentage / 100.0 , roundingMode: RoundingMode::HALF_EVEN );
170+
180171 } else {
181172 $ itemTaxAmount = Money::of (0 , $ totalTaxAmount ->getCurrency ());
182173 }
0 commit comments