diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 470461a28a7..35b8c6ed613 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -500,11 +500,12 @@ class StockMove(models.Model): :return: Recordset of moves passed to this method. If some of the passed moves were merged into another existing one, return this one and not the (now unlinked) original. """ - distinct_fields = ['price_unit', 'product_id', 'product_packaging', + distinct_fields = ['product_id', 'price_unit', 'product_packaging', 'product_uom', 'restrict_partner_id', 'scrapped', 'origin_returned_move_id'] def _keys_sorted(move): - return tuple([getattr(move, attr) for attr in distinct_fields]) + return move.product_id.id, move.price_unit, move.product_packaging.id, move.product_uom.id,\ + move.restrict_partner_id.id, move.scrapped, move.origin_returned_move_id.id # Move removed after merge moves_to_unlink = self.env['stock.move'] diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index 40a35cf4cfa..2a9625bb2f4 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -1268,6 +1268,42 @@ class TestSinglePicking(TestStockCommon): self.assertEqual(receipt.move_lines.origin.count('MPS'), 1, 'Origin not merged together or duplicated') self.assertEqual(receipt.move_lines.origin.count('PO0001'), 1, 'Origin not merged together or duplicated') + def test_merge_moves_3(self): + """ Create 2 moves without initial_demand and already a + quantity done. Check that we still have only 2 moves after + validation. + """ + receipt = self.env['stock.picking'].create({ + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + 'partner_id': self.partner_delta_id, + 'picking_type_id': self.picking_type_in, + }) + move_1 = self.MoveObj.create({ + 'name': self.productA.name, + 'product_id': self.productA.id, + 'product_uom_qty': 0, + 'product_uom': self.productA.uom_id.id, + 'picking_id': receipt.id, + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + 'origin': 'MPS' + }) + move_2 = self.MoveObj.create({ + 'name': self.productB.name, + 'product_id': self.productB.id, + 'product_uom_qty': 0, + 'product_uom': self.productB.uom_id.id, + 'picking_id': receipt.id, + 'location_id': self.supplier_location, + 'location_dest_id': self.stock_location, + 'origin': 'PO0001' + }) + move_1.quantity_done = 5 + move_2.quantity_done = 5 + receipt.button_validate() + self.assertEqual(len(receipt.move_lines), 2, 'Moves were not merged') + def test_merge_chained_moves(self): """ Imagine multiple step delivery. Two different receipt picking for the same product should only generate 1 picking from input to QC and another from QC to stock. The link at the end should follow this scheme. diff --git a/addons/stock/tests/test_stock_flow.py b/addons/stock/tests/test_stock_flow.py index 6c3a1f45226..d625d9227f9 100644 --- a/addons/stock/tests/test_stock_flow.py +++ b/addons/stock/tests/test_stock_flow.py @@ -112,7 +112,7 @@ class TestStockFlow(TestStockCommon): # ---------------------------------------------------------------------- # Check total no of move lines of incoming shipment. move line e disappear from original picking to go in backorder. - self.assertEqual(len(picking_in.move_lines), 6, 'Wrong number of move lines.') + self.assertEqual(len(picking_in.move_lines), 4, 'Wrong number of move lines.') # Check incoming shipment state. self.assertEqual(picking_in.state, 'done', 'Incoming shipment state should be done.') # Check incoming shipment move lines state. @@ -120,12 +120,10 @@ class TestStockFlow(TestStockCommon): self.assertEqual(move.state, 'done', 'Wrong state of move line.') # Check product A done quantity must be 3 and 1 moves = self.MoveObj.search([('product_id', '=', self.productA.id), ('picking_id', '=', picking_in.id)]) - a_done_qty = [move.product_uom_qty for move in moves] - self.assertEqual(set(a_done_qty), set([1.0, 3.0]), 'Wrong move quantity for product A.') + self.assertEqual(moves.product_uom_qty, 4.0, 'Wrong move quantity for product A.') # Check product B done quantity must be 4 and 1 moves = self.MoveObj.search([('product_id', '=', self.productB.id), ('picking_id', '=', picking_in.id)]) - b_done_qty = [move.product_uom_qty for move in moves] - self.assertEqual(set(b_done_qty), set([4.0, 1.0]), 'Wrong move quantity for product B.') + self.assertEqual(moves.product_uom_qty, 5.0, 'Wrong move quantity for product B.') # Check product C done quantity must be 7 c_done_qty = self.MoveObj.search([('product_id', '=', self.productC.id), ('picking_id', '=', picking_in.id)], limit=1).product_uom_qty self.assertEqual(c_done_qty, 7.0, 'Wrong move quantity of product C (%s found instead of 7)' % (c_done_qty)) @@ -254,7 +252,7 @@ class TestStockFlow(TestStockCommon): # check outgoing shipment status. self.assertEqual(picking_out.state, 'done', 'Wrong state of outgoing shipment.') # check outgoing shipment total moves and and its state. - self.assertEqual(len(picking_out.move_lines), 5, 'Wrong number of move lines') + self.assertEqual(len(picking_out.move_lines), 4, 'Wrong number of move lines') for move in picking_out.move_lines: self.assertEqual(move.state, 'done', 'Wrong state of move line.') back_order_out = self.PickingObj.search([('backorder_id', '=', picking_out.id)]) @@ -372,7 +370,7 @@ class TestStockFlow(TestStockCommon): # ---------------------------------------------------------------------- # Check total no of move lines. - self.assertEqual(len(back_order_in.move_lines), 4, 'Wrong number of move lines') + self.assertEqual(len(back_order_in.move_lines), 3, 'Wrong number of move lines') # Check incoming shipment state must be 'Done'. self.assertEqual(back_order_in.state, 'done', 'Wrong state of picking.') # Check incoming shipment move lines state must be 'Done'. @@ -383,8 +381,7 @@ class TestStockFlow(TestStockCommon): self.assertEqual(movesA.product_uom_qty, 10, "Wrong move quantity of product A (%s found instead of 10)" % (movesA.product_uom_qty)) # Check product C done quantity must be 3.0, 1.0, 2.0 movesC = self.MoveObj.search([('product_id', '=', self.productC.id), ('picking_id', '=', back_order_in.id)]) - c_done_qty = [move.product_uom_qty for move in movesC] - self.assertEqual(set(c_done_qty), set([3.0, 3.0]), 'Wrong quantity of moves product C.') + self.assertEqual(movesC.product_uom_qty, 6.0, 'Wrong quantity of moves product C.') # Check product D done quantity must be 5.0 and 3.0 movesD = self.MoveObj.search([('product_id', '=', self.productD.id), ('picking_id', '=', back_order_in.id)]) d_done_qty = [move.product_uom_qty for move in movesD]