From 465d83e88049a71162280c246ed5769471b3c56f Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 26 Nov 2013 14:49:52 +0100 Subject: [PATCH 1/4] [FIX] procurement: procurement orders does not have a `warehouse_id` field bzr revid: chs@openerp.com-20131126134952-cotbhc8s60zj44ts --- addons/procurement/schedulers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/procurement/schedulers.py b/addons/procurement/schedulers.py index c9b18dbccb4..07280b38ae7 100644 --- a/addons/procurement/schedulers.py +++ b/addons/procurement/schedulers.py @@ -197,7 +197,6 @@ class procurement_order(osv.osv): 'company_id': orderpoint.company_id.id, 'product_uom': orderpoint.product_uom.id, 'location_id': orderpoint.location_id.id, - 'warehouse_id': orderpoint.warehouse_id.id, 'procure_method': 'make_to_order', 'origin': orderpoint.name} From b81c3897ee1573641a9201f5a5ab4b270c0aa1ac Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 26 Nov 2013 14:50:26 +0100 Subject: [PATCH 2/4] [FIX] purchase: choose the right warehouse when creating purchase orders from procurement orders bzr revid: chs@openerp.com-20131126135026-echb4fq37229g637 --- addons/purchase/purchase.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 992af37222e..4a5b2567377 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1108,6 +1108,32 @@ class procurement_order(osv.osv): seller_delay = int(procurement.product_id.seller_delay) return schedule_date - relativedelta(days=seller_delay) + def _get_warehouse(self, procurement, user_company): + """ + Return the warehouse containing the procurment stock location (or one of it ancestors) + If none match, returns then first warehouse of the company + """ + # TODO refactor the domain once we implement the "parent_of" domain operator + company_id = (procurement.company_id or user_company).id + domains = [ + [ + '&', ('company_id', '=', company_id), + '|', '&', ('lot_stock_id.parent_left', '<', procurement.location_id.parent_left), + ('lot_stock_id.parent_right', '>', procurement.location_id.parent_right), + ('lot_stock_id', '=', procurement.location_id.id) + ], + [('company_id', '=', company_id)] + ] + + cr, uid = procurement._cr, procurement._uid + context = procurement._context + Warehouse = self.pool['stock.warehouse'] + for domain in domains: + ids = Warehouse.search(cr, uid, domain, context=context) + if ids: + return ids[0] + return False + def make_po(self, cr, uid, ids, context=None): """ Make purchase order from procurement @return: New created Purchase Orders procurement wise @@ -1122,7 +1148,6 @@ class procurement_order(osv.osv): prod_obj = self.pool.get('product.product') acc_pos_obj = self.pool.get('account.fiscal.position') seq_obj = self.pool.get('ir.sequence') - warehouse_obj = self.pool.get('stock.warehouse') for procurement in self.browse(cr, uid, ids, context=context): res_id = procurement.move_id.id partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement. @@ -1130,7 +1155,6 @@ class procurement_order(osv.osv): partner_id = partner.id address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery'] pricelist_id = partner.property_product_pricelist_purchase.id - warehouse_id = warehouse_obj.search(cr, uid, [('company_id', '=', procurement.company_id.id or company.id)], context=context) uom_id = procurement.product_id.uom_po_id.id qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id) @@ -1169,7 +1193,7 @@ class procurement_order(osv.osv): 'origin': procurement.origin, 'partner_id': partner_id, 'location_id': procurement.location_id.id, - 'warehouse_id': warehouse_id and warehouse_id[0] or False, + 'warehouse_id': self._get_warehouse(procurement, company), 'pricelist_id': pricelist_id, 'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'company_id': procurement.company_id.id, From b1b787545bfb3ab99754fbd8ad88ce2992bc8509 Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 26 Nov 2013 14:52:54 +0100 Subject: [PATCH 3/4] [FIX] purchase_requisition: choose the right warehouse when creating purchase requisitions from procurement orders + allow to work in batch. bzr revid: chs@openerp.com-20131126135254-96l4xk9q4fd0iwpu --- .../purchase_requisition.py | 36 +++++++++++-------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index f773bbd8505..c15d145a7cd 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -231,34 +231,40 @@ class product_product(osv.osv): product_product() class procurement_order(osv.osv): - _inherit = 'procurement.order' _columns = { - 'requisition_id' : fields.many2one('purchase.requisition','Latest Requisition') + 'requisition_id': fields.many2one('purchase.requisition', 'Latest Requisition') } + def make_po(self, cr, uid, ids, context=None): res = {} requisition_obj = self.pool.get('purchase.requisition') - warehouse_obj = self.pool.get('stock.warehouse') - procurement = self.browse(cr, uid, ids, context=context)[0] - if procurement.product_id.purchase_requisition: - warehouse_id = warehouse_obj.search(cr, uid, [('company_id', '=', procurement.company_id.id or company.id)], context=context) - res[procurement.id] = requisition_obj.create(cr, uid, - { + non_requisition = [] + for procurement in self.browse(cr, uid, ids, context=context): + if procurement.product_id.purchase_requisition: + user_company = self.pool['res.users'].browse(cr, uid, uid, context=context).company_id + req = res[procurement.id] = requisition_obj.create(cr, uid, { 'origin': procurement.origin, 'date_end': procurement.date_planned, - 'warehouse_id':warehouse_id and warehouse_id[0] or False, - 'company_id':procurement.company_id.id, - 'line_ids': [(0,0,{ + 'warehouse_id': self._get_warehouse(procurement, user_company), + 'company_id': procurement.company_id.id, + 'line_ids': [(0, 0, { 'product_id': procurement.product_id.id, 'product_uom_id': procurement.product_uom.id, 'product_qty': procurement.product_qty - })], + })], }) - self.write(cr,uid,[procurement.id],{'state': 'running','requisition_id': res[procurement.id]},context=context) - else: - res = super(procurement_order, self).make_po(cr, uid, ids, context=context) + procurement.write({ + 'state': 'running', + 'requisition_id': req + }) + else: + non_requisition.append(procurement.id) + + if non_requisition: + res.update(super(procurement_order, self).make_po(cr, uid, non_requisition, context=context)) + return res procurement_order() From 49fa5cab61cdabdccb8f6a94252a412cb0669a1a Mon Sep 17 00:00:00 2001 From: Christophe Simonis Date: Tue, 26 Nov 2013 19:07:26 +0100 Subject: [PATCH 4/4] [FIX] purchase_requisition: copy method _get_warehouse from purchase module to avoid crash if purchase_requisition is updated but not purchase bzr revid: chs@openerp.com-20131126180726-ng0gue9pedmuykj9 --- addons/purchase/purchase.py | 3 ++ .../purchase_requisition.py | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 4a5b2567377..8cae5a1cf15 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1114,6 +1114,9 @@ class procurement_order(osv.osv): If none match, returns then first warehouse of the company """ # TODO refactor the domain once we implement the "parent_of" domain operator + # NOTE This method has been copied in the `purchase_requisition` module to ensure + # retro-compatibility. This code duplication will be deleted in next stable version. + # Do not forget to update both version in case of modification. company_id = (procurement.company_id or user_company).id domains = [ [ diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index c15d145a7cd..c1d80c7bf46 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -236,6 +236,35 @@ class procurement_order(osv.osv): 'requisition_id': fields.many2one('purchase.requisition', 'Latest Requisition') } + def _get_warehouse(self, procurement, user_company): + """ + Return the warehouse containing the procurment stock location (or one of it ancestors) + If none match, returns then first warehouse of the company + """ + # NOTE This method is a copy of the one on the procurement.order defined in purchase + # module. It's been copied to ensure it been always available, even if module + # purchase is not up to date. + # Do not forget to update both version in case of modification. + company_id = (procurement.company_id or user_company).id + domains = [ + [ + '&', ('company_id', '=', company_id), + '|', '&', ('lot_stock_id.parent_left', '<', procurement.location_id.parent_left), + ('lot_stock_id.parent_right', '>', procurement.location_id.parent_right), + ('lot_stock_id', '=', procurement.location_id.id) + ], + [('company_id', '=', company_id)] + ] + + cr, uid = procurement._cr, procurement._uid + context = procurement._context + Warehouse = self.pool['stock.warehouse'] + for domain in domains: + ids = Warehouse.search(cr, uid, domain, context=context) + if ids: + return ids[0] + return False + def make_po(self, cr, uid, ids, context=None): res = {} requisition_obj = self.pool.get('purchase.requisition')