From b880b2a0250c67ae9e69d562a310966c5c21f58a Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Tue, 9 Jul 2019 09:42:36 +0200 Subject: [PATCH 01/47] [ADD] queue_job_batch [UPD] Update queue_job_batch.pot --- queue_job_batch/README.rst | 118 +++++ queue_job_batch/__init__.py | 1 + queue_job_batch/__manifest__.py | 24 + queue_job_batch/i18n/queue_job_batch.pot | 185 +++++++ queue_job_batch/models/__init__.py | 2 + queue_job_batch/models/queue_job.py | 37 ++ queue_job_batch/models/queue_job_batch.py | 126 +++++ queue_job_batch/readme/CONTRIBUTORS.rst | 1 + queue_job_batch/readme/DESCRIPTION.rst | 40 ++ queue_job_batch/readme/USAGE.rst | 2 + queue_job_batch/security/ir.model.access.csv | 4 + queue_job_batch/security/security.xml | 43 ++ queue_job_batch/static/description/icon.png | Bin 0 -> 1803 bytes queue_job_batch/static/description/icon.svg | 127 +++++ queue_job_batch/static/description/index.html | 458 ++++++++++++++++++ queue_job_batch/static/src/js/systray.js | 139 ++++++ queue_job_batch/static/src/less/systray.less | 44 ++ queue_job_batch/static/src/xml/systray.xml | 62 +++ queue_job_batch/views/assets_backend.xml | 10 + .../views/queue_job_batch_views.xml | 98 ++++ queue_job_batch/views/queue_job_views.xml | 37 ++ 21 files changed, 1558 insertions(+) create mode 100644 queue_job_batch/README.rst create mode 100644 queue_job_batch/__init__.py create mode 100644 queue_job_batch/__manifest__.py create mode 100644 queue_job_batch/i18n/queue_job_batch.pot create mode 100644 queue_job_batch/models/__init__.py create mode 100644 queue_job_batch/models/queue_job.py create mode 100644 queue_job_batch/models/queue_job_batch.py create mode 100644 queue_job_batch/readme/CONTRIBUTORS.rst create mode 100644 queue_job_batch/readme/DESCRIPTION.rst create mode 100644 queue_job_batch/readme/USAGE.rst create mode 100644 queue_job_batch/security/ir.model.access.csv create mode 100644 queue_job_batch/security/security.xml create mode 100644 queue_job_batch/static/description/icon.png create mode 100644 queue_job_batch/static/description/icon.svg create mode 100644 queue_job_batch/static/description/index.html create mode 100644 queue_job_batch/static/src/js/systray.js create mode 100644 queue_job_batch/static/src/less/systray.less create mode 100644 queue_job_batch/static/src/xml/systray.xml create mode 100644 queue_job_batch/views/assets_backend.xml create mode 100644 queue_job_batch/views/queue_job_batch_views.xml create mode 100644 queue_job_batch/views/queue_job_views.xml diff --git a/queue_job_batch/README.rst b/queue_job_batch/README.rst new file mode 100644 index 0000000000..0de1f6cadf --- /dev/null +++ b/queue_job_batch/README.rst @@ -0,0 +1,118 @@ +=============== +Job Queue Batch +=============== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fqueue-lightgray.png?logo=github + :target: https://github.com/OCA/queue/tree/11.0/queue_job_batch + :alt: OCA/queue +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/queue-11-0/queue-11-0-queue_job_batch + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/230/11.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This addon adds an a grouper for queue jobs. + +It allows to show your jobs in a batched form in order to know better the +results. + +Example: + +.. code-block:: python + + from odoo import models, fields, api + from odoo.addons.queue_job.job import job + + class MyModel(models.Model): + _name = 'my.model' + + @api.multi + @job + def my_method(self, a, k=None): + _logger.info('executed with a: %s and k: %s', a, k) + + + class MyOtherModel(models.Model): + _name = 'my.other.model' + + @api.multi + def button_do_stuff(self): + batch = self.env['queue.job.batch'].get_new_batch('Group') + for i in range(1, 100): + self.env['my.model'].with_context( + job_batch=batch + ).with_delay().my_method('a', k=i) + batch.enqueue() + + +In the snippet of code above, when we call ``button_do_stuff``, 100 jobs +capturing the method and arguments will be postponed. It will be executed as +soon as the Jobrunner has a free bucket, which can be instantaneous if no other +job is running. + +Once all the jobs have finished, the grouper will be marked as finished. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +You can manage your batch jobs from the Systray. A new button will be shown +with your currently executing job batches and the recently finished job groups. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Creu Blanca + +Contributors +~~~~~~~~~~~~ + +* Enric Tobella + +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. + +This module is part of the `OCA/queue `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/queue_job_batch/__init__.py b/queue_job_batch/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/queue_job_batch/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/queue_job_batch/__manifest__.py b/queue_job_batch/__manifest__.py new file mode 100644 index 0000000000..1c3facf102 --- /dev/null +++ b/queue_job_batch/__manifest__.py @@ -0,0 +1,24 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + + +{ + 'name': 'Job Queue Batch', + 'version': '11.0.1.1.0', + 'author': 'Creu Blanca,Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/queue', + 'license': 'AGPL-3', + 'category': 'Generic Modules', + 'depends': [ + 'queue_job', + ], + 'qweb': [ + 'static/src/xml/systray.xml', + ], + 'data': [ + 'security/security.xml', + 'security/ir.model.access.csv', + 'views/queue_job_views.xml', + 'views/queue_job_batch_views.xml', + 'views/assets_backend.xml', + ], +} diff --git a/queue_job_batch/i18n/queue_job_batch.pot b/queue_job_batch/i18n/queue_job_batch.pot new file mode 100644 index 0000000000..7e24d85f5e --- /dev/null +++ b/queue_job_batch/i18n/queue_job_batch.pot @@ -0,0 +1,185 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * queue_job_batch +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 11.0\n" +"Report-Msgid-Bugs-To: \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: queue_job_batch +#: model:ir.model,name:queue_job_batch.model_queue_job_batch +msgid "Batch of jobs" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_company_id +msgid "Company" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_completeness +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_tree +msgid "Completeness" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_display_name +msgid "Display Name" +msgstr "" + +#. module: queue_job_batch +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +#: selection:queue.job.batch,state:0 +msgid "Draft" +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,state:0 +msgid "Enqueued" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_failed_job_count +msgid "Failed Job Count" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_failed_percentage +msgid "Failed Percentage" +msgstr "" + +#. module: queue_job_batch +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +#: selection:queue.job.batch,state:0 +msgid "Finished" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_finished_job_count +msgid "Finished Job Count" +msgstr "" + +#. module: queue_job_batch +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "Group By" +msgstr "" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:52 +#, python-format +msgid "Hide" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_id +msgid "ID" +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,state:0 +msgid "In Progress" +msgstr "" + +#. module: queue_job_batch +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "In progress" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_is_read +msgid "Is Read" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_job_ids +msgid "Job" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_job_batch_id +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +msgid "Job Batch" +msgstr "" + +#. module: queue_job_batch +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_tree +msgid "Job Batches" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_job_count +msgid "Job Count" +msgstr "" + +#. module: queue_job_batch +#: model:res.groups,name:queue_job_batch.group_queue_job_batch_user +msgid "Job Queue Batch User" +msgstr "" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:7 +#: code:addons/queue_job_batch/static/src/xml/systray.xml:14 +#: model:ir.actions.act_window,name:queue_job_batch.action_queue_job_batch +#: model:ir.actions.act_window,name:queue_job_batch.action_view_your_queue_job_batch +#: model:ir.ui.menu,name:queue_job_batch.menu_queue_job_batch +#, python-format +msgid "Job batches" +msgstr "" + +#. module: queue_job_batch +#: model:ir.actions.act_window,name:queue_job_batch.action_queue_job_related +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +msgid "Jobs" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch___last_update +msgid "Last Modified on" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_name +msgid "Name" +msgstr "" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:26 +#, python-format +msgid "No jobs to view." +msgstr "" + +#. module: queue_job_batch +#: model:ir.model,name:queue_job_batch.model_queue_job +msgid "Queue Job" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_state +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "State" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch_user_id +#: model:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "User" +msgstr "" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:16 +#, python-format +msgid "View All" +msgstr "" + diff --git a/queue_job_batch/models/__init__.py b/queue_job_batch/models/__init__.py new file mode 100644 index 0000000000..f4cb3a5408 --- /dev/null +++ b/queue_job_batch/models/__init__.py @@ -0,0 +1,2 @@ +from . import queue_job +from . import queue_job_batch diff --git a/queue_job_batch/models/queue_job.py b/queue_job_batch/models/queue_job.py new file mode 100644 index 0000000000..095ab006dd --- /dev/null +++ b/queue_job_batch/models/queue_job.py @@ -0,0 +1,37 @@ +# Copyright 2019 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import models, fields, api + + +class QueueJob(models.Model): + _inherit = 'queue.job' + + job_batch_id = fields.Many2one( + 'queue.job.batch' + ) + + @api.model + def create(self, vals): + batch = self.env.context.get('job_batch') + if batch and isinstance( + batch, models.Model + ) and batch.state == 'draft': + vals.update({ + 'job_batch_id': batch.id + }) + return super().create(vals) + + @api.multi + def write(self, vals): + batches = self.env['queue.job.batch'] + for record in self: + if record.job_batch_id and record.state != 'done' and vals.get( + 'state', '' + ) == 'done': + batches |= record.job_batch_id + for batch in batches: + # We need to make it with delay in order to prevent two jobs + # to work with the same batch + batch.with_delay().check_state() + return super().write(vals) diff --git a/queue_job_batch/models/queue_job_batch.py b/queue_job_batch/models/queue_job_batch.py new file mode 100644 index 0000000000..ab4eb9e51d --- /dev/null +++ b/queue_job_batch/models/queue_job_batch.py @@ -0,0 +1,126 @@ +# Copyright 2019 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import models, fields, api +from odoo.addons.queue_job.job import job + + +class QueueJobBatch(models.Model): + _name = 'queue.job.batch' + _inherit = ['mail.thread', 'mail.activity.mixin'] + _description = 'Batch of jobs' + _log_access = False + + name = fields.Char( + required=True, + readonly=True, + track_visibility='onchange', + ) + job_ids = fields.One2many( + 'queue.job', + inverse_name='job_batch_id', + readonly=True, + ) + job_count = fields.Integer( + compute='_compute_job_count', + ) + user_id = fields.Many2one( + 'res.users', + required=True, + readonly=True, + track_visibility='onchange', + ) + state = fields.Selection( + [ + ('draft', 'Draft'), + ('enqueued', 'Enqueued'), + ('progress', 'In Progress'), + ('finished', 'Finished') + ], + default='draft', + required=True, + readonly=True, + track_visibility='onchange', + ) + finished_job_count = fields.Float( + compute='_compute_job_count', + ) + failed_job_count = fields.Float( + compute='_compute_job_count', + ) + company_id = fields.Many2one( + 'res.company', + readonly=True, + ) + is_read = fields.Boolean( + default=True + ) + completeness = fields.Float( + compute='_compute_job_count', + ) + failed_percentage = fields.Float( + compute='_compute_job_count', + ) + + def enqueue(self): + self.filtered(lambda r: r.state == 'draft').write({ + 'state': 'enqueued' + }) + for record in self: + record.check_state() + + @job + def check_state(self): + self.ensure_one() + if self.state == 'enqueued' and any( + job.state not in ['pending', 'enqueued'] for job in self.job_ids + ): + self.write({'state': 'progress'}) + if self.state != 'progress': + return True + if all(job.state == 'done' for job in self.job_ids): + self.write({ + 'state': 'finished', + 'is_read': False, + }) + return True + + @api.multi + def set_read(self): + return self.write({'is_read': True}) + + @api.model + def get_new_batch(self, name, **kwargs): + vals = kwargs.copy() + if 'company_id' in self.env.context: + company_id = self.env.context['company_id'] + else: + company_model = self.env['res.company'] + company_model = company_model.sudo(self.env.uid) + company_id = company_model._company_default_get( + object='queue.job', + field='company_id' + ).id + vals.update({ + 'user_id': self.env.uid, + 'name': name, + 'state': 'draft', + 'company_id': company_id, + }) + return self.sudo().create(vals).sudo(self.env.uid) + + @api.depends('job_ids') + def _compute_job_count(self): + for record in self: + job_count = len(record.job_ids) + failed_job_count = len(record.job_ids.filtered( + lambda r: r.state == 'failed' + )) + done_job_count = len(record.job_ids.filtered( + lambda r: r.state == 'done' + )) + record.job_count = job_count + record.finished_job_count = done_job_count + record.failed_job_count = failed_job_count + record.completeness = done_job_count / max(1, job_count) + record.failed_percentage = failed_job_count / max(1, job_count) diff --git a/queue_job_batch/readme/CONTRIBUTORS.rst b/queue_job_batch/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..93ec993e04 --- /dev/null +++ b/queue_job_batch/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Enric Tobella diff --git a/queue_job_batch/readme/DESCRIPTION.rst b/queue_job_batch/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..a35df93da7 --- /dev/null +++ b/queue_job_batch/readme/DESCRIPTION.rst @@ -0,0 +1,40 @@ +This addon adds an a grouper for queue jobs. + +It allows to show your jobs in a batched form in order to know better the +results. + +Example: + +.. code-block:: python + + from odoo import models, fields, api + from odoo.addons.queue_job.job import job + + class MyModel(models.Model): + _name = 'my.model' + + @api.multi + @job + def my_method(self, a, k=None): + _logger.info('executed with a: %s and k: %s', a, k) + + + class MyOtherModel(models.Model): + _name = 'my.other.model' + + @api.multi + def button_do_stuff(self): + batch = self.env['queue.job.batch'].get_new_batch('Group') + for i in range(1, 100): + self.env['my.model'].with_context( + job_batch=batch + ).with_delay().my_method('a', k=i) + batch.enqueue() + + +In the snippet of code above, when we call ``button_do_stuff``, 100 jobs +capturing the method and arguments will be postponed. It will be executed as +soon as the Jobrunner has a free bucket, which can be instantaneous if no other +job is running. + +Once all the jobs have finished, the grouper will be marked as finished. diff --git a/queue_job_batch/readme/USAGE.rst b/queue_job_batch/readme/USAGE.rst new file mode 100644 index 0000000000..4605405ae9 --- /dev/null +++ b/queue_job_batch/readme/USAGE.rst @@ -0,0 +1,2 @@ +You can manage your batch jobs from the Systray. A new button will be shown +with your currently executing job batches and the recently finished job groups. diff --git a/queue_job_batch/security/ir.model.access.csv b/queue_job_batch/security/ir.model.access.csv new file mode 100644 index 0000000000..70d06ff3c6 --- /dev/null +++ b/queue_job_batch/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_queue_job_batch_user,queue job manager,model_queue_job_batch,group_queue_job_batch_user,1,0,0,0 +access_queue_job_batch_manager,queue job manager,model_queue_job_batch,queue_job.group_queue_job_manager,1,1,1,1 +access_queue_job_queue_job_batch_user,queue job manager,queue_job.model_queue_job,group_queue_job_batch_user,1,0,0,0 diff --git a/queue_job_batch/security/security.xml b/queue_job_batch/security/security.xml new file mode 100644 index 0000000000..9205ca81bd --- /dev/null +++ b/queue_job_batch/security/security.xml @@ -0,0 +1,43 @@ + + + + + + Job Queue Batch User + + + + + + + + + + + Job Queue batch multi-company + + + ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])] + + + + Job Queue batch user filter + + + [('user_id', '=', uid)] + + + + Job Queue batch multi-company + + + [(1, '=', 1)] + + + + + diff --git a/queue_job_batch/static/description/icon.png b/queue_job_batch/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a735e94d10274d83c86106188a9339a8132d3e0c GIT binary patch literal 1803 zcmah~c~H~W7XAgv(y&8>7!g9?2_uX6j9M0H2w{85B1;<{1rjv~0!hFHRF)XSs%&K| zy8?01ZzMf}g@Olm>$+c8(L7t8l94@SXuM#Y%*o&QRbl=pI4m0ANqL(m=VhOB6+L z*Lhdsd4F2?`FL_11&EK2w~3@iojXOQQ*3B)XUZjxC;)(DcoLig5-P-%UeO4O;j8M> z5z5w&>``j7wRQDV!nGRcwLAY-?IhJ8X-03muA!FvvPmjPLLFW$74FebVjc)}q?aHH zFett0P9zgO$<-1zeWEsVCA51utf&wyfBnP4 zYui_Ca`pMJWPQQIM)$SdG*dPyUpzv<+obbut06zJp(C9v+kFT$g+hKQwf|ReHT?yo zHrWVM?x3A=>1bRjudwvQAYnd=b}QPoVOmDG@una4{ob^VXoI;sM^(+N)yy}cI-%^Y zH4J+>PI%}?|Ig8Hv9V1lu)ynM0`rq9YWl|x`or_sR;%k;WFB@UtQ(P@9XxApZMiKo z+b_{3xpAviio=LK&Eyevrz(1P$Eq7SVEB<^+~7Dn4m@%D2?y!`OnM_2$5XIJOuz8o^VI{hTb=VJrwRwQv(V^g40 zM?pu;)J55ClhJk;P?l=QVE^2sM1~3iyqU5ncT1n$f#}$n@pr<36201#pqWRIF|u>7 z7J02Kt>$kINfnF?DZE)hY`e|m>Gc+b-?v_)l(|CU{9;Is|*(t1cgRGs1ZNxCP^;VJCk zfD4W?m^iEkD=w_T=&wXO>FC|16^18h{$H(mfRWFW`D=8`%2$M`v@8gB!pESar2=24~@ zY0LpD0VwMR;|@76rl@fl1osV4#cDL1(&@slA5H}jHzVjumaPn#08U|4H{v`Ay1B7l)atQ5H-JJEenHC24` zlQ&RHRq71$t9}1t2!$_pd&Ec${+iT$xNYKEmT0o{wC?oMvxLval8<@^j%>H?W4V^WqaAQUGU`^1QF?3V7&bj)6;dWD0UNa*~U zy7SGt4Q;N6fvI&Qkz#&8?F6}$&D!DeC+n2T+DS=!qT~--xC=5gWM^r76L9TpT;^zU zp%#qA-g-riw9JpwQAX^#AY<^8KxI_)x8G>-A1xk>Lz^TW?yx@3!98mOy~Jp=7_w$F}>xp&gnbNY8kH_ee~;CT`T$B~s*QLN?5sOj{Q0bmRGdj$X{3Vamcw?nc&z(4hrqAcMB zC}VpL1}Vq6`*?}6?t`l`1`aJ!oWShiDjU|YhyDP$9fEDW~l4_xhFwRfP9Cw*?0`4OzpVh;{rTgy$KKSB + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/queue_job_batch/static/description/index.html b/queue_job_batch/static/description/index.html new file mode 100644 index 0000000000..47bdecb3c1 --- /dev/null +++ b/queue_job_batch/static/description/index.html @@ -0,0 +1,458 @@ + + + + + + +Job Queue Batch + + + +
+

