[FIX] product_expiry: update expiry dates correctly
Steps to reproduce: - Install product_expiry - Create Product P: - Product type: Storable - Inventory tab > Tracking: By Lots - Check Expiration Date - Expiration Date: 100 days after receipt - Best Before Date, Removal Date, Alert Date: 10 days before expiration date - Save - Products > Lots/Serial Numbers > New - Product: P - open Dates tab There are two different usecases and issues starting from this point. Usecase 1: - Dates tab, delete all dates, save - set the Expiration Date, all other dates are set - without saving, update the Expiration Date again Issue 1: The other dates don't update according to the new Expiration Date. This happens because neither if conditions in `_compute_dates` match the case where the product has an expiration date set, but it has not been saved to the lot. Solution 1: Add an additional condition in the `_compute_dates` method where `lot.expiration_date` is set, but `lot._origin.expiration_date` is not set. This will ensure the other dates are updated correctly when setting the Expiration Date without saving. Usecase 2: - Dates tab, set an Expiration Date, save - Without saving the record, update the Expiration Date several times, with dates in the future Issue 2: The other dates (Best Before Date, Removal Date, Alert Date) will drift off further in the future, while they should always be 10 days apart from the expiration date. This happens because the new dates are being set relative to the actual value of the date, which changes with each successive update. Solution 2: set the new dates relative to the value of the `lot._origin` dates, which remain constant between successive (saveless) updates. This will ensure that the other dates maintain a 10-day difference from the Expiration Date consistently. opw-3374135 closes odoo/odoo#130599 X-original-commit: a275cbcd2d8a87bbd8cadf85c094625ebd8358c4 Signed-off-by: Tiffany Chang <tic@odoo.com>
This commit is contained in:
@@ -47,8 +47,9 @@ class StockLot(models.Model):
|
||||
lot.alert_date = False
|
||||
elif lot.expiration_date:
|
||||
# when create
|
||||
if lot.product_id != lot._origin.product_id or\
|
||||
(not lot.use_date and not lot.removal_date and not lot.alert_date):
|
||||
if lot.product_id != lot._origin.product_id or \
|
||||
(not lot.use_date and not lot.removal_date and not lot.alert_date) or \
|
||||
(lot.expiration_date and not lot._origin.expiration_date):
|
||||
product_tmpl = lot.product_id.product_tmpl_id
|
||||
lot.use_date = lot.expiration_date - datetime.timedelta(days=product_tmpl.use_time)
|
||||
lot.removal_date = lot.expiration_date - datetime.timedelta(days=product_tmpl.removal_time)
|
||||
@@ -56,9 +57,9 @@ class StockLot(models.Model):
|
||||
# when change
|
||||
elif lot._origin.expiration_date:
|
||||
time_delta = lot.expiration_date - lot._origin.expiration_date
|
||||
lot.use_date = lot.use_date and lot.use_date + time_delta
|
||||
lot.removal_date = lot.removal_date and lot.removal_date + time_delta
|
||||
lot.alert_date = lot.alert_date and lot.alert_date + time_delta
|
||||
lot.use_date = lot._origin.use_date and lot._origin.use_date + time_delta
|
||||
lot.removal_date = lot._origin.removal_date and lot._origin.removal_date + time_delta
|
||||
lot.alert_date = lot._origin.alert_date and lot._origin.alert_date + time_delta
|
||||
|
||||
@api.model
|
||||
def _alert_date_exceeded(self):
|
||||
|
||||
@@ -236,6 +236,20 @@ class TestStockLot(TestStockCommon):
|
||||
def test_03_onchange_expiration_date(self):
|
||||
""" Updates the `expiration_date` of the lot production and checks other date
|
||||
fields are updated as well. """
|
||||
def check_expiration_dates(product, lot, start_date, delta):
|
||||
self.assertAlmostEqual(
|
||||
start_date + timedelta(days=product.expiration_time),
|
||||
lot.expiration_date, delta=delta)
|
||||
self.assertAlmostEqual(
|
||||
lot.expiration_date - timedelta(days=product.use_time),
|
||||
lot.use_date, delta=delta)
|
||||
self.assertAlmostEqual(
|
||||
lot.expiration_date - timedelta(days=product.removal_time),
|
||||
lot.removal_date, delta=delta)
|
||||
self.assertAlmostEqual(
|
||||
lot.expiration_date - timedelta(days=product.alert_time),
|
||||
lot.alert_date, delta=delta)
|
||||
|
||||
# Keeps track of the current datetime and set a delta for the compares.
|
||||
today_date = datetime.today()
|
||||
time_gap = timedelta(seconds=10)
|
||||
@@ -246,37 +260,36 @@ class TestStockLot(TestStockCommon):
|
||||
lot_form.company_id = self.env.company
|
||||
apple_lot = lot_form.save()
|
||||
# ...then checks date fields have the expected values.
|
||||
self.assertAlmostEqual(
|
||||
today_date + timedelta(days=self.apple_product.expiration_time),
|
||||
apple_lot.expiration_date, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.expiration_date - timedelta(days=self.apple_product.use_time),
|
||||
apple_lot.use_date, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.expiration_date - timedelta(days=self.apple_product.removal_time),
|
||||
apple_lot.removal_date, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.expiration_date - timedelta(days=self.apple_product.alert_time),
|
||||
apple_lot.alert_date, delta=time_gap)
|
||||
check_expiration_dates(self.apple_product, apple_lot, today_date, time_gap)
|
||||
|
||||
difference = timedelta(days=20)
|
||||
new_date = apple_lot.expiration_date + difference
|
||||
old_use_date = apple_lot.use_date
|
||||
old_removal_date = apple_lot.removal_date
|
||||
old_alert_date = apple_lot.alert_date
|
||||
new_expiration_date = apple_lot.expiration_date + difference
|
||||
new_start_date = new_expiration_date - timedelta(days=self.apple_product.expiration_time)
|
||||
random_date = new_expiration_date + difference
|
||||
|
||||
# Modifies the lot `expiration_date`...
|
||||
# Modifies the lot `expiration_date` several times, without saving...
|
||||
lot_form = Form(apple_lot)
|
||||
lot_form.expiration_date = new_date
|
||||
lot_form.expiration_date = new_expiration_date
|
||||
lot_form.expiration_date = random_date
|
||||
lot_form.expiration_date = new_expiration_date
|
||||
apple_lot = lot_form.save()
|
||||
|
||||
# ...then checks all other date fields were correclty updated.
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.use_date, old_use_date + difference, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.removal_date, old_removal_date + difference, delta=time_gap)
|
||||
self.assertAlmostEqual(
|
||||
apple_lot.alert_date, old_alert_date + difference, delta=time_gap)
|
||||
# ...then checks all other date fields were correctly updated.
|
||||
check_expiration_dates(self.apple_product, apple_lot, new_start_date, time_gap)
|
||||
|
||||
# Remove all dates, save, update expiration date twice, then save again
|
||||
lot_form = Form(apple_lot)
|
||||
lot_form.expiration_date = False
|
||||
lot_form.use_date = False
|
||||
lot_form.removal_date = False
|
||||
lot_form.alert_date = False
|
||||
lot_form.save()
|
||||
lot_form.expiration_date = random_date
|
||||
lot_form.expiration_date = new_expiration_date
|
||||
apple_lot = lot_form.save()
|
||||
|
||||
# ...then check all other date fields were correctly updated.
|
||||
check_expiration_dates(self.apple_product, apple_lot, new_start_date, time_gap)
|
||||
|
||||
def test_04_expiration_date_on_receipt(self):
|
||||
""" Test we can set an expiration date on receipt and all expiration
|
||||
|
||||
Reference in New Issue
Block a user