diff --git a/addons/purchase_mrp/__manifest__.py b/addons/purchase_mrp/__manifest__.py index dea571c9844..381224ba3bb 100644 --- a/addons/purchase_mrp/__manifest__.py +++ b/addons/purchase_mrp/__manifest__.py @@ -14,6 +14,7 @@ It is basically used when we want to keep track of production orders generated from purchase order. """, 'data': [ + 'views/mrp_bom_views.xml', 'views/purchase_order_views.xml', 'views/mrp_production_views.xml', 'security/ir.model.access.csv', diff --git a/addons/purchase_mrp/models/__init__.py b/addons/purchase_mrp/models/__init__.py index e2f71af6120..7b2d54d8ecc 100644 --- a/addons/purchase_mrp/models/__init__.py +++ b/addons/purchase_mrp/models/__init__.py @@ -4,4 +4,5 @@ from . import account_move from . import purchase from . import mrp_production +from . import mrp_bom from . import stock_move diff --git a/addons/purchase_mrp/models/mrp_bom.py b/addons/purchase_mrp/models/mrp_bom.py new file mode 100644 index 00000000000..dfa662b8b35 --- /dev/null +++ b/addons/purchase_mrp/models/mrp_bom.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models, _ +from odoo.exceptions import UserError + + +class MrpBom(models.Model): + _inherit = 'mrp.bom' + + def _check_bom_lines(self): + res = super()._check_bom_lines() + for bom in self: + if all(not bl.cost_share for bl in bom.bom_lines): + continue + if any(bl.cost_share < 0 for bl in bom.bom_lines): + raise UserError(_("Components cost share have to be positive or equals to zero.")) + if sum(bom.bom_lines.mapped('cost_share')) != 100: + raise UserError(_("The total cost share for a BoM's component have to be 100")) + return res + + +class MrpBomLine(models.Model): + _inherit = 'mrp.bom.line' + + cost_share = fields.Float( + "Cost Share (%)", digits=(5, 2), # decimal = 2 is important for rounding calculations!! + help="The percentage of the component repartition cost when purchasing a kit." + "The total of all components' cost have to be equal to 100.") + + def _get_cost_share(self): + self.ensure_one() + if self.cost_share: + return fields.Float.round(self.cost_share / 100, 2) + bom = self.bom_id + bom_lines_without_cost_share = bom.bom_line_ids.filtered(lambda bl: not bl.cost_share) + return fields.Float.round(1 / len(bom_lines_without_cost_share), 2) diff --git a/addons/purchase_mrp/models/stock_move.py b/addons/purchase_mrp/models/stock_move.py index 57322213a58..2274b5750ca 100644 --- a/addons/purchase_mrp/models/stock_move.py +++ b/addons/purchase_mrp/models/stock_move.py @@ -16,6 +16,13 @@ class StockMove(models.Model): vals['purchase_line_id'] = self.purchase_line_id.id return vals + def _get_price_unit(self): + price_unit = super()._get_price_unit() + if self.product_id == self.purchase_line_id.product_id or not self.bom_line_id: + return price_unit + cost_share = self.bom_line_id._get_cost_share() + return price_unit * cost_share + def _get_valuation_price_and_qty(self, related_aml, to_curr): valuation_price_unit_total, valuation_total_qty = super()._get_valuation_price_and_qty(related_aml, to_curr) boms = self.env['mrp.bom']._bom_find(related_aml.product_id, company_id=related_aml.company_id.id, bom_type='phantom') diff --git a/addons/purchase_mrp/views/mrp_bom_views.xml b/addons/purchase_mrp/views/mrp_bom_views.xml new file mode 100644 index 00000000000..0af2e237aeb --- /dev/null +++ b/addons/purchase_mrp/views/mrp_bom_views.xml @@ -0,0 +1,13 @@ + + + + mrp.bom.view.form.inherited.purchase.mrp + mrp.bom + + + + + + + + \ No newline at end of file diff --git a/addons/purchase_stock/models/stock_move.py b/addons/purchase_stock/models/stock_move.py index b6d5c0efaa1..e70323dfb34 100644 --- a/addons/purchase_stock/models/stock_move.py +++ b/addons/purchase_stock/models/stock_move.py @@ -29,7 +29,7 @@ class StockMove(models.Model): def _get_price_unit(self): """ Returns the unit price for the move""" self.ensure_one() - if self.purchase_line_id and self.product_id.id == self.purchase_line_id.product_id.id: + if self.purchase_line_id and self.product_id.id: price_unit_prec = self.env['decimal.precision'].precision_get('Product Price') line = self.purchase_line_id order = line.order_id