[FIX] stock: when matching moves with pack operations through quants, it did not match the packages correctly. Courtesy of Pedro Baeza
Before, it did a search to see if the package existed, but the only thing it needs to do is see if the package on the pack operation corresponds to that of the quant. (no need to check children also) There is a test added: A picking with 120 pieces incoming, 120 in pack 1, 80 in pack2 When we deliver those in a picking out, with product pack operations: (by taking them out of the pack) 120 from pack 1 and 80 from pack2, we should only have 2 quants and links between moves in the end And before, it generated 3 because it matched the wrong quants and made the wrong links. opw 693760 closes #13836
This commit is contained in:
parent
46ce74cdde
commit
1de37862d6
|
@ -1314,7 +1314,7 @@ class stock_picking(osv.osv):
|
|||
|
||||
#check if the quant is matching the operation details
|
||||
if ops.package_id:
|
||||
flag = quant.package_id and bool(package_obj.search(cr, uid, [('id', 'child_of', [ops.package_id.id])], context=context)) or False
|
||||
flag = quant.package_id == ops.package_id
|
||||
else:
|
||||
flag = not quant.package_id.id
|
||||
flag = flag and ((ops.lot_id and ops.lot_id.id == quant.lot_id.id) or not ops.lot_id)
|
||||
|
|
|
@ -35,6 +35,7 @@ class TestStockCommon(common.TransactionCase):
|
|||
self.productB = self.ProductObj.create({'name': 'Product B'})
|
||||
self.productC = self.ProductObj.create({'name': 'Product C'})
|
||||
self.productD = self.ProductObj.create({'name': 'Product D'})
|
||||
self.productE = self.ProductObj.create({'name': 'Product E', 'type': 'product'})
|
||||
|
||||
# Configure unit of measure.
|
||||
self.uom_kg = self.UomObj.create({
|
||||
|
|
|
@ -1114,6 +1114,9 @@ class TestStockFlow(TestStockCommon):
|
|||
lot1 = lot_obj.create({'name': 'Lot001', 'product_id': lotproduct.id})
|
||||
move = self.MoveObj.search([('product_id', '=', productKG.id), ('inventory_id', '=', inventory.id)], limit=1)
|
||||
self.assertEqual(len(move), 0, "Partial filter should not create a lines upon prepare")
|
||||
|
||||
|
||||
|
||||
|
||||
line_vals = []
|
||||
line_vals += [{'location_id': self.stock_location, 'product_id': packproduct.id, 'product_qty': 10, 'product_uom_id': packproduct.uom_id.id}]
|
||||
|
@ -1127,7 +1130,7 @@ class TestStockFlow(TestStockCommon):
|
|||
quants = self.StockQuantObj.search([('product_id', '=', packproduct.id), ('location_id', '=', self.stock_location), ('package_id', '=', pack1.id)])
|
||||
total_qty = sum([quant.qty for quant in quants])
|
||||
self.assertEqual(total_qty, 20, 'Expecting 20 units on package 1 of packproduct, but we got %.4f on location stock!' % (total_qty))
|
||||
|
||||
|
||||
#Create an inventory that will put the lots without lot to 0 and check that taking without pack will not take it from the pack
|
||||
inventory2 = self.InvObj.create({'name': 'Test Partial Lot and Pack2',
|
||||
'filter': 'partial',
|
||||
|
@ -1146,4 +1149,124 @@ class TestStockFlow(TestStockCommon):
|
|||
self.assertEqual(total_qty, 10, 'Expecting 0 units lot of lotproduct, but we got %.4f on location stock!' % (total_qty))
|
||||
quants = self.StockQuantObj.search([('product_id', '=', lotproduct.id), ('location_id', '=', self.stock_location), ('lot_id', '=', False)])
|
||||
total_qty = sum([quant.qty for quant in quants])
|
||||
self.assertEqual(total_qty, 0, 'Expecting 0 units lot of lotproduct, but we got %.4f on location stock!' % (total_qty))
|
||||
self.assertEqual(total_qty, 0, 'Expecting 0 units lot of lotproduct, but we got %.4f on location stock!' % (total_qty))
|
||||
|
||||
|
||||
def test_30_create_in_out_with_product_pack_lines(self):
|
||||
picking_in = self.PickingObj.create({
|
||||
'partner_id': self.partner_delta_id,
|
||||
'picking_type_id': self.picking_type_in})
|
||||
self.MoveObj.create({
|
||||
'name': self.productE.name,
|
||||
'product_id': self.productE.id,
|
||||
'product_uom_qty': 10,
|
||||
'product_uom': self.productE.uom_id.id,
|
||||
'picking_id': picking_in.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
|
||||
picking_in.action_confirm()
|
||||
picking_in.do_prepare_partial()
|
||||
pack_obj = self.env['stock.quant.package']
|
||||
pack1 = pack_obj.create({'name': 'PACKINOUTTEST1'})
|
||||
pack2 = pack_obj.create({'name': 'PACKINOUTTEST2'})
|
||||
picking_in.pack_operation_ids[0].result_package_id = pack1
|
||||
picking_in.pack_operation_ids[0].product_qty = 4
|
||||
packop2 = picking_in.pack_operation_ids[0].copy()
|
||||
packop2.product_qty = 6
|
||||
packop2.result_package_id = pack2
|
||||
picking_in.do_transfer()
|
||||
self.assertEqual(sum([x.qty for x in picking_in.move_lines[0].quant_ids]), 10.0, 'Expecting 10 pieces in stock')
|
||||
#check the quants are in the package
|
||||
self.assertEqual(sum(x.qty for x in pack1.quant_ids), 4.0, 'Pack 1 should have 4 pieces')
|
||||
self.assertEqual(sum(x.qty for x in pack2.quant_ids), 6.0, 'Pack 2 should have 6 pieces')
|
||||
picking_out = self.PickingObj.create({
|
||||
'partner_id': self.partner_agrolite_id,
|
||||
'picking_type_id': self.picking_type_out})
|
||||
self.MoveObj.create({
|
||||
'name': self.productE.name,
|
||||
'product_id': self.productE.id,
|
||||
'product_uom_qty': 3,
|
||||
'product_uom': self.productE.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location})
|
||||
picking_out.action_confirm()
|
||||
picking_out.action_assign()
|
||||
picking_out.do_prepare_partial()
|
||||
packout1 = picking_out.pack_operation_ids[0]
|
||||
packout2 = picking_out.pack_operation_ids[0].copy()
|
||||
packout1.product_qty = 2
|
||||
packout1.package_id = pack1
|
||||
packout2.package_id = pack2
|
||||
packout2.product_qty = 1
|
||||
picking_out.do_transfer()
|
||||
#Check there are no negative quants
|
||||
neg_quants = self.env['stock.quant'].search([('product_id', '=', self.productE.id), ('qty', '<', 0.0)])
|
||||
self.assertEqual(len(neg_quants), 0, 'There are negative quants!')
|
||||
self.assertEqual(len(picking_out.move_lines[0].linked_move_operation_ids), 2, 'We should have 2 links in the matching between the move and the operations')
|
||||
self.assertEqual(len(picking_out.move_lines[0].quant_ids), 2, 'We should have exactly 2 quants in the end')
|
||||
|
||||
|
||||
def test_40_create_in_out_with_product_pack_lines(self):
|
||||
picking_in = self.PickingObj.create({
|
||||
'partner_id': self.partner_delta_id,
|
||||
'picking_type_id': self.picking_type_in})
|
||||
self.MoveObj.create({
|
||||
'name': self.productE.name,
|
||||
'product_id': self.productE.id,
|
||||
'product_uom_qty': 200,
|
||||
'product_uom': self.productE.uom_id.id,
|
||||
'picking_id': picking_in.id,
|
||||
'location_id': self.supplier_location,
|
||||
'location_dest_id': self.stock_location})
|
||||
|
||||
picking_in.action_confirm()
|
||||
picking_in.do_prepare_partial()
|
||||
pack_obj = self.env['stock.quant.package']
|
||||
pack1 = pack_obj.create({'name': 'PACKINOUTTEST1'})
|
||||
pack2 = pack_obj.create({'name': 'PACKINOUTTEST2'})
|
||||
picking_in.pack_operation_ids[0].result_package_id = pack1
|
||||
picking_in.pack_operation_ids[0].product_qty = 120
|
||||
packop2 = picking_in.pack_operation_ids[0].copy()
|
||||
packop2.product_qty = 80
|
||||
packop2.result_package_id = pack2
|
||||
picking_in.do_transfer()
|
||||
self.assertEqual(sum([x.qty for x in picking_in.move_lines[0].quant_ids]), 200.0, 'Expecting 200 pieces in stock')
|
||||
#check the quants are in the package
|
||||
self.assertEqual(sum(x.qty for x in pack1.quant_ids), 120, 'Pack 1 should have 120 pieces')
|
||||
self.assertEqual(sum(x.qty for x in pack2.quant_ids), 80, 'Pack 2 should have 80 pieces')
|
||||
picking_out = self.PickingObj.create({
|
||||
'partner_id': self.partner_agrolite_id,
|
||||
'picking_type_id': self.picking_type_out})
|
||||
self.MoveObj.create({
|
||||
'name': self.productE.name,
|
||||
'product_id': self.productE.id,
|
||||
'product_uom_qty': 200 ,
|
||||
'product_uom': self.productE.uom_id.id,
|
||||
'picking_id': picking_out.id,
|
||||
'location_id': self.stock_location,
|
||||
'location_dest_id': self.customer_location})
|
||||
picking_out.action_confirm()
|
||||
picking_out.action_assign()
|
||||
picking_out.do_prepare_partial()
|
||||
#Convert entire packs into taking out of packs
|
||||
packout0 = picking_out.pack_operation_ids[0]
|
||||
packout1 = picking_out.pack_operation_ids[1]
|
||||
packout0.write({'product_id': self.productE.id,
|
||||
'product_qty' : 120.0,
|
||||
'product_uom_id' : self.productE.uom_id.id,
|
||||
'package_id': pack1.id,
|
||||
})
|
||||
packout1.write({'product_id': self.productE.id,
|
||||
'product_qty' : 80.0,
|
||||
'product_uom_id' : self.productE.uom_id.id,
|
||||
'package_id': pack2.id,
|
||||
})
|
||||
picking_out.do_transfer()
|
||||
#Check there are no negative quants
|
||||
neg_quants = self.env['stock.quant'].search([('product_id', '=', self.productE.id), ('qty', '<', 0.0)])
|
||||
self.assertEqual(len(neg_quants), 0, 'There are negative quants!')
|
||||
# We should also make sure that when matching stock moves with pack operations, it takes the correct
|
||||
self.assertEqual(len(picking_out.move_lines[0].linked_move_operation_ids), 2, 'We should only have 2 links beween the move and the 2 operations')
|
||||
self.assertEqual(len(picking_out.move_lines[0].quant_ids), 2, 'We should have exactly 2 quants in the end')
|
Loading…
Reference in New Issue