From 858c2e4da0a49235309103f2714fbf296aa52065 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Mon, 17 Feb 2020 11:00:48 +0000 Subject: [PATCH] [FIX] stock, mrp: move with zero as initial demand Set the following product configuration: Storable finished product with a flexible BOM made of storable components in manufacture + MTO: Component choice 1 Quantity = 0 with BOM made of component 1, quantity 1 with purchase mto route Component choice 2 Quantity = 0 with BOM made of component 2, quantity 1 with purchase mto route Create a MO for finished product, set the "to consume" quantity of "Component choice 1" to 1, and try to mark it as to do. The following issue is raised: The quantity to produce must be positive! This is because a procurement with 0 quantity will be solved in a MO producing 0 quantity. We fix this issue by ignoring procurements with 0 quantities. Also, this MO without initial demand is not considered assigned. We fix this issue by considering 0 move as assigned. task-2159374 closes odoo/odoo#45552 X-original-commit: dffb3a1f2762d6e1517eb9b7d225521f99d874d5 Signed-off-by: Simon Lejeune (sle) --- .../test_warehouse_multistep_manufacturing.py | 18 ++++++++++++++++++ addons/stock/models/stock_move.py | 4 +++- addons/stock/models/stock_rule.py | 4 +++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/addons/mrp/tests/test_warehouse_multistep_manufacturing.py b/addons/mrp/tests/test_warehouse_multistep_manufacturing.py index 20ebd7a3d63..6d503549db7 100644 --- a/addons/mrp/tests/test_warehouse_multistep_manufacturing.py +++ b/addons/mrp/tests/test_warehouse_multistep_manufacturing.py @@ -255,3 +255,21 @@ class TestMultistepManufacturingWarehouse(TestMrpCommon): self.assertEqual(production_order.state, 'confirmed') production_order.action_cancel() self.assertTrue(move_stock_postprod.state, 'cancel') + + def test_no_initial_demand(self): + """ Test MO/picking before manufacturing/picking after manufacturing + components and move_orig/move_dest. Ensure that everything is created + correctly. + """ + with Form(self.warehouse) as warehouse: + warehouse.manufacture_steps = 'pbm_sam' + production_form = Form(self.env['mrp.production']) + production_form.product_id = self.finished_product + production_form.picking_type_id = self.warehouse.manu_type_id + production = production_form.save() + production.move_raw_ids.product_uom_qty = 0 + production.action_confirm() + production.action_assign() + self.assertFalse(production.move_raw_ids.move_orig_ids) + self.assertEqual(production.state, 'confirmed') + self.assertEqual(production.reservation_state, 'assigned') diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 106791b471b..740854283dc 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -1167,7 +1167,9 @@ class StockMove(models.Model): move_line_vals_list.append(move._prepare_move_line_vals(quantity=missing_reserved_quantity)) assigned_moves |= move else: - if not move.move_orig_ids: + if float_is_zero(move.product_uom_qty, precision_rounding=move.product_uom.rounding): + assigned_moves |= move + elif not move.move_orig_ids: if move.procure_method == 'make_to_order': continue # If we don't need any quantity, consider the move assigned. diff --git a/addons/stock/models/stock_rule.py b/addons/stock/models/stock_rule.py index b608c230e45..faa4d699876 100644 --- a/addons/stock/models/stock_rule.py +++ b/addons/stock/models/stock_rule.py @@ -11,7 +11,7 @@ from psycopg2 import OperationalError from odoo import SUPERUSER_ID, _, api, fields, models, registry from odoo.exceptions import UserError from odoo.osv import expression -from odoo.tools import float_compare, float_round, frozendict, html_escape +from odoo.tools import float_compare, float_is_zero, float_round, frozendict, html_escape from odoo.tools.misc import split_every _logger = logging.getLogger(__name__) @@ -399,6 +399,8 @@ class ProcurementGroup(models.Model): procurement.values.setdefault('company_id', self.env.company) procurement.values.setdefault('priority', '1') procurement.values.setdefault('date_planned', fields.Datetime.now()) + if float_is_zero(procurement.product_qty, precision_rounding=procurement.product_uom.rounding): + continue rule = self._get_rule(procurement.product_id, procurement.location_id, procurement.values) if not rule: error = _('No rule has been found to replenish "%s" in "%s".\nVerify the routes configuration on the product.') %\