diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index a254417e11d..daeb05dbea1 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -155,6 +155,27 @@ class StockMoveLine(models.Model): @api.model def create(self, vals): vals['ordered_qty'] = vals.get('product_uom_qty') + + # If the move line is directly create on the picking view. + # If this picking is already done we should generate an + # associated done move. + if 'picking_id' in vals and 'move_id' not in vals: + picking = self.env['stock.picking'].browse(vals['picking_id']) + if picking.state == 'done': + product = self.env['product.product'].browse(vals['product_id']) + new_move = self.env['stock.move'].create({ + 'name': _('New Move:') + product.display_name, + 'product_id': product.id, + 'product_uom_qty': 'qty_done' in vals and vals['qty_done'] or 0, + 'product_uom': vals['product_uom_id'], + 'location_id': 'location_id' in vals and vals['location_id'] or picking.location_id.id, + 'location_dest_id': 'location_dest_id' in vals and vals['location_dest_id'] or picking.location_dest_id.id, + 'state': 'done', + 'additional': True, + 'picking_id': picking.id, + }) + vals['move_id'] = new_move.id + ml = super(StockMoveLine, self).create(vals) if ml.state == 'done': if ml.product_id.type == 'product': diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index ef23b7c9496..aa6adaf1778 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -3095,3 +3095,45 @@ class StockMove(TransactionCase): self.product1.type = 'product' move2._action_cancel() self.product1.type = 'product' + + def test_edit_done_picking_1(self): + """ Add a new move line in a done picking should generate an + associated move. + """ + self.env['stock.quant']._update_available_quantity(self.product1, self.stock_location, 12) + picking = self.env['stock.picking'].create({ + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'picking_type_id': self.env.ref('stock.picking_type_in').id, + }) + move1 = self.env['stock.move'].create({ + 'name': 'test_transit_1', + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'product_id': self.product1.id, + 'product_uom': self.uom_unit.id, + 'product_uom_qty': 10.0, + 'picking_id': picking.id, + }) + picking.action_confirm() + picking.action_assign() + move1.quantity_done = 10 + picking.action_done() + + self.assertEqual(len(picking.move_lines), 1, 'One move should exist for the picking.') + self.assertEqual(len(picking.move_line_ids), 1, 'One move line should exist for the picking.') + + ml = self.env['stock.move.line'].create({ + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + 'product_id': self.product1.id, + 'product_uom_id': self.uom_unit.id, + 'qty_done': 2.0, + 'picking_id': picking.id, + }) + + self.assertEqual(len(picking.move_lines), 2, 'The new move associated to the move line does not exist.') + self.assertEqual(len(picking.move_line_ids), 2, 'It should be 2 move lines for the picking.') + self.assertTrue(ml.move_id in picking.move_lines, 'Links are not correct between picking, moves and move lines.') + self.assertEqual(picking.state, 'done', 'Picking should still done after adding a new move line.') + self.assertTrue(all(move.state == 'done' for move in picking.move_lines), 'Wrong state for move.') diff --git a/addons/stock/views/stock_picking_views.xml b/addons/stock/views/stock_picking_views.xml index 1a329e7db6b..118cdda7690 100644 --- a/addons/stock/views/stock_picking_views.xml +++ b/addons/stock/views/stock_picking_views.xml @@ -255,7 +255,7 @@ - + @@ -277,7 +277,7 @@ - +