From 74b7b97209d1dbe32f374355a05bfa3e0714d07b Mon Sep 17 00:00:00 2001 From: Alexandre Fayolle Date: Fri, 7 Aug 2015 16:01:36 +0200 Subject: [PATCH] [FIX] stock: let resupply from warehouse work If you set WH B to be resupplied from WH A, then the scheduler will generate a procurement with warehouse_id = B and location_id = B.stock. Running the procurement will find the resupply rule, and this will create another procurement with warehouse_id = A and location_id = transit location. However, without this patch, the resupply route is not part of the route_ids of warehouse A, and so the 2nd procurement goes in exception because if cannot find a rule (the search will force a rule linked to a route which is part of A.route_ids). Closes #7956 --- addons/stock/stock.py | 4 +-- addons/stock/tests/__init__.py | 1 + addons/stock/tests/test_resupply.py | 51 +++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 addons/stock/tests/test_resupply.py diff --git a/addons/stock/stock.py b/addons/stock/stock.py index bb0a9a7a061..6e23e5f629a 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -3039,7 +3039,7 @@ class stock_warehouse(osv.osv): 'crossdock_route_id': fields.many2one('stock.location.route', 'Crossdock Route'), 'reception_route_id': fields.many2one('stock.location.route', 'Receipt Route'), 'delivery_route_id': fields.many2one('stock.location.route', 'Delivery Route'), - 'resupply_from_wh': fields.boolean('Resupply From Other Warehouses'), + 'resupply_from_wh': fields.boolean('Resupply From Other Warehouses', help='Unused field'), 'resupply_wh_ids': fields.many2many('stock.warehouse', 'stock_wh_resupply_table', 'supplied_wh_id', 'supplier_wh_id', 'Resupply Warehouses'), 'resupply_route_ids': fields.one2many('stock.location.route', 'supplied_wh_id', 'Resupply Routes', help="Routes will be created for these resupply warehouses and you can select them on products and product categories"), @@ -3099,7 +3099,7 @@ class stock_warehouse(osv.osv): pull_obj.create(cr, uid, vals=pull_rule, context=context) #if the warehouse is also set as default resupply method, assign this route automatically to the warehouse if default_resupply_wh and default_resupply_wh.id == wh.id: - self.write(cr, uid, [warehouse.id], {'route_ids': [(4, inter_wh_route_id)]}, context=context) + self.write(cr, uid, [warehouse.id, wh.id], {'route_ids': [(4, inter_wh_route_id)]}, context=context) _defaults = { 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c), diff --git a/addons/stock/tests/__init__.py b/addons/stock/tests/__init__.py index 4c20f7a769a..c372f3c8fb5 100644 --- a/addons/stock/tests/__init__.py +++ b/addons/stock/tests/__init__.py @@ -2,3 +2,4 @@ from . import test_stock_flow from . import test_owner_available +from . import test_resupply diff --git a/addons/stock/tests/test_resupply.py b/addons/stock/tests/test_resupply.py new file mode 100644 index 00000000000..79ecbf456b7 --- /dev/null +++ b/addons/stock/tests/test_resupply.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +from openerp.addons.stock.tests.common import TestStockCommon +from openerp.tools import mute_logger, float_round + + +class TestResupply(TestStockCommon): + def setUp(self): + super(TestResupply, self).setUp() + self.Warehouse = self.env['stock.warehouse'] + # create 2 WH, BIG and SMALL + # SMALL resupplies from BIG + self.bigwh = self.Warehouse.create({'name': 'BIG', 'code': 'B'}) + self.smallwh = self.Warehouse.create({'name': 'SMALL', 'code': 'S', + 'default_resupply_wh_id': self.bigwh.id, + 'resupply_wh_ids': [(6, 0, [self.bigwh.id])], + }) + # minimum stock rule for Product A on SMALL + Orderpoint = self.env['stock.warehouse.orderpoint'] + Orderpoint.create({'warehouse_id': self.smallwh.id, + 'location_id': self.smallwh.lot_stock_id.id, + 'product_id': self.productA.id, + 'product_min_qty': 100, + 'product_max_qty': 200, + 'product_uom': self.uom_unit.id, + }) + # create some stock on BIG + Wiz = self.env['stock.change.product.qty'] + wiz = Wiz.create({'product_id': self.productA.id, + 'new_quantity': 1000, + 'location_id': self.bigwh.lot_stock_id.id, + }) + wiz.change_product_qty() + + def test_resupply_from_wh(self): + sched = self.env['procurement.order'] + sched.run_scheduler() + # we generated 2 procurements for product A: one on small wh and the + # other one on the transit location + procs = sched.search([('product_id', '=', self.productA.id)]) + self.assertEqual(len(procs), 2) + proc1 = sched.search([('product_id', '=', self.productA.id), + ('warehouse_id', '=', self.smallwh.id)]) + self.assertEqual(proc1.state, 'running') + proc2 = sched.search([('product_id', '=', self.productA.id), + ('warehouse_id', '=', self.bigwh.id)]) + self.assertEqual(proc2.location_id.usage, 'transit') + self.assertNotEqual(proc2.state, 'exception') + proc2.run() + self.assertEqual(proc2.state, 'running') + self.assertTrue(proc2.rule_id)