[FIX] stock: filter quants when updating qty
In some cases, when making an inventory adjustment, the `in_date` of the
new quant will be incorrect
To reproduce the issue:
(Let D01 be the current date)
1. Create a storable product P
2. Set its quantity to 1
3. Process a delivery order with 1 x P
4. Set the date in the future
- Let D02 be this date
5. Make an inventory adjustment with 1 x P
Error: The `in_date` of the quant (for P in the stock location) is D01
instead of D02 (can be observed either directly in PSQL, on the form
view of the quant (via Locations > Current Stock), or by adding the
field on the tree view)
When validating the stock adjustment, at some point, the module calls
`_action_done` on a SML (1 x P from Inventory Adjustment to the Stock
Location). To do so, it decreases the quantity of the origin location
and increases the quantity of the destination location thanks to
`_update_available_quantity`:
https://github.com/odoo/odoo/blob/b4a9e5b8307ab1b730effe2de23f15260326ef6c/addons/stock/models/stock_move_line.py#L485-L493
But here is the issue: when decreasing the quantity in the virtual
location (Inventory Adjustment), it finds an old quant (the one from
step 2 in above use case). It then stores its `in_date` (D01) and since
this date is before the current one (D02), D01 is kept, used to update
the quant quantity and returned in `action_done`. As a result, when
increasing the quantity in the stock location,
`_update_available_quantity` is called with the parameter `in_date`
defined and equal to D01. Again, D01 will be the earliest date, so the
date will be used to create/update the quant in stock location.
OPW-2702198
closes odoo/odoo#83009
X-original-commit: e27ee5cd6b19351a00030310d1db3a0defe5b31a
Signed-off-by: Arnold Moyaux <arm@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
This commit is contained in:
@@ -688,7 +688,11 @@ class StockQuant(models.Model):
|
||||
self = self.sudo()
|
||||
quants = self._gather(product_id, location_id, lot_id=lot_id, package_id=package_id, owner_id=owner_id, strict=True)
|
||||
|
||||
incoming_dates = [d for d in quants.mapped('in_date') if d]
|
||||
if location_id.should_bypass_reservation():
|
||||
incoming_dates = []
|
||||
else:
|
||||
incoming_dates = [quant.in_date for quant in quants if quant.in_date and
|
||||
float_compare(quant.quantity, 0, precision_rounding=quant.product_uom_id.rounding) > 0]
|
||||
if in_date:
|
||||
incoming_dates += [in_date]
|
||||
# If multiple incoming dates are available for a given lot_id/package_id/owner_id, we
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
|
||||
from contextlib import closing
|
||||
from datetime import datetime, timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo import fields
|
||||
from odoo.addons.mail.tests.common import mail_new_test_user
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tests.common import TransactionCase
|
||||
@@ -687,3 +689,42 @@ class StockQuant(TransactionCase):
|
||||
self.assertEqual(quants[0][0].reserved_quantity, 2)
|
||||
# The last one should then be taken in stock_location/subloc3 since the first location doesn't have enough products
|
||||
self.assertEqual(quants[1][0].reserved_quantity, 1)
|
||||
|
||||
def test_in_date_6(self):
|
||||
"""
|
||||
One P in stock, P is delivered. Later on, a stock adjustement adds one P. This test checks
|
||||
the date value of the related quant
|
||||
"""
|
||||
self.env['stock.quant']._update_available_quantity(self.product, self.stock_location, 1.0)
|
||||
|
||||
move = self.env['stock.move'].create({
|
||||
'name': 'OUT 1 product',
|
||||
'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.ref('stock.stock_location_customers'),
|
||||
})
|
||||
move._action_confirm()
|
||||
move._action_assign()
|
||||
move.quantity_done = 1
|
||||
move._action_done()
|
||||
|
||||
|
||||
tomorrow = fields.Datetime.now() + timedelta(days=1)
|
||||
with patch.object(fields.Datetime, 'now', lambda: tomorrow):
|
||||
move = self.env['stock.move'].create({
|
||||
'name': 'IN 1 product',
|
||||
'product_id': self.product.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': self.product.uom_id.id,
|
||||
'location_id': self.ref('stock.stock_location_suppliers'),
|
||||
'location_dest_id': self.stock_location.id,
|
||||
})
|
||||
move._action_confirm()
|
||||
move._action_assign()
|
||||
move.quantity_done = 1
|
||||
move._action_done()
|
||||
|
||||
quant = self.env['stock.quant'].search([('product_id', '=', self.product.id), ('location_id', '=', self.stock_location.id), ('quantity', '>', 0)])
|
||||
self.assertEqual(quant.in_date, tomorrow)
|
||||
|
||||
Reference in New Issue
Block a user