From 53a98610a6be8ae0ec9332035a4ebf7ed4a7c8e5 Mon Sep 17 00:00:00 2001 From: "Mohit Ahir (moahi)" Date: Mon, 25 May 2026 17:26:22 +0530 Subject: [PATCH] [ADD] zero_stock_sale_approval: add zero stock approval field on sale order Sales users were able to confirm orders even when stock was not available. This could lead to wrong commitments, stock issues, and lack of proper control. Introduced a zero stock approval mechanism in sale orders. Added a Boolean field zero_stock_approval to control confirmation behavior. - Created a new module for zero stock approval - Added zero_stock_approval field in sale.order model - Restricted field editing to Admin/Sales Manager only - Updated action_confirm to validate stock before confirming - Blocked confirmation when stock is insufficient unless approval is enabled - Extended sale order form view to display the new field --- zero_stock_sale_approval/__init__.py | 1 + zero_stock_sale_approval/__manifest__.py | 10 ++++++++ zero_stock_sale_approval/models/__init__.py | 1 + .../models/sale_zero_stock.py | 23 +++++++++++++++++++ .../views/sale_order_views.xml | 18 +++++++++++++++ 5 files changed, 53 insertions(+) create mode 100644 zero_stock_sale_approval/__init__.py create mode 100644 zero_stock_sale_approval/__manifest__.py create mode 100644 zero_stock_sale_approval/models/__init__.py create mode 100644 zero_stock_sale_approval/models/sale_zero_stock.py create mode 100644 zero_stock_sale_approval/views/sale_order_views.xml diff --git a/zero_stock_sale_approval/__init__.py b/zero_stock_sale_approval/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/zero_stock_sale_approval/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/zero_stock_sale_approval/__manifest__.py b/zero_stock_sale_approval/__manifest__.py new file mode 100644 index 00000000000..86d2c0bbd10 --- /dev/null +++ b/zero_stock_sale_approval/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': 'Sale Zero Stock Approval', + 'description': 'Grant permission to confirm approved orders without stock.', + 'depends': ['sale_management', 'sale_stock'], + 'author': 'moahi', + 'license': 'LGPL-3', + 'data': [ + 'views/sale_order_views.xml', + ] +} diff --git a/zero_stock_sale_approval/models/__init__.py b/zero_stock_sale_approval/models/__init__.py new file mode 100644 index 00000000000..06ba4c532b6 --- /dev/null +++ b/zero_stock_sale_approval/models/__init__.py @@ -0,0 +1 @@ +from . import sale_zero_stock diff --git a/zero_stock_sale_approval/models/sale_zero_stock.py b/zero_stock_sale_approval/models/sale_zero_stock.py new file mode 100644 index 00000000000..fe3649a9244 --- /dev/null +++ b/zero_stock_sale_approval/models/sale_zero_stock.py @@ -0,0 +1,23 @@ +from odoo import fields, models +from odoo.exceptions import AccessError + + +class SaleZeroStock(models.Model): + _inherit = 'sale.order' + + zero_stock_approval = fields.Boolean(string="Approval by Manager", default=False) + + def action_confirm(self): + for record in self: + for item in record.order_line: + if ( + not record.zero_stock_approval + and not self.env.user.has_group("sales_team.group_sale_manager") + and item.product_id.type == "consu" + and item.product_id.is_storable + and item.product_id.qty_available < item.product_uom_qty + ): + raise AccessError( + "Access denied: You are not allowed to confirm this sales order." + ) + return super().action_confirm() diff --git a/zero_stock_sale_approval/views/sale_order_views.xml b/zero_stock_sale_approval/views/sale_order_views.xml new file mode 100644 index 00000000000..4ad9dfb9960 --- /dev/null +++ b/zero_stock_sale_approval/views/sale_order_views.xml @@ -0,0 +1,18 @@ + + + + + sale.order.form.inherit.sale.zero.stock + sale.order + + + + + + + + + + + +