From d0378548a1ab709f135de456082de8cbddcb8241 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 7 Aug 2013 12:04:28 +0200 Subject: [PATCH 01/30] [IMP] added availability functional field on stock.move bzr revid: qdp-launchpad@openerp.com-20130807100428-jz5xnniftxq28am4 --- addons/stock/stock.py | 16 ++++++++++++++++ addons/stock/stock_view.xml | 1 + 2 files changed, 17 insertions(+) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index e6f57c4cfd3..47e0cc9a822 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -903,6 +903,21 @@ class stock_move(osv.osv): res[move.id] = [q.id for q in move.reserved_quant_ids] return res + def _get_product_availability(self, cr, uid, ids, field_name, args, context=None): + quant_obj = self.pool.get('stock.quant') + res = dict.fromkeys(ids, False) + for move in self.browse(cr, uid, ids, context=context): + if move.state == 'done': + res[move.id] = move.product_qty + else: + sublocation_ids = self.pool.get('stock.location').search(cr, uid, [('id', 'child_of', [move.location_id.id])], context=context) + quant_ids = quant_obj.search(cr, uid, [('location_id', 'in', sublocation_ids), ('product_id', '=', move.product_id.id), ('reservation_id', '=', False)], context=context) + availability = 0 + for quant in quant_obj.browse(cr, uid, quant_ids, context=context): + availability += quant.qty + res[move.id] = min(move.product_qty, availability) + return res + _columns = { 'name': fields.char('Description', required=True, select=True), 'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'), @@ -978,6 +993,7 @@ class stock_move(osv.osv): 'lot_ids': fields.function(_get_lot_ids, type='many2many', relation='stock.quant', string='Lots'), 'origin_returned_move_id': fields.many2one('stock.move', 'Origin return move', help='move that created the return move'), 'returned_move_ids': fields.one2many('stock.move', 'origin_returned_move_id', 'All returned moves', help='Optional: all returned moves created from this move'), + 'availability': fields.function(_get_product_availability, type='float', string='Availability'), } def copy(self, cr, uid, id, default=None, context=None): diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 8b07114d506..7327ecfce8e 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -803,6 +803,7 @@ + From 41ab601cef8336b557dc4348da119c8435ad5a87 Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 7 Aug 2013 12:22:57 +0200 Subject: [PATCH 02/30] [IMP] usability in quant views bzr revid: qdp-launchpad@openerp.com-20130807102257-egzkuadf6k32v732 --- addons/stock/stock.py | 1 + addons/stock/stock_view.xml | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 47e0cc9a822..7369d723ed1 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -152,6 +152,7 @@ class stock_quant(osv.osv): 'location_id': fields.many2one('stock.location', 'Location', required=True), 'qty': fields.float('Quantity', required=True, help="Quantity of products in this quant, in the default unit of measure of the product"), 'package_id': fields.many2one('stock.quant.package', string='Package', help="The package containing this quant"), + 'packaging_type_id': fields.related('package_id', 'packaging_id', type='many2one', relation='product.packaging', string='Type of packaging', store=True), 'reservation_id': fields.many2one('stock.move', 'Reserved for Move', help="Is this quant reserved for a stock.move?"), 'lot_id': fields.many2one('stock.production.lot', 'Lot'), 'cost': fields.float('Unit Cost'), diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 7327ecfce8e..da202f04d10 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1478,8 +1478,10 @@ + + @@ -1522,6 +1524,9 @@ + + + From 05e01eafe6a825f8e38c10b5dd6500e4c5fb4e92 Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Wed, 7 Aug 2013 13:02:19 +0200 Subject: [PATCH 03/30] [FIX]scrap bzr revid: csn@openerp.com-20130807110219-82bky3atj4jefox8 --- addons/mrp/stock.py | 1 - addons/mrp_repair/mrp_repair.py | 2 -- addons/point_of_sale/point_of_sale.py | 1 - addons/stock/report/lot_move_label.xml | 2 -- addons/stock/report/lot_move_label.xsl | 4 ---- addons/stock/stock.py | 4 ++-- 6 files changed, 2 insertions(+), 12 deletions(-) diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index 1738ffe1065..476d8d00410 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -129,7 +129,6 @@ class StockMove(osv.osv): for move in self.browse(cr, uid, ids, context=context): new_moves = super(StockMove, self).action_scrap(cr, uid, [move.id], product_qty, location_id, context=context) #If we are not scrapping our whole move, tracking and lot references must not be removed - #self.write(cr, uid, [move.id], {'prodlot_id': False, 'tracking_id': False}) production_ids = production_obj.search(cr, uid, [('move_lines', 'in', [move.id])]) for prod_id in production_ids: production_obj.signal_button_produce(cr, uid, [prod_id]) diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py index 6e8a56ad7f0..fbfcac36c32 100644 --- a/addons/mrp_repair/mrp_repair.py +++ b/addons/mrp_repair/mrp_repair.py @@ -513,7 +513,6 @@ class mrp_repair(osv.osv): 'partner_id': repair.address_id and repair.address_id.id or False, 'location_id': move.location_id.id, 'location_dest_id': move.location_dest_id.id, - 'tracking_id': False, 'state': 'done', }) repair_line_obj.write(cr, uid, [move.id], {'move_id': move_id, 'state': 'done'}, context=context) @@ -537,7 +536,6 @@ class mrp_repair(osv.osv): 'partner_id': repair.address_id and repair.address_id.id or False, 'location_id': repair.location_id.id, 'location_dest_id': repair.location_dest_id.id, - 'tracking_id': False, 'state': 'assigned', }) pick_obj.signal_button_confirm(cr, uid, [picking]) diff --git a/addons/point_of_sale/point_of_sale.py b/addons/point_of_sale/point_of_sale.py index 91a56e329ef..2782f822149 100644 --- a/addons/point_of_sale/point_of_sale.py +++ b/addons/point_of_sale/point_of_sale.py @@ -724,7 +724,6 @@ class pos_order(osv.osv): 'product_id': line.product_id.id, 'product_uos_qty': abs(line.qty), 'product_uom_qty': abs(line.qty), - 'tracking_id': False, 'state': 'draft', 'location_id': location_id, 'location_dest_id': output_id, diff --git a/addons/stock/report/lot_move_label.xml b/addons/stock/report/lot_move_label.xml index cad14e70f68..028e244b894 100644 --- a/addons/stock/report/lot_move_label.xml +++ b/addons/stock/report/lot_move_label.xml @@ -6,7 +6,5 @@ - - diff --git a/addons/stock/report/lot_move_label.xsl b/addons/stock/report/lot_move_label.xsl index 57b29e69405..73f99558932 100644 --- a/addons/stock/report/lot_move_label.xsl +++ b/addons/stock/report/lot_move_label.xsl @@ -54,10 +54,6 @@ , - Serial: - Tracking: - - diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 5bd89fdd44c..c0d08da98c1 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1381,8 +1381,8 @@ class stock_move(osv.osv): 'state': move.state, 'scrapped': True, 'location_dest_id': location_id, - 'tracking_id': move.tracking_id.id, - 'lot_id': move.lot_id.id, + #TODO lot_id is now on quant and not on move, need to do something for this + #'lot_id': move.lot_id.id, } new_move = self.copy(cr, uid, move.id, default_val) From 6cdf121d5013f39fc0f0b8edcefd6f7a268dd86f Mon Sep 17 00:00:00 2001 From: "Quentin (OpenERP)" Date: Wed, 7 Aug 2013 13:13:58 +0200 Subject: [PATCH 04/30] [FIX] scrap moves bzr revid: qdp-launchpad@openerp.com-20130807111358-3lsceekxczxup8ov --- addons/stock/stock.py | 2 +- addons/stock/wizard/stock_move.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index b379b290ec3..b79cb0c6ca6 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1396,7 +1396,7 @@ class stock_move(osv.osv): uos_qty = quantity / move_qty * move.product_uos_qty default_val = { 'location_id': source_location.id, - 'product_qty': quantity, + 'product_uom_qty': quantity, 'product_uos_qty': uos_qty, 'state': move.state, 'scrapped': True, diff --git a/addons/stock/wizard/stock_move.py b/addons/stock/wizard/stock_move.py index cf1ae986c08..6e2c9a5db71 100644 --- a/addons/stock/wizard/stock_move.py +++ b/addons/stock/wizard/stock_move.py @@ -103,7 +103,7 @@ class stock_move_scrap(osv.osv_memory): res = super(stock_move_consume, self).default_get(cr, uid, fields, context=context) move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context) location_obj = self.pool.get('stock.location') - scrpaed_location_ids = location_obj.search(cr, uid, [('scrap_location','=',True)]) + scrap_location_id = location_obj.search(cr, uid, [('scrap_location','=',True)]) if 'product_id' in fields: res.update({'product_id': move.product_id.id}) @@ -112,8 +112,8 @@ class stock_move_scrap(osv.osv_memory): if 'product_qty' in fields: res.update({'product_qty': move.product_qty}) if 'location_id' in fields: - if scrpaed_location_ids: - res.update({'location_id': scrpaed_location_ids[0]}) + if scrap_location_id: + res.update({'location_id': scrap_location_id[0]}) else: res.update({'location_id': False}) From 2e6415973fe88a002f8b4601272c3853c2e3c0c4 Mon Sep 17 00:00:00 2001 From: "Bharat R. Devnani (OpenERP)" Date: Thu, 8 Aug 2013 18:11:51 +0530 Subject: [PATCH 05/30] [REM] removed reference of note field from procurement object as it is removed from object bzr revid: bde@tinyerp.com-20130808124151-yfkom98gsdarh04d --- addons/sale/sale.py | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 57c3cbf1224..b55fccc8984 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -633,7 +633,6 @@ class sale_order(osv.osv): 'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty, 'product_uos': (line.product_uos and line.product_uos.id) or line.product_uom.id, 'company_id': order.company_id.id, - 'note': line.name, 'group_id': group_id, 'invoice_state': (order.order_policy=='picking') and '2binvoiced' or 'none', 'sale_line_id': line.id From d20cfc65bd4c070b4b6f28e3fd0908ac213554b4 Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Thu, 8 Aug 2013 15:21:02 +0200 Subject: [PATCH 06/30] [FIX]stock: fix a bug in get_quant_name when there is no code defined on product and no lot bzr revid: csn@openerp.com-20130808132102-d0xx8hgqmd4l2ccb --- addons/stock/stock.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index b79cb0c6ca6..a8d4ea6a802 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -140,7 +140,8 @@ class stock_quant(osv.osv): """ res = {} for q in self.browse(cr, uid, ids, context=context): - res[q.id] = q.product_id.code + + res[q.id] = q.product_id.code or '' if q.lot_id: res[q.id] = q.lot_id.name res[q.id] += ': '+ str(q.qty) + q.product_id.uom_id.name From 2cda30253f55f55cbb459995e06cd51abe4966e3 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 12 Aug 2013 14:37:17 +0200 Subject: [PATCH 07/30] [IMP] Change move_id in move_dest_id where needed (thanks to branch of psi), give error message when making purchase order for product without supplier bzr revid: jco@openerp.com-20130812123717-y6golm2oaxn6n9pm --- addons/mrp/procurement.py | 8 +- addons/procurement/procurement.py | 2 +- addons/purchase/purchase.py | 106 +++++++++--------- .../purchase_requisition.py | 2 +- addons/stock/procurement.py | 1 - 5 files changed, 60 insertions(+), 59 deletions(-) diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index b667f2e075f..76c9f229fdc 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -92,10 +92,10 @@ class procurement_order(osv.osv): def get_phantom_bom_id(self, cr, uid, ids, context=None): for procurement in self.browse(cr, uid, ids, context=context): - if procurement.move_id and procurement.move_id.product_id.supply_method=='produce' \ - and procurement.move_id.product_id.procure_method=='make_to_order': + if procurement.move_dest_id and procurement.move_dest_id.product_id.supply_method=='produce' \ + and procurement.move_dest_id.product_id.procure_method=='make_to_order': phantom_bom_id = self.pool.get('mrp.bom').search(cr, uid, [ - ('product_id', '=', procurement.move_id.product_id.id), + ('product_id', '=', procurement.move_dest_id.product_id.id), ('bom_id', '=', False), ('type', '=', 'phantom')]) return phantom_bom_id @@ -120,7 +120,7 @@ class procurement_order(osv.osv): move_obj = self.pool.get('stock.move') procurement_obj = self.pool.get('procurement.order') for procurement in procurement_obj.browse(cr, uid, ids, context=context): - res_id = procurement.move_id.id + res_id = procurement.move_dest_id and procurement.move_dest_id.id or False newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0) newdate = newdate - relativedelta(days=company.manufacturing_lead) produce_id = production_obj.create(cr, uid, { diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 62823369add..69e2b1cbf23 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -125,7 +125,7 @@ class procurement_order(osv.osv): ('running', 'Running'), ('done', 'Done') ], 'Status', required=True, track_visibility='onchange'), - 'message': fields.text('Latest error', help="Exception occurred while computing procurement orders."), + 'message': fields.text('Latest error', help="Exception occurred while computing procurement orders.", track_visibility='onchange'), } _defaults = { diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 31522c26dd9..a80b84bddbc 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1218,63 +1218,65 @@ class procurement_order(osv.osv): acc_pos_obj = self.pool.get('account.fiscal.position') seq_obj = self.pool.get('ir.sequence') warehouse_obj = self.pool.get('stock.warehouse') + pass_ids = [] for procurement in self.browse(cr, uid, ids, context=context): - res_id = procurement.move_id.id + res_id = procurement.move_dest_id and procurement.move_dest_id.id or False partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement. - assert partner, ('There is no supplier associated to product %s', (procurements.product_id.name)) - seller_qty = procurement.product_id.seller_qty - 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 + if not partner: + procurement.write({'message': _('There is no supplier associated to product %s') % (procurement.product_id.name)}) + else: + seller_qty = procurement.product_id.seller_qty + 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) + if seller_qty: + qty = max(qty,seller_qty) - qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id) - if seller_qty: - qty = max(qty,seller_qty) + price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, partner_id, {'uom': uom_id})[pricelist_id] - price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, partner_id, {'uom': uom_id})[pricelist_id] + schedule_date = self._get_purchase_schedule_date(cr, uid, procurement, company, context=context) + purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context) - schedule_date = self._get_purchase_schedule_date(cr, uid, procurement, company, context=context) - purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context) - - #Passing partner_id to context for purchase order line integrity of Line name - new_context = context.copy() - new_context.update({'lang': partner.lang, 'partner_id': partner_id}) - - product = prod_obj.browse(cr, uid, procurement.product_id.id, context=new_context) - taxes_ids = procurement.product_id.supplier_taxes_id - taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids) - - name = product.partner_ref - if product.description_purchase: - name += '\n'+ product.description_purchase - line_vals = { - 'name': name, - 'product_qty': qty, - 'product_id': procurement.product_id.id, - 'product_uom': uom_id, - 'price_unit': price or 0.0, - 'date_planned': schedule_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'move_dest_id': res_id, - 'taxes_id': [(6,0,taxes)], - } - name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name - po_vals = { - 'name': name, - 'origin': procurement.origin, - 'partner_id': partner_id, - 'location_id': procurement.location_id.id, - 'warehouse_id': warehouse_id and warehouse_id[0] or False, - 'pricelist_id': pricelist_id, - 'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'company_id': procurement.company_id.id, - 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False, - 'payment_term_id': partner.property_supplier_payment_term.id or False, - } - res[procurement.id] = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=new_context) - self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': res[procurement.id]}) - self.message_post(cr, uid, ids, body=_("Draft Purchase Order created"), context=context) + #Passing partner_id to context for purchase order line integrity of Line name + new_context = context.copy() + new_context.update({'lang': partner.lang, 'partner_id': partner_id}) + product = prod_obj.browse(cr, uid, procurement.product_id.id, context=new_context) + taxes_ids = procurement.product_id.supplier_taxes_id + taxes = acc_pos_obj.map_tax(cr, uid, partner.property_account_position, taxes_ids) + name = product.partner_ref + if product.description_purchase: + name += '\n'+ product.description_purchase + line_vals = { + 'name': name, + 'product_qty': qty, + 'product_id': procurement.product_id.id, + 'product_uom': uom_id, + 'price_unit': price or 0.0, + 'date_planned': schedule_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT), + 'move_dest_id': res_id, + 'taxes_id': [(6,0,taxes)], + } + name = seq_obj.get(cr, uid, 'purchase.order') or _('PO: %s') % procurement.name + po_vals = { + 'name': name, + 'origin': procurement.origin, + 'partner_id': partner_id, + 'location_id': procurement.location_id.id, + 'warehouse_id': warehouse_id and warehouse_id[0] or False, + 'pricelist_id': pricelist_id, + 'date_order': purchase_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT), + 'company_id': procurement.company_id.id, + 'fiscal_position': partner.property_account_position and partner.property_account_position.id or False, + 'payment_term_id': partner.property_supplier_payment_term.id or False, + } + res[procurement.id] = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=new_context) + self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': res[procurement.id]}) + pass_ids += [procurement.id] + if pass_ids: + self.message_post(cr, uid, pass_ids, body=_("Draft Purchase Order created"), context=context) return res def _product_virtual_get(self, cr, uid, order_point): diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index 7f23e1b548e..85fda69a65e 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -391,7 +391,7 @@ class procurement_order(osv.osv): 'date_end': procurement.date_planned, 'warehouse_id': warehouse_id and warehouse_id[0] or False, 'company_id': procurement.company_id.id, - 'move_dest_id': procurement.move_id.id, + 'move_dest_id': procurement.move_dest_id and procurement.move_dest_id.id or False, 'line_ids': [(0, 0, { 'product_id': procurement.product_id.id, 'product_uom_id': procurement.product_uom.id, diff --git a/addons/stock/procurement.py b/addons/stock/procurement.py index 71864afab13..7f36871b9d1 100644 --- a/addons/stock/procurement.py +++ b/addons/stock/procurement.py @@ -107,7 +107,6 @@ class procurement_order(osv.osv): return False else: return True - return procurement.move_id.state == 'done' return super(procurement_order, self)._check(cr, uid, procurement, context) From 3902aa61dc2fda0408390af95bba2bcba11ae40b Mon Sep 17 00:00:00 2001 From: "Jitendra Prajapati (OpenERP)" Date: Tue, 13 Aug 2013 13:13:30 +0530 Subject: [PATCH 08/30] [IMP]Improve domain syntact bzr revid: prajapatijitendra7969@gmail.com-20130813074330-i1rp7ew5i0zvm7p2 --- addons/stock/stock_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index da202f04d10..0948f445f73 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1046,7 +1046,7 @@ ir.actions.act_window form tree,form - ['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False)] + ['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),('picking_id','!=',False)] {'product_receive': True, 'search_default_future': True} @@ -1141,7 +1141,7 @@ ir.actions.act_window form tree,form - ['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),'&',('picking_id','!=',False)] + ['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),('picking_id','!=',False)] {'search_default_future': True} From f33adec29dbfceda1bef194a68b5a8820db8d9b3 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 16:23:44 +0200 Subject: [PATCH 09/30] [WIP] Change workflow of mrp and add field ready_production which checks if the raw material moves to consume are assigned, change prepare_order_line_procurement with correct params bzr revid: jco@openerp.com-20130813142344-c6n7awvjj796iliu --- addons/mrp/mrp.py | 22 +++++++++++++++++++++- addons/mrp/mrp_workflow.xml | 4 ++-- addons/project_mrp/project_mrp.py | 4 ++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 62e64dbbd59..15d034e0010 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -452,6 +452,25 @@ class mrp_production(osv.osv): result[mrp_production.id] = done / mrp_production.product_qty * 100 return result + def _moves_assigned(self, cr, uid, ids, name, arg, context=None): + """ Test whether all the consume lines are assigned """ + res = True + for production in self.browse(cr, uid, ids, context=context): + states = [x.state != 'assigned' for x in production.move_lines if x] + if any(states) or len(states) == 0: + return False + return res + + + def _mrp_from_move(self, cr, uid, ids, context=None): + """ Return mrp""" + res = [] + for move in self.browse(cr, uid, ids, context=context): + res += self.pool.get("mrp.production").search(cr, uid, [('move_lines', 'in', move.id)], context=context) + return res + + + _columns = { 'name': fields.char('Reference', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}), 'origin': fields.char('Source Document', size=64, readonly=True, states={'draft': [('readonly', False)]}, @@ -510,6 +529,8 @@ class mrp_production(osv.osv): 'cycle_total': fields.function(_production_calc, type='float', string='Total Cycles', multi='workorder', store=True), 'user_id':fields.many2one('res.users', 'Responsible'), 'company_id': fields.many2one('res.company','Company',required=True), + 'ready_production': fields.function(_moves_assigned, type='boolean', store={'stock.move': (_mrp_from_move, ['state'], 10)}), + } _defaults = { 'priority': lambda *a: '1', @@ -554,7 +575,6 @@ class mrp_production(osv.osv): 'move_created_ids2' : [], 'product_lines' : [], 'move_prod_id' : False, - 'picking_id' : False }) return super(mrp_production, self).copy(cr, uid, id, default, context) diff --git a/addons/mrp/mrp_workflow.xml b/addons/mrp/mrp_workflow.xml index 23119bf9490..388dd9039b3 100644 --- a/addons/mrp/mrp_workflow.xml +++ b/addons/mrp/mrp_workflow.xml @@ -43,7 +43,7 @@ True function - action_production_end() + action_production_end() done @@ -70,7 +70,7 @@ - picking_id and picking_id.state=='done' + ready_production diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py index 08227a8dae0..f9aea33f2fb 100644 --- a/addons/project_mrp/project_mrp.py +++ b/addons/project_mrp/project_mrp.py @@ -123,9 +123,9 @@ class product_product(osv.osv): class sale_order(osv.osv): _inherit = 'sale.order' - def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None): + def _prepare_order_line_procurement(self, cr, uid, order, line, group_id=False, context=None): proc_data = super(sale_order, self)._prepare_order_line_procurement(cr, - uid, order, line, move_id, date_planned, context=context) + uid, order, line, group_id = group_id, context=context) proc_data['sale_line_id'] = line.id return proc_data From 794f31aa7626b43a1abf1822ed00c4c07883a0e1 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 16:52:28 +0200 Subject: [PATCH 10/30] [IMP] Further remove procure_method in product bzr revid: jco@openerp.com-20130813145228-17q4z7rgqs8dwrw0 --- addons/mrp/procurement.py | 3 +-- addons/project_mrp/project_mrp_view.xml | 7 ------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 76c9f229fdc..9dad9aa5899 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -92,8 +92,7 @@ class procurement_order(osv.osv): def get_phantom_bom_id(self, cr, uid, ids, context=None): for procurement in self.browse(cr, uid, ids, context=context): - if procurement.move_dest_id and procurement.move_dest_id.product_id.supply_method=='produce' \ - and procurement.move_dest_id.product_id.procure_method=='make_to_order': + if procurement.move_dest_id and procurement.move_dest_id.product_id.supply_method=='produce': phantom_bom_id = self.pool.get('mrp.bom').search(cr, uid, [ ('product_id', '=', procurement.move_dest_id.product_id.id), ('bom_id', '=', False), diff --git a/addons/project_mrp/project_mrp_view.xml b/addons/project_mrp/project_mrp_view.xml index 6539f52155a..302225a24ec 100644 --- a/addons/project_mrp/project_mrp_view.xml +++ b/addons/project_mrp/project_mrp_view.xml @@ -49,13 +49,6 @@ False - -

