Skip to content

Commit 718c0b0

Browse files
committed
[ADD] sale_discount_recompute: recompute global discount on order line changes
Ensure that the global discount line in Sale Orders is kept in sync with the current order lines. - Recalculate discount when order lines are added, updated, or removed. - Remove discount line when no order line is present. - Handle for single discount and multi-discount lines as well. task-5008128
1 parent fbf9ee9 commit 718c0b0

File tree

4 files changed

+57
-0
lines changed

4 files changed

+57
-0
lines changed

sale_discount_recompute/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
'name': 'Sale Discount Recompute',
3+
'version': '1.0',
4+
'depends': ['sale_management'],
5+
'author': 'Jay Chauhan',
6+
'category': 'Sales',
7+
'summary': 'Automatic Global Discount Recalculation on Sale Orders',
8+
'description': '''
9+
This feature ensures proper handling of a global discount on Sale Orders.
10+
11+
- When order lines are added, removed, or updated, the discount line is automatically recalculated to reflect the new subtotal.
12+
- If all order lines are removed, the discount line is also removed.
13+
- Prevents stale discount amounts from remaining when order content changes.
14+
''',
15+
'installable': True,
16+
'application': False,
17+
'auto_install': False,
18+
'license': 'LGPL-3'
19+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import sale_order
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from odoo import Command, api, models
2+
3+
4+
class SaleOrder(models.Model):
5+
_inherit = "sale.order"
6+
7+
@api.onchange('order_line')
8+
def _onchange_order_line(self):
9+
"""
10+
Triggered in the UI when order lines or global_discount changes.
11+
Applies the global discount to each order line.
12+
"""
13+
# Get the default discount productid
14+
discount_product_id = self.company_id.sale_discount_product_id
15+
16+
# Separate Product lines and Discount lines [Old: without changed value, New: with changed value in UI]
17+
old_product_lines = self._origin.order_line.filtered(lambda line: line.product_id != discount_product_id)
18+
new_product_lines = self.order_line.filtered(lambda line: line.product_id != discount_product_id)
19+
old_discount_lines = (self._origin.order_line - old_product_lines)
20+
new_discount_lines = (self.order_line - new_product_lines)
21+
22+
# Calculate Product total
23+
old_product_total = sum(old_product_lines.mapped('price_subtotal'))
24+
new_product_total = sum(new_product_lines.mapped('price_subtotal'))
25+
26+
# If product lines exists, calculate new discount unit rates else remove discount lines
27+
if new_product_lines:
28+
if old_product_total != new_product_total:
29+
old_discount_units = old_discount_lines.mapped('price_unit')
30+
for index, line in enumerate(new_discount_lines):
31+
discount_percentage = (abs(old_discount_units[index]) / old_product_total * 100) if old_product_total else 0.0
32+
line.price_unit = -((new_product_total * discount_percentage) / 100)
33+
else:
34+
commands = [Command.unlink(line_id) for line_id in new_discount_lines.mapped('id')]
35+
if commands:
36+
self.order_line = [c for c in commands]

0 commit comments

Comments
 (0)