Skip to content

Commit d989819

Browse files
committed
[FIX] sale_global_discount: discount amounts with round_globally rounding method
1 parent 75051a8 commit d989819

2 files changed

Lines changed: 81 additions & 2 deletions

File tree

sale_global_discount/models/sale_order.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,26 @@ def _compute_amounts(self):
100100
res = super()._compute_amounts()
101101
for order in self:
102102
order._check_global_discounts_sanity()
103-
amount_untaxed_before_global_discounts = order.amount_untaxed
104-
amount_total_before_global_discounts = order.amount_total
105103
discounts = order.global_discount_ids.mapped("discount")
104+
if not any(discounts):
105+
order.update(
106+
{
107+
"amount_untaxed_before_global_discounts": (
108+
order.amount_untaxed
109+
),
110+
"amount_total_before_global_discounts": order.amount_total,
111+
"amount_global_discount": 0.0,
112+
}
113+
)
114+
continue
115+
amount_untaxed_before_global_discounts = 0
116+
amount_total_before_global_discounts = 0
106117
amount_discounted_untaxed = amount_discounted_tax = 0
107118
for line in order.order_line:
119+
# Compare per-line rounded amounts with per-line rounded
120+
# amounts.
121+
amount_untaxed_before_global_discounts += line.price_subtotal
122+
amount_total_before_global_discounts += line.price_total
108123
discounted_subtotal = line.price_subtotal
109124
if not line.product_id.bypass_global_discount:
110125
discounted_subtotal = self.get_discounted_global(
@@ -145,6 +160,8 @@ def _compute_amounts(self):
145160
def _compute_tax_totals(self):
146161
res = super()._compute_tax_totals()
147162
for order in self:
163+
if not any(order.global_discount_ids.mapped("discount")):
164+
continue
148165
amount_discount_by_group = {}
149166
cumulative_discount_rate = 1.0
150167
currency = order.currency_id

sale_global_discount/tests/test_sale_global_discount.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,65 @@ def test_08_global_discount_with_tax_included(self):
271271
self.assertAlmostEqual(
272272
self.get_taxes_widget_total_tax(self.sale), self.sale.amount_tax
273273
)
274+
275+
def _create_rounding_sale(self):
276+
"""Order whose per-line rounded subtotals (90.67) differ from the
277+
globally rounded untaxed amount (90.66) with 3-decimal unit prices."""
278+
self.env.ref("product.decimal_price").digits = 3
279+
self.sale.company_id.tax_calculation_rounding_method = "round_globally"
280+
sale_form = Form(self.env["sale.order"])
281+
sale_form.partner_id = self.partner_1
282+
for qty, price in [(3, 3.460), (1, 25.000), (6, 4.713), (6, 4.501)]:
283+
with sale_form.order_line.new() as order_line:
284+
order_line.product_id = self.product_1
285+
order_line.tax_id.clear()
286+
order_line.tax_id.add(self.tax_1)
287+
order_line.product_uom_qty = qty
288+
order_line.price_unit = price
289+
return sale_form.save()
290+
291+
def test_09_no_phantom_discount_round_globally(self):
292+
"""Without global discounts the core totals must stay untouched."""
293+
sale = self._create_rounding_sale()
294+
self.assertFalse(sale.global_discount_ids)
295+
self.assertAlmostEqual(sale.amount_global_discount, 0.0)
296+
self.assertAlmostEqual(sale.amount_untaxed, 90.66)
297+
self.assertAlmostEqual(sale.amount_untaxed_before_global_discounts, 90.66)
298+
self.assertAlmostEqual(sale.tax_totals["base_amount_currency"], 90.66)
299+
300+
def test_10_zero_discount_round_globally(self):
301+
"""A 0% global discount must behave like no discount at all."""
302+
zero_discount = self.global_discount_obj.create(
303+
{
304+
"name": "Zero Discount",
305+
"discount_scope": "sale",
306+
"discount": 0,
307+
"account_id": self.account.id,
308+
}
309+
)
310+
sale = self._create_rounding_sale()
311+
sale.global_discount_ids = zero_discount
312+
sale._compute_amounts()
313+
sale._compute_tax_totals()
314+
self.assertAlmostEqual(sale.amount_global_discount, 0.0)
315+
self.assertAlmostEqual(sale.amount_untaxed, 90.66)
316+
self.assertAlmostEqual(sale.amount_untaxed_before_global_discounts, 90.66)
317+
self.assertAlmostEqual(sale.tax_totals["base_amount_currency"], 90.66)
318+
319+
def test_11_real_discount_round_globally_consistency(self):
320+
"""With a real discount the shown triplet must be coherent:
321+
before - discount == untaxed, all built from per-line amounts."""
322+
sale = self._create_rounding_sale()
323+
sale.global_discount_ids = self.global_discount_1 # 20%
324+
sale._compute_amounts()
325+
self.assertAlmostEqual(sale.amount_untaxed_before_global_discounts, 90.67)
326+
self.assertAlmostEqual(sale.amount_global_discount, 18.13)
327+
self.assertAlmostEqual(sale.amount_untaxed, 72.54)
328+
self.assertAlmostEqual(
329+
sale.amount_untaxed_before_global_discounts - sale.amount_global_discount,
330+
sale.amount_untaxed,
331+
)
332+
self.assertAlmostEqual(
333+
sale.amount_total_before_global_discounts,
334+
sum(sale.order_line.mapped("price_total")),
335+
)

0 commit comments

Comments
 (0)