← Back to team overview

savoirfairelinux-openerp team mailing list archive

[Merge] lp:~savoirfairelinux-openerp/openobject-addons/7.0-bug-1168398-tta+afe+vv into lp:openobject-addons/7.0

 

Vincent Vinet has proposed merging lp:~savoirfairelinux-openerp/openobject-addons/7.0-bug-1168398-tta+afe+vv into lp:openobject-addons/7.0.

Requested reviews:
  OpenERP Core Team (openerp)
Related bugs:
  Bug #1168398 in Odoo Addons: "[trunk/7.0] Incorrect behaviour when producing MO with component split in serial numbers"
  https://bugs.launchpad.net/openobject-addons/+bug/1168398

For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/openobject-addons/7.0-bug-1168398-tta+afe+vv/+merge/225525

based on lp:~camptocamp/openobject-addons/7.0-bug-1168398-tta+afe with additional test
that shows wrong behavior.
-- 
https://code.launchpad.net/~savoirfairelinux-openerp/openobject-addons/7.0-bug-1168398-tta+afe+vv/+merge/225525
Your team Savoir-faire Linux' OpenERP is subscribed to branch lp:~savoirfairelinux-openerp/openobject-addons/7.0-bug-1168398-tta+afe+vv.
=== modified file 'mrp/__openerp__.py'
--- mrp/__openerp__.py	2014-04-04 12:30:03 +0000
+++ mrp/__openerp__.py	2014-07-03 17:21:41 +0000
@@ -75,11 +75,19 @@
     ],
     'demo': ['mrp_demo.xml'],
     'test': [
+<<<<<<< TREE
          'test/bom_with_service_type_product.yml',
          'test/mrp_users.yml',
          'test/order_demo.yml',
          'test/order_process.yml',
          'test/cancel_order.yml',
+=======
+#         'test/order_demo.yml',
+#         'test/order_process.yml',
+#         'test/cancel_order.yml',
+        'test/order_process_prodlot_split.yml',
+        'test/order_process_prodlot_partial_consume.yml',
+>>>>>>> MERGE-SOURCE
     ],
     'installable': True,
     'application': True,

=== modified file 'mrp/mrp.py'
--- mrp/mrp.py	2014-03-06 09:45:04 +0000
+++ mrp/mrp.py	2014-07-03 17:21:41 +0000
@@ -780,8 +780,17 @@
                     if float_compare(qty, 0, precision_rounding=scheduled.product_id.uom_id.rounding) <= 0:                        
                         # we already have more qtys consumed than we need
                         continue
-
-                    raw_product[0].action_consume(qty, raw_product[0].location_id.id, context=context)
+                    splitqty = qty
+                    moves = sorted(raw_product, key=lambda k: (k.product_qty))
+                    for move in moves:
+                        if splitqty <= 0:
+                            break
+                        elif move.product_qty >= splitqty:
+                            move.action_consume(splitqty, move.location_id.id, context=context)
+                            splitqty = 0
+                        else:
+                            move.action_consume(move.product_qty, move.location_id.id, context=context)
+                            splitqty = splitqty - move.product_qty
 
         if production_mode == 'consume_produce':
             # To produce remaining qty of final product

=== added file 'mrp/test/order_process_prodlot_partial_consume.yml'
--- mrp/test/order_process_prodlot_partial_consume.yml	1970-01-01 00:00:00 +0000
+++ mrp/test/order_process_prodlot_partial_consume.yml	2014-07-03 17:21:41 +0000
@@ -0,0 +1,66 @@
+-
+ I create a MO for 10 PCSC349
+-
+ !record {model: mrp.production, id: test_mo_pcsc349_2}:
+   product_id: product.product_product_4
+   product_qty: 10
+   product_uom: product.product_uom_unit
+   location_src_id: stock.stock_location_stock
+   location_dest_id: stock.stock_location_stock
+   bom_id: mrp_bom_24
+-
+ I confirm the MO
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: test_mo_pcsc349_2}
+-
+ I split the 20 RAM SR3 in 2 production lots of 5, 15 units
+-
+ !python {model: stock.move.split}: |
+   order = self.pool.get('mrp.production').browse(cr, uid, ref('test_mo_pcsc349_2'), context=context)
+   ram_lines = [line for line in order.move_lines if line.product_id.default_code == 'RAM-SR3']
+   assert len(ram_lines) == 1, 'no RAM-SR3 lines found'
+   ctxt = context.copy()
+   ctxt['active_id'] = ram_lines[0].id
+   ctxt['active_ids'] = [ram_lines[0].id]
+   ctxt['active_model'] = 'stock.move'
+   values = self.default_get(cr, uid,
+                             ['product_id', 'product_uom', 'qty', 'use_exist', 'location_id'],
+                             ctxt)
+   wizard_id = self.create(cr, uid, values, context=ctxt)
+   prodlot_obj = self.pool.get('stock.production.lot')
+   split_line_obj = self.pool.get('stock.move.split.lines')
+   split_line_obj.create(cr, uid, {'wizard_id': wizard_id,
+                                   'name': 'ram_sn_3',
+                                   'quantity': 5,}, context=ctxt)
+   split_line_obj.create(cr, uid, {'wizard_id': wizard_id,
+                                   'name': 'ram_sn_4',
+                                   'quantity': 15,}, context=ctxt)
+   self.split_lot(cr, uid, [wizard_id], context=ctxt)
+   order.refresh()
+   ram_lines = [line for line in order.move_lines if line.product_id.default_code == 'RAM-SR3']
+   assert len(ram_lines) == 2, 'RAM-SR3 line not split'
+
+
+-
+  I click on the "Produce" button of the Manufacturing Order and in the wizard select "Consume and Produce" mode.
+  I produce 5 units, which should consume 10 RAM-SR3
+-
+ !python {model: mrp.product.produce}: |
+   ctxt = context.copy()
+   order = self.pool.get('mrp.production').browse(cr, uid, ref('test_mo_pcsc349_2'), context=context)
+   ctxt['active_id'] = order.id
+   ctxt['active_model'] = 'mrp.production'
+   wizard_id = self.create(cr, uid,
+                           {'product_qty': 5,
+                            'mode': 'consume_produce'}, ctxt)
+   self.do_produce(cr, uid, [wizard_id], ctxt)
+-
+  I expect 10 RAM-SR3 to be consumed, takling 5 ram_sn3 and 5 ram_sn4
+-
+ !python {model: mrp.production}: |
+   order = self.browse(cr, uid, ref('test_mo_pcsc349_2'), context=context)
+   ram_lines = [line for line in order.move_lines2 if line.product_id.default_code == 'RAM-SR3']
+   ram_sn_3 = [line for line in ram_lines if line.prodlot_id.name == 'ram_sn_3']
+   ram_sn_4 = [line for line in ram_lines if line.prodlot_id.name == 'ram_sn_4']
+   assert ram_sn_3 and ram_sn_3[0].product_qty == 5, 'should have consumed 5 ram_sn3, not %d' % ram_sn_3[0].product_qty
+   assert ram_sn_4 and ram_sn_4[0].product_qty == 5, 'should have consumed 5 ram_sn4. not %d' % ram_sn_4[0].product_qty

