From 87a2537c5efd72447ba1d6910a3d7b13acb7b894 Mon Sep 17 00:00:00 2001 From: Jordi Ballester Date: Sun, 23 Jul 2017 07:11:58 +0200 Subject: [PATCH] [IMP] should not auto-confirm the MO. Added test cases --- mrp_mto_with_stock/README.rst | 2 +- mrp_mto_with_stock/models/__init__.py | 2 +- .../models/{mrp.py => mrp_production.py} | 13 +- mrp_mto_with_stock/tests/__init__.py | 5 + .../tests/test_mrp_mto_with_stock.py | 139 ++++++++++++++++++ 5 files changed, 147 insertions(+), 14 deletions(-) rename mrp_mto_with_stock/models/{mrp.py => mrp_production.py} (85%) create mode 100644 mrp_mto_with_stock/tests/__init__.py create mode 100644 mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py diff --git a/mrp_mto_with_stock/README.rst b/mrp_mto_with_stock/README.rst index 5e9c0f9fb..4c9ffdd47 100644 --- a/mrp_mto_with_stock/README.rst +++ b/mrp_mto_with_stock/README.rst @@ -9,7 +9,7 @@ MRP MTO with Stock This module extends the functionality of Manufacturing to support the creation of procurements when there is no stock available. This allow you to pull from stock until the quantity on hand is zero, and then create a procurement -for fulfill the MO requirements. +to fulfill the MO requirements. Configuration ============= diff --git a/mrp_mto_with_stock/models/__init__.py b/mrp_mto_with_stock/models/__init__.py index 709cb97b3..c4a684fa2 100644 --- a/mrp_mto_with_stock/models/__init__.py +++ b/mrp_mto_with_stock/models/__init__.py @@ -3,5 +3,5 @@ # Copyright 2015 John Walsh # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from . import mrp +from . import mrp_production from . import product_template diff --git a/mrp_mto_with_stock/models/mrp.py b/mrp_mto_with_stock/models/mrp_production.py similarity index 85% rename from mrp_mto_with_stock/models/mrp.py rename to mrp_mto_with_stock/models/mrp_production.py index 87d1c082f..281fc9ea8 100644 --- a/mrp_mto_with_stock/models/mrp.py +++ b/mrp_mto_with_stock/models/mrp_production.py @@ -11,19 +11,9 @@ _logger = logging.getLogger(__name__) class MrpProduction(models.Model): _inherit = 'mrp.production' - @api.one - def action_confirm(self): - """Confirms stock move or put it in waiting if it's linked to another move. - @returns list of ids""" - # change the qty to make two moves (if needed) - res = super(MrpProduction, self).action_confirm() - # try to assign moves (and generate procurements!) - self.action_assign() - return res - @api.one def action_assign(self): - """Reserves available products to the production order but also reates + """Reserves available products to the production order but also creates procurements for more items if we cannot reserve enough (MTO with stock). @returns list of ids""" @@ -34,7 +24,6 @@ class MrpProduction(models.Model): if (move.state == 'confirmed' and move.location_id in move.product_id.mrp_mts_mto_location_ids): domain = [('product_id', '=', move.product_id.id), - ('state', '=', 'running'), ('move_dest_id', '=', move.id)] if move.group_id: domain.append(('group_id', '=', move.group_id.id)) diff --git a/mrp_mto_with_stock/tests/__init__.py b/mrp_mto_with_stock/tests/__init__.py new file mode 100644 index 000000000..f8065ee2e --- /dev/null +++ b/mrp_mto_with_stock/tests/__init__.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_mrp_mto_with_stock diff --git a/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py b/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py new file mode 100644 index 000000000..464195aa9 --- /dev/null +++ b/mrp_mto_with_stock/tests/test_mrp_mto_with_stock.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Eficent Business and IT Consulting Services S.L. +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from openerp.tests.common import TransactionCase +from openerp import fields + + +class TestMrpMtoWithStock(TransactionCase): + def setUp(self, *args, **kwargs): + super(TestMrpMtoWithStock, self).setUp(*args, **kwargs) + self.production_model = self.env['mrp.production'] + self.bom_model = self.env['mrp.bom'] + self.stock_location_stock = self.env.ref('stock.stock_location_stock') + self.manufacture_route = self.env.ref( + 'mrp.route_warehouse0_manufacture') + self.uom_unit = self.env.ref('product.product_uom_unit') + + self.product_fp = self.env['product.product'].create({ + 'name': 'FP', + 'type': 'product', + 'uom_id': self.uom_unit.id, + 'route_ids': [(4, self.manufacture_route.id)] + }) + self.product_c1 = self.env['product.product'].create({ + 'name': 'C1', + 'type': 'product', + 'uom_id': self.uom_unit.id, + 'route_ids': [(4, self.manufacture_route.id)] + }) + self.product_c2 = self.env['product.product'].create({ + 'name': 'C2', + 'type': 'product', + 'uom_id': self.uom_unit.id, + }) + self._update_product_qty(self.product_c2, + self.stock_location_stock, 10) + + self.bom_fp = self.env['mrp.bom'].create({ + 'product_id': self.product_fp.id, + 'product_tmpl_id': self.product_fp.product_tmpl_id.id, + 'bom_line_ids': ([ + (0, 0, { + 'product_id': self.product_c1.id, + 'product_qty': 1, + 'product_uom': self.uom_unit.id + }), + (0, 0, { + 'product_id': self.product_c2.id, + 'product_qty': 1, + 'product_uom': self.uom_unit.id + }), + ]) + }) + + self.bom_c1 = self.env['mrp.bom'].create({ + 'product_id': self.product_c1.id, + 'product_tmpl_id': self.product_c1.product_tmpl_id.id, + 'bom_line_ids': ([(0, 0, { + 'product_id': self.product_c2.id, + 'product_qty': 1, + 'product_uom': self.uom_unit.id + })]) + }) + self.product_c1.mrp_mts_mto_location_ids = [ + (6, 0, [self.stock_location_stock.id])] + + def _update_product_qty(self, product, location, quantity): + """Update Product quantity.""" + product_qty = self.env['stock.change.product.qty'].create({ + 'location_id': location.id, + 'product_id': product.id, + 'new_quantity': quantity, + }) + product_qty.change_product_qty() + return product_qty + + def create_procurement(self, name, product): + values = { + 'name': name, + 'date_planned': fields.Datetime.now(), + 'product_id': product.id, + 'product_qty': 4.0, + 'product_uom': product.uom_id.id, + 'warehouse_id': self.env.ref('stock.warehouse0').id, + 'location_id': self.stock_location_stock.id, + 'route_ids': [ + (4, self.env.ref('mrp.route_warehouse0_manufacture').id, 0)], + } + return self.env['procurement.order'].create(values) + + def test_manufacture(self): + + procurement_fp = self.create_procurement('TEST/01', self.product_fp) + production_fp = procurement_fp.production_id + self.assertEqual(production_fp.state, 'confirmed') + + production_fp.action_assign() + self.assertEqual(production_fp.state, 'confirmed') + + procurement_c1 = self.env['procurement.order'].search( + [('product_id', '=', self.product_c1.id), + ('move_dest_id', 'in', production_fp.move_lines.ids)], limit=1) + self.assertEquals(len(procurement_c1), 1) + + procurement_c2 = self.env['procurement.order'].search( + [('product_id', '=', self.product_c2.id), + ('move_dest_id', 'in', production_fp.move_lines.ids)], limit=1) + self.assertEquals(len(procurement_c2), 0) + + procurement_c1.run() + production_c1 = procurement_c1.production_id + self.assertEqual(production_c1.state, 'confirmed') + + production_c1.action_assign() + self.assertEqual(production_c1.state, 'ready') + + procurement_c2 = self.env['procurement.order'].search( + [('product_id', '=', self.product_c2.id), + ('move_dest_id', 'in', production_c1.move_lines.ids)], limit=1) + self.assertEquals(len(procurement_c2), 0) + + wizard = self.env['mrp.product.produce'].create({ + 'product_id': self.product_c1.id, + 'product_qty': 1, + }) + self.env['mrp.production'].action_produce( + production_c1.id, 1, 'consume_produce', wizard) + production_c1.refresh() + self.assertEqual(production_fp.state, 'confirmed') + + wizard = self.env['mrp.product.produce'].create({ + 'product_id': self.product_c1.id, + 'product_qty': 3, + }) + self.env['mrp.production'].action_produce( + production_c1.id, 3, 'consume_produce', wizard) + production_c1.refresh() + self.assertEqual(production_fp.state, 'ready')