From 4beeff79a5f521a85f59e03037b48594c6f2e4d8 Mon Sep 17 00:00:00 2001 From: Jinal Patel Date: Mon, 20 May 2019 06:15:04 +0000 Subject: [PATCH] [FIX] stock: create SM from SML In this commit, creating SM from SML if trasfer is immediate. Due to which following issues are getting resolve - For immediate trasfer - 1) Unable to cancel the picking in draft state and SML is created by view directly (No SM). 2) Unable to see button Put in pack. 3) Picking remains in state draft instead of ready. task-2275833 closes odoo/odoo#61887 X-original-commit: f933c15794ec733be51d879de2410302d9804121 Signed-off-by: William Henrotin --- addons/stock/models/stock_move_line.py | 55 ++++++++++++++++---------- addons/stock/models/stock_picking.py | 22 ----------- addons/stock/tests/test_move2.py | 49 +++++++++++++++++++++++ 3 files changed, 84 insertions(+), 42 deletions(-) diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index d98f5778a6b..19825276ec3 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -180,26 +180,41 @@ class StockMoveLine(models.Model): vals['company_id'] = self.env['stock.move'].browse(vals['move_id']).company_id.id elif vals.get('picking_id'): vals['company_id'] = self.env['stock.picking'].browse(vals['picking_id']).company_id.id - # 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 not vals.get('move_id'): - 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 - mls = super(StockMoveLine, self).create(vals_list) + + mls = super().create(vals_list) + + def create_move(move_line): + new_move = self.env['stock.move'].create({ + 'name': _('New Move:') + move_line.product_id.display_name, + 'product_id': move_line.product_id.id, + 'product_uom_qty': move_line.qty_done, + 'product_uom': move_line.product_uom_id.id, + 'description_picking': move_line.description_picking, + 'location_id': move_line.picking_id.location_id.id, + 'location_dest_id': move_line.picking_id.location_dest_id.id, + 'picking_id': move_line.picking_id.id, + 'state': move_line.picking_id.state, + 'picking_type_id': move_line.picking_id.picking_type_id.id, + 'restrict_partner_id': move_line.picking_id.owner_id.id, + 'company_id': move_line.picking_id.company_id.id, + }) + move_line.move_id = new_move.id + + # If the move line is directly create on the picking view. + # If this picking is already done we should generate an + # associated done move. + for move_line in mls: + if move_line.move_id or not move_line.picking_id: + continue + if move_line.picking_id.state != 'done': + moves = move_line.picking_id.move_lines.filtered(lambda x: x.product_id == move_line.product_id) + moves = sorted(moves, key=lambda m: m.quantity_done < m.product_qty, reverse=True) + if moves: + move_line.move_id = moves[0].id + else: + create_move(move_line) + else: + create_move(move_line) for ml, vals in zip(mls, vals_list): if ml.move_id and \ diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 4645ce7a9af..e932bf0c217 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -742,28 +742,6 @@ class Picking(models.Model): if picking.owner_id: picking.move_lines.write({'restrict_partner_id': picking.owner_id.id}) picking.move_line_ids.write({'owner_id': picking.owner_id.id}) - for move_line in picking.move_line_ids.filtered(lambda x: not x.move_id): - moves = picking.move_lines.filtered(lambda x: x.product_id == move_line.product_id) - moves = sorted(moves, key=lambda m: m.quantity_done < m.product_qty, reverse=True) - if moves: - move_line.move_id = moves[0].id - else: - new_move = self.env['stock.move'].create({ - 'name': _('New Move:') + move_line.product_id.display_name, - 'product_id': move_line.product_id.id, - 'product_uom_qty': move_line.qty_done, - 'product_uom': move_line.product_uom_id.id, - 'description_picking': move_line.description_picking, - 'location_id': picking.location_id.id, - 'location_dest_id': picking.location_dest_id.id, - 'picking_id': picking.id, - 'picking_type_id': picking.picking_type_id.id, - 'restrict_partner_id': picking.owner_id.id, - 'company_id': picking.company_id.id, - }) - move_line.move_id = new_move.id - new_move._action_confirm() - todo_moves |= new_move todo_moves._action_done(cancel_backorder=self.env.context.get('cancel_backorder')) self.write({'date_done': fields.Datetime.now(), 'priority': '0'}) diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index e41dabb488a..d2e251cb1b7 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -2042,6 +2042,55 @@ class TestSinglePicking(TestStockCommon): self.assertEqual(receipt.location_dest_id.id, stock_location.id) self.assertEqual(receipt.move_line_ids.location_dest_id.id, shelf_location.id) + def test_cancel_plan_transfer(self): + """ Test canceling plan transfer """ + # Create picking with stock move. + picking = self.env['stock.picking'].create({ + 'location_id': self.pack_location, + 'location_dest_id': self.customer_location, + 'picking_type_id': self.picking_type_out, + 'move_lines': [(0, 0, { + 'name': self.productA.name, + 'product_id': self.productA.id, + 'product_uom_qty': 10, + 'product_uom': self.productA.uom_id.id, + 'location_id': self.pack_location, + 'location_dest_id': self.customer_location, + })] + }) + # Confirm the outgoing picking, state should be changed. + picking.action_confirm() + self.assertEqual(picking.state, 'confirmed', "Picking should be in a confirmed state.") + + # Picking in a confirmed state and try to cancel it. + picking.action_cancel() + self.assertEqual(picking.state, 'cancel', "Picking should be in a cancel state.") + + def test_immediate_transfer(self): + """ Test picking should be in ready state if immediate transfer and SML is created via view + + Test picking cancelation with immediate transfer and done quantity""" + # create picking with stock move line + picking = self.env['stock.picking'].create({ + 'location_id': self.pack_location, + 'location_dest_id': self.customer_location, + 'picking_type_id': self.picking_type_out, + 'immediate_transfer': True, + 'move_line_ids': [(0, 0, { + 'product_id': self.productA.id, + 'qty_done': 10, + 'product_uom_id': self.productA.uom_id.id, + 'location_id': self.pack_location, + 'location_dest_id': self.customer_location, + })] + }) + + self.assertEqual(picking.state, 'assigned', "Picking should not be in a draft state.") + self.assertEqual(len(picking.move_lines), 1, "Picking should have stock move.") + picking.action_cancel() + self.assertEqual(picking.move_lines.state, 'cancel', "Stock move should be in a cancel state.") + self.assertEqual(picking.state, 'cancel', "Picking should be in a cancel state.") + + class TestStockUOM(TestStockCommon): def setUp(self): super(TestStockUOM, self).setUp()