diff --git a/modules/web_shop_product_data_feed/CHANGELOG b/modules/web_shop_product_data_feed/CHANGELOG index 68b4ef56de..4f00d97968 100644 --- a/modules/web_shop_product_data_feed/CHANGELOG +++ b/modules/web_shop_product_data_feed/CHANGELOG @@ -1,3 +1,4 @@ +* Add scheduled task to update cached feeds Version 7.2.0 - 2024-04-29 -------------------------- diff --git a/modules/web_shop_product_data_feed/__init__.py b/modules/web_shop_product_data_feed/__init__.py index 4500ca3f19..4ec9c03aaf 100644 --- a/modules/web_shop_product_data_feed/__init__.py +++ b/modules/web_shop_product_data_feed/__init__.py @@ -3,13 +3,14 @@ from trytond.pool import Pool -from . import product, routes, web +from . import ir, product, routes, web __all__ = ['register', 'routes'] def register(): Pool.register( + ir.Cron, product.UoM, product.Template, product.Product, diff --git a/modules/web_shop_product_data_feed/doc/usage.rst b/modules/web_shop_product_data_feed/doc/usage.rst index 06ac749d9c..b09a5df9b9 100644 --- a/modules/web_shop_product_data_feed/doc/usage.rst +++ b/modules/web_shop_product_data_feed/doc/usage.rst @@ -2,6 +2,16 @@ Usage ***** +.. _Scheduling Product Data Feed updates: + +Scheduling Product Data Feed updates +==================================== + +You may want to define some "Scheduled tasks" :guilabel:`Update Web Shop +Product Data Feed` to keep the cache of the feeds up to date. +The task updates each feed already in the cache if their last modification was +before half of the `cache duration `. + .. _Fill Google Product Category: Fill Google Product Category diff --git a/modules/web_shop_product_data_feed/ir.py b/modules/web_shop_product_data_feed/ir.py new file mode 100644 index 0000000000..23c6c29214 --- /dev/null +++ b/modules/web_shop_product_data_feed/ir.py @@ -0,0 +1,15 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. + +from trytond.pool import PoolMeta + + +class Cron(metaclass=PoolMeta): + __name__ = 'ir.cron' + + @classmethod + def __setup__(cls): + super().__setup__() + cls.method.selection.append( + ('web.shop|update_product_data_feed_csv', + "Update Web Shop Product Data Feed")) diff --git a/modules/web_shop_product_data_feed/tests/test_module.py b/modules/web_shop_product_data_feed/tests/test_module.py index 85d6dfcee9..8809cbb5c3 100644 --- a/modules/web_shop_product_data_feed/tests/test_module.py +++ b/modules/web_shop_product_data_feed/tests/test_module.py @@ -4,7 +4,7 @@ import os import tempfile from decimal import Decimal -from unittest.mock import Mock, patch +from unittest.mock import ANY, Mock, patch from trytond.modules.account.tests import create_chart from trytond.modules.company.tests import create_company, set_company @@ -133,6 +133,12 @@ class WebShopProductDataFeedTestCase(ModuleTestCase): os.path.dirname(__file__), 'google-products.csv')).read()) + with patch.object(Shop, 'product_data_feed_csv') as feed: + Shop.update_product_data_feed_csv() + + feed.assert_called_once_with( + 'google', language=None, duration=ANY) + class WebShopProductDataFeedRouteTestCase(RouteTestCase): "Test Web Shop Product Data Feed route" diff --git a/modules/web_shop_product_data_feed/web.py b/modules/web_shop_product_data_feed/web.py index cd7061b38b..533fee0550 100644 --- a/modules/web_shop_product_data_feed/web.py +++ b/modules/web_shop_product_data_feed/web.py @@ -2,6 +2,7 @@ # this repository contains the full copyright notices and license terms. import csv +import fnmatch import os import shutil import tempfile @@ -75,7 +76,25 @@ class Shop(metaclass=PoolMeta): context['language'] = language return context - def product_data_feed_csv(self, format, language=None): + @classmethod + def update_product_data_feed_csv(cls, shops=None): + if shops is None: + shops = cls.search([]) + + directory = _get_directory() + for shop in shops: + for name in fnmatch.filter( + os.listdir(directory), + f'{shop.name}-{shop.id}-*.csv'): + name = name[len(f'{shop.name}-{shop.id}-'):-len('.csv')] + if '-' in name: + format, language = name.rsplit('-', 1) + else: + format, language = name, None + shop.product_data_feed_csv( + format, language=language, duration=_duration / 2) + + def product_data_feed_csv(self, format, language=None, duration=_duration): transaction = Transaction() directory = _get_directory() if language: @@ -85,10 +104,12 @@ class Shop(metaclass=PoolMeta): filename = os.path.join(directory, filename) try: - if (time.time() - os.path.getmtime(filename)) < _duration: + if (time.time() - os.path.getmtime(filename)) < duration: return filename except OSError: - pass + # Create the file so cron will update it + # even if this generation fails + open(filename, 'a').close() with transaction.set_context(_product_data_language=language): products, prices, taxes = self.get_products()