From 8ca4845d63e0765b94de636f4d047875124797c0 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Wed, 16 Oct 2013 12:00:50 +0200 Subject: [PATCH 01/18] update display according warehouse configuration [groups] bzr revid: jke@openerp.com-20131016100050-22g7hykaff372x3g --- addons/stock/stock_view.xml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 3e4ab8bcc1c..31aab252bfb 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -129,9 +129,9 @@ - + - + @@ -142,8 +142,8 @@ - - + + @@ -1572,19 +1572,19 @@ - - - + + + - - + + - - + + @@ -1606,14 +1606,14 @@
- - + + - + @@ -1628,9 +1628,9 @@ - - - + + + From 73e0290e9d06f832a5700f27c0f1064f307bff92 Mon Sep 17 00:00:00 2001 From: jke-openerp Date: Thu, 17 Oct 2013 09:21:31 +0200 Subject: [PATCH 02/18] continue bzr revid: jke@openerp.com-20131017072131-lv1omqmqnb39ucsy --- addons/stock/stock_view.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 31aab252bfb..e93c3564b47 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -130,7 +130,7 @@ - + @@ -144,7 +144,7 @@ - + @@ -1585,7 +1585,7 @@ - +
From 1df2d9e4db4c94b396c088c8ed04d6524f3315a2 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Fri, 18 Oct 2013 14:20:34 +0200 Subject: [PATCH 03/18] [FIX] stock: picking assignation now accept draft picking as well. This is hardly needed because picking state is based on stock.move state, and at the time of picking creation from a PO, we won't confirm the stock.move one by one (so the picking state stays draft untill all moves are confirmed) bzr revid: qdp-launchpad@openerp.com-20131018122034-fpj8sgi4sh1n7vsw --- addons/stock/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 0ccc19799ca..8cbe8307f15 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1591,7 +1591,7 @@ class stock_move(osv.osv): ('group_id', '=', group), ('location_id', '=', move.location_id.id), ('location_dest_id', '=', move.location_dest_id.id), - ('state', 'in', ['confirmed', 'waiting'])], context=context) + ('state', 'in', ['draft', 'confirmed', 'waiting'])], context=context) if picks: pick = picks[0] else: From 90319d5e2a248e70e342d691fbce3c19ebbf09d2 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 21 Oct 2013 11:55:44 +0200 Subject: [PATCH 04/18] [FIX] purchase: create suppier invoice based on incomming shipment + [FIX] stock_complex_route: fixed yaml test bzr revid: qdp-launchpad@openerp.com-20131021095544-i0n6fd8jz31jo1l6 --- addons/purchase/stock.py | 32 ++++++++++++++----- addons/purchase/stock_view.xml | 16 ++-------- addons/stock/stock.py | 2 +- addons/stock_complex_routes/test/dropship.yml | 5 +-- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/addons/purchase/stock.py b/addons/purchase/stock.py index 34d8c8df595..c6fd849854f 100644 --- a/addons/purchase/stock.py +++ b/addons/purchase/stock.py @@ -38,19 +38,35 @@ class stock_move(osv.osv): workflow.trg_trigger(uid, 'stock.move', id, cr) return res -# -# Inherit of picking to add the link to the PO -# class stock_picking(osv.osv): _inherit = 'stock.picking' + + def _get_to_invoice(self, cr, uid, ids, name, args, context=None): + res = {} + for picking in self.browse(cr, uid, ids, context=context): + res[picking.id] = False + for move in picking.move_lines: + if move.purchase_line_id and move.purchase_line_id.order_id.invoice_method == 'picking': + if not move.move_orig_ids: + res[picking.id] = True + return res + + def _get_picking_to_recompute(self, cr, uid, ids, context=None): + picking_ids = set() + for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context): + if move.picking_id: + picking_ids.add(move.picking_id.id) + return list(picking_ids) + _columns = { - 'purchase_id': fields.many2one('purchase.order', 'Purchase Order', - ondelete='set null', select=True), + 'reception_to_invoice': fields.function(_get_to_invoice, type='boolean', string='Invoiceable on incoming shipment?', + help='Does the picking contains some moves related to a purchase order invoiceable on the reception?', + store={ + 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['move_lines'], 10), + 'stock.move': (_get_picking_to_recompute, ['purchase_line_id', 'picking_id'], 10), + }), } - _defaults = { - 'purchase_id': False, - } # TODO: Invoice based on receptions # Here is how it should work: diff --git a/addons/purchase/stock_view.xml b/addons/purchase/stock_view.xml index 18ad626b84b..9e8f321cdfd 100644 --- a/addons/purchase/stock_view.xml +++ b/addons/purchase/stock_view.xml @@ -12,24 +12,13 @@
- - Picking Inherited - stock.picking - - - - - - - - stock.picking.in.search.inherit stock.picking - + @@ -58,8 +47,7 @@ ir.actions.act_window form tree,form,calendar - [('purchase_id.invoice_method','=','picking')] - {"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_to_invoice": 1} + {"default_type": "in", "contact_display": "partner_address", "search_default_done": 1, "search_default_reception_to_invoice": 1}

diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 8cbe8307f15..d47b2fc1d63 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1310,7 +1310,7 @@ class stock_move(osv.osv): 'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Optional: next stock move when chaining them", select=True), 'move_orig_ids': fields.one2many('stock.move', 'move_dest_id', 'Original Move', help="Optional: previous stock move when chaining them", select=True), - 'picking_id': fields.many2one('stock.picking', 'Reference', select=True,states={'done': [('readonly', True)]}), + 'picking_id': fields.many2one('stock.picking', 'Reference', select=True, states={'done': [('readonly', True)]}), 'picking_priority': fields.related('picking_id','priority', type='selection', selection=[('0','Low'),('1','Normal'),('2','High')], string='Picking Priority'), 'note': fields.text('Notes'), 'state': fields.selection([('draft', 'New'), diff --git a/addons/stock_complex_routes/test/dropship.yml b/addons/stock_complex_routes/test/dropship.yml index ab2d972af2b..502231df81a 100644 --- a/addons/stock_complex_routes/test/dropship.yml +++ b/addons/stock_complex_routes/test/dropship.yml @@ -71,8 +71,9 @@ - !python {model: stock.picking}: | po_id = self.pool.get('purchase.order').search(cr, uid, [('partner_id', '=', ref('supplier_dropship'))]) - picking_id = self.search(cr, uid, [('purchase_id', '=', po_id[0])]) - self.do_partial(cr, uid, picking_id) + assert po_id and len(po_id) == 1, 'Problem with the Purchase Order detected' + picking_ids = [pick.id for pick in self.pool.get('purchase.order').browse(cr, uid, po_id[0]).picking_ids] + self.do_partial(cr, uid, picking_ids) - Check one quant was created in Customers location with 200 pieces and one move in the history_ids - From 0f0d6cad63d88d9f6fc890726e96b45bc95ada6e Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 21 Oct 2013 13:25:18 +0200 Subject: [PATCH 05/18] [FIX] purchase: purhcase_id field on stock.picking doesn't exist anymore bzr revid: qdp-launchpad@openerp.com-20131021112518-2gwjvmoehlzxherf --- addons/purchase/purchase.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 0a7829d2660..e378ec83e20 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -102,13 +102,13 @@ class purchase_order(osv.osv): for id in ids: res[id] = [0.0,0.0] cr.execute('''SELECT - p.purchase_id,sum(m.product_qty), m.state + p.order_id, sum(m.product_qty), m.state FROM stock_move m LEFT JOIN - stock_picking p on (p.id=m.picking_id) + purchase_order_line p on (p.id=m.purchase_line_id) WHERE - p.purchase_id IN %s GROUP BY m.state, p.purchase_id''',(tuple(ids),)) + p.order_id IN %s GROUP BY m.state, p.order_id''',(tuple(ids),)) for oid,nbr,state in cr.fetchall(): if state=='cancel': continue From e0b7ff8de62a7bf0864111a26fffa25560567ea8 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Mon, 21 Oct 2013 17:12:35 +0200 Subject: [PATCH 06/18] [IMP] stock, procurement, purchase, mrp: cancelation of a procurement now propagate the cancellation upstream if the rule says so bzr revid: qdp-launchpad@openerp.com-20131021151235-y0kjr9vy06a3curr --- addons/mrp/procurement.py | 5 +++++ addons/purchase/purchase.py | 5 +++++ addons/stock/procurement.py | 26 ++++++++++++++++++++------ addons/stock/stock.py | 8 +++++++- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index df80ac2ea9f..d342198e461 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -40,6 +40,11 @@ class procurement_order(osv.osv): 'production_id': fields.many2one('mrp.production', 'Manufacturing Order'), } + def propagate_cancel(self, cr, uid, procurement, context=None): + if procurement.rule_id.action == 'manufacture' and procurement.production_id: + self.pool.get('mrp.production').action_cancel(cr, uid, [procurement.production_id.id], context=context) + return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context) + def _run(self, cr, uid, procurement, context=None): if procurement.rule_id and procurement.rule_id.action == 'manufacture': #make a manufacturing order for the procurement diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index e378ec83e20..4f610575740 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1082,6 +1082,11 @@ class procurement_order(osv.osv): 'purchase_line_id': fields.many2one('purchase.order.line', 'Purchase Order'), } + def propagate_cancel(self, cr, uid, procurement, context=None): + if procurement.rule_id.action == 'buy' and procurement.purchase_line_id: + self.pool.get('purchase.order.line').write(cr, uid, [procurement.purchase_line_id.id], {'state': 'cancel'}, context=context) + return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context) + def _run(self, cr, uid, procurement, context=None): if procurement.rule_id: print procurement.rule_id.action diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index c1866867894..eb73980f47e 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -66,23 +66,22 @@ class procurement_rule(osv.osv): help="Source location is action=move"), 'route_id': fields.many2one('stock.location.route', 'Route', help="If route_id is False, the rule is global"), - 'procure_method': fields.selection([('make_to_stock','Make to Stock'),('make_to_order','Make to Order')], 'Procure Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."), + 'procure_method': fields.selection([('make_to_stock', 'Make to Stock'), ('make_to_order', 'Make to Order')], 'Procure Method', required=True, help="'Make to Stock': When needed, take from the stock or wait until re-supplying. 'Make to Order': When needed, purchase or produce for the procurement request."), 'route_sequence': fields.related('route_id', 'sequence', string='Route Sequence', store={ 'stock.location.route': (_get_rules, ['sequence'], 10), 'procurement.rule': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 10), }), 'sequence': fields.integer('Sequence'), - 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', + 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="Picking Type determines the way the picking should be shown in the view, reports, ..."), 'active': fields.related('route_id', 'active', type='boolean', string='Active', store={ 'stock.location.route': (_get_route, ['active'], 20), - 'procurement.rule': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 20),}, - help="If the active field is set to False, it will allow you to hide the rule without removing it." ), + 'procurement.rule': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 20)}, + help="If the active field is set to False, it will allow you to hide the rule without removing it."), 'delay': fields.integer('Number of Days'), 'partner_address_id': fields.many2one('res.partner', 'Partner Address'), 'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'), - } _defaults = { @@ -102,7 +101,22 @@ class procurement_order(osv.osv): 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"), } - + + def propagate_cancel(self, cr, uid, procurement, context=None): + if procurement.rule_id.action == 'move' and procurement.move_ids: + self.pool.get('stock.move').action_cancel(cr, uid, [m.id for m in procurement.move_ids], context=context) + + def cancel(self, cr, uid, ids, context=None): + if context is None: + context = {} + ctx = context.copy() + #set the context for the propagation of the procurement cancelation + ctx['cancel_procurement'] = True + for procurement in self.browse(cr, uid, ids, context=ctx): + if procurement.rule_id and procurement.rule_id.propagate: + self.propagate_cancel(cr, uid, procurement, context=ctx) + return super(procurement_order, self).cancel(cr, uid, ids, context=ctx) + def _find_parent_locations(self, cr, uid, procurement, context=None): location = procurement.location_id res = [location.id] diff --git a/addons/stock/stock.py b/addons/stock/stock.py index d47b2fc1d63..fb5c92d4c71 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1700,6 +1700,7 @@ class stock_move(osv.osv): """ Cancels the moves and if all moves are cancelled it cancels the picking. @return: True """ + procurement_obj = self.pool.get('procurement.order') context = context or {} for move in self.browse(cr, uid, ids, context=context): if move.state == 'done': @@ -1707,7 +1708,12 @@ class stock_move(osv.osv): _('You cannot cancel a stock move that has been set to \'Done\'.')) if move.reserved_quant_ids: self.pool.get("stock.quant").quants_unreserve(cr, uid, move, context=context) - if move.move_dest_id: + if context.get('cancel_procurement'): + if move.propagate: + procurement_ids = procurement_obj.search(cr, uid, [('move_dest_id', '=', move.id)], context=context) + procurement_obj.cancel(cr, uid, procurement_ids, context=context) + elif move.move_dest_id: + #cancel chained moves if move.propagate: self.action_cancel(cr, uid, [move.move_dest_id.id], context=context) elif move.move_dest_id.state == 'waiting': From 4d8a5750de9588aecdd3fdd298a855613aa7c5c8 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 10:58:56 +0200 Subject: [PATCH 07/18] [IMP] purchase: cancellation of a procurement related to a PO + some usability changes bzr revid: qdp-launchpad@openerp.com-20131022085856-i9m00f1hh0qkrkk9 --- addons/purchase/purchase.py | 11 +++++++++-- addons/purchase/purchase_view.xml | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 4f610575740..c5890edd5b7 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -964,6 +964,12 @@ class purchase_order_line(osv.osv): supplier_delay = int(supplier_info.delay) if supplier_info else 0 return datetime.strptime(date_order_str, DEFAULT_SERVER_DATE_FORMAT) + relativedelta(days=supplier_delay) + def action_cancel(self, cr, uid, ids, context=None): + self.write(cr, uid, ids, {'state': 'cancel'}, context=context) + for po_line in self.browse(cr, uid, ids, context=context): + if all([l.state == 'cancel' for l in po_line.order_id.order_line]): + self.pool.get('purchase.order').action_cancel(cr, uid, [po_line.order_id.id], context=context) + def _check_product_uom_group(self, cr, uid, context=None): group_uom = self.pool.get('ir.model.data').get_object(cr, uid, 'product', 'group_uom') res = [user for user in group_uom.users if user.id == uid] @@ -1079,12 +1085,13 @@ class procurement_rule(osv.osv): class procurement_order(osv.osv): _inherit = 'procurement.order' _columns = { - 'purchase_line_id': fields.many2one('purchase.order.line', 'Purchase Order'), + 'purchase_line_id': fields.many2one('purchase.order.line', 'Purchase Order Line'), + 'purchase_id': fields.related('purchase_line_id', 'order_id', type='many2one', relation='purchase.order', string='Purchase Order'), } def propagate_cancel(self, cr, uid, procurement, context=None): if procurement.rule_id.action == 'buy' and procurement.purchase_line_id: - self.pool.get('purchase.order.line').write(cr, uid, [procurement.purchase_line_id.id], {'state': 'cancel'}, context=context) + self.pool.get('purchase.order.line').action_cancel(cr, uid, [procurement.purchase_line_id.id], context=context) return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context) def _run(self, cr, uid, procurement, context=None): diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index a88004c3063..e2e722f38ce 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -208,7 +208,7 @@ - + @@ -219,6 +219,7 @@ + @@ -550,7 +551,7 @@ - + From 52cfccf2cedf694e5c3ab4f51694300e20788191 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 14:01:00 +0200 Subject: [PATCH 08/18] [FIX] sale_stock: onchange_product_id parameters fixed in form view (warehouse_id wasn't passed) bzr revid: qdp-launchpad@openerp.com-20131022120100-t4d0y7q80sjmafnw --- addons/sale_stock/sale_stock_view.xml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index 448df25c446..01b978a0dc7 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -29,13 +29,24 @@ - + - + + + + + + + From 441d0bc0093c8924828c04b97eefbdfb7b94a55b Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 14:06:05 +0200 Subject: [PATCH 09/18] [FIX] stock, sale_stock: changed the way the procurements look for a suitable rule => Added a m2o field warehouse_id on procurement.order, procurement.rule and stock.move. There was a problem with MTO products because they weren't following the route of the chosen warehouse at all (since all warehouse were creating their rule in the same route, there was no garantee that the route chosen was included in the warehouse selected on the SO) bzr revid: qdp-launchpad@openerp.com-20131022120605-3dj65nm5yc96sj5r --- addons/sale_stock/sale_stock.py | 11 +++++------ addons/stock/procurement.py | 14 ++++++++++++-- addons/stock/stock.py | 14 +++++++++++++- addons/stock/stock_view.xml | 14 ++------------ 4 files changed, 32 insertions(+), 21 deletions(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 512a3bc2261..3ea0621e2f0 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -85,15 +85,14 @@ class sale_order(osv.osv): res[sale.id] = list(picking_ids) return res - def _prepare_order_line_procurement(self, cr, uid, order, line, group_id = False, context=None): + def _prepare_order_line_procurement(self, cr, uid, order, line, group_id=False, context=None): vals = super(sale_order, self)._prepare_order_line_procurement(cr, uid, order, line, group_id=group_id, context=context) location_id = order.partner_shipping_id.property_stock_customer.id vals['location_id'] = location_id - - routes = [] - routes += order.warehouse_id and [(4, x.id) for x in order.warehouse_id.route_ids] or [] #route_ids - routes += line.route_id and [(4, line.route_id.id)] or [] #route_id - vals['route_ids'] = routes + + routes = line.route_id and [(4, line.route_id.id)] or [] + vals['route_ids'] = routes + vals['warehouse_id'] = order.warehouse_id and order.warehouse_id.id or False return vals _columns = { diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index eb73980f47e..dfa92f80733 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -82,6 +82,7 @@ class procurement_rule(osv.osv): 'delay': fields.integer('Number of Days'), 'partner_address_id': fields.many2one('res.partner', 'Partner Address'), 'propagate': fields.boolean('Propagate cancel and split', help='If checked, when the previous move of the move (which was generated by a next procurement) is cancelled or split, the move generated by this move will too'), + 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), } _defaults = { @@ -99,7 +100,7 @@ class procurement_order(osv.osv): 'move_ids': fields.one2many('stock.move', 'procurement_id', 'Moves', help="Moves created by the procurement"), 'move_dest_id': fields.many2one('stock.move', 'Destination Move', help="Move which caused (created) the procurement"), 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_procurement', 'procurement_id', 'route_id', 'Followed Route', help="Preferred route to be followed by the procurement order"), - + 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Warehouse to consider for the route selection"), } def propagate_cancel(self, cr, uid, procurement, context=None): @@ -125,10 +126,18 @@ class procurement_order(osv.osv): res.append(location.id) return res + def change_warehouse_id(self, cr, uid, ids, warehouse_id, context=None): + if warehouse_id: + warehouse = self.pool.get('stock.warehouse').browse(cr, uid, warehouse_id, context=context) + return {'value': {'location_id': warehouse.lot_stock_id.id}} + return {} + def _search_suitable_rule(self, cr, uid, procurement, domain, context=None): '''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior''' + if procurement.warehouse_id: + domain += [('warehouse_id', '=', procurement.warehouse_id.id)] product_route_ids = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids] - procurement_route_ids = [x.id for x in procurement.route_ids] + procurement_route_ids = [x.id for x in procurement.route_ids] + [x.id for x in procurement.warehouse_id.route_ids] res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order = 'route_sequence, sequence', context=context) if not res: res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order = 'route_sequence, sequence', context=context) @@ -171,6 +180,7 @@ class procurement_order(osv.osv): 'picking_type_id': procurement.rule_id.picking_type_id.id, 'group_id': procurement.group_id and procurement.group_id.id or False, 'route_ids': [(4, x.id) for x in procurement.route_ids], + 'warehouse_id': procurement.rule_id.warehouse_id.id, } if procurement.rule_id: newdate = (datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.rule_id.delay or 0)).strftime('%Y-%m-%d %H:%M:%S') diff --git a/addons/stock/stock.py b/addons/stock/stock.py index fb5c92d4c71..e149a67e02d 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1356,6 +1356,7 @@ class stock_move(osv.osv): 'restrict_partner_id': fields.many2one('res.partner', 'Owner ', help="Technical field used to depict a restriction on the ownership of quants to consider when marking this move as 'done'"), 'putaway_ids': fields.one2many('stock.move.putaway', 'move_id', 'Put Away Suggestions'), 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_move', 'move_id', 'route_id', 'Destination route', help="Preferred route to be followed by the procurement order"), + 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse', help="Technical field depicting the warehouse to consider for the route selection on the next procurement (if any)."), } def copy(self, cr, uid, id, default=None, context=None): @@ -1420,6 +1421,7 @@ class stock_move(osv.osv): 'move_dest_id': move.id, 'group_id': move.group_id and move.group_id.id or False, 'route_ids' : [(4, x.id) for x in move.route_ids], + 'warehouse_id': move.warehouse_id and move.warehouse_id.id or False, } def _push_apply(self, cr, uid, moves, context): @@ -1429,7 +1431,10 @@ class stock_move(osv.osv): routes = [x.id for x in move.product_id.route_ids + move.product_id.categ_id.total_route_ids] routes = routes or [x.id for x in move.route_ids] if routes: - rules = push_obj.search(cr, uid, [('route_id', 'in', routes), ('location_from_id', '=', move.location_dest_id.id)], context=context) + domain = [('route_id', 'in', routes), ('location_from_id', '=', move.location_dest_id.id)] + if move.warehouse_id: + domain += [('warehouse_id', '=', move.warehouse_id.id)] + rules = push_obj.search(cr, uid, domain, context=context) if rules: rule = push_obj.browse(cr, uid, rules[0], context=context) push_obj._apply(cr, uid, rule, move, context=context) @@ -2225,6 +2230,7 @@ class stock_warehouse(osv.osv): 'name': fields.char('Name', size=128, required=True, select=True), 'company_id': fields.many2one('res.company', 'Company', required=True, select=True), 'partner_id': fields.many2one('res.partner', 'Address'), + 'view_location_id': fields.many2one('stock.location', 'View Location', required=True, domain=[('usage', '=', 'view')]), 'lot_stock_id': fields.many2one('stock.location', 'Location Stock', required=True, domain=[('usage', '=', 'internal')]), 'code': fields.char('Short Name', size=5, required=True, help="Short name used to identify your warehouse"), 'route_ids': fields.many2many('stock.location.route', 'stock_route_warehouse', 'warehouse_id', 'route_id', 'Routes', domain="[('warehouse_selectable', '=', True)]", help='Defaults routes through the warehouse'), @@ -2382,6 +2388,7 @@ class stock_warehouse(osv.osv): 'auto': 'manual', 'picking_type_id': pick_type_id, 'active': active, + 'warehouse_id': warehouse.id, }) pull_rules_list.append({ 'name': self._format_rulename(cr, uid, warehouse, from_loc, dest_loc, context=context), @@ -2392,6 +2399,7 @@ class stock_warehouse(osv.osv): 'picking_type_id': pick_type_id, 'procure_method': first_rule is True and 'make_to_stock' or 'make_to_order', 'active': active, + 'warehouse_id': warehouse.id, }) first_rule = False return push_rules_list, pull_rules_list @@ -2416,6 +2424,7 @@ class stock_warehouse(osv.osv): 'picking_type_id': pick_type_id, 'procure_method': 'make_to_order', 'active': True, + 'warehouse_id': warehouse.id, } def _get_crossdock_route(self, cr, uid, warehouse, route_name, context=None): @@ -2546,6 +2555,7 @@ class stock_warehouse(osv.osv): 'usage': 'view', 'location_id': data_obj.get_object_reference(cr, uid, 'stock', 'stock_location_locations')[1] }, context=context) + vals['view_location_id'] = wh_loc_id #create all location reception_steps = vals.get('reception_steps', False) delivery_steps = vals.get('delivery_steps', False) @@ -2834,6 +2844,7 @@ class stock_location_path(osv.osv): 'stock.location.route': (_get_route, ['active'], 20), 'stock.location.path': (lambda self, cr, uid, ids, c={}: ids, ['route_id'], 20),}, help="If the active field is set to False, it will allow you to hide the rule without removing it." ), + 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), } _defaults = { 'auto': 'auto', @@ -2865,6 +2876,7 @@ class stock_location_path(osv.osv): 'picking_type_id': rule.picking_type_id and rule.picking_type_id.id or False, 'rule_id': rule.id, 'propagate': rule.propagate, + 'warehouse_id': rule.warehouse_id and rule.warehouse_id.id or False, }) move_obj.write(cr, uid, [move.id], { 'move_dest_id': move_id, diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 5d161878078..19c29f7dd0b 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1667,7 +1667,8 @@ - + + @@ -2128,17 +2129,6 @@ - - - procurement.order.form.view.inherit - - procurement.order - - - - - - product.template.procurement.rule.inherit From 492b4b568a3db9943a8e7f0a5b2937d304888724 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 14:29:58 +0200 Subject: [PATCH 10/18] [IMP] stock: give highest priority to routes set directly on the procurement.order (and thus on SO lines) bzr revid: qdp-launchpad@openerp.com-20131022122958-gkm1unk3n4g7a3j0 --- addons/stock/procurement.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index dfa92f80733..6526287ef83 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -134,15 +134,19 @@ class procurement_order(osv.osv): def _search_suitable_rule(self, cr, uid, procurement, domain, context=None): '''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior''' + pull_obj = self.pool.get('procurement.rule') if procurement.warehouse_id: domain += [('warehouse_id', '=', procurement.warehouse_id.id)] product_route_ids = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids] - procurement_route_ids = [x.id for x in procurement.route_ids] + [x.id for x in procurement.warehouse_id.route_ids] - res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order = 'route_sequence, sequence', context=context) + procurement_route_ids = [x.id for x in procurement.route_ids] + warehouse_route_ids = [x.id for x in procurement.warehouse_id.route_ids] + res = pull_obj.search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order='route_sequence, sequence', context=context) if not res: - res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order = 'route_sequence, sequence', context=context) + res = pull_obj.search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order='route_sequence, sequence', context=context) if not res: - res = self.pool.get('procurement.rule').search(cr, uid, domain + [('route_id', '=', False)], order='sequence', context=context) + res = pull_obj.search(cr, uid, domain + [('route_id', 'in', warehouse_route_ids)], order='route_sequence, sequence', context=context) + if not res: + res = pull_obj.search(cr, uid, domain + [('route_id', '=', False)], order='sequence', context=context) return res def _find_suitable_rule(self, cr, uid, procurement, context=None): From 176c1dde30515dd3c1f1862b5e9e75b484f7fb02 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 15:13:58 +0200 Subject: [PATCH 11/18] [FIX] stock: fixed case whre warehouse_id is not defined on procurement.order bzr revid: qdp-launchpad@openerp.com-20131022131358-617w4747w9pw254x --- addons/stock/procurement.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index 6526287ef83..1ccef353f0c 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -135,16 +135,17 @@ class procurement_order(osv.osv): def _search_suitable_rule(self, cr, uid, procurement, domain, context=None): '''we try to first find a rule among the ones defined on the procurement order group and if none is found, we try on the routes defined for the product, and finally we fallback on the default behavior''' pull_obj = self.pool.get('procurement.rule') + warehouse_route_ids = [] if procurement.warehouse_id: domain += [('warehouse_id', '=', procurement.warehouse_id.id)] + warehouse_route_ids = [x.id for x in procurement.warehouse_id.route_ids] product_route_ids = [x.id for x in procurement.product_id.route_ids + procurement.product_id.categ_id.total_route_ids] procurement_route_ids = [x.id for x in procurement.route_ids] - warehouse_route_ids = [x.id for x in procurement.warehouse_id.route_ids] res = pull_obj.search(cr, uid, domain + [('route_id', 'in', procurement_route_ids)], order='route_sequence, sequence', context=context) if not res: res = pull_obj.search(cr, uid, domain + [('route_id', 'in', product_route_ids)], order='route_sequence, sequence', context=context) if not res: - res = pull_obj.search(cr, uid, domain + [('route_id', 'in', warehouse_route_ids)], order='route_sequence, sequence', context=context) + res = warehouse_route_ids and pull_obj.search(cr, uid, domain + [('route_id', 'in', warehouse_route_ids)], order='route_sequence, sequence', context=context) or [] if not res: res = pull_obj.search(cr, uid, domain + [('route_id', '=', False)], order='sequence', context=context) return res From 533d176df743896eacec44bd39cf50b25a187522 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 17:29:58 +0200 Subject: [PATCH 12/18] [FIX] warning: fixed dependancies and product_id_change() method bzr revid: qdp-launchpad@openerp.com-20131022152958-2w7xpn0fox88m5w2 --- addons/warning/__openerp__.py | 2 +- addons/warning/warning.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/addons/warning/__openerp__.py b/addons/warning/__openerp__.py index e44b9624251..887e43b939c 100644 --- a/addons/warning/__openerp__.py +++ b/addons/warning/__openerp__.py @@ -32,7 +32,7 @@ Warning messages can be displayed for objects like sale order, purchase order, picking and invoice. The message is triggered by the form's onchange event. """, 'author': 'OpenERP SA', - 'depends': ['base', 'sale', 'purchase'], + 'depends': ['base', 'sale_stock', 'purchase'], 'data': ['warning_view.xml'], 'demo': [], 'installable': True, diff --git a/addons/warning/warning.py b/addons/warning/warning.py index aaf15d350bd..fe3b93dff0a 100644 --- a/addons/warning/warning.py +++ b/addons/warning/warning.py @@ -170,8 +170,6 @@ class stock_picking(osv.osv): return {'value': result.get('value',{}), 'warning':warning} -# FIXME:(class stock_picking_in and stock_picking_out) this is a temporary workaround because of a framework bug (ref: lp:996816). -# It should be removed as soon as the bug is fixed class stock_picking(osv.osv): _inherit = 'stock.picking' @@ -218,7 +216,7 @@ class sale_order_line(osv.osv): def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, - fiscal_position=False, flag=False, context=None): + fiscal_position=False, flag=False, warehouse_id=False, context=None): warning = {} if not product: return {'value': {'th_weight' : 0, 'product_packaging': False, @@ -239,7 +237,7 @@ class sale_order_line(osv.osv): result = super(sale_order_line, self).product_id_change( cr, uid, ids, pricelist, product, qty, uom, qty_uos, uos, name, partner_id, - lang, update_tax, date_order, packaging, fiscal_position, flag, context=context) + lang, update_tax, date_order, packaging, fiscal_position, flag, warehouse_id=warehouse_id, context=context) if result.get('warning',False): warning['title'] = title and title +' & '+result['warning']['title'] or result['warning']['title'] From 87450a8f13866d0b8556b8537dc5d8438d013ac3 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Tue, 22 Oct 2013 18:03:12 +0200 Subject: [PATCH 13/18] [FIX] stock: fixed crossdock route priority + [IMP] added the possibility to group picking by group_id bzr revid: qdp-launchpad@openerp.com-20131022160312-p5o0i7fd6m6kd21y --- addons/stock/stock.py | 7 ++++++- addons/stock/stock_view.xml | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index e149a67e02d..5239c9a7d47 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -664,7 +664,11 @@ class stock_picking(osv.osv): 'product_id': fields.related('move_lines', 'product_id', type='many2one', relation='product.product', string='Product'),#? 'location_id': fields.related('move_lines', 'location_id', type='many2one', relation='stock.location', string='Location', readonly=True), 'location_dest_id': fields.related('move_lines', 'location_dest_id', type='many2one', relation='stock.location', string='Destination Location', readonly=True), - 'group_id': fields.related('move_lines', 'group_id', type='many2one', relation='procurement.group', string='Procurement Group', readonly=True), + 'group_id': fields.related('move_lines', 'group_id', type='many2one', relation='procurement.group', string='Procurement Group', readonly=True, + store={ + 'stock.picking': (lambda cr, uid, ids, c: ids, ['move_lines'], 10), + 'stock.move': (_get_pickings, ['group_id', 'picking_id'], 10), + }), } _defaults = { @@ -2434,6 +2438,7 @@ class stock_warehouse(osv.osv): 'product_selectable': True, 'product_categ_selectable': True, 'active': warehouse.delivery_steps != 'ship_only' and warehouse.reception_steps != 'one_step', + 'sequence': 20, } def create_routes(self, cr, uid, ids, warehouse, context=None): diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 19c29f7dd0b..775b5d7b307 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -751,6 +751,7 @@ + @@ -862,6 +863,7 @@ + From fcbfec15192f9668a898f2819bf00fcb3d11eed7 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Oct 2013 10:57:58 +0200 Subject: [PATCH 14/18] [FIX] sale_stock, warning: fixed inheritancy of product_id_change in order to be more modular with other modules bzr revid: qdp-launchpad@openerp.com-20131023085758-1kz7r8kepmuhthr3 --- addons/sale_stock/sale_stock.py | 2 +- addons/sale_stock/sale_stock_view.xml | 4 ++-- addons/warning/warning.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 3ea0621e2f0..648c3c3444e 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -328,7 +328,7 @@ class sale_order_line(osv.osv): return {'value': result, 'warning': warning} - def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, + def product_id_change_with_wh(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, warehouse_id=False, context=None): context = context or {} diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index 01b978a0dc7..92826be34ec 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -33,12 +33,12 @@ + on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, True, parent.date_order, product_packaging, parent.fiscal_position, False, parent.warehouse_id, context)"/> + on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, parent.warehouse_id, context)"/> Date: Wed, 23 Oct 2013 11:25:08 +0200 Subject: [PATCH 15/18] [FIX] stock: reception pull rule are now configured with procure_method='make_to_order' because once the procurement order is made on the stock location, the flow should be treated without waiting for the scheduler/an orderpoint bzr revid: qdp-launchpad@openerp.com-20131023092508-a3xak2lsbgaxgzd9 --- addons/stock/stock.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 5239c9a7d47..738490f3a4b 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -2457,6 +2457,8 @@ class stock_warehouse(osv.osv): for push_rule in push_rules_list: push_obj.create(cr, uid, vals=push_rule, context=context) for pull_rule in pull_rules_list: + #all pull rules in reception route are mto, because we don't won't to wait for the scheduler to trigger an orderpoint on input location + pull_rule['procure_method'] = 'make_to_order' pull_obj.create(cr, uid, vals=pull_rule, context=context) #create MTS route and pull rules for delivery a specific route MTO to be set on the product From d4cbef2cb84d3f3a1933b18ce5be376b3d772f87 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Oct 2013 11:30:47 +0200 Subject: [PATCH 16/18] [FIX] stock: missing parameter in lambda function for store_get_values bzr revid: qdp-launchpad@openerp.com-20131023093047-8c6pp6euxhwna5z9 --- addons/stock/stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 738490f3a4b..abcd5a464c1 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -666,7 +666,7 @@ class stock_picking(osv.osv): 'location_dest_id': fields.related('move_lines', 'location_dest_id', type='many2one', relation='stock.location', string='Destination Location', readonly=True), 'group_id': fields.related('move_lines', 'group_id', type='many2one', relation='procurement.group', string='Procurement Group', readonly=True, store={ - 'stock.picking': (lambda cr, uid, ids, c: ids, ['move_lines'], 10), + 'stock.picking': (lambda self, cr, uid, ids, ctx: ids, ['move_lines'], 10), 'stock.move': (_get_pickings, ['group_id', 'picking_id'], 10), }), } From 7cf0f9227789b29ec2210513850f41436048c9b3 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Oct 2013 11:40:25 +0200 Subject: [PATCH 17/18] [FIX] sale_stock: fixed inheritancy of product_id_change in order to be more modular with other modules bzr revid: qdp-launchpad@openerp.com-20131023094025-rkcf0ccs8j95d4su --- addons/sale_stock/sale_stock_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/sale_stock/sale_stock_view.xml b/addons/sale_stock/sale_stock_view.xml index 92826be34ec..7f3f2f12871 100644 --- a/addons/sale_stock/sale_stock_view.xml +++ b/addons/sale_stock/sale_stock_view.xml @@ -44,12 +44,12 @@ + on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, True, parent.date_order, product_packaging, parent.fiscal_position, False, parent.warehouse_id, context)"/> + on_change="product_id_change_with_wh(parent.pricelist_id,product_id,product_uom_qty,product_uom,product_uos_qty,product_uos,name,parent.partner_id, False, False, parent.date_order, product_packaging, parent.fiscal_position, True, parent.warehouse_id, context)"/> From 177abaeccf600a00c2423e08d0f4ed5384bd9ef9 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 23 Oct 2013 12:00:05 +0200 Subject: [PATCH 18/18] [IMP] purchase: removed debug statement bzr revid: qdp-launchpad@openerp.com-20131023100005-30p2uo874zsdaum6 --- addons/purchase/purchase.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index c5890edd5b7..b4054416440 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1095,8 +1095,6 @@ class procurement_order(osv.osv): return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context) def _run(self, cr, uid, procurement, context=None): - if procurement.rule_id: - print procurement.rule_id.action if procurement.rule_id and procurement.rule_id.action == 'buy': #make a purchase order for the procurement return self.make_po(cr, uid, [procurement.id], context=context)[procurement.id]