diff --git a/queue_job_batch/README.rst b/queue_job_batch/README.rst new file mode 100644 index 0000000000..a150ebd3e5 --- /dev/null +++ b/queue_job_batch/README.rst @@ -0,0 +1,122 @@ +=============== +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/14.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-14-0/queue-14-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/14.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 + + class MyModel(models.Model): + _name = 'my.model' + + 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' + + 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 +* Lois Rilo +* `Trobz `_: + * Hoang Diep + +Other credits +~~~~~~~~~~~~~ + +The migration of this module from 12.0 to 14.0 was financially supported by Camptocamp + +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..f5b907a6c3 --- /dev/null +++ b/queue_job_batch/__manifest__.py @@ -0,0 +1,31 @@ +# Copyright 2019 Creu Blanca +# Copyright 2019 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +{ + "name": "Job Queue Batch", + "version": "14.0.1.0.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": [ + # data + "data/queue_job_channel_data.xml", + "data/queue_job_function_data.xml", + # security + "security/security.xml", + "security/ir.model.access.csv", + # views + "views/queue_job_views.xml", + "views/queue_job_batch_views.xml", + "views/assets_backend.xml", + ], +} diff --git a/queue_job_batch/data/queue_job_channel_data.xml b/queue_job_batch/data/queue_job_channel_data.xml new file mode 100644 index 0000000000..04dd328c59 --- /dev/null +++ b/queue_job_batch/data/queue_job_channel_data.xml @@ -0,0 +1,6 @@ + + + queue.job.batch + + + diff --git a/queue_job_batch/data/queue_job_function_data.xml b/queue_job_batch/data/queue_job_function_data.xml new file mode 100644 index 0000000000..c9606d4f6d --- /dev/null +++ b/queue_job_batch/data/queue_job_function_data.xml @@ -0,0 +1,7 @@ + + + + + check_state + + diff --git a/queue_job_batch/i18n/fr.po b/queue_job_batch/i18n/fr.po new file mode 100644 index 0000000000..be7d376f06 --- /dev/null +++ b/queue_job_batch/i18n/fr.po @@ -0,0 +1,349 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * queue_job_batch +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-11-20 16:54+0000\n" +"Last-Translator: Yann Papouin \n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.10\n" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_needaction +msgid "Action Needed" +msgstr "Action requise" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_ids +msgid "Activities" +msgstr "Activités" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_state +msgid "Activity State" +msgstr "Statut de l'activité" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_attachment_count +msgid "Attachment Count" +msgstr "Compteur de pièce jointe" + +#. module: queue_job_batch +#: model:ir.model,name:queue_job_batch.model_queue_job_batch +msgid "Batch of jobs" +msgstr "Lot de travaux" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__company_id +msgid "Company" +msgstr "Société" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__completeness +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_tree +msgid "Completeness" +msgstr "Achèvement" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +#: selection:queue.job.batch,state:0 +msgid "Draft" +msgstr "Brouillon" + +#. module: queue_job_batch +#: selection:queue.job.batch,state:0 +msgid "Enqueued" +msgstr "Mis en file d'attente" + +#. 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 "Nombre de travaux échoués" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__failed_percentage +msgid "Failed Percentage" +msgstr "Pourcentage d'échec" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +#: selection:queue.job.batch,state:0 +msgid "Finished" +msgstr "Terminés" + +#. 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 "Nombre de travaux terminés" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_follower_ids +msgid "Followers" +msgstr "Abonnés" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_channel_ids +msgid "Followers (Channels)" +msgstr "Abonnés (Canaux)" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_partner_ids +msgid "Followers (Partners)" +msgstr "Abonnés (Partenaires)" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "Group By" +msgstr "Regrouper par" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__id +msgid "ID" +msgstr "ID" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_unread +msgid "If checked new messages require your attention." +msgstr "Si coché, de nouveaux messages requièrent votre attention." + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_needaction +msgid "If checked, new messages require your attention." +msgstr "Si coché, de nouveaux messages requièrent votre attention." + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "Si coché, des messages n'ont pas pu être livré." + +#. module: queue_job_batch +#: selection:queue.job.batch,state:0 +msgid "In Progress" +msgstr "En cours" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "In progress" +msgstr "En cours" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_is_follower +msgid "Is Follower" +msgstr "Est abonné" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__is_read +msgid "Is Read" +msgstr "Est lu" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__job_ids +msgid "Job" +msgstr "Poste" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job__job_batch_id +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +msgid "Job Batch" +msgstr "Lot de travaux" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_tree +msgid "Job Batches" +msgstr "Lots de travaux" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__job_count +msgid "Job Count" +msgstr "Nombre de travaux" + +#. module: queue_job_batch +#: model:res.groups,name:queue_job_batch.group_queue_job_batch_user +msgid "Job Queue Batch User" +msgstr "Utilisateur des lots de file d'attente de travaux" + +#. 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 "Lots de travaux" + +#. module: queue_job_batch +#: model:ir.actions.act_window,name:queue_job_batch.action_queue_job_related +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +msgid "Jobs" +msgstr "Travaux" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_main_attachment_id +msgid "Main Attachment" +msgstr "Pièce jointe principale" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:53 +#, python-format +msgid "Mark as Read" +msgstr "Marquer comme lu" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_has_error +msgid "Message Delivery error" +msgstr "Erreur lors de livraison du message" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_ids +msgid "Messages" +msgstr "Messages" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__name +msgid "Name" +msgstr "Nom" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "Échéance de la prochaine activité" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_summary +msgid "Next Activity Summary" +msgstr "Résumé de la prochaine activité" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_type_id +msgid "Next Activity Type" +msgstr "Type de la prochaine activité" + +#. 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 "Aucun travail à voir." + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_needaction_counter +msgid "Number of Actions" +msgstr "Nombre d'activités" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_has_error_counter +msgid "Number of error" +msgstr "Nombre d'erreurs" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "Nombre de messages qui nécessitent une action" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "Nombre de messages avec erreur de livraison" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_unread_counter +msgid "Number of unread messages" +msgstr "Nombre de messages non lus" + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Overdue" +msgstr "Dû" + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Planned" +msgstr "Planifié" + +#. module: queue_job_batch +#: model:ir.model,name:queue_job_batch.model_queue_job +msgid "Queue Job" +msgstr "File d'attente des travaux" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_user_id +msgid "Responsible User" +msgstr "Responsable" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__state +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "State" +msgstr "État" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__activity_state +msgid "Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" +"Statut basé sur les activités\n" +"En retard : La date d'échéance est déjà dépassée\n" +"Aujourd'hui : L'activité est planifiée pour aujourd'hui\n" +"Planifiées : activités futures." + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Today" +msgstr "Aujourd'hui" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_unread +msgid "Unread Messages" +msgstr "Messages non lus" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_unread_counter +msgid "Unread Messages Counter" +msgstr "Compteur de messages non-lus" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__user_id +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "User" +msgstr "Utilisateur" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:16 +#, python-format +msgid "View All" +msgstr "Voir tout" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__website_message_ids +msgid "Website Messages" +msgstr "Messages du sites web" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__website_message_ids +msgid "Website communication history" +msgstr "Historique de la communication du site web" 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..ee7827b286 --- /dev/null +++ b/queue_job_batch/i18n/queue_job_batch.pot @@ -0,0 +1,343 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * queue_job_batch +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.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.fields,field_description:queue_job_batch.field_queue_job_batch__message_needaction +msgid "Action Needed" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_ids +msgid "Activities" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_state +msgid "Activity State" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_attachment_count +msgid "Attachment Count" +msgstr "" + +#. 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_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +#: model_terms: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_terms: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_terms: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.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_follower_ids +msgid "Followers" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_channel_ids +msgid "Followers (Channels)" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_partner_ids +msgid "Followers (Partners)" +msgstr "" + +#. module: queue_job_batch +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "Group By" +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 +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_unread +msgid "If checked new messages require your attention." +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_needaction +msgid "If checked, new messages require your attention." +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_has_error +msgid "If checked, some messages have a delivery error." +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,state:0 +msgid "In Progress" +msgstr "" + +#. module: queue_job_batch +#: model_terms: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__message_is_follower +msgid "Is Follower" +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_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_form +msgid "Job Batch" +msgstr "" + +#. module: queue_job_batch +#: model_terms: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_terms: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__message_main_attachment_id +msgid "Main Attachment" +msgstr "" + +#. module: queue_job_batch +#. openerp-web +#: code:addons/queue_job_batch/static/src/xml/systray.xml:53 +#, python-format +msgid "Mark as Read" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_has_error +msgid "Message Delivery error" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_ids +msgid "Messages" +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 +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_date_deadline +msgid "Next Activity Deadline" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_summary +msgid "Next Activity Summary" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__activity_type_id +msgid "Next Activity Type" +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.fields,field_description:queue_job_batch.field_queue_job_batch__message_needaction_counter +msgid "Number of Actions" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_has_error_counter +msgid "Number of error" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_needaction_counter +msgid "Number of messages which requires an action" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_has_error_counter +msgid "Number of messages with delivery error" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__message_unread_counter +msgid "Number of unread messages" +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Overdue" +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Planned" +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__activity_user_id +msgid "Responsible User" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__state +#: model_terms:ir.ui.view,arch_db:queue_job_batch.view_queue_job_batch_search +msgid "State" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__activity_state +msgid "Status based on activities\n" +"Overdue: Due date is already passed\n" +"Today: Activity date is today\n" +"Planned: Future activities." +msgstr "" + +#. module: queue_job_batch +#: selection:queue.job.batch,activity_state:0 +msgid "Today" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_unread +msgid "Unread Messages" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__message_unread_counter +msgid "Unread Messages Counter" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__user_id +#: model_terms: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 "" + +#. module: queue_job_batch +#: model:ir.model.fields,field_description:queue_job_batch.field_queue_job_batch__website_message_ids +msgid "Website Messages" +msgstr "" + +#. module: queue_job_batch +#: model:ir.model.fields,help:queue_job_batch.field_queue_job_batch__website_message_ids +msgid "Website communication history" +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..342bf3b856 --- /dev/null +++ b/queue_job_batch/models/queue_job.py @@ -0,0 +1,32 @@ +# Copyright 2019 Creu Blanca +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import api, fields, models + + +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) + + 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..09e925838c --- /dev/null +++ b/queue_job_batch/models/queue_job_batch.py @@ -0,0 +1,124 @@ +# Copyright 2019 Creu Blanca +# Copyright 2019 Eficent Business and IT Consulting Services S.L. +# (http://www.eficent.com) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) + +from odoo import api, fields, models + + +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, + tracking=True, + ) + 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, + tracking=True, + ) + state = fields.Selection( + [ + ("draft", "Draft"), + ("enqueued", "Enqueued"), + ("progress", "In Progress"), + ("finished", "Finished"), + ], + default="draft", + required=True, + readonly=True, + tracking=True, + ) + 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() + + 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 + + def set_read(self): + res = self.write({"is_read": True}) + notifications = [] + channel = "queue.job.batch" + notifications.append([channel, {}]) + self.env["bus.bus"].sendmany(notifications) + return res + + @api.model + def get_new_batch(self, name, **kwargs): + vals = kwargs.copy() + company_id = self.env.user.company_id.id + + if "company_id" in self.env.context: + company_id = self.env.context["company_id"] + + vals.update( + { + "user_id": self.env.uid, + "name": name, + "state": "draft", + "company_id": company_id, + } + ) + return self.sudo().create(vals).with_user(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..76bc3d9075 --- /dev/null +++ b/queue_job_batch/readme/CONTRIBUTORS.rst @@ -0,0 +1,4 @@ +* Enric Tobella +* Lois Rilo +* `Trobz `_: + * Hoang Diep diff --git a/queue_job_batch/readme/CREDITS.rst b/queue_job_batch/readme/CREDITS.rst new file mode 100644 index 0000000000..ca6e4f9cdb --- /dev/null +++ b/queue_job_batch/readme/CREDITS.rst @@ -0,0 +1 @@ +The migration of this module from 12.0 to 14.0 was financially supported by Camptocamp 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..e3da256bbb --- /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,1,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..53f186ae34 --- /dev/null +++ b/queue_job_batch/security/security.xml @@ -0,0 +1,49 @@ + + + + + + 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', '=', user.id)] + + + + Job Queue batch manager + + + [(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 0000000000..a735e94d10 Binary files /dev/null and b/queue_job_batch/static/description/icon.png differ diff --git a/queue_job_batch/static/description/icon.svg b/queue_job_batch/static/description/icon.svg new file mode 100644 index 0000000000..653fcebfa6 --- /dev/null +++ b/queue_job_batch/static/description/icon.svg @@ -0,0 +1,127 @@ + + + + + + + + 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..e6006cb5dd --- /dev/null +++ b/queue_job_batch/static/description/index.html @@ -0,0 +1,472 @@ + + + + + + +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

