diff --git a/addons/stock/models/stock_move.py b/addons/stock/models/stock_move.py index 762bbd1406e..8ca2f46368f 100644 --- a/addons/stock/models/stock_move.py +++ b/addons/stock/models/stock_move.py @@ -422,7 +422,8 @@ class StockMove(models.Model): if move.picking_type_id.code in self._consuming_picking_types() and is_unreserved: outgoing_unreserved_moves_per_warehouse[warehouse_by_location[move.location_id]] |= move elif move.picking_type_id.code in self._consuming_picking_types(): - move.forecast_availability = move.reserved_availability + move.forecast_availability = move.product_uom._compute_quantity( + move.reserved_availability, move.product_id.uom_id, rounding_method='HALF-UP') elif move.picking_type_id.code == 'incoming': move._get_forecast_availability_incoming() diff --git a/addons/stock/tests/test_move.py b/addons/stock/tests/test_move.py index 2e2efda28aa..84b06a5b1ab 100644 --- a/addons/stock/tests/test_move.py +++ b/addons/stock/tests/test_move.py @@ -5409,3 +5409,37 @@ class StockMove(TransactionCase): warning = move._onchange_lot_ids() self.assertTrue(warning, 'Reuse of existing serial number (record) not detected') self.assertEqual(list(warning.keys())[0], 'warning', 'Warning message was not returned') + + def test_forecast_availability(self): + """ Make an outgoing picking in dozens for a product stored in units. + Check that reserved_availabity is expressed in move uom and forecast_availability is in product base uom + """ + # create product + product = self.env['product.product'].create({ + 'name': 'Product In Units', + 'type': 'product', + 'categ_id': self.env.ref('product.product_category_all').id, + }) + # make some stock + self.env['stock.quant']._update_available_quantity(product, self.stock_location, 36.0) + # create picking + picking_out = self.env['stock.picking'].create({ + 'picking_type_id': self.env.ref('stock.picking_type_out').id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id}) + move = self.env['stock.move'].create({ + 'name': product.name, + 'product_id': product.id, + 'product_uom': self.uom_dozen.id, + 'product_uom_qty': 2.0, + 'picking_id': picking_out.id, + 'location_id': self.stock_location.id, + 'location_dest_id': self.customer_location.id}) + # confirm + picking_out.action_confirm() + # check availability + picking_out.action_assign() + # check reserved_availabity expressed in move uom + self.assertEqual(move.reserved_availability, 2) + # check forecast_availability expressed in product base uom + self.assertEqual(move.forecast_availability, 24)