From e6237ee1a0086601d7695cf835be68063064eee7 Mon Sep 17 00:00:00 2001 From: Sylvain LE GAL Date: Fri, 21 Sep 2018 10:55:50 +0200 Subject: [PATCH] [ADD] new module cron_inactivity_period (#1346) --- cron_inactivity_period/README.rst | 70 +++++++++++++ cron_inactivity_period/__init__.py | 2 + cron_inactivity_period/__openerp__.py | 26 +++++ cron_inactivity_period/demo/res_groups.xml | 13 +++ cron_inactivity_period/i18n/fr.po | 95 ++++++++++++++++++ cron_inactivity_period/models/__init__.py | 3 + cron_inactivity_period/models/ir_cron.py | 30 ++++++ .../models/ir_cron_inactivity_period.py | 63 ++++++++++++ .../security/ir.model.access.csv | 3 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/ir_cron_form.png | Bin 0 -> 26332 bytes cron_inactivity_period/tests/__init__.py | 2 + cron_inactivity_period/tests/test_module.py | 44 ++++++++ cron_inactivity_period/views/ir_cron.xml | 28 ++++++ 14 files changed, 379 insertions(+) create mode 100644 cron_inactivity_period/README.rst create mode 100644 cron_inactivity_period/__init__.py create mode 100644 cron_inactivity_period/__openerp__.py create mode 100644 cron_inactivity_period/demo/res_groups.xml create mode 100644 cron_inactivity_period/i18n/fr.po create mode 100644 cron_inactivity_period/models/__init__.py create mode 100644 cron_inactivity_period/models/ir_cron.py create mode 100644 cron_inactivity_period/models/ir_cron_inactivity_period.py create mode 100644 cron_inactivity_period/security/ir.model.access.csv create mode 100644 cron_inactivity_period/static/description/icon.png create mode 100644 cron_inactivity_period/static/description/ir_cron_form.png create mode 100644 cron_inactivity_period/tests/__init__.py create mode 100644 cron_inactivity_period/tests/test_module.py create mode 100644 cron_inactivity_period/views/ir_cron.xml diff --git a/cron_inactivity_period/README.rst b/cron_inactivity_period/README.rst new file mode 100644 index 000000000..a15ebc3de --- /dev/null +++ b/cron_inactivity_period/README.rst @@ -0,0 +1,70 @@ +.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: https://www.gnu.org/licenses/agpl + :alt: License: AGPL-3 + +======================== +Cron - Inactivity Period +======================== + + +This module allows you to disable cron Jobs during periods. +It can be usefull if you want to disable your cron jobs during maintenance +period, or for other reasons. + +Note +---- + +If you have installed ``cron_run_manually`` module, it is still possible to run +your job, during inactivity periods. + +Configuration +============= + +To configure this module, you need to: + +#. Go to Settings > Technical > Automation > Scheduled Actions and select a + cron +#. Add new option inactivity periods + +.. figure:: https://raw.githubusercontent.com/OCA/server-tools/8.0/cron_inactivity_period/static/description/ir_cron_form.png + :alt: Inactivity Period Settings + :width: 80 % + :align: center + + +Known issues / Roadmap +====================== + +* For the time being, only one type of inactivity period is available. ('hour') + It should be great to add other options like 'week_day', to allow user to + disable cron jobs for given week days. + + +Credits +======= + +Authors +~~~~~~~ + +* GRAP, Groupement Régional Alimentaire de Proximité (http://www.grap.coop) + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL (https://www.twitter.com/legalsylvain) + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. + diff --git a/cron_inactivity_period/__init__.py b/cron_inactivity_period/__init__.py new file mode 100644 index 000000000..042e239ed --- /dev/null +++ b/cron_inactivity_period/__init__.py @@ -0,0 +1,2 @@ +# coding: utf-8 +from . import models diff --git a/cron_inactivity_period/__openerp__.py b/cron_inactivity_period/__openerp__.py new file mode 100644 index 000000000..6d5fe9f3a --- /dev/null +++ b/cron_inactivity_period/__openerp__.py @@ -0,0 +1,26 @@ +# coding: utf-8 +# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +{ + 'name': 'Inactivity Periods for Cron Jobs', + 'version': '8.0.1.0.0', + 'author': "GRAP,Odoo Community Association (OCA)", + 'license': 'AGPL-3', + 'category': 'Tools', + 'depends': [ + 'base', + ], + 'data': [ + 'security/ir.model.access.csv', + 'views/ir_cron.xml', + ], + 'demo': [ + 'demo/res_groups.xml', + ], + 'images': [ + 'static/description/ir_cron_form.png', + ], + 'installable': True, +} diff --git a/cron_inactivity_period/demo/res_groups.xml b/cron_inactivity_period/demo/res_groups.xml new file mode 100644 index 000000000..86277adc1 --- /dev/null +++ b/cron_inactivity_period/demo/res_groups.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/cron_inactivity_period/i18n/fr.po b/cron_inactivity_period/i18n/fr.po new file mode 100644 index 000000000..fb424b5bb --- /dev/null +++ b/cron_inactivity_period/i18n/fr.po @@ -0,0 +1,95 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * cron_inactivity_period +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-24 09:48+0000\n" +"PO-Revision-Date: 2018-08-24 09:48+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,inactivity_hour_begin:0 +msgid "Begin Hour" +msgstr "Heure de début" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,create_uid:0 +msgid "Created by" +msgstr "crééé par" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,create_date:0 +msgid "Created on" +msgstr "Créé le" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,cron_id:0 +msgid "Cron id" +msgstr "Cron id" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,display_name:0 +msgid "Display Name" +msgstr "Nom affiché" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,inactivity_hour_end:0 +msgid "End Hour" +msgstr "Heure de fin" + +#. module: cron_inactivity_period +#: selection:ir.cron.inactivity.period,type:0 +msgid "Hour" +msgstr "Heure" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,id:0 +msgid "ID" +msgstr "ID" + +#. module: cron_inactivity_period +#: view:ir.cron:cron_inactivity_period.view_ir_cron_form +#: field:ir.cron,inactivity_period_ids:0 +msgid "Inactivity Periods" +msgstr "Périodes d'inactivité" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,__last_update:0 +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,write_uid:0 +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,write_date:0 +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: cron_inactivity_period +#: code:addons/cron_inactivity_period/models/ir_cron_inactivity_period.py:36 +#, python-format +msgid "The End Hour should be greater than the Begin Hour" +msgstr "L'heure de fin doit être strictement supérieure à l'heure de début" + +#. module: cron_inactivity_period +#: field:ir.cron.inactivity.period,type:0 +msgid "Type" +msgstr "Type" + +#. module: cron_inactivity_period +#: code:addons/cron_inactivity_period/models/ir_cron_inactivity_period.py:62 +#, python-format +msgid "Unimplemented Feature: Inactivity Period type '%s'" +msgstr "Fonctionnalité non implémentée : Période d'inactivité de type '%s'" + diff --git a/cron_inactivity_period/models/__init__.py b/cron_inactivity_period/models/__init__.py new file mode 100644 index 000000000..c100f22be --- /dev/null +++ b/cron_inactivity_period/models/__init__.py @@ -0,0 +1,3 @@ +# coding: utf-8 +from . import ir_cron +from . import ir_cron_inactivity_period diff --git a/cron_inactivity_period/models/ir_cron.py b/cron_inactivity_period/models/ir_cron.py new file mode 100644 index 000000000..1f86ab94d --- /dev/null +++ b/cron_inactivity_period/models/ir_cron.py @@ -0,0 +1,30 @@ +# coding: utf-8 +# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from openerp import api, fields, models + + +_logger = logging.getLogger(__name__) + + +class IrCron(models.Model): + _inherit = 'ir.cron' + + inactivity_period_ids = fields.One2many( + comodel_name='ir.cron.inactivity.period', string='Inactivity Periods', + inverse_name='cron_id') + + @api.model + def _callback(self, model_name, method_name, args, job_id): + job = self.browse(job_id) + if any(job.inactivity_period_ids._check_inactivity_period()): + _logger.info( + "Job %s skipped during inactivity period", + job.name) + return + return super(IrCron, self)._callback( + model_name, method_name, args, job_id) diff --git a/cron_inactivity_period/models/ir_cron_inactivity_period.py b/cron_inactivity_period/models/ir_cron_inactivity_period.py new file mode 100644 index 000000000..a6a0ccbb4 --- /dev/null +++ b/cron_inactivity_period/models/ir_cron_inactivity_period.py @@ -0,0 +1,63 @@ +# coding: utf-8 +# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from datetime import datetime + +from openerp import _, api, fields, models +from openerp.exceptions import Warning as UserError + + +class IrCronInactivityPeriod(models.Model): + _name = 'ir.cron.inactivity.period' + + _SELECTION_TYPE = [ + ('hour', 'Hour'), + ] + + cron_id = fields.Many2one( + comodel_name='ir.cron', ondelete='cascade', required=True) + + type = fields.Selection( + string='Type', selection=_SELECTION_TYPE, + required=True, default='hour') + + inactivity_hour_begin = fields.Float( + string='Begin Hour', default=0) + + inactivity_hour_end = fields.Float( + string='End Hour', default=1) + + @api.constrains('inactivity_hour_begin', 'inactivity_hour_end') + def _check_activity_hour(self): + for period in self: + if period.inactivity_hour_begin >= period.inactivity_hour_end: + raise UserError(_( + "The End Hour should be greater than the Begin Hour")) + + @api.multi + def _check_inactivity_period(self): + res = [] + for period in self: + res.append(period._check_inactivity_period_one()) + return res + + @api.multi + def _check_inactivity_period_one(self): + self.ensure_one() + now = fields.Datetime.context_timestamp(self, datetime.now()) + if self.type == 'hour': + begin_inactivity = now.replace( + hour=int(self.inactivity_hour_begin), + minute=int((self.inactivity_hour_begin % 1) * 60), + second=0) + end_inactivity = now.replace( + hour=int(self.inactivity_hour_end), + minute=int((self.inactivity_hour_end % 1) * 60), + second=0) + return now >= begin_inactivity and now < end_inactivity + else: + raise UserError( + _("Unimplemented Feature: Inactivity Period type '%s'") % ( + self.type)) diff --git a/cron_inactivity_period/security/ir.model.access.csv b/cron_inactivity_period/security/ir.model.access.csv new file mode 100644 index 000000000..d44bc01dd --- /dev/null +++ b/cron_inactivity_period/security/ir.model.access.csv @@ -0,0 +1,3 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_ir_cron_inactivity_period_user,access_ir_cron_inactivity_period_user,model_ir_cron_inactivity_period,base.group_user,1,,, +access_ir_cron_inactivity_period_manager,access_ir_cron_inactivity_period_manager,model_ir_cron_inactivity_period,base.group_system,1,1,1,1 diff --git a/cron_inactivity_period/static/description/icon.png b/cron_inactivity_period/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/cron_inactivity_period/static/description/ir_cron_form.png b/cron_inactivity_period/static/description/ir_cron_form.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc67389b70d235bf23c7da0ad8512ac4ddddfce GIT binary patch literal 26332 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�|^)Z#YNbtkq_@F_#{Uc;M}2C0HuEMk%J<$m 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 V2d)nhZlWOp=osCrz5D#_{{T>8YnuQ7 literal 0 HcmV?d00001 diff --git a/cron_inactivity_period/tests/__init__.py b/cron_inactivity_period/tests/__init__.py new file mode 100644 index 000000000..17b82062c --- /dev/null +++ b/cron_inactivity_period/tests/__init__.py @@ -0,0 +1,2 @@ +# coding: utf-8 +from . import test_module diff --git a/cron_inactivity_period/tests/test_module.py b/cron_inactivity_period/tests/test_module.py new file mode 100644 index 000000000..a54bae61c --- /dev/null +++ b/cron_inactivity_period/tests/test_module.py @@ -0,0 +1,44 @@ +# coding: utf-8 +# Copyright (C) 2018 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from openerp.tests.common import TransactionCase + + +class TestModule(TransactionCase): + """Tests for 'Cron - Inactivity Period' Module""" + + def setUp(self): + super(TestModule, self).setUp() + self.config_obj = self.env['res.config'] + self.cron_obj = self.env['ir.cron'] + self.inactivity_period = self.env['ir.cron.inactivity.period'] + self.cron_job = self.env.ref('base.cronjob_osv_memory_autovacuum') + + # Test Section + def test_01_no_inactivity_period(self): + count = self._create_transient_model() + self.assertEqual( + count, 0, + "Calling a cron without inactivity period should run the cron") + + def test_02_no_activity_period(self): + self.inactivity_period.create({ + 'cron_id': self.cron_job.id, + 'type': 'hour', + 'inactivity_hour_begin': 0.0, + 'inactivity_hour_end': 23.59, + }) + count = self._create_transient_model() + self.assertEqual( + count, 1, + "Calling a cron with inactivity period should not run the cron") + + def _create_transient_model(self): + self.config_obj.search([]).unlink() + self.config_obj.create({}) + self.env.cr.execute("update res_config set write_date = '1970-01-01'") + self.cron_obj._callback( + 'osv_memory.autovacuum', 'power_on', (), self.cron_job.id) + return len(self.config_obj.search([])) diff --git a/cron_inactivity_period/views/ir_cron.xml b/cron_inactivity_period/views/ir_cron.xml new file mode 100644 index 000000000..016461e4b --- /dev/null +++ b/cron_inactivity_period/views/ir_cron.xml @@ -0,0 +1,28 @@ + + + + + + ir.cron + + + + + + + + + + + + + + + + + +