From 993de2d354f655251cba5e17487d4d46daf2580d Mon Sep 17 00:00:00 2001 From: amoyaux Date: Wed, 20 Sep 2017 15:06:56 +0200 Subject: [PATCH] [FIX] stock: move without initial demand/quantity When processing picking containing moves without quantity done and without initial demand. These moves were moving automatically to a new backorder. It was also possible to validate picking without quantity done for all moves. This commit raise an error if the user try to valiate a picking with all moves without quantity done and without initial demand. Or cancel all these moves if the picking is validate with correct moves. --- addons/stock/models/stock_move.py | 2 + addons/stock/models/stock_picking.py | 4 ++ addons/stock/tests/test_move2.py | 74 ++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index ca7b081acaa..f7353ab7521 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -932,6 +932,8 @@ class StockMove(models.Model): # rounding = move.product_uom.rounding # move.quantity_done = float_round(move.quantity_done, precision_rounding=rounding, rounding_method ='UP') if move.quantity_done <= 0: + if float_compare(move.product_uom_qty, 0.0, precision_rounding=move.product_uom.rounding) == 0: + move._action_cancel() continue moves_todo |= move moves_todo |= move._create_extra_move() diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index f01532da49d..cf53fe3c708 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -617,6 +617,10 @@ class Picking(models.Model): # If no lots when needed, raise error picking_type = self.picking_type_id no_quantities_done = all(line.qty_done == 0.0 for line in self.move_line_ids) + no_initial_demand = all(move.product_uom_qty == 0.0 for move in self.move_lines) + if no_initial_demand and no_quantities_done: + raise UserError(_('You cannot validate a transfer if you have not processed any quantity.')) + if picking_type.use_create_lots or picking_type.use_existing_lots: lines_to_check = self.move_line_ids if not no_quantities_done: diff --git a/addons/stock/tests/test_move2.py b/addons/stock/tests/test_move2.py index 0dc7904c561..40a35cf4cfa 100644 --- a/addons/stock/tests/test_move2.py +++ b/addons/stock/tests/test_move2.py @@ -1331,6 +1331,80 @@ class TestSinglePicking(TestStockCommon): self.assertEqual(len(qc_move), 1) self.assertTrue(qc_move.move_orig_ids == input_move, 'Move between QC and stock should only have the input move as origin') + def test_empty_moves_validation_1(self): + """ Use button validate on a picking that contains only moves + without initial demand and without quantity done should be + impossible and raise a usererror. + """ + delivery_order = self.env['stock.picking'].create({ + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + 'partner_id': self.partner_delta_id, + 'picking_type_id': self.picking_type_out, + }) + 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': delivery_order.id, + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + }) + 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': delivery_order.id, + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + }) + delivery_order.action_confirm() + delivery_order.action_assign() + with self.assertRaises(UserError): + delivery_order.button_validate() + + def test_empty_moves_validation_2(self): + """ Use button validate on a picking that contains only moves + without initial demand but at least one with a quantity done + should process the move with quantity done and cancel the + other. + """ + delivery_order = self.env['stock.picking'].create({ + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + 'partner_id': self.partner_delta_id, + 'picking_type_id': self.picking_type_out, + }) + move_a = 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': delivery_order.id, + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + }) + move_b = 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': delivery_order.id, + 'location_id': self.stock_location, + 'location_dest_id': self.customer_location, + }) + delivery_order.action_confirm() + delivery_order.action_assign() + move_a.quantity_done = 1 + delivery_order.button_validate() + + self.assertEqual(move_a.state, 'done') + self.assertEqual(move_b.state, 'cancel') + back_order = self.env['stock.picking'].search([('backorder_id', '=', delivery_order.id)]) + self.assertFalse(back_order, 'There should be no back order') + class TestStockUOM(TestStockCommon):