diff --git a/addons/base_automation/models/base_automation.py b/addons/base_automation/models/base_automation.py
index 3695a82f55c..17be94a5664 100644
--- a/addons/base_automation/models/base_automation.py
+++ b/addons/base_automation/models/base_automation.py
@@ -25,6 +25,14 @@ DATE_RANGE_FUNCTION = {
False: lambda interval: relativedelta(0),
}
+DATE_RANGE_FACTOR = {
+ 'minutes': 1,
+ 'hour': 60,
+ 'day': 24 * 60,
+ 'month': 30 * 24 * 60,
+ False: 0,
+}
+
class BaseAutomation(models.Model):
_name = 'base.automation'
@@ -64,9 +72,11 @@ class BaseAutomation(models.Model):
trigger_field_ids = fields.Many2many('ir.model.fields', string='Trigger Fields',
help="The action will be triggered if and only if one of these fields is updated."
"If empty, all fields are watched.")
+ least_delay_msg = fields.Char(compute='_compute_least_delay_msg')
- # which fields have an impact on the registry
+ # which fields have an impact on the registry and the cron
CRITICAL_FIELDS = ['model_id', 'active', 'trigger', 'on_change_field_ids']
+ RANGE_FIELDS = ['trg_date_range', 'trg_date_range_type']
@api.onchange('model_id')
def onchange_model_id(self):
@@ -109,6 +119,8 @@ class BaseAutomation(models.Model):
if set(vals).intersection(self.CRITICAL_FIELDS):
self._update_cron()
self._update_registry()
+ elif set(vals).intersection(self.RANGE_FIELDS):
+ self._update_cron()
return res
def unlink(self):
@@ -119,10 +131,18 @@ class BaseAutomation(models.Model):
def _update_cron(self):
""" Activate the cron job depending on whether there exists action rules
- based on time conditions.
+ based on time conditions. Also update its frequency according to
+ the smallest action delay, or restore the default 4 hours if there
+ is no time based action.
"""
cron = self.env.ref('base_automation.ir_cron_data_base_automation_check', raise_if_not_found=False)
- return cron and cron.toggle(model=self._name, domain=[('trigger', '=', 'on_time')])
+ if cron:
+ actions = self.with_context(active_test=True).search([('trigger', '=', 'on_time')])
+ cron.try_write({
+ 'active': bool(actions),
+ 'interval_type': 'minutes',
+ 'interval_number': self._get_cron_interval(actions),
+ })
def _update_registry(self):
""" Update the registry after a modification on action rules. """
@@ -154,6 +174,22 @@ class BaseAutomation(models.Model):
'user': self.env.user,
}
+ def _get_cron_interval(self, actions=None):
+ """ Return the expected time interval used by the cron, in minutes. """
+ def get_delay(rec):
+ return rec.trg_date_range * DATE_RANGE_FACTOR[rec.trg_date_range_type]
+
+ if actions is None:
+ actions = self.with_context(active_test=True).search([('trigger', '=', 'on_time')])
+
+ # Minimum 1 minute, maximum 4 hours, 10% tolerance
+ delay = min(actions.mapped(get_delay), default=0)
+ return min(max(1, delay // 10), 4 * 60) if delay else 4 * 60
+
+ def _compute_least_delay_msg(self):
+ msg = _("Note that this action can be trigged up to %d minutes after its schedule.")
+ self.least_delay_msg = msg % self._get_cron_interval()
+
def _filter_pre(self, records):
""" Filter the records that satisfy the precondition of action ``self``. """
if self.filter_pre_domain and records:
diff --git a/addons/base_automation/views/base_automation_view.xml b/addons/base_automation/views/base_automation_view.xml
index 197459957fd..317ddfd8e3b 100644
--- a/addons/base_automation/views/base_automation_view.xml
+++ b/addons/base_automation/views/base_automation_view.xml
@@ -66,6 +66,11 @@
+
+
+
+
+