+ +
+
+

Other credits

+

The migration of this module from 12.0 to 14.0 was financially supported by Camptocamp

+
+
+

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..75f71ecada --- /dev/null +++ b/queue_job_batch/static/src/js/systray.js @@ -0,0 +1,154 @@ +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"); + require("bus.BusService"); + + var QWeb = core.qweb; + + var QueueJobBatchMenu = Widget.extend({ + template: "queue_job_batch.view.Menu", + events: { + click: "_onMenuClick", + "click .o_mail_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_systray_dropdown_items" + ); + self._updateQueueJobBatchesPreview(); + var channel = "queue.job.batch"; + self.call("bus_service", "addChannel", channel); + self.call("bus_service", "startPolling"); + self.call( + "bus_service", + "onNotification", + 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) { + // Hide the batch without navigating to it. + event.preventDefault(); + event.stopPropagation(); + 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; +}); diff --git a/queue_job_batch/static/src/scss/systray.scss b/queue_job_batch/static/src/scss/systray.scss new file mode 100644 index 0000000000..ddc0ccb14d --- /dev/null +++ b/queue_job_batch/static/src/scss/systray.scss @@ -0,0 +1,38 @@ +.o_job_batch_navbar_item { + .o_notification_counter { + margin-top: -0.8rem; + margin-right: 0; + margin-left: -0.6rem; + background: $o-enterprise-primary-color; + color: white; + vertical-align: super; + font-size: 0.7em; + } + .o_job_batch_navbar_dropdown { + width: 350px; + padding: 0; + } + .o_view_all_batch_jobs { + padding: 5px; + } + .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; + } + } +} 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..8f49761344 --- /dev/null +++ b/queue_job_batch/static/src/xml/systray.xml @@ -0,0 +1,98 @@ + + + + +
  • + + +
  • +
    + + + + + + +
    +
    + + + +
    +
    +
    + + + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    + + + + diff --git a/queue_job_batch/views/assets_backend.xml b/queue_job_batch/views/assets_backend.xml new file mode 100644 index 0000000000..c635d4bc2c --- /dev/null +++ b/queue_job_batch/views/assets_backend.xml @@ -0,0 +1,16 @@ + + +