Job Queue Batch

+ + +

Beta License: AGPL-3 OCA/queue Translate me on Weblate Try me on Runbot

+

This addon adds an a grouper for queue jobs.

+

It allows to show your jobs in a batched form in order to know better the +results.

+

Example:

+
+from odoo import models, fields, api
+from odoo.addons.queue_job.job import job
+
+class MyModel(models.Model):
+   _name = 'my.model'
+
+   @api.multi
+   @job
+   def my_method(self, a, k=None):
+       _logger.info('executed with a: %s and k: %s', a, k)
+
+
+class MyOtherModel(models.Model):
+    _name = 'my.other.model'
+
+    @api.multi
+    def button_do_stuff(self):
+        batch = self.env['queue.job.batch'].get_new_batch('Group')
+        for i in range(1, 100):
+            self.env['my.model'].with_context(
+                job_batch=batch
+            ).with_delay().my_method('a', k=i)
+        batch.enqueue()
+
+

In the snippet of code above, when we call button_do_stuff, 100 jobs +capturing the method and arguments will be postponed. It will be executed as +soon as the Jobrunner has a free bucket, which can be instantaneous if no other +job is running.

+

Once all the jobs have finished, the grouper will be marked as finished.

+

Table of contents

+ +
+

Usage

+

You can manage your batch jobs from the Systray. A new button will be shown +with your currently executing job batches and the recently finished job groups.

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Creu Blanca
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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.

