From 5e595e9f2b03a4ebc721ce50e3908d9f50d89080 Mon Sep 17 00:00:00 2001 From: Raman Marikanti Date: Fri, 12 Dec 2025 12:15:57 +0530 Subject: [PATCH] fix -ve stock issue --- .../costing_mrp_bom/models/__init__.py | 3 +- custom_addons/costing_mrp_bom/models/mrp.py | 4 +- .../costing_mrp_bom/models/sale_order_line.py | 25 ++- .../costing_mrp_bom/models/stock_quant.py | 39 ++++ .../report/samashti_invoice_print.xml | 176 ++++++++++++++++++ .../costing_mrp_bom/views/bom_view.xml | 6 +- 6 files changed, 247 insertions(+), 6 deletions(-) create mode 100644 custom_addons/costing_mrp_bom/models/stock_quant.py create mode 100644 custom_addons/costing_mrp_bom/report/samashti_invoice_print.xml diff --git a/custom_addons/costing_mrp_bom/models/__init__.py b/custom_addons/costing_mrp_bom/models/__init__.py index d060c996b..2648ee3d2 100644 --- a/custom_addons/costing_mrp_bom/models/__init__.py +++ b/custom_addons/costing_mrp_bom/models/__init__.py @@ -1,2 +1,3 @@ from . import mrp -from . import sale_order_line \ No newline at end of file +from . import sale_order_line +from . import stock_quant \ No newline at end of file diff --git a/custom_addons/costing_mrp_bom/models/mrp.py b/custom_addons/costing_mrp_bom/models/mrp.py index af4c5ab1e..99dbe8ff0 100644 --- a/custom_addons/costing_mrp_bom/models/mrp.py +++ b/custom_addons/costing_mrp_bom/models/mrp.py @@ -4,8 +4,8 @@ from ast import literal_eval from collections import defaultdict from odoo import fields, models, _, api -from odoo.tools import float_round -from odoo.exceptions import ValidationError +from odoo.tools import float_round, float_compare +from odoo.exceptions import ValidationError, UserError class MrpProduction(models.Model): diff --git a/custom_addons/costing_mrp_bom/models/sale_order_line.py b/custom_addons/costing_mrp_bom/models/sale_order_line.py index d5f262f86..60d6c99fb 100644 --- a/custom_addons/costing_mrp_bom/models/sale_order_line.py +++ b/custom_addons/costing_mrp_bom/models/sale_order_line.py @@ -68,11 +68,19 @@ class SaleOrderLine(models.Model): digits='Product Price', store=True, readonly=False, precompute=True, groups="base.group_user") - @api.depends('product_id', 'company_id', 'product_uom','product_uom_qty') + price_unit_kg = fields.Float(string="Rate(kg)") + + @api.depends('product_uom_qty') def _compute_bag_weight(self): for line in self: line.bag_weight = line.product_id.weight * line.product_uom_qty + @api.onchange('bag_weight') + def _onchange_bag_update_qty(self): + for line in self: + if line.product_id and line.product_id.weight: + line.product_uom_qty = line.bag_weight / line.product_id.weight + @api.depends('product_id', 'company_id', 'currency_id', 'product_uom') def _compute_purchase_price(self): @@ -100,4 +108,19 @@ class SaleOrderLine(models.Model): if line.order_id and line.order_id.state == 'sale': continue line.price_unit = 0.0 + + # @api.onchange('price_unit', 'price_unit_kg', 'bag_weight') + # def _onchange_prices(self): + # for line in self: + # if not line.bag_weight: + # line.price_unit_kg = 0.0 + # return + # + # # If price_unit is changed by user → update price_unit_kg + # if line.price_unit and not self._origin.price_unit == line.price_unit: + # line.price_unit_kg = line.price_unit / line.bag_weight + # + # # If price_unit_kg is changed by user → update price_unit + # elif line.price_unit_kg and not self._origin.price_unit_kg == line.price_unit_kg: + # line.price_unit = line.price_unit_kg * line.bag_weight diff --git a/custom_addons/costing_mrp_bom/models/stock_quant.py b/custom_addons/costing_mrp_bom/models/stock_quant.py new file mode 100644 index 000000000..299ff8dc6 --- /dev/null +++ b/custom_addons/costing_mrp_bom/models/stock_quant.py @@ -0,0 +1,39 @@ +from odoo import fields, models, _, api +from odoo.tools import float_round, float_compare +from odoo.exceptions import ValidationError, UserError + + +class StockQuant(models.Model): + _inherit = "stock.quant" + + @api.constrains("product_id", "quantity") + def check_negative_qty(self): + if self.env.context.get("skip_negative_qty_check"): + return + p = self.env["decimal.precision"].precision_get("Product Unit of Measure") + + + for quant in self: + if ( + float_compare(quant.quantity, 0, precision_digits=p) == -1 + and quant.product_id.type == "consu" + and quant.location_id.usage in ["internal", "transit"] + ): + msg_add = "" + if quant.lot_id: + msg_add = _(" lot {}").format(quant.lot_id.name_get()[0][1]) + raise ValidationError( + _( + "You cannot validate this stock operation because the " + "stock level of the product '{name}'{name_lot} would " + "become negative " + "({q_quantity}) on the stock location '{complete_name}' " + "and negative stock is " + "not allowed for this product and/or location." + ).format( + name=quant.product_id.display_name, + name_lot=msg_add, + q_quantity=quant.quantity, + complete_name=quant.location_id.complete_name, + ) + ) \ No newline at end of file diff --git a/custom_addons/costing_mrp_bom/report/samashti_invoice_print.xml b/custom_addons/costing_mrp_bom/report/samashti_invoice_print.xml new file mode 100644 index 000000000..e488d2f6b --- /dev/null +++ b/custom_addons/costing_mrp_bom/report/samashti_invoice_print.xml @@ -0,0 +1,176 @@ + + + + + + + + \ No newline at end of file diff --git a/custom_addons/costing_mrp_bom/views/bom_view.xml b/custom_addons/costing_mrp_bom/views/bom_view.xml index f847d8e21..d4b03fd33 100644 --- a/custom_addons/costing_mrp_bom/views/bom_view.xml +++ b/custom_addons/costing_mrp_bom/views/bom_view.xml @@ -21,9 +21,11 @@ sale.order - + + + - +