From 07caac0a0aac30a6b776caf87c95d908fe32bad8 Mon Sep 17 00:00:00 2001 From: Benoit Socias Date: Fri, 21 May 2021 10:00:20 +0000 Subject: [PATCH] [FIX] product: touch impacted products upon updating product templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, products relying on values of template fields (i.e. image) were not considered updated when their fallback template field was updated. After this commit, upon update of a template image, all products that would fallback on that template are "touched". This avoids side-effects such as displaying an outdated template image in the e-commerce for a given product. task-2477438 closes odoo/odoo#71139 Signed-off-by: Sébastien Theys (seb) --- addons/product/models/product_template.py | 6 ++++++ addons/product/tests/test_variants.py | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/addons/product/models/product_template.py b/addons/product/models/product_template.py index d96442d78a8..3586370cf63 100644 --- a/addons/product/models/product_template.py +++ b/addons/product/models/product_template.py @@ -441,6 +441,12 @@ class ProductTemplate(models.Model): 'image_128', 'can_image_1024_be_zoomed', ]) + # Touch all products that will fall back on the template field + # This is done because __last_update is used to compute the 'unique' SHA in image URLs + # for making sure that images are not retrieved from the browser cache after a change + # Performance discussion outcome: + # Actually touch all variants to avoid using filtered on the image_variant_1920 field + self.product_variant_ids.write({}) return res @api.returns('self', lambda value: value.id) diff --git a/addons/product/tests/test_variants.py b/addons/product/tests/test_variants.py index e952ad1abe4..573f5c06d18 100644 --- a/addons/product/tests/test_variants.py +++ b/addons/product/tests/test_variants.py @@ -3,6 +3,7 @@ import base64 from collections import OrderedDict +from datetime import timedelta import io from PIL import Image @@ -622,6 +623,13 @@ class TestVariantsImages(common.TestProductCommon): """Check that on variant, the image used is the image_variant_1920 if set, and defaults to the template image otherwise. """ + # Pretend setup happened in an older transaction by updating on the SQL layer and making sure it gets reloaded + # Using _write() instead of write() because write() only allows updating log access fields at boot time + self.variants._write({ + 'write_date': self.cr.now() - timedelta(milliseconds=1), + }) + self.variants.invalidate_cache(['write_date'], self.variants.ids) + f = io.BytesIO() Image.new('RGB', (800, 500), '#000000').save(f, 'PNG') f.seek(0) @@ -629,10 +637,12 @@ class TestVariantsImages(common.TestProductCommon): images = self.variants.mapped('image_1920') self.assertEqual(len(set(images)), 4) - variant_no_image = self.variants[0] + old_last_update = variant_no_image['__last_update'] + self.assertFalse(variant_no_image.image_1920) self.template.image_1920 = image_black + new_last_update = variant_no_image['__last_update'] # the first has no image variant, all the others do self.assertFalse(variant_no_image.image_variant_1920) @@ -643,6 +653,9 @@ class TestVariantsImages(common.TestProductCommon): # having changed the template image should not have changed these self.assertEqual(images[1:], self.variants.mapped('image_1920')[1:]) + # last update changed for the variant without image + self.assertLess(old_last_update, new_last_update) + def test_update_images_with_archived_variants(self): """Update images after variants have been archived""" self.variants[1:].write({'active': False})