=== added file 'mrp/test/order_process_prodlot_split.yml'
--- mrp/test/order_process_prodlot_split.yml	1970-01-01 00:00:00 +0000
+++ mrp/test/order_process_prodlot_split.yml	2014-07-03 17:21:41 +0000
@@ -0,0 +1,67 @@
+-
+ I create a MO for 1 PCSC349
+-
+ !record {model: mrp.production, id: test_mo_pcsc349}:
+   product_id: product.product_product_4
+   product_qty: 1
+   product_uom: product.product_uom_unit
+   location_src_id: stock.stock_location_stock
+   location_dest_id: stock.stock_location_stock
+   bom_id: mrp_bom_24
+-
+ I confirm the MO
+-
+ !workflow {model: mrp.production, action: button_confirm, ref: test_mo_pcsc349}
+-
+ I split the RAM SR3 in 2 production lots
+-
+ !python {model: stock.move.split}: |
+   order = self.pool.get('mrp.production').browse(cr, uid, ref('test_mo_pcsc349'), context=context)
+   ram_lines = [line for line in order.move_lines if line.product_id.default_code == 'RAM-SR3']
+   assert len(ram_lines) == 1, 'no RAM-SR3 lines found'
+   ctxt = context.copy()
+   ctxt['active_id'] = ram_lines[0].id
+   ctxt['active_ids'] = [ram_lines[0].id]
+   ctxt['active_model'] = 'stock.move'
+   values = self.default_get(cr, uid,
+                             ['product_id', 'product_uom', 'qty', 'use_exist', 'location_id'],
+                             ctxt)
+   wizard_id = self.create(cr, uid, values, context=ctxt)
+   prodlot_obj = self.pool.get('stock.production.lot')
+   split_line_obj = self.pool.get('stock.move.split.lines')
+   split_line_obj.create(cr, uid, {'wizard_id': wizard_id,
+                                   'name': 'ram_sn_1',
+                                   'quantity': 1,}, context=ctxt)
+   split_line_obj.create(cr, uid, {'wizard_id': wizard_id,
+                                   'name': 'ram_sn_2',
+                                   'quantity': 1,}, context=ctxt)
+   self.split_lot(cr, uid, [wizard_id], context=ctxt)
+   order.refresh()
+   ram_lines = [line for line in order.move_lines if line.product_id.default_code == 'RAM-SR3']
+   assert len(ram_lines) == 2, 'RAM-SR3 line not split'
+
+
+-
+  I click on the "Produce" button of the Manufacturing Order and in the wizard select "Consume and Produce" mode
+-
+ !python {model: mrp.product.produce}: |
+   ctxt = context.copy()
+   order = self.pool.get('mrp.production').browse(cr, uid, ref('test_mo_pcsc349'), context=context)
+   ctxt['active_id'] = order.id
+   ctxt['active_model'] = 'mrp.production'
+   wizard_id = self.create(cr, uid,
+                           {'product_qty': 1,
+                            'mode': 'consume_produce'}, ctxt)
+   self.do_produce(cr, uid, [wizard_id], ctxt)
+-
+  I expect
+  all the Products in the "Products to consume" lists to be consumed
+  and moved to the "consumed products" list,
+  and the manufacturing order to be in state "Done"
+-
+ !python {model: mrp.production}: |
+   order = self.browse(cr, uid, ref('test_mo_pcsc349'), context=context)
+   assert order.state == 'done', "wrong state for the production order (%r, expected: 'done')" % order.state
+   assert len(order.move_lines) == 0, "%d leftover move lines in 'products to consume'" % len(order.move_lines)
+   ram_lines = [line for line in order.move_lines2 if line.product_id.default_code == 'RAM-SR3']
+   assert len(ram_lines) == 2, 'not all RAM-SR3 were consumed'