- When you sell this service to a customer, a task will be - created to follow up the job to do. This task will appear - in the project related to the contract of the sales order. -

-
From 6484c55eee39b38920952b11f821c306807b58bd Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 17:55:19 +0200 Subject: [PATCH 11/30] [IMP] Remove get_type_from_usage bzr revid: jco@openerp.com-20130813155519-uavabjg8x6z80i64 --- addons/stock/stock.py | 10 ---------- addons/stock_location/stock_location.py | 1 - 2 files changed, 11 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index a8d4ea6a802..9788a0c33d8 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1510,16 +1510,6 @@ class stock_move(osv.osv): }, context=context) return new_move - def get_type_from_usage(self, cr, uid, location, location_dest, context=None): - ''' - Returns the type to be chosen based on the usages of the locations - ''' - if location.usage == 'internal' and location_dest.usage in ['supplier', 'customer']: - return 'out' - if location.usage in ['supplier', 'customer'] and location_dest.usage == 'internal' : - return 'in' - return 'internal' - class stock_inventory(osv.osv): _name = "stock.inventory" _description = "Inventory" diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index 26992746edb..668b80ae72a 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -102,7 +102,6 @@ class stock_location_path(osv.osv): 'date_expected': newdate, 'picking_id': False, 'picking_type_id': rule.picking_type_id and rule.picking_type_id.id or False, - 'type': move_obj.get_type_from_usage(cr, uid, move.location_id, move.location_dest_id, context=context), 'rule_id': rule.id, 'propagate': rule.propagate, }) From 3f44214b4e59a12281551756fb5f8f3f8155dca2 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 18:16:54 +0200 Subject: [PATCH 12/30] [IMP] typo product_id instead of product_it bzr revid: jco@openerp.com-20130813161654-pylu2asod3kwwp3m --- addons/project_mrp/project_mrp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/project_mrp/project_mrp.py b/addons/project_mrp/project_mrp.py index f9aea33f2fb..e00883ed764 100644 --- a/addons/project_mrp/project_mrp.py +++ b/addons/project_mrp/project_mrp.py @@ -32,7 +32,7 @@ class procurement_order(osv.osv): } def _is_procurement_task(self, cr, uid, procurement, context=None): - return procurement.product_id.type == 'service' and procurement.product_it.auto_create_task or False + return procurement.product_id.type == 'service' and procurement.product_id.auto_create_task or False def _assign(self, cr, uid, procurement, context=None): res = super(procurement_order, self)._assign(cr, uid, procurement, context=context) From 28e8d5df95794c76ced4e8a6384deab574e61547 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 18:31:15 +0200 Subject: [PATCH 13/30] [IMP] fields_id is required in ir_property bzr revid: jco@openerp.com-20130813163115-xy3z861ww0bdftot --- addons/l10n_ca/account_chart_template_en.xml | 2 ++ addons/l10n_ca/account_chart_template_fr.xml | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/addons/l10n_ca/account_chart_template_en.xml b/addons/l10n_ca/account_chart_template_en.xml index 635fa7b8bb1..24505dac8e6 100644 --- a/addons/l10n_ca/account_chart_template_en.xml +++ b/addons/l10n_ca/account_chart_template_en.xml @@ -16,11 +16,13 @@ + + diff --git a/addons/l10n_ca/account_chart_template_fr.xml b/addons/l10n_ca/account_chart_template_fr.xml index 7d1cc0a9ae2..169f6c45f1e 100644 --- a/addons/l10n_ca/account_chart_template_fr.xml +++ b/addons/l10n_ca/account_chart_template_fr.xml @@ -15,11 +15,13 @@ + - + + From 5326a67564cc5cbdcc65804010ee4a0985d5960b Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 13 Aug 2013 21:12:33 +0200 Subject: [PATCH 14/30] [IMP] Invoice directly should work differently as partial picking wizard disappeared bzr revid: jco@openerp.com-20130813191233-1b851jczqu7a15bb --- .../wizard/stock_invoice.py | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/addons/stock_invoice_directly/wizard/stock_invoice.py b/addons/stock_invoice_directly/wizard/stock_invoice.py index ba41de626da..5c126f33374 100644 --- a/addons/stock_invoice_directly/wizard/stock_invoice.py +++ b/addons/stock_invoice_directly/wizard/stock_invoice.py @@ -21,29 +21,29 @@ from openerp.osv import fields, osv -class invoice_directly(osv.osv_memory): - _inherit = 'stock.partial.picking' - - def do_partial(self, cr, uid, ids, context=None): - """Launch Create invoice wizard if invoice state is To be Invoiced, - after processing the partial picking. - """ - if context is None: context = {} - result = super(invoice_directly, self).do_partial(cr, uid, ids, context) - partial = self.browse(cr, uid, ids[0], context) - context.update(active_model='stock.picking', - active_ids=[partial.picking_id.id]) - if partial.picking_id.invoice_state == '2binvoiced': - return { - 'name': 'Create Invoice', - 'view_type': 'form', - 'view_mode': 'form', - 'res_model': 'stock.invoice.onshipping', - 'type': 'ir.actions.act_window', - 'target': 'new', - 'context': context - } - return {'type': 'ir.actions.act_window_close'} +# class invoice_directly(osv.osv_memory): +# _inherit = 'stock.partial.picking' +# +# def do_partial(self, cr, uid, ids, context=None): +# """Launch Create invoice wizard if invoice state is To be Invoiced, +# after processing the partial picking. +# """ +# if context is None: context = {} +# result = super(invoice_directly, self).do_partial(cr, uid, ids, context) +# partial = self.browse(cr, uid, ids[0], context) +# context.update(active_model='stock.picking', +# active_ids=[partial.picking_id.id]) +# if partial.picking_id.invoice_state == '2binvoiced': +# return { +# 'name': 'Create Invoice', +# 'view_type': 'form', +# 'view_mode': 'form', +# 'res_model': 'stock.invoice.onshipping', +# 'type': 'ir.actions.act_window', +# 'target': 'new', +# 'context': context +# } +# return {'type': 'ir.actions.act_window_close'} # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From b8220056f775477720fb9f560b4b88a3ed1521bd Mon Sep 17 00:00:00 2001 From: "Randhir Mayatra (OpenERP)" Date: Wed, 14 Aug 2013 16:14:26 +0530 Subject: [PATCH 15/30] [IMP] remove procure_method in yml that not in procurement anymore bzr revid: rma@tinyerp.com-20130814104426-o8w3mu3dxtgd17d9 --- addons/sale_stock/test/sale_order_onchange.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/sale_stock/test/sale_order_onchange.yml b/addons/sale_stock/test/sale_order_onchange.yml index 1026e5627c3..c97acdcb8c9 100644 --- a/addons/sale_stock/test/sale_order_onchange.yml +++ b/addons/sale_stock/test/sale_order_onchange.yml @@ -4,7 +4,6 @@ !record {model: product.product, id: product_onchange1}: name: 'Devil Worship Book' list_price: 66.6 - procure_method: 'make_to_order' - Now i create a sale order that uses my new product - From d565a50c35babe211ebd9a5e0abc5f6c1f937e52 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Wed, 14 Aug 2013 14:13:49 +0200 Subject: [PATCH 16/30] [IMP] steps procrule bzr revid: jco@openerp.com-20130814121349-go02w2gs0bhi46dj --- addons/stock/test/procrule.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/addons/stock/test/procrule.yml b/addons/stock/test/procrule.yml index a8baad650e8..d1762ae4806 100644 --- a/addons/stock/test/procrule.yml +++ b/addons/stock/test/procrule.yml @@ -1,5 +1,11 @@ - - Create new delivery order from output -> customers + Create new global procurement rule from Stock -> Output +- + !record {model: procurement.rule, ref:} + location_id: stock + location_dest_id: output +- + Create Delivery Order from Output -> Customer - !record {model: stock.picking, ref:} - From 290d3b31ccaa0cc54411357c8f7da99b8943f7bd Mon Sep 17 00:00:00 2001 From: "Randhir Mayatra (OpenERP)" Date: Wed, 14 Aug 2013 17:44:45 +0530 Subject: [PATCH 17/30] [IMP] remove extra assert bzr revid: rma@tinyerp.com-20130814121445-i29uhxxd43rdzw2g --- addons/sale_stock/test/sale_order_onchange.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/sale_stock/test/sale_order_onchange.yml b/addons/sale_stock/test/sale_order_onchange.yml index c97acdcb8c9..1c3a4a5b4c3 100644 --- a/addons/sale_stock/test/sale_order_onchange.yml +++ b/addons/sale_stock/test/sale_order_onchange.yml @@ -18,4 +18,3 @@ !assert {model: sale.order, id: sale_order_onchange1, string: The onchange function of product was not correctly triggered}: - order_line[0].name == u'Devil Worship Book' - order_line[0].price_unit == 66.6 - - order_line[0].type == 'make_to_order' From 24b1f53cce839f6cf7602bfe7aecd5114fead50f Mon Sep 17 00:00:00 2001 From: "Jitendra Prajapati (OpenERP)" Date: Wed, 14 Aug 2013 18:43:02 +0530 Subject: [PATCH 18/30] [IMP]improve domain bzr revid: prajapatijitendra7969@gmail.com-20130814131302-t4k5258dixltd6dm --- addons/stock/stock_view.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 0948f445f73..3054abfd60f 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1046,7 +1046,7 @@ ir.actions.act_window form tree,form - ['|','&',('picking_id','=',False),('location_id.usage', 'in', ['customer','supplier']),('picking_id','!=',False)] + {'product_receive': True, 'search_default_future': True} @@ -1141,7 +1141,7 @@ ir.actions.act_window form tree,form - ['|','&',('picking_id','=',False),('location_dest_id.usage', 'in', ['customer','supplier']),('picking_id','!=',False)] + {'search_default_future': True} From 2642c4a3798688720298d3a9a9378a79edaaf776 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 16 Aug 2013 09:48:46 +0200 Subject: [PATCH 19/30] [IMP] procurement state == done instead of != for test_state bzr revid: jco@openerp.com-20130816074846-di9cajwmylsvsg3s --- addons/sale_stock/sale_stock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 707adb27a7e..95ebfa33e89 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -207,7 +207,7 @@ class sale_order(osv.osv): for order in self.browse(cr, uid, ids, context={}): for line in order.order_line: for procurement in line.procurement_ids: - if procurement.state != 'done': + if procurement.state == 'done': write_done_ids.append(line.id) else: finished = False From 349833452a0eb1c0f620a05e5feec5608999895a Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 16 Aug 2013 12:27:34 +0200 Subject: [PATCH 20/30] [IMP] Change test_state according to procurement_ids, do not allow running a procurement twice when it was successful and adapt view in sale_journal bzr revid: jco@openerp.com-20130816102734-j4xrxqbz26q942ps --- addons/mrp_jit/mrp_jit.py | 1 + addons/procurement/procurement.py | 15 ++++++++------- addons/sale_journal/sale_journal_view.xml | 2 +- addons/sale_stock/sale_stock.py | 23 +++++++++++++---------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/addons/mrp_jit/mrp_jit.py b/addons/mrp_jit/mrp_jit.py index 4ad5cca5f20..01d94692a9d 100644 --- a/addons/mrp_jit/mrp_jit.py +++ b/addons/mrp_jit/mrp_jit.py @@ -27,6 +27,7 @@ class procurement_order(osv.osv): def create(self, cr, uid, vals, context=None): procurement_id = super(procurement_order, self).create(cr, uid, vals, context=context) + # TODO: maybe this is not necessary anymore as we do this already self.run(cr, uid, [procurement_id], context=context) self.check(cr, uid, [procurement_id], context=context) return procurement_id diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 69e2b1cbf23..4e8b163eced 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -154,13 +154,14 @@ class procurement_order(osv.osv): def run(self, cr, uid, ids, context=None): for procurement in self.browse(cr, uid, ids, context=context): - if self._assign(cr, uid, procurement, context=context): - procurement.refresh() - self._run(cr, uid, procurement, context=context or {}) - self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) - else: - self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context) - self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) + if procurement.state not in ("running", "done"): + if self._assign(cr, uid, procurement, context=context): + procurement.refresh() + self._run(cr, uid, procurement, context=context or {}) + self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) + else: + self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context) + self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) return True def check(self, cr, uid, ids, context=None): diff --git a/addons/sale_journal/sale_journal_view.xml b/addons/sale_journal/sale_journal_view.xml index 3247f73d1cd..0c11029b48b 100644 --- a/addons/sale_journal/sale_journal_view.xml +++ b/addons/sale_journal/sale_journal_view.xml @@ -128,7 +128,7 @@ stock.picking - + diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py index 95ebfa33e89..3163365ffc0 100644 --- a/addons/sale_stock/sale_stock.py +++ b/addons/sale_stock/sale_stock.py @@ -205,16 +205,20 @@ class sale_order(osv.osv): write_done_ids = [] write_cancel_ids = [] for order in self.browse(cr, uid, ids, context={}): + #TODO: Need to rethink what happens when cancelling for line in order.order_line: - for procurement in line.procurement_ids: - if procurement.state == 'done': - write_done_ids.append(line.id) - else: - finished = False - if (procurement.state == 'cancel'): - canceled = True - if line.state != 'exception': + states = [x.state for x in line.procurement_ids] + cancel = all([x == 'cancel' for x in states]) + doneorcancel = all([x in ('done', 'cancel') for x in states]) + if cancel: + canceled = True + if line.state != 'exception': write_cancel_ids.append(line.id) + if not doneorcancel: + finished = False + if doneorcancel and not cancel: + write_done_ids.append(line.id) + if write_done_ids: self.pool.get('sale.order.line').write(cr, uid, write_done_ids, {'state': 'done'}) if write_cancel_ids: @@ -256,8 +260,7 @@ class sale_order(osv.osv): res = [] for order in self.browse(cr, uid, ids, context={}): for line in order.order_line: - if line.procurement_id: - res.append(line.procurement_id.id) + res += [x.id for x in line.procurement_ids] return res class sale_order_line(osv.osv): From bcbd83f242a2fd3e02d1636f0424f1574ad59c73 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 16 Aug 2013 14:30:30 +0200 Subject: [PATCH 21/30] [IMP] Invoice_state store should be triggered when moves are grouped into picking bzr revid: jco@openerp.com-20130816123030-kfapqsh40dg8qni9 --- addons/sale_stock/stock.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/addons/sale_stock/stock.py b/addons/sale_stock/stock.py index 2af7e1518f8..e404ab3dd7b 100644 --- a/addons/sale_stock/stock.py +++ b/addons/sale_stock/stock.py @@ -22,6 +22,7 @@ from openerp.osv import fields, osv from openerp.tools.translate import _ + class stock_picking(osv.osv): _inherit = 'stock.picking' def __get_invoice_state(self, cr, uid, ids, name, arg, context=None): @@ -45,16 +46,24 @@ class stock_picking(osv.osv): result[move.picking_id.id] = True return result.keys() + def __get_picking_move(self, cr, uid, ids, context={}): + res = [] + for move in self.pool.get('stock.move').browse(cr, uid, ids, context=context): + if move.picking_id: + res.append(move.picking_id.id) + return res + _columns = { 'invoice_state': fields.function(__get_invoice_state, type='selection', selection=[ ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable") - ], string="Invoice Control", required=True, - store={ - 'procurement.order': (__get_picking_procurement, ['invoice_state'], 10), - 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10) - }, + ], string="Invoice Control", required=True, + store={ + 'procurement.order': (__get_picking_procurement, ['invoice_state'], 10), + 'stock.picking': (lambda self, cr, uid, ids, c={}: ids, ['state'], 10), + 'stock.move': (__get_picking_move, ['picking_id'], 10), + }, ), } _defaults = { From 593f1ddc8a74760456ec6bb9cbff102b253ad829 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 16 Aug 2013 17:02:26 +0200 Subject: [PATCH 22/30] [IMP] Change auto in waiting for picking state, add picking type in push rule view bzr revid: jco@openerp.com-20130816150226-th1rpjoozdf6p1wt --- addons/stock/stock.py | 8 ++++---- addons/stock_location/stock_location.py | 5 +---- addons/stock_location/stock_location_view.xml | 11 ++++++----- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 9788a0c33d8..2dff89acfa2 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -61,7 +61,7 @@ class stock_location(osv.osv): _order = 'parent_left' def name_get(self, cr, uid, ids, context=None): res = self._complete_name(cr, uid, ids, 'complete_name', None, context=context) - return res.items() + return res.items() def _complete_name(self, cr, uid, ids, name, args, context=None): """ Forms complete name of location from parent location to child location. @@ -432,7 +432,7 @@ class stock_picking(osv.osv): res[pick.id] = 'done' continue - order = {'confirmed':0, 'auto':1, 'assigned':2} + order = {'confirmed':0, 'waiting':1, 'assigned':2} order_inv = dict(zip(order.values(),order.keys())) lst = [order[x.state] for x in pick.move_lines if x.state not in ('cancel','done')] if pick.move_lines == 'one': @@ -467,7 +467,7 @@ class stock_picking(osv.osv): 'stock.move': (_get_pickings, ['state', 'picking_id'], 20)}, selection = [ ('draft', 'Draft'), ('cancel', 'Cancelled'), - ('auto', 'Waiting Another Operation'), + ('waiting', 'Waiting Another Operation'), ('confirmed', 'Waiting Availability'), ('assigned', 'Ready to Transfer'), ('done', 'Transferred'), @@ -1199,7 +1199,7 @@ class stock_move(osv.osv): ('group_id', '=', move.group_id.id), ('location_id', '=', move.location_id.id), ('location_dest_id', '=', move.location_dest_id.id), - ('state', 'in', ['confirmed', 'auto'])], context=context) + ('state', 'in', ['confirmed', 'waiting'])], context=context) if picks: pick = picks[0] else: diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index 668b80ae72a..d01bbbca5e0 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -52,9 +52,6 @@ class stock_location_path(osv.osv): 'name': fields.char('Operation', size=64), 'company_id': fields.many2one('res.company', 'Company'), 'route_id': fields.many2one('stock.location.route', 'Route'), - - 'product_id' : fields.many2one('product.product', 'Products', ondelete='cascade', select=1), - 'location_from_id' : fields.many2one('stock.location', 'Source Location', ondelete='cascade', select=1, required=True), 'location_dest_id' : fields.many2one('stock.location', 'Destination Location', ondelete='cascade', select=1, required=True), 'delay': fields.integer('Delay (days)', help="Number of days to do this transition"), @@ -62,7 +59,7 @@ class stock_location_path(osv.osv): ("invoiced", "Invoiced"), ("2binvoiced", "To Be Invoiced"), ("none", "Not Applicable")], "Invoice Status", - required=True,), + required=True,), 'picking_type_id': fields.many2one('stock.picking.type', 'Picking Type', help="This is the picking type associated with the different pickings"), 'auto': fields.selection( [('auto','Automatic Move'), ('manual','Manual Operation'),('transparent','Automatic No Step Added')], diff --git a/addons/stock_location/stock_location_view.xml b/addons/stock_location/stock_location_view.xml index 088dceb8803..8a42f2afb46 100644 --- a/addons/stock_location/stock_location_view.xml +++ b/addons/stock_location/stock_location_view.xml @@ -87,14 +87,15 @@
- + - - - - + + + + +
From 3e7dcc7ad14b1613f8c1a12639994e62304d84d9 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Fri, 16 Aug 2013 17:47:08 +0200 Subject: [PATCH 23/30] [IMP] Picking type on stock move when purchase, needs to be improved further anyways bzr revid: jco@openerp.com-20130816154708-arzapc37lccq63ea --- addons/purchase/purchase.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index a80b84bddbc..3e2446568af 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -653,7 +653,6 @@ class purchase_order(osv.osv): def _prepare_order_picking(self, cr, uid, order, context=None): type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'picking_type_in')[1] type = self.pool.get("stock.picking.type").browse(cr, uid, type_id, context=context) - return { 'name': self.pool.get('ir.sequence').get_id(cr, uid, type.sequence_id.id, 'id'), 'origin': order.name + ((order.origin and (':' + order.origin)) or ''), @@ -664,11 +663,14 @@ class purchase_order(osv.osv): 'purchase_id': order.id, 'company_id': order.company_id.id, 'move_lines' : [], - 'picking_type_id': type_id, + 'picking_type_id': type_id, } def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, context=None): ''' prepare the stock move data from the PO line ''' + type_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'picking_type_in')[1] + type = self.pool.get("stock.picking.type").browse(cr, uid, type_id, context=context) + return { 'name': order_line.name or '', 'product_id': order_line.product_id.id, @@ -686,7 +688,8 @@ class purchase_order(osv.osv): 'state': 'draft', 'purchase_line_id': order_line.id, 'company_id': order.company_id.id, - 'price_unit': order_line.price_unit, + 'price_unit': order_line.price_unit, + 'picking_type_id': type_id, } def _create_pickings(self, cr, uid, order, order_lines, picking_id=False, context=None): From 128586c59c25ca74d214b03f399ccfc4086ea89f Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 19 Aug 2013 11:19:37 +0200 Subject: [PATCH 24/30] [IMP] location_id should be location_spec_id when applying putaway strats (psi) bzr revid: jco@openerp.com-20130819091937-r7zht49op1nupyrr --- addons/stock_location/stock_location.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index d01bbbca5e0..6daaf0858b1 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -269,16 +269,16 @@ class stock_move(osv.osv): if putaway: # Should call different methods here in later versions # TODO: take care of lots - if putaway.method == 'fixed' and putaway.location_id: + if putaway.method == 'fixed' and putaway.location_spec_id: moveputaway_obj.create(cr, uid, {'move_id': move.id, - 'location_id': putaway.location_id.id, + 'location_id': putaway.location_spec_id.id, 'quantity': move.product_uom_qty}, context=context) return True def action_assign(self, cr, uid, ids, context=None): - result = super(stock_move, self).action_assign(cr, uid, ids, context=context) - self._putaway_apply(cr, uid, ids, context=context) - return result + result = super(stock_move, self).action_assign(cr, uid, ids, context=context) + self._putaway_apply(cr, uid, ids, context=context) + return result def action_confirm(self, cr, uid, ids, context=None): result = super(stock_move, self).action_confirm(cr, uid, ids, context) @@ -286,6 +286,8 @@ class stock_move(osv.osv): self._push_apply(cr, uid, moves, context=context) return result + + def _create_procurement(self, cr, uid, move, context=None): """ Next to creating the procurement order, it will propagate the routes From 0d56b1b2f08e0465d6072b5098445f21556f828e Mon Sep 17 00:00:00 2001 From: "Jitendra Prajapati (OpenERP)" Date: Mon, 19 Aug 2013 15:44:11 +0530 Subject: [PATCH 25/30] [MERGE] lp:~openerp-dev/openobject-addons/trunk-wmsimplement-seduce-fp-product_kanban_link-jitendra bzr revid: prajapatijitendra7969@gmail.com-20130819101411-bbqg50aqu719b9xh --- addons/stock/product_view.xml | 4 ++-- addons/stock/stock_view.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/stock/product_view.xml b/addons/stock/product_view.xml index d057c47cc80..9c14a150b96 100644 --- a/addons/stock/product_view.xml +++ b/addons/stock/product_view.xml @@ -48,7 +48,7 @@ ir.actions.act_window form tree,form - [('picking_type_id','=',ref("picking_type_in")), ('location_id.usage','!=','internal'), ('location_dest_id.usage', '=', 'internal')] + @@ -69,7 +69,7 @@ form tree,form - [('picking_type_id','=',ref("picking_type_out")), ('location_id.usage','=','internal'), ('location_dest_id.usage', '!=', 'internal')] +

diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 3054abfd60f..575712ad771 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -1046,7 +1046,7 @@ ir.actions.act_window form tree,form - + {'product_receive': True, 'search_default_future': True} @@ -1141,7 +1141,7 @@ ir.actions.act_window form tree,form - + {'search_default_future': True} From a4a742e1a345082ca92e391b2344aba988c184f7 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 19 Aug 2013 12:46:57 +0200 Subject: [PATCH 26/30] [IMP] Procurement should go to exception when no supplier bzr revid: jco@openerp.com-20130819104657-6ee5gmn9v7vxqi2c --- addons/purchase/purchase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 3e2446568af..5f4471ce408 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1226,7 +1226,7 @@ class procurement_order(osv.osv): res_id = procurement.move_dest_id and procurement.move_dest_id.id or False partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement. if not partner: - procurement.write({'message': _('There is no supplier associated to product %s') % (procurement.product_id.name)}) + procurement.write({'message': _('There is no supplier associated to product %s') % (procurement.product_id.name), 'state': 'exception'}) else: seller_qty = procurement.product_id.seller_qty partner_id = partner.id From 3c8390289be3cfe0db96233a78f1ab9f737a2cd0 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 19 Aug 2013 15:46:15 +0200 Subject: [PATCH 27/30] [IMP] _run method should return whether it succeeded and change the state. Other methods migth do a message_post bzr revid: jco@openerp.com-20130819134615-m0divzqr7rslzhcx --- addons/mrp/procurement.py | 60 ++++++++++++++++--------------- addons/procurement/procurement.py | 7 ++-- addons/purchase/purchase.py | 7 ++-- 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/addons/mrp/procurement.py b/addons/mrp/procurement.py index 9dad9aa5899..be19980ff24 100644 --- a/addons/mrp/procurement.py +++ b/addons/mrp/procurement.py @@ -44,7 +44,7 @@ class procurement_order(osv.osv): rule_id = super(procurement_order, self)._find_suitable_rule(cr, uid, procurement, context=context) if not rule_id: #if there isn't any specific procurement.rule defined for the product, we try to directly supply it from a supplier - if procurement.product_id.supply_method == 'manufacture' and self.check_bom_exists(cr, uid, [procurement.id], context=context): + if procurement.product_id.supply_method == 'manufacture': rule_id = self._search_suitable_rule(cr, uid, procurement, [('action', '=', 'manufacture'), ('location_id', '=', procurement.location_id.id)], context=context) rule_id = rule_id and rule_id[0] or False return rule_id @@ -52,7 +52,7 @@ class procurement_order(osv.osv): 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 - return self.make_mo(cr, uid, [procurement.id], context=context) + return self.make_mo(cr, uid, [procurement.id], context=context)[procurement.id] return super(procurement_order, self)._run(cr, uid, procurement, context=context) def _check(self, cr, uid, procurement, context=None): @@ -119,32 +119,36 @@ class procurement_order(osv.osv): move_obj = self.pool.get('stock.move') procurement_obj = self.pool.get('procurement.order') for procurement in procurement_obj.browse(cr, uid, ids, context=context): - res_id = procurement.move_dest_id and procurement.move_dest_id.id or False - newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0) - newdate = newdate - relativedelta(days=company.manufacturing_lead) - produce_id = production_obj.create(cr, uid, { - 'origin': procurement.origin, - 'product_id': procurement.product_id.id, - 'product_qty': procurement.product_qty, - 'product_uom': procurement.product_uom.id, - 'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False, - 'product_uos': procurement.product_uos and procurement.product_uos.id or False, - 'location_src_id': procurement.location_id.id, - 'location_dest_id': procurement.location_id.id, - 'bom_id': procurement.bom_id and procurement.bom_id.id or False, - 'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'), - 'move_prod_id': res_id, - 'company_id': procurement.company_id.id, - }) - - res[procurement.id] = produce_id - self.write(cr, uid, [procurement.id], {'state': 'running', 'production_id': produce_id}) - bom_result = production_obj.action_compute(cr, uid, - [produce_id], properties=[x.id for x in procurement.property_ids]) - production_obj.signal_button_confirm(cr, uid, [produce_id]) - if res_id: - move_obj.write(cr, uid, [res_id], - {'location_id': procurement.location_id.id}) + if self.check_bom_exists(cr, uid, [procurement.id], context=context): + res_id = procurement.move_dest_id and procurement.move_dest_id.id or False + newdate = datetime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S') - relativedelta(days=procurement.product_id.produce_delay or 0.0) + newdate = newdate - relativedelta(days=company.manufacturing_lead) + produce_id = production_obj.create(cr, uid, { + 'origin': procurement.origin, + 'product_id': procurement.product_id.id, + 'product_qty': procurement.product_qty, + 'product_uom': procurement.product_uom.id, + 'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False, + 'product_uos': procurement.product_uos and procurement.product_uos.id or False, + 'location_src_id': procurement.location_id.id, + 'location_dest_id': procurement.location_id.id, + 'bom_id': procurement.bom_id and procurement.bom_id.id or False, + 'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'), + 'move_prod_id': res_id, + 'company_id': procurement.company_id.id, + }) + + res[procurement.id] = produce_id + self.write(cr, uid, [procurement.id], {'production_id': produce_id}) + bom_result = production_obj.action_compute(cr, uid, + [produce_id], properties=[x.id for x in procurement.property_ids]) + production_obj.signal_button_confirm(cr, uid, [produce_id]) + if res_id: + move_obj.write(cr, uid, [res_id], + {'location_id': procurement.location_id.id}) + else: + res[procurement.id] = False + self.message_post(cr, uid, [procurement.id], body=_("No BoM exists for this product!"), context=context) self.production_order_create_note(cr, uid, ids, context=context) return res diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py index 4e8b163eced..62170c13eea 100644 --- a/addons/procurement/procurement.py +++ b/addons/procurement/procurement.py @@ -157,8 +157,11 @@ class procurement_order(osv.osv): if procurement.state not in ("running", "done"): if self._assign(cr, uid, procurement, context=context): procurement.refresh() - self._run(cr, uid, procurement, context=context or {}) - self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) + res = self._run(cr, uid, procurement, context=context or {}) + if res: + self.write(cr, uid, [procurement.id], {'state': 'running'}, context=context) + else: + self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) else: self.message_post(cr, uid, [procurement.id], body=_('No rule matching this procurement'), context=context) self.write(cr, uid, [procurement.id], {'state': 'exception'}, context=context) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 5f4471ce408..4948a292a04 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -1115,7 +1115,7 @@ class procurement_order(osv.osv): def _run(self, cr, uid, procurement, context=None): 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) + return self.make_po(cr, uid, [procurement.id], context=context)[procurement.id] return super(procurement_order, self)._run(cr, uid, procurement, context=context) def _check(self, cr, uid, procurement, context=None): @@ -1226,7 +1226,8 @@ class procurement_order(osv.osv): res_id = procurement.move_dest_id and procurement.move_dest_id.id or False partner = procurement.product_id.seller_id # Taken Main Supplier of Product of Procurement. if not partner: - procurement.write({'message': _('There is no supplier associated to product %s') % (procurement.product_id.name), 'state': 'exception'}) + self.message_post(cr, uid, [procurement.id],_('There is no supplier associated to product %s') % (procurement.product_id.name)) + res[procurement.id] = False else: seller_qty = procurement.product_id.seller_qty partner_id = partner.id @@ -1276,7 +1277,7 @@ class procurement_order(osv.osv): 'payment_term_id': partner.property_supplier_payment_term.id or False, } res[procurement.id] = self.create_procurement_purchase_order(cr, uid, procurement, po_vals, line_vals, context=new_context) - self.write(cr, uid, [procurement.id], {'state': 'running', 'purchase_id': res[procurement.id]}) + self.write(cr, uid, [procurement.id], {'purchase_id': res[procurement.id]}) pass_ids += [procurement.id] if pass_ids: self.message_post(cr, uid, pass_ids, body=_("Draft Purchase Order created"), context=context) From 69fa5dbec2c671733e30c70ea260725238328c71 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Mon, 19 Aug 2013 19:03:19 +0200 Subject: [PATCH 28/30] [ADD] Add test for procurement exceptions bzr revid: jco@openerp.com-20130819170319-rd0zqen2pqot1e3p --- .../test/procurementexception.yml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 addons/stock_complex_routes/test/procurementexception.yml diff --git a/addons/stock_complex_routes/test/procurementexception.yml b/addons/stock_complex_routes/test/procurementexception.yml new file mode 100644 index 00000000000..67afc101089 --- /dev/null +++ b/addons/stock_complex_routes/test/procurementexception.yml @@ -0,0 +1,37 @@ +- + Create product with no seller_ids +- + +- + Create a sales order with 1 piece for that product and route crossdock +- + !record{sale.order} +- + Confirm sales order +- + !python { +- + Check there is a procurement in exception that has the procurement group of the sales order +- + !python { + assert +- + Adjust the product that it has at least one seller_id +- + !record{id: model: product.product) or in !python +- + Run the Scheduler +- + !python +- + Check the status changed there is no procurement order in exception any more from that procurement group +- + !python{model: procurement.order} + search procurement from +- + Check a purchase quotation was created +- + + + + From 49e1cc58ad929635a6dfe0e079d2c7cd51dd8a73 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 20 Aug 2013 11:22:01 +0200 Subject: [PATCH 29/30] [IMP] Remove product from stock_location_path demo bzr revid: jco@openerp.com-20130820092201-skxo7gygyvtofqe6 --- addons/stock_location/stock_location_demo_cpu3.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/stock_location/stock_location_demo_cpu3.yml b/addons/stock_location/stock_location_demo_cpu3.yml index 52a18c4a68e..d1d4a2c8348 100644 --- a/addons/stock_location/stock_location_demo_cpu3.yml +++ b/addons/stock_location/stock_location_demo_cpu3.yml @@ -21,7 +21,6 @@ - !record {model: stock.location.path, id: push_pick}: name: Pick List - product_id: product.product_product_10 location_from_id: stock.stock_location_output location_dest_id: location_pack_zone picking_type_id: stock.picking_type_internal \ No newline at end of file From fb22df1f63e8450de458003bec51c0d1fb5d2696 Mon Sep 17 00:00:00 2001 From: Josse Colpaert Date: Tue, 20 Aug 2013 18:25:55 +0200 Subject: [PATCH 30/30] [IMP] Don't apply push when there is a move_dest_id bzr revid: jco@openerp.com-20130820162555-1pnhtnkeya6eccbe --- addons/purchase/purchase.py | 1 + addons/stock/stock.py | 8 +++++--- addons/stock_location/stock_location.py | 17 +++++++++-------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 4948a292a04..79df9f31103 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -290,6 +290,7 @@ class purchase_order(osv.osv): return {} return {'value': {'currency_id': self.pool.get('product.pricelist').browse(cr, uid, pricelist_id, context=context).currency_id.id}} + #Destination address is used when dropshipping def onchange_dest_address_id(self, cr, uid, ids, address_id): if not address_id: return {} diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 2dff89acfa2..357da1a3927 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -697,7 +697,8 @@ class stock_picking(osv.osv): self.action_done(cr, uid, [picking.id], context=context) continue for op in picking.pack_operation_ids: - if op.package_id: + #TODO: op.package_id can not work as quants_get is not defined on quant package => gives traceback + if op.package_id: for quant in quant_package_obj.quants_get(cr, uid, op.package_id, context=context): self._do_partial_product_move(cr, uid, picking, quant.product_id, quant.qty, quant, context=context) op.package_id.write(cr, uid, { @@ -705,12 +706,14 @@ class stock_picking(osv.osv): }, context=context) elif op.product_id: moves = self._do_partial_product_move(cr, uid, picking, op.product_id, op.product_qty, op.quant_id, context=context) + quants = [] for m in moves: for quant in m.quant_ids: quants.append(quant.id) quant_obj.write(cr, uid, quants, { 'package_id': op.result_package_id.id + }, context=context) self._create_backorder(cr, uid, picking, context=context) @@ -1506,7 +1509,7 @@ class stock_move(osv.osv): self.write(cr, uid, [move.id], { 'product_uom_qty': move.product_uom_qty - uom_qty, 'product_uos_qty': move.product_uos_qty - uos_qty, - 'reserved_quant_ids': [] + 'reserved_quant_ids': [(6,0,[])] }, context=context) return new_move @@ -1932,7 +1935,6 @@ class stock_pack_operation(osv.osv): 'lot_id': fields.many2one('stock.production.lot', 'Lot/Serial Number'), 'result_package_id': fields.many2one('stock.quant.package', 'Container Package', help="If set, the operations are packed into this package", required=False, ondelete='cascade'), 'date': fields.datetime('Date', required=True), - #'lot_id': fields.many2one('stock.production.lot', 'Serial Number', ondelete='CASCADE'), #'update_cost': fields.boolean('Need cost update'), 'cost': fields.float("Cost", help="Unit Cost for this product line"), 'currency': fields.many2one('res.currency', string="Currency", help="Currency in which Unit cost is expressed", ondelete='CASCADE'), diff --git a/addons/stock_location/stock_location.py b/addons/stock_location/stock_location.py index 6daaf0858b1..7f27496ff0d 100644 --- a/addons/stock_location/stock_location.py +++ b/addons/stock_location/stock_location.py @@ -251,14 +251,15 @@ class stock_move(osv.osv): def _push_apply(self, cr, uid, moves, context): for move in moves: - for route in move.product_id.route_ids: - found = False - for rule in route.push_ids: - if rule.location_from_id.id == move.location_dest_id.id: - self.pool.get('stock.location.path')._apply(cr, uid, rule, move, context=context) - found = True - break - if found: break + if not move.move_dest_id: + for route in move.product_id.route_ids: + found = False + for rule in route.push_ids: + if rule.location_from_id.id == move.location_dest_id.id: + self.pool.get('stock.location.path')._apply(cr, uid, rule, move, context=context) + found = True + break + if found: break return True # Create the stock.move.putaway records