diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py index 64859aae120..3d5a8c3126e 100644 --- a/addons/mrp/models/mrp_production.py +++ b/addons/mrp/models/mrp_production.py @@ -920,9 +920,9 @@ class MrpProduction(models.Model): self.qty_producing = self.product_id.uom_id._compute_quantity(1, self.product_uom_id, rounding_method='HALF-UP') for move in (self.move_raw_ids | self.move_finished_ids.filtered(lambda m: m.product_id != self.product_id)): - if move._should_bypass_set_qty_producing(): + if move._should_bypass_set_qty_producing() or not move.product_uom: continue - new_qty = self.product_uom_id._compute_quantity((self.qty_producing - self.qty_produced) * move.unit_factor, self.product_uom_id, rounding_method='HALF-UP') + new_qty = float_round((self.qty_producing - self.qty_produced) * move.unit_factor, precision_rounding=move.product_uom.rounding) move.move_line_ids.filtered(lambda ml: ml.state not in ('done', 'cancel')).qty_done = 0 move.move_line_ids = move._set_quantity_done_prepare_vals(new_qty) diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py index 10232cf48a9..55dd6289275 100644 --- a/addons/mrp/models/stock_move.py +++ b/addons/mrp/models/stock_move.py @@ -165,14 +165,14 @@ class StockMove(models.Model): moves_with_reference |= move super(StockMove, self - moves_with_reference)._compute_reference() - @api.depends('raw_material_production_id.qty_producing', 'product_uom_qty') + @api.depends('raw_material_production_id.qty_producing', 'product_uom_qty', 'product_uom') def _compute_should_consume_qty(self): for move in self: mo = move.raw_material_production_id - if not mo: + if not mo or not move.product_uom: move.should_consume_qty = 0 continue - move.should_consume_qty = mo.product_uom_id._compute_quantity((mo.qty_producing - mo.qty_produced) * move.unit_factor, mo.product_uom_id, rounding_method='HALF-UP') + move.should_consume_qty = float_round((mo.qty_producing - mo.qty_produced) * move.unit_factor, precision_rounding=move.product_uom.rounding) @api.onchange('product_uom_qty') def _onchange_product_uom_qty(self): diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py index b00cb6a267c..af7374e99c6 100644 --- a/addons/mrp/tests/test_order.py +++ b/addons/mrp/tests/test_order.py @@ -1521,6 +1521,61 @@ class TestMrpOrder(TestMrpCommon): self.assertEqual(mo.move_finished_ids.quantity_done, 1) self.assertEqual(component.qty_available, 13) + def test_immediate_validate_uom_2(self): + """The rounding precision of a component should be based on the UoM used in the MO for this component, + not on the produced product's UoM nor the default UoM of the component""" + uom_units = self.env['ir.model.data'].xmlid_to_object('uom.product_uom_unit') + uom_L = self.env['ir.model.data'].xmlid_to_object('uom.product_uom_litre') + uom_cL = self.env['uom.uom'].create({ + 'name': 'cL', + 'category_id': uom_L.category_id.id, + 'uom_type': 'smaller', + 'factor': 100, + 'rounding': 1, + }) + uom_units.rounding = 1 + uom_L.rounding = 0.01 + + product = self.env['product.product'].create({ + 'name': 'SuperProduct', + 'uom_id': uom_units.id, + }) + consumable_component = self.env['product.product'].create({ + 'name': 'Consumable Component', + 'type': 'consu', + 'uom_id': uom_cL.id, + 'uom_po_id': uom_cL.id, + }) + storable_component = self.env['product.product'].create({ + 'name': 'Storable Component', + 'type': 'product', + 'uom_id': uom_cL.id, + 'uom_po_id': uom_cL.id, + }) + self.env['stock.quant']._update_available_quantity(storable_component, self.env.ref('stock.stock_location_stock'), 100) + + for component in [consumable_component, storable_component]: + bom = self.env['mrp.bom'].create({ + 'product_tmpl_id': product.product_tmpl_id.id, + 'bom_line_ids': [(0, 0, { + 'product_id': component.id, + 'product_qty': 0.2, + 'product_uom_id': uom_L.id, + })], + }) + + mo_form = Form(self.env['mrp.production']) + mo_form.bom_id = bom + mo = mo_form.save() + mo.action_confirm() + action = mo.button_mark_done() + self.assertEqual(action.get('res_model'), 'mrp.immediate.production') + wizard = Form(self.env[action['res_model']].with_context(action['context'])).save() + action = wizard.process() + + self.assertEqual(mo.move_raw_ids.product_uom_qty, 0.2) + self.assertEqual(mo.move_raw_ids.quantity_done, 0.2) + def test_copy(self): """ Check that copying a done production, create all the stock moves""" mo, bom, p_final, p1, p2 = self.generate_mo(qty_final=1, qty_base_1=1, qty_base_2=1)