diff --git a/addons/mrp/models/stock_warehouse.py b/addons/mrp/models/stock_warehouse.py index 8480af0f2cf..4f97f3c38d5 100644 --- a/addons/mrp/models/stock_warehouse.py +++ b/addons/mrp/models/stock_warehouse.py @@ -57,6 +57,7 @@ class StockWarehouse(models.Model): self.Routing(warehouse.sam_loc_id, warehouse.lot_stock_id, warehouse.sam_type_id, 'push'), ], }) + result[warehouse.id].update(warehouse._get_receive_rules_dict()) return result @api.model @@ -88,6 +89,7 @@ class StockWarehouse(models.Model): } } }) + routes.update(self._get_receive_routes_values('manufacture_to_resupply')) return routes def _get_route_name(self, route_type): diff --git a/addons/purchase_stock/__init__.py b/addons/purchase_stock/__init__.py index 6fee2cb6173..849b2eb3699 100644 --- a/addons/purchase_stock/__init__.py +++ b/addons/purchase_stock/__init__.py @@ -14,5 +14,4 @@ def _create_buy_rules(cr, registry): """ env = api.Environment(cr, SUPERUSER_ID, {}) warehouse_ids = env['stock.warehouse'].search([('buy_pull_id', '=', False)]) - for warehouse_id in warehouse_ids: - warehouse_id._create_or_update_global_routes_rules() + warehouse_ids.write({'buy_to_resupply': True}) diff --git a/addons/purchase_stock/models/stock.py b/addons/purchase_stock/models/stock.py index 660fb32c0f0..a5e61fecd75 100644 --- a/addons/purchase_stock/models/stock.py +++ b/addons/purchase_stock/models/stock.py @@ -142,6 +142,17 @@ class StockWarehouse(models.Model): routes |= self.filtered(lambda self: self.buy_to_resupply and self.buy_pull_id and self.buy_pull_id.route_id).mapped('buy_pull_id').mapped('route_id') return routes + def get_rules_dict(self): + result = super(StockWarehouse, self).get_rules_dict() + for warehouse in self: + result[warehouse.id].update(warehouse._get_receive_rules_dict()) + return result + + def _get_routes_values(self): + routes = super(StockWarehouse, self)._get_routes_values() + routes.update(self._get_receive_routes_values('buy_to_resupply')) + return routes + def _update_name_and_code(self, name=False, code=False): res = super(StockWarehouse, self)._update_name_and_code(name, code) warehouse = self[0] diff --git a/addons/stock/models/stock_warehouse.py b/addons/stock/models/stock_warehouse.py index ead232b7cdd..96e77ba907a 100644 --- a/addons/stock/models/stock_warehouse.py +++ b/addons/stock/models/stock_warehouse.py @@ -468,7 +468,6 @@ class Warehouse(models.Model): }, 'rules_values': { 'active': True, - 'procure_method': 'make_to_order', 'propagate_cancel': True, } }, @@ -511,6 +510,42 @@ class Warehouse(models.Model): } } + def _get_receive_routes_values(self, installed_depends): + """ Return receive route values with 'procure_method': 'make_to_order' + in order to update warehouse routes. + + This function has the same receive route values as _get_routes_values with the addition of + 'procure_method': 'make_to_order' to the 'rules_values'. This is expected to be used by + modules that extend stock and add actions that can trigger receive 'make_to_order' rules (i.e. + we don't want any of the generated rules by get_rules_dict to default to 'make_to_stock'). + Additionally this is expected to be used in conjunction with _get_receive_rules_dict(). + + args: + installed_depends - string value of installed (warehouse) boolean to trigger updating of reception route. + """ + return { + 'reception_route_id': { + 'routing_key': self.reception_steps, + 'depends': ['reception_steps', installed_depends], + 'route_update_values': { + 'name': self._format_routename(route_type=self.reception_steps), + 'active': self.active, + }, + 'route_create_values': { + 'product_categ_selectable': True, + 'warehouse_selectable': True, + 'product_selectable': False, + 'company_id': self.company_id.id, + 'sequence': 9, + }, + 'rules_values': { + 'active': True, + 'propagate_cancel': True, + 'procure_method': 'make_to_order', + } + } + } + def _find_existing_rule_or_create(self, rules_list): """ This method will find existing rules or create new one. """ for rule_vals in rules_list: @@ -664,9 +699,12 @@ class Warehouse(models.Model): customer_loc, supplier_loc = self._get_partner_locations() return { warehouse.id: { - 'one_step': [], - 'two_steps': [self.Routing(warehouse.wh_input_stock_loc_id, warehouse.lot_stock_id, warehouse.int_type_id, 'pull_push')], + 'one_step': [self.Routing(supplier_loc, warehouse.lot_stock_id, warehouse.in_type_id, 'pull')], + 'two_steps': [ + self.Routing(supplier_loc, warehouse.wh_input_stock_loc_id, warehouse.in_type_id, 'pull'), + self.Routing(warehouse.wh_input_stock_loc_id, warehouse.lot_stock_id, warehouse.int_type_id, 'pull_push')], 'three_steps': [ + self.Routing(supplier_loc, warehouse.wh_input_stock_loc_id, warehouse.in_type_id, 'pull'), self.Routing(warehouse.wh_input_stock_loc_id, warehouse.wh_qc_stock_loc_id, warehouse.int_type_id, 'pull_push'), self.Routing(warehouse.wh_qc_stock_loc_id, warehouse.lot_stock_id, warehouse.int_type_id, 'pull_push')], 'crossdock': [ @@ -684,6 +722,22 @@ class Warehouse(models.Model): } for warehouse in self } + def _get_receive_rules_dict(self): + """ Return receive route rules without initial pull rule in order to update warehouse routes. + + This function has the same receive route rules as get_rules_dict without an initial pull rule. + This is expected to be used by modules that extend stock and add actions that can trigger receive + 'make_to_order' rules (i.e. we don't expect the receive route to be able to pull on its own anymore). + This is also expected to be used in conjuction with _get_receive_routes_values() + """ + return { + 'one_step': [], + 'two_steps': [self.Routing(self.wh_input_stock_loc_id, self.lot_stock_id, self.int_type_id, 'pull_push')], + 'three_steps': [ + self.Routing(self.wh_input_stock_loc_id, self.wh_qc_stock_loc_id, self.int_type_id, 'pull_push'), + self.Routing(self.wh_qc_stock_loc_id, self.lot_stock_id, self.int_type_id, 'pull_push')], + } + def _get_inter_warehouse_route_values(self, supplier_warehouse): return { 'name': _('%s: Supply Product from %s') % (self.name, supplier_warehouse.name), diff --git a/addons/stock/tests/test_proc_rule.py b/addons/stock/tests/test_proc_rule.py index cababaebeef..190eaa25cfc 100644 --- a/addons/stock/tests/test_proc_rule.py +++ b/addons/stock/tests/test_proc_rule.py @@ -176,16 +176,17 @@ class TestProcRule(TransactionCase): orderpoint_form.product_max_qty = 5.0 orderpoint = orderpoint_form.save() - self.env['stock.rule'].create({ - 'name': 'Rule Supplier', - 'route_id': warehouse.reception_route_id.id, - 'location_id': warehouse.lot_stock_id.id, - 'location_src_id': self.env.ref('stock.stock_location_suppliers').id, - 'action': 'pull', - 'delay': 9.0, - 'procure_method': 'make_to_stock', - 'picking_type_id': warehouse.in_type_id.id, - }) + # get auto-created pull rule from when warehouse is created + rule = self.env['stock.rule'].search([ + ('route_id', '=', warehouse.reception_route_id.id), + ('location_id', '=', warehouse.lot_stock_id.id), + ('location_src_id', '=', self.env.ref('stock.stock_location_suppliers').id), + ('action', '=', 'pull'), + ('procure_method', '=', 'make_to_stock'), + ('picking_type_id', '=', warehouse.in_type_id.id)]) + + # add a delay [i.e. lead days] so procurement will be triggered based on forecasted stock + rule.delay = 9.0 delivery_move = self.env['stock.move'].create({ 'name': 'Delivery', diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index e1dc46edb4f..e5e301d723b 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -1723,8 +1723,7 @@ class TestStockFlow(TestStockCommon): 'location_id': self.stock_location, 'location_dest_id': self.customer_location}) - with self.assertRaises(UserError): - move_mto_alone._action_confirm() + move_mto_alone._action_confirm() move_with_ancestors._action_confirm() other_move._action_confirm() @@ -1732,7 +1731,7 @@ class TestStockFlow(TestStockCommon): move_with_ancestors._do_unreserve() other_move._do_unreserve() - self.assertEqual(move_mto_alone.state, "draft") + self.assertEqual(move_mto_alone.state, "waiting") self.assertEqual(move_with_ancestors.state, "waiting") self.assertEqual(other_move.state, "confirmed")