From 7d0990ca70c17a6e2a3c8c1c1058a7de7d903c5d Mon Sep 17 00:00:00 2001 From: pupat-odoo Date: Fri, 27 Mar 2026 11:25:07 +0530 Subject: [PATCH] [ADD] purchase_global_discount: added global discount on purchase order lines. Purpose : - Applying global discount to all order lines , avoids the manual setting of indivial discount enrtries. - Allows discount value to be represented in native monetary values. Features : - Added a discount button below the order lines which opens a wizard dialog box. - Implemented wizard view for adding the discount value with its specific type. - with a single click on 'Apply' button, all the order lines amount get updated with new one. Technical insights: 1) Added 'purchase_order' model which is implemented using Transient model. 2) 'purchase_order_discount' wizard view added . --- purchase_global_discount/__init__.py | 4 ++ purchase_global_discount/__manifest__.py | 18 +++++++ purchase_global_discount/models/__init__.py | 3 ++ .../models/purchase_order.py | 15 ++++++ .../security/ir.model.access.csv | 2 + .../views/purchase_order_views.xml | 15 ++++++ purchase_global_discount/wizard/__init__.py | 1 + .../wizard/purchase_order_discount.py | 50 +++++++++++++++++++ .../wizard/purchase_order_discount_views.xml | 22 ++++++++ 9 files changed, 130 insertions(+) create mode 100644 purchase_global_discount/__init__.py create mode 100644 purchase_global_discount/__manifest__.py create mode 100644 purchase_global_discount/models/__init__.py create mode 100644 purchase_global_discount/models/purchase_order.py create mode 100644 purchase_global_discount/security/ir.model.access.csv create mode 100644 purchase_global_discount/views/purchase_order_views.xml create mode 100644 purchase_global_discount/wizard/__init__.py create mode 100644 purchase_global_discount/wizard/purchase_order_discount.py create mode 100644 purchase_global_discount/wizard/purchase_order_discount_views.xml diff --git a/purchase_global_discount/__init__.py b/purchase_global_discount/__init__.py new file mode 100644 index 00000000000..3f1aab2085f --- /dev/null +++ b/purchase_global_discount/__init__.py @@ -0,0 +1,4 @@ +from . import ( + models, # noqa : F401 + wizard, # noqa : F401 +) diff --git a/purchase_global_discount/__manifest__.py b/purchase_global_discount/__manifest__.py new file mode 100644 index 00000000000..1762d608944 --- /dev/null +++ b/purchase_global_discount/__manifest__.py @@ -0,0 +1,18 @@ +{ + "name": "purchase_dicount", + "description": "Add discount button with its wizard", + "author": "odoo-pupat", + "website": "https://www.odoo.com/", + "category": "Purchase-custom", + "version": "0.1", + "application": True, + "installable": True, + "depends": ["purchase"], + "data": [ + "security/ir.model.access.csv", + "views/purchase_order_views.xml", + "wizard/purchase_order_discount_views.xml", + ], + "assets": {}, + "license": "LGPL-3", +} diff --git a/purchase_global_discount/models/__init__.py b/purchase_global_discount/models/__init__.py new file mode 100644 index 00000000000..307a154a11f --- /dev/null +++ b/purchase_global_discount/models/__init__.py @@ -0,0 +1,3 @@ +from . import ( + purchase_order, # noqa: F401 +) diff --git a/purchase_global_discount/models/purchase_order.py b/purchase_global_discount/models/purchase_order.py new file mode 100644 index 00000000000..c7013a035e8 --- /dev/null +++ b/purchase_global_discount/models/purchase_order.py @@ -0,0 +1,15 @@ +from odoo import models + + +class InheritedPurchaseOrder(models.Model): + _inherit = "purchase.order" + + def action_open_discount_wizard(self): + self.ensure_one() + return { + "name": "Discount", + "type": "ir.actions.act_window", + "res_model": "purchase.order.discount", + "view_mode": "form", + "target": "new", + } diff --git a/purchase_global_discount/security/ir.model.access.csv b/purchase_global_discount/security/ir.model.access.csv new file mode 100644 index 00000000000..f68ace605d0 --- /dev/null +++ b/purchase_global_discount/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_purchase_discount_wizard,purchase.discount.wizard,model_purchase_order_discount,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/purchase_global_discount/views/purchase_order_views.xml b/purchase_global_discount/views/purchase_order_views.xml new file mode 100644 index 00000000000..5352365e4d8 --- /dev/null +++ b/purchase_global_discount/views/purchase_order_views.xml @@ -0,0 +1,15 @@ + + + + purchase.view.form.purchase.discount + purchase.order + + + +
+
+
+
+
+
diff --git a/purchase_global_discount/wizard/__init__.py b/purchase_global_discount/wizard/__init__.py new file mode 100644 index 00000000000..07afb7cc183 --- /dev/null +++ b/purchase_global_discount/wizard/__init__.py @@ -0,0 +1 @@ +from . import purchase_order_discount # noqa: F401 diff --git a/purchase_global_discount/wizard/purchase_order_discount.py b/purchase_global_discount/wizard/purchase_order_discount.py new file mode 100644 index 00000000000..a258d8c8083 --- /dev/null +++ b/purchase_global_discount/wizard/purchase_order_discount.py @@ -0,0 +1,50 @@ +from odoo import api, fields, models +from odoo.exceptions import ValidationError + + +class PurchaseOrderDiscount(models.TransientModel): + _name = "purchase.order.discount" + _description = "Discount Wizard" + + purchase_order_id = fields.Many2one( + "purchase.order", + default=lambda self: self.env.context.get("active_id"), + required=True, + ) + discount_percentage = fields.Float(string="Percentage") + discount_type = fields.Selection( + selection=[ + ("percentage", "%"), + ("amount", "$"), + ], + default="percentage", + ) + percentage = fields.Float(compute="_compute_initial_discount") + + @api.depends("discount_type", "discount_percentage") + def _compute_initial_discount(self): + if self.discount_type == "amount": + if self.purchase_order_id.amount_untaxed == 0: + raise ValidationError("No more discount possible") + self.percentage = ( + self.discount_percentage * 100 / self.purchase_order_id.amount_untaxed + ) + else: + self.percentage = self.discount_percentage + + def action_apply_discount(self): + self.ensure_one() + if self.discount_type == "amount": + self.purchase_order_id.order_line.write( + { + "discount": ( + self.discount_percentage + * 100 + / self.purchase_order_id.amount_untaxed + ) + } + ) + else: + self.purchase_order_id.order_line.write( + {"discount": self.discount_percentage} + ) diff --git a/purchase_global_discount/wizard/purchase_order_discount_views.xml b/purchase_global_discount/wizard/purchase_order_discount_views.xml new file mode 100644 index 00000000000..f0acb906e5c --- /dev/null +++ b/purchase_global_discount/wizard/purchase_order_discount_views.xml @@ -0,0 +1,22 @@ + + + + + purchase.order.discount.form + purchase.order.discount + +
+ + + + + + + +
+
+
+