+

This module is part of the OCA/queue project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/queue_job_batch/static/src/js/systray.js b/queue_job_batch/static/src/js/systray.js new file mode 100644 index 0000000000..5833a8fa7d --- /dev/null +++ b/queue_job_batch/static/src/js/systray.js @@ -0,0 +1,139 @@ +odoo.define('queue_job_batch.systray', function (require) { + "use strict"; + + var core = require('web.core'); + var session = require('web.session'); + var SystrayMenu = require('web.SystrayMenu'); + var Widget = require('web.Widget'); + var bus = require('bus.bus').bus; + + var QWeb = core.qweb; + + var QueueJobBatchMenu = Widget.extend({ + template:'queue_job_batch.view.Menu', + events: { + "click": "_onMenuClick", + "click .o_mail_channel_preview": "_onQueueJobBatchClick", + "click .o_view_all_batch_jobs": "_viewAllQueueJobBatches", + "click .o_queue_job_batch_hide": "_hideJobBatchClick", + }, + renderElement: function () { + this._super(); + var self = this; + session.user_has_group( + 'queue_job_batch.group_queue_job_batch_user' + ).then(function (data) { + self.manager = data; + if (data) { + self.do_show(); + } + }); + }, + start: function () { + var self = this; + session.user_has_group( + 'queue_job_batch.group_queue_job_batch_user' + ).then(function (data) { + self.manager = data; + if (data) { + self.$queue_job_batch_preview = self.$( + '.o_mail_navbar_dropdown_channels' + ); + self._updateQueueJobBatchesPreview(); + var channel = 'queue.job.batch'; + bus.add_channel(channel); + bus.on( + 'notification', + self, self._updateQueueJobBatchesPreview + ); + } + }); + return this._super(); + }, + + _getQueueJobBatchesData: function () { + var self = this; + + return self._rpc({ + model: 'queue.job.batch', + method: 'search_read', + args: [[ + ['user_id', '=', session.uid], + '|', ['state', 'in', ['draft', 'progress']], + ['is_read', '=', false], + ], [ + 'name', 'job_count', 'completeness', 'failed_percentage', + 'finished_job_count', 'failed_job_count', 'state', + ]], + kwargs: { + context: session.user_context, + }, + }).then(function (data) { + self.job_batches = data; + self.jobBatchesCounter = data.length; + self.$('.o_notification_counter').text(self.jobBatchesCounter); + self.$el.toggleClass( + 'o_no_notification', !self.jobBatchesCounter + ); + }); + }, + + _isOpen: function () { + return this.$el.hasClass('open'); + }, + + _updateQueueJobBatchesPreview: function () { + var self = this; + self._getQueueJobBatchesData().then(function () { + self.$queue_job_batch_preview.html(QWeb.render( + 'queue_job_batch.view.Data', { + job_batches : self.job_batches, + } + )); + }); + }, + _hideJobBatchClick: function (event) { + var queue_job_batch_id = parseInt( + $(event.currentTarget, 10).data('job-batch-id'), 10); + this._hideJobBatch(event, queue_job_batch_id); + }, + _hideJobBatch: function (event, queue_job_batch_id) { + this._rpc({ + model: 'queue.job.batch', + method: 'set_read', + args: [[queue_job_batch_id]], + kwargs: { + context: session.user_context, + }, + }); + }, + _onQueueJobBatchClick: function (event) { + var queue_job_batch_id = parseInt( + $(event.currentTarget, 10).data('job-batch-id'), 10); + this._hideJobBatch(event, queue_job_batch_id); + this.do_action({ + type: 'ir.actions.act_window', + name: 'Job batches', + res_model: 'queue.job.batch', + views: [[false, 'form']], + res_id: queue_job_batch_id, + }); + }, + _viewAllQueueJobBatches: function () { + this.do_action( + 'queue_job_batch.action_view_your_queue_job_batch'); + }, + _onMenuClick: function () { + if (!this._isOpen()) { + this._updateQueueJobBatchesPreview(); + } + }, + + }); + + SystrayMenu.Items.push(QueueJobBatchMenu); + + return { + QueueJobBatchMenu: QueueJobBatchMenu, + }; +}); diff --git a/queue_job_batch/static/src/less/systray.less b/queue_job_batch/static/src/less/systray.less new file mode 100644 index 0000000000..a4958d5c6c --- /dev/null +++ b/queue_job_batch/static/src/less/systray.less @@ -0,0 +1,44 @@ +.o_job_batch_navbar_item { + + &.open .o_job_batch_navbar_dropdown { + .o-flex-display(); + .o-flex-flow(column, nowrap); + } + .o_notification_counter { + .o-position-absolute(@top: 20%, @right: 1px); + background: @odoo-brand-optional; + color: white; + padding: 0em 0.3em; + font-size: 0.7em; + } + .o_job_batch_navbar_dropdown { + width: 350px; + padding: 0; + } + + .o_job_queue_failed { + color: red; + } + .o_job_queue_finished { + color: green; + } + .o_job_queue_progress { + color: gray; + } + .o_progressbar_complete { + &.o_queue_job_finished_progressbar { + background-color:green; + float:left; + } + + &.o_queue_job_failed_progressbar { + background-color:red; + float:right; + } + } +} + +.o_view_all_job_batches { + .btn-link; + padding: 5px; +} \ No newline at end of file diff --git a/queue_job_batch/static/src/xml/systray.xml b/queue_job_batch/static/src/xml/systray.xml new file mode 100644 index 0000000000..9fb2441afc --- /dev/null +++ b/queue_job_batch/static/src/xml/systray.xml @@ -0,0 +1,62 @@ + + + + +
  • + + +
  • +
    + + + +
  • + No jobs to view. +
  • +
    + +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + + + + + diff --git a/queue_job_batch/views/assets_backend.xml b/queue_job_batch/views/assets_backend.xml new file mode 100644 index 0000000000..1c6799f6ab --- /dev/null +++ b/queue_job_batch/views/assets_backend.xml @@ -0,0 +1,10 @@ + + +