diff options
| author | Cedric Snauwaert <csn@openerp.com> | 2014-02-07 12:26:06 +0100 |
|---|---|---|
| committer | Cedric Snauwaert <csn@openerp.com> | 2014-02-07 12:26:06 +0100 |
| commit | 31348b1e4a16b5649e0b869de76cfb60dd547d44 (patch) | |
| tree | 9d9be0feaa27d7ed9a9628097408e9dcd8a493b0 | |
| parent | 0a74a775c5443eb4bc21a8695268f1d673995394 (diff) | |
[FIX]sale_order with product using phantom bom
bzr revid: csn@openerp.com-20140207112606-k0cxzhpytlodjd1y
| -rw-r--r-- | addons/mrp/mrp.py | 4 | ||||
| -rw-r--r-- | addons/mrp/mrp_view.xml | 2 | ||||
| -rw-r--r-- | addons/mrp/stock.py | 74 | ||||
| -rw-r--r-- | addons/mrp/test/order_process.yml | 2 | ||||
| -rw-r--r-- | addons/sale_mrp/tests/__init__.py | 28 | ||||
| -rw-r--r-- | addons/sale_mrp/tests/test_move_explode.py | 59 |
6 files changed, 121 insertions, 48 deletions
diff --git a/addons/mrp/mrp.py b/addons/mrp/mrp.py index 4fbe2cb63e6..59dc7df4ed2 100644 --- a/addons/mrp/mrp.py +++ b/addons/mrp/mrp.py @@ -1033,8 +1033,8 @@ class mrp_production(osv.osv): 'company_id': production.company_id.id, } move_id = stock_move.create(cr, uid, data, context=context) - stock_move.action_confirm(cr, uid, [move_id], context=context) production.write({'move_created_ids': [(6, 0, [move_id])]}, context=context) + stock_move.action_confirm(cr, uid, [move_id], context=context) return move_id def _make_production_consume_line(self, cr, uid, production_line, parent_move_id, source_location_id=False, context=None): @@ -1059,8 +1059,8 @@ class mrp_production(osv.osv): 'company_id': production.company_id.id, 'procure_method': 'make_to_order', }) - stock_move.action_confirm(cr, uid, [move_id], context=context) production.write({'move_lines': [(4, move_id)]}, context=context) + stock_move.action_confirm(cr, uid, [move_id], context=context) return move_id def action_confirm(self, cr, uid, ids, context=None): diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 82a1f9a4a2a..389c7f7b3b0 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -687,7 +687,7 @@ </div> <group> <group> - <field name="product_id" on_change="product_id_change(product_id)" domain="[('bom_ids','!=',False),('bom_ids.bom_id','=',False)]" class="oe_inline" context='{"default_type": "product"}'/> + <field name="product_id" on_change="product_id_change(product_id)" domain="[('bom_ids','!=',False),('bom_ids.bom_id','=',False),('bom_ids.type','!=','phantom')]" class="oe_inline" context='{"default_type": "product"}'/> <label for="product_qty"/> <div> <field name="product_qty" class="oe_inline"/> diff --git a/addons/mrp/stock.py b/addons/mrp/stock.py index 59b41e71c90..6cbaa08eb28 100644 --- a/addons/mrp/stock.py +++ b/addons/mrp/stock.py @@ -22,6 +22,7 @@ from openerp.osv import fields from openerp.osv import osv from openerp.tools.translate import _ +from openerp import SUPERUSER_ID class StockMove(osv.osv): @@ -33,6 +34,14 @@ class StockMove(osv.osv): 'consumed_for': fields.many2one('stock.move', 'Consumed for', help='Technical field used to make the traceability of produced products'), } + def copy(self, cr, uid, id, default=None, context=None): + if not default: + default = {} + default.update({ + 'production_id': False, + }) + return super(StockMove, self).copy(cr, uid, id, default, context=context) + def check_tracking(self, cr, uid, move, lot_id, context=None): super(StockMove, self).check_tracking(cr, uid, move, lot_id, context=context) if move.product_id.track_production and (move.location_id.usage == 'production' or move.location_dest_id.usage == 'production') and not lot_id: @@ -49,8 +58,7 @@ class StockMove(osv.osv): move_obj = self.pool.get('stock.move') procurement_obj = self.pool.get('procurement.order') product_obj = self.pool.get('product.product') - processed_ids = [move.id] - + processed_ids = [] bis = bom_obj.search(cr, uid, [ ('product_id', '=', move.product_id.id), ('bom_id', '=', False), @@ -64,45 +72,39 @@ class StockMove(osv.osv): state = 'assigned' for line in res[0]: valdef = { - 'picking_id': move.picking_id.id, + 'picking_id': move.picking_id.id if move.picking_id else False, 'product_id': line['product_id'], 'product_uom': line['product_uom'], 'product_qty': line['product_qty'], 'product_uos': line['product_uos'], 'product_uos_qty': line['product_uos_qty'], - 'move_dest_id': move.id, 'state': state, 'name': line['name'], - 'procurements': [], } mid = move_obj.copy(cr, uid, move.id, default=valdef) processed_ids.append(mid) - prodobj = product_obj.browse(cr, uid, line['product_id'], context=context) - proc_id = procurement_obj.create(cr, uid, { - 'name': (move.picking_id.origin or ''), - 'origin': (move.picking_id.origin or ''), - 'date_planned': move.date, - 'product_id': line['product_id'], - 'product_qty': line['product_qty'], - 'product_uom': line['product_uom'], - 'product_uos_qty': line['product_uos'] and line['product_uos_qty'] or False, - 'product_uos': line['product_uos'], - 'location_id': move.location_id.id, - 'procure_method': prodobj.procure_method, - 'move_id': mid, - }) - procurement_obj.signal_button_confirm(cr, uid, [proc_id]) - move_obj.write(cr, uid, [move.id], { - 'location_dest_id': move.location_id.id, # dummy move for the kit - 'picking_id': False, - 'state': 'confirmed' - }) - procurement_ids = procurement_obj.search(cr, uid, [('move_id', '=', move.id)], context) - procurement_obj.signal_button_confirm(cr, uid, procurement_ids) - procurement_obj.signal_button_wait_done(cr, uid, procurement_ids) + move_obj.unlink(cr, SUPERUSER_ID, [move.id], context=context) + #confirm all new confirm moves + move_obj.action_confirm(cr, uid, processed_ids, context=context) return processed_ids + def action_confirm(self, cr, uid, ids, context=None): + move_exploded = [] + for move in self.browse(cr, uid, ids, context=context): + #in order to explode a move, we must have a picking_id on that move! + #if action_explode return a list of new move, it means it has exploded + #and that original move has been deleted, so we should remove that id + #from super call to prevent problem + move_id = move.id + if move.picking_type_id and self._action_explode(cr, uid, move, context=context): + move_exploded.append(move_id) + #if no more id, don't call super + move_unexploded = list(set(ids)-set(move_exploded)) + if not len(move_unexploded): + return True + return super(StockMove, self).action_confirm(cr, uid, move_unexploded, context=context) + def action_consume(self, cr, uid, ids, product_qty, location_id=False, restrict_lot_id=False, restrict_partner_id=False, consumed_for=False, context=None): """ Consumed product with specific quantity from specific source location. @@ -182,22 +184,6 @@ class StockMove(osv.osv): workflow.trg_trigger(uid, 'stock.move', move.id, cr) return res - -class StockPicking(osv.osv): - _inherit = 'stock.picking' - - # - # Explode picking by replacing phantom BoMs - # - def action_explode(self, cr, uid, move_ids, *args): - """Explodes moves by expanding kit components""" - move_obj = self.pool.get('stock.move') - todo = move_ids[:] - for move in move_obj.browse(cr, uid, move_ids): - todo.extend(move_obj._action_explode(cr, uid, move)) - return list(set(todo)) - - class stock_warehouse(osv.osv): _inherit = 'stock.warehouse' _columns = { diff --git a/addons/mrp/test/order_process.yml b/addons/mrp/test/order_process.yml index dd9bc2ef7d4..6b7aa8a0d63 100644 --- a/addons/mrp/test/order_process.yml +++ b/addons/mrp/test/order_process.yml @@ -14,7 +14,7 @@ - !python {model: mrp.production}: | order = self.browse(cr, uid, ref("mrp_production_test1"), context=context) - assert len(order.product_lines) == 5, "Production lines are not generated proper." + assert len(order.product_lines) == 1, "Production lines are not generated proper." - Now I check workcenter lines. - diff --git a/addons/sale_mrp/tests/__init__.py b/addons/sale_mrp/tests/__init__.py new file mode 100644 index 00000000000..0ca809f8e9c --- /dev/null +++ b/addons/sale_mrp/tests/__init__.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +from . import test_move_explode + +checks = [ + test_move_explode, +] + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_mrp/tests/test_move_explode.py b/addons/sale_mrp/tests/test_move_explode.py new file mode 100644 index 00000000000..5bb8e8550cc --- /dev/null +++ b/addons/sale_mrp/tests/test_move_explode.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Business Applications +# Copyright (c) 2012-TODAY OpenERP S.A. <http://openerp.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# +############################################################################## + +from openerp.tests import common + + +class TestMoveExplode(common.TransactionCase): + + def setUp(self): + super(TestMoveExplode, self).setUp() + cr, uid = self.cr, self.uid + + # Usefull models + self.ir_model_data = self.registry('ir.model.data') + self.sale_order_line = self.registry('sale.order.line') + self.sale_order = self.registry('sale.order') + self.mrp_bom = self.registry('mrp.bom') + + #product that has a phantom bom + self.product_bom_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_product_4')[1] + #bom with that product + self.bom_id = self.ir_model_data.get_object_reference(cr, uid, 'mrp', 'mrp_bom_24')[1] + #partner agrolait + self.partner_id = self.ir_model_data.get_object_reference(cr, uid, 'base', 'res_partner_1')[1] + + def test_00_sale_move_explode(self): + """check that when creating a sale order with a product that has a phantom BoM, move explode into content of the + BoM""" + cr, uid, context = self.cr, self.uid, {} + #create sale order with one sale order line containing product with a phantom bom + so_id = self.sale_order.create(cr, uid, vals={'partner_id': self.partner_id}, context=context) + self.sale_order_line.create(cr, uid, values={'order_id': so_id, 'product_id': self.product_bom_id, 'product_uom_qty': 1}, context=context) + #confirm sale order + self.sale_order.action_button_confirm(cr, uid, [so_id], context=context) + #get all move associated to that sale_order + browse_move_ids = self.sale_order.browse(cr, uid, so_id, context=context).picking_ids[0].move_lines + move_ids = [x.id for x in browse_move_ids] + #we should have same amount of move as the component in the phatom bom + bom = self.mrp_bom.browse(cr, uid, self.bom_id, context=context) + bom_component_length = self.mrp_bom._bom_explode(cr, uid, bom, 1, []) + self.assertEqual(len(move_ids), len(bom_component_length[0])) |
