diff --git a/addons/mrp/models/mrp_unbuild.py b/addons/mrp/models/mrp_unbuild.py index c3ca662652b..6dd4f0a55c5 100644 --- a/addons/mrp/models/mrp_unbuild.py +++ b/addons/mrp/models/mrp_unbuild.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, _ from odoo.exceptions import AccessError, UserError -from odoo.tools import float_compare +from odoo.tools import float_compare, float_round from odoo.osv import expression @@ -182,7 +182,7 @@ class MrpUnbuild(models.Model): }) needed_quantity -= taken_quantity else: - move.quantity_done = move.product_uom_qty + move.quantity_done = float_round(move.product_uom_qty, precision_rounding=move.product_uom.rounding) finished_moves._action_done() consume_moves._action_done() diff --git a/addons/mrp/tests/test_unbuild.py b/addons/mrp/tests/test_unbuild.py index 778225c3bc8..dee22c6a46e 100644 --- a/addons/mrp/tests/test_unbuild.py +++ b/addons/mrp/tests/test_unbuild.py @@ -598,3 +598,36 @@ class TestUnbuild(TestMrpCommon): self.assertEqual(StockQuant._get_available_quantity(finshed_product, self.stock_location), 0, 'Table should not be available in stock') self.assertEqual(StockQuant._get_available_quantity(component1, self.stock_location), 1, 'Table head should be available in stock as the picking is transferred') self.assertEqual(StockQuant._get_available_quantity(component2, self.stock_location), 1, 'Table stand should be available in stock as the picking is transferred') + + def test_unbuild_decimal_qty(self): + """ + Use case: + - decimal accuracy of Product UoM > decimal accuracy of Units + - unbuild a product with a decimal quantity of component + """ + self.env['decimal.precision'].search([('name', '=', 'Product Unit of Measure')]).digits = 4 + self.uom_unit.rounding = 0.001 + + self.bom_1.product_qty = 3 + self.bom_1.bom_line_ids.product_qty = 5 + self.env['stock.quant']._update_available_quantity(self.product_2, self.stock_location, 3) + + mo_form = Form(self.env['mrp.production']) + mo_form.product_id = self.bom_1.product_id + mo_form.bom_id = self.bom_1 + mo = mo_form.save() + mo.action_confirm() + mo.action_assign() + + mo_form = Form(mo) + mo_form.qty_producing = 3 + mo_form.save() + mo.button_mark_done() + + uo_form = Form(self.env['mrp.unbuild']) + uo_form.mo_id = mo + # Unbuilding one product means a decimal quantity equal to 1 / 3 * 5 for each component + uo_form.product_qty = 1 + uo = uo_form.save() + uo.action_unbuild() + self.assertEqual(uo.state, 'done') diff --git a/addons/stock/i18n/stock.pot b/addons/stock/i18n/stock.pot index e449a30cf0e..3e985401f66 100644 --- a/addons/stock/i18n/stock.pot +++ b/addons/stock/i18n/stock.pot @@ -7298,10 +7298,8 @@ msgstr "" #, python-format msgid "" "The quantity done for the product \"%s\" doesn't respect the rounding " -"precision defined on the unit of measure " -"\"%s\". Please change the quantity done or the" -" rounding precision of your unit of " -"measure." +"precision defined on the unit of measure \"%s\". Please change the quantity " +"done or the rounding precision of your unit of measure." msgstr "" #. module: stock diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index 3bf15f053aa..034af4ee6e5 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -506,9 +506,9 @@ class StockMoveLine(models.Model): precision_digits = self.env['decimal.precision'].precision_get('Product Unit of Measure') qty_done = float_round(ml.qty_done, precision_digits=precision_digits, rounding_method='HALF-UP') if float_compare(uom_qty, qty_done, precision_digits=precision_digits) != 0: - raise UserError(_('The quantity done for the product "%s" doesn\'t respect the rounding precision \ - defined on the unit of measure "%s". Please change the quantity done or the \ - rounding precision of your unit of measure.') % (ml.product_id.display_name, ml.product_uom_id.name)) + raise UserError(_('The quantity done for the product "%s" doesn\'t respect the rounding precision ' + 'defined on the unit of measure "%s". Please change the quantity done or the ' + 'rounding precision of your unit of measure.') % (ml.product_id.display_name, ml.product_uom_id.name)) qty_done_float_compared = float_compare(ml.qty_done, 0, precision_rounding=ml.product_uom_id.rounding) if qty_done_float_compared > 0: