diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py index ff5154ee22a..bb6d19d6d46 100644 --- a/addons/stock/models/stock_move_line.py +++ b/addons/stock/models/stock_move_line.py @@ -408,9 +408,10 @@ class StockMoveLine(models.Model): for ml in self: if ml.product_id.type != 'product' or ml.state == 'done': continue - if 'quantity' in vals: - new_reserved_qty = ml.product_uom_id._compute_quantity( - vals['quantity'], ml.product_id.uom_id, rounding_method='HALF-UP') + if 'quantity' in vals or 'product_uom_id' in vals: + new_ml_uom = updates.get('product_uom_id', ml.product_uom_id) + new_reserved_qty = new_ml_uom._compute_quantity( + vals.get('quantity', ml.quantity), ml.product_id.uom_id, rounding_method='HALF-UP') # Make sure `reserved_uom_qty` is not negative. if float_compare(new_reserved_qty, 0, precision_rounding=ml.product_id.uom_id.rounding) < 0: raise UserError(_('Reserving a negative quantity is not allowed.')) @@ -428,7 +429,7 @@ class StockMoveLine(models.Model): lot=updates.get('lot_id', ml.lot_id), package=updates.get('package_id', ml.package_id), owner=updates.get('owner_id', ml.owner_id)) - if 'quantity' in vals and vals['quantity'] != ml.quantity: + if ('quantity' in vals and vals['quantity'] != ml.quantity) or 'product_uom_id' in vals: moves_to_recompute_state |= ml.move_id # When editing a done move line, the reserved availability of a potential chained move is impacted. Take care of running again `_action_assign` on the concerned moves. diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index bef76702e97..0017e336cdd 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -6312,3 +6312,32 @@ class StockMove(TransactionCase): line_form.lot_ids.add(sn01) picking = picking_form.save() self.assertEqual(picking.move_ids_without_package.lot_ids, sn01) + + def test_change_move_line_uom(self): + """Check the reserved_quantity of the quant is correctly updated when changing the UOM in the move line""" + Quant = self.env['stock.quant'] + Quant._update_available_quantity(self.product, self.stock_location, 100) + quant = Quant._gather(self.product, self.stock_location) + move = self.env['stock.move'].create({ + 'name': 'Test move', + 'product_id': self.product.id, + 'product_uom_qty': 1, + 'product_uom': self.product.uom_id.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id, + }) + move._action_confirm() + move._action_assign() + ml = move.move_line_ids + + # The product's uom is in units, which means we currently have 1 reserved unit + self.assertEqual(quant.reserved_quantity, 1) + + # Firstly, we test changing the quantity and the uom together: 2 dozens = 24 reserved units + ml.write({'quantity': 2, 'product_uom_id': self.uom_dozen.id}) + self.assertEqual(quant.reserved_quantity, 24) + self.assertEqual(ml.quantity * self.uom_dozen.ratio, 24) + # Secondly, we test changing only the uom: 2 units -> expected 2 units + ml.write({'product_uom_id': self.uom_unit.id}) + self.assertEqual(quant.reserved_quantity, 2) + self.assertEqual(ml.quantity * self.uom_unit.ratio, 2)