diff --git a/addons/account_asset/data/account_asset_data.xml b/addons/account_asset/data/account_asset_data.xml
index f858fbb2237..3f9a28987df 100644
--- a/addons/account_asset/data/account_asset_data.xml
+++ b/addons/account_asset/data/account_asset_data.xml
@@ -1,13 +1,13 @@
-
- Generate Asset Entries
+
+ Account Asset: Generate asset entries
+
+ code
+ model._cron_generate_entries()
1
months
-1
-
-
-
\ No newline at end of file
diff --git a/addons/base_action_rule/data/base_action_rule_data.xml b/addons/base_action_rule/data/base_action_rule_data.xml
index afcc01447a4..3e3604ead62 100644
--- a/addons/base_action_rule/data/base_action_rule_data.xml
+++ b/addons/base_action_rule/data/base_action_rule_data.xml
@@ -1,18 +1,16 @@
-
-
- Check Action Rules
+
+ Base Action Rule: check and execute
+
+ code
+ model._check(True)
4
hours
-1
-
-
-
-
diff --git a/addons/base_action_rule/models/base_action_rule.py b/addons/base_action_rule/models/base_action_rule.py
index 7f13bf9f3ef..84100a1cc1e 100644
--- a/addons/base_action_rule/models/base_action_rule.py
+++ b/addons/base_action_rule/models/base_action_rule.py
@@ -119,7 +119,7 @@ class BaseActionRule(models.Model):
""" Activate the cron job depending on whether there exists action rules
based on time conditions.
"""
- cron = self.env.ref('base_action_rule.ir_cron_crm_action', raise_if_not_found=False)
+ cron = self.env.ref('base_action_rule.ir_cron_data_bar_check', raise_if_not_found=False)
return cron and cron.toggle(model=self._name, domain=[('kind', '=', 'on_time')])
def _update_registry(self):
diff --git a/addons/base_gengo/data/ir_cron_data.xml b/addons/base_gengo/data/ir_cron_data.xml
index a88cc78910e..20d62c5db57 100644
--- a/addons/base_gengo/data/ir_cron_data.xml
+++ b/addons/base_gengo/data/ir_cron_data.xml
@@ -3,28 +3,26 @@
- Gengo Sync Translation (Response)
-
+ Gengo: Sync translation (Response)
+
+ code
+ model._sync_response(20)
6
hours
-1
-
-
-
- Gengo Sync Translation (Request)
-
+ Gengo: Sync translation (Request)
+
+ code
+ model._sync_request(20)
6
hours
-1
-
-
-
diff --git a/addons/calendar/data/calendar_cron.xml b/addons/calendar/data/calendar_cron.xml
index 09cda419a54..f195dce4d1e 100644
--- a/addons/calendar/data/calendar_cron.xml
+++ b/addons/calendar/data/calendar_cron.xml
@@ -3,16 +3,16 @@
- Run Event Reminder
+ Calendar: Event Reminder
+
+ code
+ model.get_next_mail()
30
minutes
-1
-
-
-
\ No newline at end of file
diff --git a/addons/event/data/event_data.xml b/addons/event/data/event_data.xml
index 3232b5514a4..b4c1070bf0d 100644
--- a/addons/event/data/event_data.xml
+++ b/addons/event/data/event_data.xml
@@ -13,16 +13,15 @@
- [event] mail scheduler
- True
+ Event: Mail Scheduler
+
+ code
+ model.run(True)
1
hours
-1
-
- event.mail
- run
diff --git a/addons/fetchmail/data/fetchmail_data.xml b/addons/fetchmail/data/fetchmail_data.xml
index 34469793c6e..d98c3d1f92f 100644
--- a/addons/fetchmail/data/fetchmail_data.xml
+++ b/addons/fetchmail/data/fetchmail_data.xml
@@ -2,14 +2,14 @@
- Fetchmail Service
+ Mail: Fetchmail Service
+
+ code
+ model._fetch_mails()
5
minutes
-1
- fetchmail.server
- _fetch_mails
- ()
diff --git a/addons/fleet/data/fleet_data.xml b/addons/fleet/data/fleet_data.xml
index 0d9a4640f2b..3ba311c878e 100644
--- a/addons/fleet/data/fleet_data.xml
+++ b/addons/fleet/data/fleet_data.xml
@@ -1,16 +1,15 @@
- Generation of contracts costs based on the costs frequency
-
+ Fleet: Generate contracts costs based on costs frequency
+
+ code
+ model.run_scheduler()
1
days
-1
-
-
-
diff --git a/addons/gamification/data/cron.xml b/addons/gamification/data/cron.xml
index 6e273ef4405..0ed59d39e11 100644
--- a/addons/gamification/data/cron.xml
+++ b/addons/gamification/data/cron.xml
@@ -1,15 +1,14 @@
-
- Run Goal Challenge Checker
+
+ Gamification: Goal Challenge Check
+
+ code
+ model._cron_update()
1
days
-1
- gamification.challenge
- _cron_update
- ()
diff --git a/addons/google_calendar/data/google_calendar_data.xml b/addons/google_calendar/data/google_calendar_data.xml
index 3fc26e25351..42b583cf7da 100644
--- a/addons/google_calendar/data/google_calendar_data.xml
+++ b/addons/google_calendar/data/google_calendar_data.xml
@@ -2,15 +2,15 @@
- Calendar synchronization
-
+ Google Calendar: synchronization
+
+ code
+ model.synchronize_events_cron()
12
hours
-1
-
-
\ No newline at end of file
diff --git a/addons/mail/data/mail_data.xml b/addons/mail/data/mail_data.xml
index aa4cae02f30..6db20b0f592 100644
--- a/addons/mail/data/mail_data.xml
+++ b/addons/mail/data/mail_data.xml
@@ -2,29 +2,28 @@
- Email Queue Manager
+ Mail: Email Queue Manager
+
+ code
+ model.process_email_queue()
1
hours
-1
-
-
-
- Update Notification
-
+ Publisher: Update Notification
+
+ code
+ model.update_notification(None)
1
weeks
-1
-
-
-
1000
diff --git a/addons/maintenance/data/maintenance_cron.xml b/addons/maintenance/data/maintenance_cron.xml
index 141ae9757c3..4345cca6216 100644
--- a/addons/maintenance/data/maintenance_cron.xml
+++ b/addons/maintenance/data/maintenance_cron.xml
@@ -1,13 +1,13 @@
- Generate preventive maintenance requests
+ Maintenance: generate preventive maintenance requests
+
+ code
+ model._cron_generate_requests()
1
days
-1
-
-
-
\ No newline at end of file
diff --git a/addons/marketing_campaign/data/marketing_campaign_data.xml b/addons/marketing_campaign/data/marketing_campaign_data.xml
index 986b58508c9..6e92b7ab1e7 100644
--- a/addons/marketing_campaign/data/marketing_campaign_data.xml
+++ b/addons/marketing_campaign/data/marketing_campaign_data.xml
@@ -3,27 +3,26 @@
-
Marketing Campaign: Campaign workitems processing
+
+ code
+ model.process_all()
1
hours
-1
-
-
-
Marketing Campaign: Segment Sync
+
+ code
+ model.process_segment()
1
days
-1
-
-
-
diff --git a/addons/mass_mailing/views/mass_mailing_views.xml b/addons/mass_mailing/views/mass_mailing_views.xml
index 3c15424e9f7..36748205c52 100644
--- a/addons/mass_mailing/views/mass_mailing_views.xml
+++ b/addons/mass_mailing/views/mass_mailing_views.xml
@@ -794,17 +794,16 @@
-
- Process Mass Mailing Queue
-
+
+ Mass Mailing: Process queue
+
+ code
+ model._process_mass_mailing_queue()
60
minutes
-1
- mail.mass_mailing
- _process_mass_mailing_queue
- ()
diff --git a/addons/pos_cache/data/pos_cache_data.xml b/addons/pos_cache/data/pos_cache_data.xml
index 709e6edea35..8bb58b41a4a 100644
--- a/addons/pos_cache/data/pos_cache_data.xml
+++ b/addons/pos_cache/data/pos_cache_data.xml
@@ -2,15 +2,15 @@
- Refresh POS Cache
+ PoS: refresh cache
+
+ code
+ model.refresh_all_caches()
1
hours
-1
-
-
-
diff --git a/addons/procurement/data/procurement_data.xml b/addons/procurement/data/procurement_data.xml
index 9003b860efd..3538b404f7d 100644
--- a/addons/procurement/data/procurement_data.xml
+++ b/addons/procurement/data/procurement_data.xml
@@ -1,18 +1,18 @@
-
+
- Run mrp scheduler
+ Procurement: run MRP scheduler
+
+ code
+ model.run_scheduler(True)
1
days
-1
-
-
-
diff --git a/addons/rating_project/data/project_data.xml b/addons/rating_project/data/project_data.xml
index d60e24ef33c..3a6146b229c 100644
--- a/addons/rating_project/data/project_data.xml
+++ b/addons/rating_project/data/project_data.xml
@@ -2,11 +2,12 @@
- Send Customer Rating Forms
+ Project: Send rating
+
+ code
+ model._send_rating_all()
days
-1
- project.project
- _send_rating_all
diff --git a/addons/website_twitter/data/website_twitter_data.xml b/addons/website_twitter/data/website_twitter_data.xml
index 470fdddc6a2..fca63620cda 100644
--- a/addons/website_twitter/data/website_twitter_data.xml
+++ b/addons/website_twitter/data/website_twitter_data.xml
@@ -1,16 +1,14 @@
-
-
-
+
diff --git a/odoo/addons/base/ir/ir_actions.py b/odoo/addons/base/ir/ir_actions.py
index 7c4b14f898d..d66abd39c67 100644
--- a/odoo/addons/base/ir/ir_actions.py
+++ b/odoo/addons/base/ir/ir_actions.py
@@ -458,7 +458,8 @@ class IrActionsServer(models.Model):
name = fields.Char(string='Action Name', translate=True)
type = fields.Char(default='ir.actions.server')
usage = fields.Selection([
- ('ir_actions_server', 'Server Action')], string='Usage',
+ ('ir_actions_server', 'Server Action'),
+ ('ir_cron', 'Scheduled Action')], string='Usage',
default='ir_actions_server', required=True)
state = fields.Selection([
('code', 'Execute Python Code'),
diff --git a/odoo/addons/base/ir/ir_autovacuum.xml b/odoo/addons/base/ir/ir_autovacuum.xml
index 1e015c89395..52e07855b63 100644
--- a/odoo/addons/base/ir/ir_autovacuum.xml
+++ b/odoo/addons/base/ir/ir_autovacuum.xml
@@ -1,13 +1,12 @@
-
- Auto-vacuum internal data
- 1
- days
- -1
- True
- ir.autovacuum
- power_on
- ()
-
+
+ Base: Auto-vacuum internal data
+
+ code
+ model.power_on()
+ 1
+ days
+ -1
+
diff --git a/odoo/addons/base/ir/ir_cron.py b/odoo/addons/base/ir/ir_cron.py
index 12927e93bdb..cf8f7d97a26 100644
--- a/odoo/addons/base/ir/ir_cron.py
+++ b/odoo/addons/base/ir/ir_cron.py
@@ -10,17 +10,13 @@ from dateutil.relativedelta import relativedelta
import odoo
from odoo import api, fields, models, _
-from odoo.exceptions import UserError, ValidationError
-from odoo.tools.safe_eval import safe_eval
+from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
BASE_VERSION = odoo.modules.load_information_from_description_file('base')['version']
-def str2tuple(s):
- return safe_eval('tuple(%s)' % (s or ''))
-
_intervalTypes = {
'days': lambda interval: relativedelta(days=interval),
'hours': lambda interval: relativedelta(hours=interval),
@@ -40,9 +36,12 @@ class ir_cron(models.Model):
# See also odoo.cron
_name = "ir.cron"
- _order = 'name'
+ _order = 'cron_name'
- name = fields.Char(required=True)
+ ir_actions_server_id = fields.Many2one(
+ 'ir.actions.server', 'Server action',
+ delegate=True, ondelete='restrict', required=True)
+ cron_name = fields.Char('Name', related='ir_actions_server_id.name', store=True)
user_id = fields.Many2one('res.users', string='User', default=lambda self: self.env.user, required=True)
active = fields.Boolean(default=True)
interval_number = fields.Integer(default=1, help="Repeat every x.")
@@ -54,77 +53,50 @@ class ir_cron(models.Model):
numbercall = fields.Integer(string='Number of Calls', default=1, help='How many times the method is called,\na negative number indicates no limit.')
doall = fields.Boolean(string='Repeat Missed', help="Specify if missed occurrences should be executed when the server restarts.")
nextcall = fields.Datetime(string='Next Execution Date', required=True, default=fields.Datetime.now, help="Next planned execution date for this job.")
- model = fields.Char(string='Object', help="Model name on which the method to be called is located, e.g. 'res.partner'.")
- function = fields.Char(string='Method', help="Name of the method to be called when this job is processed.")
- args = fields.Text(string='Arguments', help="Arguments to be passed to the method, e.g. (uid,).")
priority = fields.Integer(default=5, help='The priority of the job, as an integer: 0 means higher priority, 10 means lower priority.')
- @api.constrains('args')
- def _check_args(self):
- try:
- for this in self:
- str2tuple(this.args)
- except Exception:
- raise ValidationError(_('Invalid arguments'))
+ @api.model
+ def create(self, values):
+ values['usage'] = 'ir_cron'
+ return super(ir_cron, self).create(values)
@api.multi
def method_direct_trigger(self):
for cron in self:
- self.sudo(user=cron.user_id.id)._callback(cron.model, cron.function, cron.args, cron.id)
+ self.sudo(user=cron.user_id.id).ir_actions_server_id.run()
return True
@api.model
- def _handle_callback_exception(self, model_name, method_name, args, job_id, job_exception):
+ def _handle_callback_exception(self, cron_name, server_action_id, job_id, job_exception):
""" Method called when an exception is raised by a job.
- Simply logs the exception and rollback the transaction.
-
- :param model_name: model name on which the job method is located.
- :param method_name: name of the method to call when this job is processed.
- :param args: arguments of the method (without the usual self, cr, uid).
- :param job_id: job id.
- :param job_exception: exception raised by the job.
-
- """
+ Simply logs the exception and rollback the transaction. """
self._cr.rollback()
- _logger.exception("Call of self.env[%r].%s(*%r) failed in Job %s",
- model_name, method_name, args, job_id)
+ _logger.exception("Call from cron %s for server action %d failed in Job %s",
+ cron_name, server_action_id, job_id)
@api.model
- def _callback(self, model_name, method_name, args, job_id):
- """ Run the method associated to a given job
-
- It takes care of logging and exception handling.
-
- :param model_name: model name on which the job method is located.
- :param method_name: name of the method to call when this job is processed.
- :param args: arguments of the method (without the usual self, cr, uid).
- :param job_id: job id.
- """
+ def _callback(self, cron_name, server_action_id, job_id):
+ """ Run the method associated to a given job. It takes care of logging
+ and exception handling. Note that the user running the server action
+ is the user calling this method. """
try:
- args = str2tuple(args)
if self.pool != self.pool.check_signaling():
# the registry has changed, reload self in the new registry
self.env.reset()
self = self.env()[self._name]
- if model_name in self.env:
- model = self.env[model_name]
- if hasattr(model, method_name):
- log_depth = (None if _logger.isEnabledFor(logging.DEBUG) else 1)
- odoo.netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (self._cr.dbname, self._uid, '*', model_name, method_name)+tuple(args), depth=log_depth)
- if _logger.isEnabledFor(logging.DEBUG):
- start_time = time.time()
- getattr(model, method_name)(*args)
- if _logger.isEnabledFor(logging.DEBUG):
- end_time = time.time()
- _logger.debug('%.3fs (%s, %s)', end_time - start_time, model_name, method_name)
- self.pool.signal_caches_change()
- else:
- _logger.warning("Method '%s.%s' does not exist.", model_name, method_name)
- else:
- _logger.warning("Model %r does not exist.", model_name)
+
+ log_depth = (None if _logger.isEnabledFor(logging.DEBUG) else 1)
+ odoo.netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (self._cr.dbname, self._uid, '*', cron_name, server_action_id), depth=log_depth)
+ if _logger.isEnabledFor(logging.DEBUG):
+ start_time = time.time()
+ self.env['ir.actions.server'].browse(server_action_id).run()
+ if _logger.isEnabledFor(logging.DEBUG):
+ end_time = time.time()
+ _logger.debug('%.3fs (cron %s, server action %d with uid %d)', end_time - start_time, cron_name, server_action_id, self.env.uid)
+ self.pool.signal_caches_change()
except Exception, e:
- self._handle_callback_exception(model_name, method_name, args, job_id, e)
+ self._handle_callback_exception(cron_name, server_action_id, job_id, e)
@classmethod
def _process_job(cls, job_cr, job, cron_cr):
@@ -151,7 +123,7 @@ class ir_cron(models.Model):
if numbercall > 0:
numbercall -= 1
if not ok or job['doall']:
- cron._callback(job['model'], job['function'], job['args'], job['id'])
+ cron._callback(job['cron_name'], job['ir_actions_server_id'], job['id'])
if numbercall:
nextcall += _intervalTypes[job['interval_type']](job['interval_number'])
ok = True
@@ -223,10 +195,10 @@ class ir_cron(models.Model):
locked_job = lock_cr.fetchone()
if not locked_job:
- _logger.debug("Job `%s` already executed by another process/thread. skipping it", job['name'])
+ _logger.debug("Job `%s` already executed by another process/thread. skipping it", job['cron_name'])
continue
# Got the lock on the job row, run its code
- _logger.debug('Starting job `%s`.', job['name'])
+ _logger.debug('Starting job `%s`.', job['cron_name'])
job_cr = db.cursor()
try:
registry = odoo.registry(db_name)
@@ -239,7 +211,7 @@ class ir_cron(models.Model):
except psycopg2.OperationalError, e:
if e.pgcode == '55P03':
# Class 55: Object not in prerequisite state; 55P03: lock_not_available
- _logger.debug('Another process/thread is already busy executing job `%s`, skipping it.', job['name'])
+ _logger.debug('Another process/thread is already busy executing job `%s`, skipping it.', job['cron_name'])
continue
else:
# Unexpected OperationalError
diff --git a/odoo/addons/base/ir/ir_cron_view.xml b/odoo/addons/base/ir/ir_cron_view.xml
index 57232252696..045fa688ef3 100644
--- a/odoo/addons/base/ir/ir_cron_view.xml
+++ b/odoo/addons/base/ir/ir_cron_view.xml
@@ -1,42 +1,28 @@
-
+
+ ir.cron.view.form
ir.cron
+ primary
+
-
+
diff --git a/odoo/addons/base/tests/test_search.py b/odoo/addons/base/tests/test_search.py
index 8fba34ca025..d52cd9db9c4 100644
--- a/odoo/addons/base/tests/test_search.py
+++ b/odoo/addons/base/tests/test_search.py
@@ -105,7 +105,7 @@ class test_search(TransactionCase):
cron_ids = {}
for u in 'BAC':
user_ids[u] = Users.create({'name': u, 'login': u}).id
- cron_ids[u] = Cron.create({'name': u, 'user_id': user_ids[u]}).id
+ cron_ids[u] = Cron.create({'name': u, 'model_id': self.env.ref('base.model_res_partner').id, 'user_id': user_ids[u]}).id
ids = Cron.search([('id', 'in', cron_ids.values())], order='user_id').ids
expected_ids = [cron_ids[l] for l in 'ABC']