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 - () - Check membership payment + Membership: update memberships + + code + model._cron_update_membership() days -1 - res.partner - _cron_update_membership 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 @@ - - - Fetch new Twitter favorites - 2 - hours - -1 - - website - _refresh_favorite_tweets - () - - + + Twitter: Fetch new favorites + + code + model._refresh_favorite_tweets() + 2 + hours + -1 + + 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 + -
-
-
- - - - - - + +