From d5a583eaf1e6169119d7eabb8505aaa188c0301f Mon Sep 17 00:00:00 2001 From: arkp-odoo Date: Tue, 22 Jul 2025 18:41:56 +0530 Subject: [PATCH] [ADD] sale: Auto-recalculate global discount on order line changes Enhanced the Sales Order logic to automatically recalculate and update the global discount line whenever sale order lines are added, updated, or deleted. This ensures that the discount remains in sync with the current order total. If all product lines are removed, the discount line is also removed. This improves data consistency and reduces the need for manual discount updates. task-4962389 --- discount_price/__init__.py | 2 ++ discount_price/__manifest__.py | 7 ++++++ discount_price/models/__init__.py | 3 +++ discount_price/models/sale_order.py | 32 ++++++++++++++++++++++++ discount_price/models/sale_order_line.py | 31 +++++++++++++++++++++++ 5 files changed, 75 insertions(+) create mode 100644 discount_price/__init__.py create mode 100644 discount_price/__manifest__.py create mode 100644 discount_price/models/__init__.py create mode 100644 discount_price/models/sale_order.py create mode 100644 discount_price/models/sale_order_line.py diff --git a/discount_price/__init__.py b/discount_price/__init__.py new file mode 100644 index 00000000000..d581b39cea7 --- /dev/null +++ b/discount_price/__init__.py @@ -0,0 +1,2 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import models diff --git a/discount_price/__manifest__.py b/discount_price/__manifest__.py new file mode 100644 index 00000000000..30f297648e0 --- /dev/null +++ b/discount_price/__manifest__.py @@ -0,0 +1,7 @@ +{ + 'name': 'Discount Price', + 'version': '1.0', + 'depends': ['sale_management'], + 'installable': True, + 'license': 'LGPL-3', +} diff --git a/discount_price/models/__init__.py b/discount_price/models/__init__.py new file mode 100644 index 00000000000..feb2b96170a --- /dev/null +++ b/discount_price/models/__init__.py @@ -0,0 +1,3 @@ +# Part of Odoo. See LICENSE file for full copyright and licensing details. +from . import sale_order +from . import sale_order_line diff --git a/discount_price/models/sale_order.py b/discount_price/models/sale_order.py new file mode 100644 index 00000000000..4e623883394 --- /dev/null +++ b/discount_price/models/sale_order.py @@ -0,0 +1,32 @@ +from odoo import fields, models + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + discount_percentage = fields.Float(string="Global Discount (%)") + wizard_ids = fields.One2many("sale.order.discount", "sale_order_id", string="Discount Wizards") + + def _update_discount(self): + discount_product = self.env["product.product"].search([("name", "=", "Discount")], limit=1) + if not discount_product: + return + total_amount = sum(line.price_total for line in self.order_line if not line.is_discount_line()) + if not total_amount: + discount_lines = self.order_line.filtered(lambda l: l.is_discount_line()) + discount_lines.unlink() + return + + if self.wizard_ids: + discount_percentage = self.wizard_ids[-1].discount_percentage + else: + return + discount_amount = total_amount * (discount_percentage) + discount_line = self.order_line.filtered(lambda l: l.is_discount_line()) + if discount_line: + discount_line.write( + { + "price_unit": discount_amount * (-1), + "name": f"Discount{discount_percentage * 100:.2f}%", + } + ) diff --git a/discount_price/models/sale_order_line.py b/discount_price/models/sale_order_line.py new file mode 100644 index 00000000000..b4b439127b5 --- /dev/null +++ b/discount_price/models/sale_order_line.py @@ -0,0 +1,31 @@ +from odoo import api, models + + +class SaleOrderLine(models.Model): + _inherit = "sale.order.line" + + def is_discount_line(self): + discount_product = self.order_id.env["product.product"].search([("name", "=", "Discount")], limit=1) + return self.product_id == discount_product + + def unlink(self): + order_ids = self.mapped("order_id") + res = super().unlink() + for order in order_ids: + order._update_discount() + return res + + @api.model_create_multi + def create(self, vals): + lines = super().create(vals) + for line in lines: + if line.order_id and not line.is_discount_line(): + line.order_id._update_discount() + return lines + + def write(self, vals): + res = super().write(vals) + for line in self: + if not line.is_discount_line(): + line.order_id._update_discount() + return res