From 0f89721cdad3ad17baba3aa5f7705809c7b431df Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 14 Sep 2015 17:26:22 +0200 Subject: [PATCH] [IMP] procurement: Integrate procurement_jit in other modules and change to sale_auto_reserve As procurement_jit has been optimized (by running multiple procurements at once), it does not make sense to still have a module that without it, does not generate Pick > Pack > Ship automatically, but only Ship. We can do it anyways. That way, the procurement_jit module can become clearer in its functionality to the user: when a sale order is confirmed, it will automatically reserve the picking from the stock location (in case of MTS) and people who don't want that functionality can still immediately have the Pick > Pack > Ship. Make sure also push_apply works with manually created pickings. --- addons/procurement/procurement.py | 7 ++++++ addons/procurement/test/procurement.yml | 5 ---- addons/procurement_jit/__init__.py | 1 - addons/procurement_jit/__openerp__.py | 23 ++++++++++--------- addons/procurement_jit/procurement_jit.py | 23 ------------------- addons/procurement_jit/sale.py | 5 +--- .../procurement_jit/test/procurement_jit.yml | 16 ------------- addons/sale/sale.py | 6 +++-- addons/stock/procurement.py | 5 ++++ addons/stock/res_config.py | 9 ++++---- addons/stock/stock.py | 6 +++-- 11 files changed, 37 insertions(+), 69 deletions(-) delete mode 100644 addons/procurement_jit/procurement_jit.py delete mode 100644 addons/procurement_jit/test/procurement_jit.yml diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index a7adae93ebf..67271810c0a 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -139,6 +139,13 @@ class procurement_order(osv.osv): raise UserError(_('Cannot delete Procurement Order(s) which are in %s state.') % s['state']) return osv.osv.unlink(self, cr, uid, unlink_ids, context=context) + def create(self, cr, uid, vals, context=None): + context = context or {} + procurement_id = super(procurement_order, self).create(cr, uid, vals, context=context) + if not context.get('procurement_autorun_defer'): + self.run(cr, uid, [procurement_id], context=context) + return procurement_id + def do_view_procurements(self, cr, uid, ids, context=None): ''' This function returns an action that display existing procurement orders diff --git a/addons/procurement/test/procurement.yml b/addons/procurement/test/procurement.yml index f9774f70e7b..1f89e28bbdb 100644 --- a/addons/procurement/test/procurement.yml +++ b/addons/procurement/test/procurement.yml @@ -7,11 +7,6 @@ product_id: product.product_product_32 product_qty: 15.0 product_uom: product.product_uom_unit -- - I run the scheduler. -- - !python {model: procurement.order}: | - self.run_scheduler(cr, uid) - I check that procurement order is in exception, as at first there isn't any suitable rule - diff --git a/addons/procurement_jit/__init__.py b/addons/procurement_jit/__init__.py index 93f0b78639b..1047b552da3 100644 --- a/addons/procurement_jit/__init__.py +++ b/addons/procurement_jit/__init__.py @@ -1,5 +1,4 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. -import procurement_jit import sale diff --git a/addons/procurement_jit/__openerp__.py b/addons/procurement_jit/__openerp__.py index a6faf73dd69..740bc457aa3 100644 --- a/addons/procurement_jit/__openerp__.py +++ b/addons/procurement_jit/__openerp__.py @@ -7,24 +7,25 @@ 'version': '1.0', 'category': 'Base', 'description': """ -This module allows Just In Time computation of procurement orders. -================================================================== +This module will automatically reserve the picking from stock when a sale order is confirmed +============================================================================================ +Upon confirmation of a sale order or when quantities are added, +the picking that reserves from stock will be reserved if the +necessary quantities are available. -If you install this module, you will not have to run the regular procurement -scheduler anymore (but you still need to run the minimum order point rule -scheduler, or for example let it run daily). -All procurement orders will be processed immediately, which could in some -cases entail a small performance impact. +In the simplest configurations, this is an easy way of working: +first come, first served. However, when not installed, you can +use manual reservation or run the schedulers where the system +will take into account the expected date and the priority. -It may also increase your stock size because products are reserved as soon -as possible and the scheduler time range is not taken into account anymore. -In that case, you can not use priorities any more on the different picking. +If this automatic reservation would reserve too much, you can +still unreserve a picking. """, 'website': 'https://www.odoo.com/page/manufacturing', 'depends': ['sale_stock'], 'data': [], 'demo': [], - 'test': ['test/procurement_jit.yml'], + 'test': [], 'installable': True, 'auto_install': True, } diff --git a/addons/procurement_jit/procurement_jit.py b/addons/procurement_jit/procurement_jit.py deleted file mode 100644 index b48ad5f937b..00000000000 --- a/addons/procurement_jit/procurement_jit.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# Part of Odoo. See LICENSE file for full copyright and licensing details. - - -from openerp.osv import osv - -class procurement_order(osv.osv): - _inherit = "procurement.order" - - def create(self, cr, uid, vals, context=None): - context = context or {} - procurement_id = super(procurement_order, self).create(cr, uid, vals, context=context) - self.run(cr, uid, [procurement_id], context=context) - return procurement_id - - def run(self, cr, uid, ids, autocommit=False, context=None): - res = super(procurement_order, self).run(cr, uid, ids, autocommit=autocommit, context=context) - procurement_ids = self.search(cr, uid, [('move_dest_id.procurement_id', 'in', ids)], order='id', context=context) - if procurement_ids: - result = self.run(cr, uid, procurement_ids, autocommit=autocommit, context=context) - return result - return res - diff --git a/addons/procurement_jit/sale.py b/addons/procurement_jit/sale.py index bff11a5524e..d4708e00f5c 100644 --- a/addons/procurement_jit/sale.py +++ b/addons/procurement_jit/sale.py @@ -10,8 +10,5 @@ class SaleOrder(models.Model): def action_confirm(self): res = super(SaleOrder, self).action_confirm() for order in self: - for pick in order.picking_ids: - print pick.state order.picking_ids.filtered(lambda x: x.state=='confirmed').action_assign() - return res - + return res \ No newline at end of file diff --git a/addons/procurement_jit/test/procurement_jit.yml b/addons/procurement_jit/test/procurement_jit.yml deleted file mode 100644 index 1be88c6a7dd..00000000000 --- a/addons/procurement_jit/test/procurement_jit.yml +++ /dev/null @@ -1,16 +0,0 @@ -- - In order to test procurement_jit module with OpenERP, I create procurement order for - Computer Case product and check whether it runs without scheduler or not. -- - !record {model: procurement.order, id: procurement_order_test1}: - company_id: base.main_company - date_planned: !eval datetime.today().strftime("%Y-%m-%d %H:%M:%S") - name: PROC/TEST/0001 - product_id: product.product_product_16 - product_qty: 10.0 - product_uom: product.product_uom_unit -- - I check that the procurement is automatically in exception because nothing is configured to handle this procurement. -- - !assert {model: procurement.order, id: procurement_order_test1, string: procstate}: - - state == 'exception' diff --git a/addons/sale/sale.py b/addons/sale/sale.py index ec00f26a8a6..72380c4786e 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -468,6 +468,7 @@ class SaleOrderLine(models.Model): @api.multi def _action_procurement_create(self): precision = self.env['decimal.precision'].precision_get('Product Unit of Measure') + new_procs = self.env['procurement.order'] #Empty recordset for line in self: if line.state != 'sale': continue @@ -484,8 +485,9 @@ class SaleOrderLine(models.Model): vals = line._prepare_order_line_procurement(group_id=line.order_id.procurement_group_id.id) vals['product_qty'] = line.product_uom_qty - qty new_proc = self.env["procurement.order"].create(vals) - new_proc.run() - return True + new_procs += new_proc + new_procs.run() + return new_procs @api.model def _get_analytic_invoice_policy(self): diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index 03ad7ccda6c..c2aac6a75a8 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -321,6 +321,7 @@ class procurement_order(osv.osv): def run(self, cr, uid, ids, autocommit=False, context=None): new_ids = [x.id for x in self.browse(cr, uid, ids, context=context) if x.state not in ('running', 'done', 'cancel')] + context = dict(context or {}, procurement_auto_defer=True) #When creating res = super(procurement_order, self).run(cr, uid, new_ids, autocommit=autocommit, context=context) #after all the procurements are run, check if some created a draft stock move that needs to be confirmed @@ -331,6 +332,10 @@ class procurement_order(osv.osv): move_to_confirm_ids += [m.id for m in procurement.move_ids if m.state == 'draft'] if move_to_confirm_ids: self.pool.get('stock.move').action_confirm(cr, uid, move_to_confirm_ids, context=context) + # If procurements created other procurements, run the created in batch + procurement_ids = self.search(cr, uid, [('move_dest_id.procurement_id', 'in', new_ids)], order='id', context=context) + if procurement_ids: + res = res and self.run(cr, uid, procurement_ids, autocommit=autocommit, context=context) return res def _check(self, cr, uid, procurement, context=None): diff --git a/addons/stock/res_config.py b/addons/stock/res_config.py index 8fdb56cc8f2..533f11a0bf0 100644 --- a/addons/stock/res_config.py +++ b/addons/stock/res_config.py @@ -79,12 +79,11 @@ class stock_config_settings(osv.osv_memory): implied_group='product.group_product_variant'), 'company_id': fields.many2one('res.company', 'Company', required=True), 'module_procurement_jit': fields.selection([ - (1, 'Schedule orders in real time'), - (0, 'Run scheduler once a day') + (1, 'Reserve Sale Orders Immediately On Confirmation'), + (0, 'Reserve Sale Orders Manually or by Running the Schedulers') ], "Procurements", - help="""This allows Just In Time computation of procurement orders. - All procurement orders will be processed immediately, which could in some - cases entail a small performance impact. + help="""Allows you to automatically reserve the available + products when confirming a sale order. This installs the module procurement_jit."""), 'module_claim_from_delivery': fields.selection([ (0, 'Do not manage claims'), diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 387d12c528d..cfa2dfd51dd 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2055,8 +2055,8 @@ class stock_move(osv.osv): wh_route_ids = [] if move.warehouse_id: wh_route_ids = [x.id for x in move.warehouse_id.route_ids] - elif move.picking_type_id and move.picking_type_id.warehouse_id: - wh_route_ids = [x.id for x in move.picking_type_id.warehouse_id.route_ids] + elif move.picking_id.picking_type_id.warehouse_id: + wh_route_ids = [x.id for x in move.picking_id.picking_type_id.warehouse_id.route_ids] if wh_route_ids: rules = push_obj.search(cr, uid, domain + [('route_id', 'in', wh_route_ids)], order='route_sequence, sequence', context=context) if not rules: @@ -2077,6 +2077,8 @@ class stock_move(osv.osv): res = [] for move in moves: res.append(self._create_procurement(cr, uid, move, context=context)) + # Run procurements immediately when generated from multiple moves + self.pool['procurement.order'].run(cr, uid, res, context=context) return res def write(self, cr, uid, ids, vals, context=None):