diff --git a/.docker_files/main/__manifest__.py b/.docker_files/main/__manifest__.py index 539880fc..104fe594 100644 --- a/.docker_files/main/__manifest__.py +++ b/.docker_files/main/__manifest__.py @@ -13,6 +13,7 @@ "depends": [ "project", "project_task_date_planned", + "project_task_description_template", "project_task_full_text_search", "project_type_advanced", "project_default_task_stage", diff --git a/Dockerfile b/Dockerfile index 5396fbbb..16fc3d05 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,12 @@ USER odoo COPY project_stage_allow_timesheet mnt/extra-addons/project_stage_allow_timesheet COPY project_task_date_planned /mnt/extra-addons/project_task_date_planned +COPY project_task_description_template /mnt/extra-addons/project_task_description_template COPY project_task_full_text_search /mnt/extra-addons/project_task_full_text_search COPY project_type_advanced /mnt/extra-addons/project_type_advanced COPY project_default_task_stage /mnt/extra-addons/project_default_task_stage + COPY .docker_files/main /mnt/extra-addons/main COPY .docker_files/odoo.conf /etc/odoo diff --git a/project_task_description_template/README.rst b/project_task_description_template/README.rst new file mode 100644 index 00000000..4c7d43fb --- /dev/null +++ b/project_task_description_template/README.rst @@ -0,0 +1,34 @@ +Project Task Description Templates +================================== +This module allows to autocomplete descriptions on tasks. + +.. contents:: Table of Contents + +Context +------- +When using ``Projects`` for field interventions for example, the description of tasks is very repetitive. +It is therefore convenient to automatically fill the description with a template. + +Usage +----- +As ``Project / Manager``, I go to ``Project / Configuration / Task Description Templates``. + +I find the list of description templates. + +.. image:: static/description/description_template_list.png + +Each record contains a name and a HTML description. + +.. image:: static/description/description_template_form.png + +In the form view of a task, I can select a description template. + +.. image:: static/description/task_form.png + +The description is automatically copied from the template. + +.. image:: static/description/task_form_description_filled.png + +Contributors +------------ +* Numigi (tm) and all its contributors (https://bit.ly/numigiens) diff --git a/project_task_description_template/__init__.py b/project_task_description_template/__init__.py new file mode 100644 index 00000000..d6a63ca0 --- /dev/null +++ b/project_task_description_template/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/project_task_description_template/__manifest__.py b/project_task_description_template/__manifest__.py new file mode 100644 index 00000000..5aaaeb12 --- /dev/null +++ b/project_task_description_template/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Project Task Description Template", + "version": "16.0.1.0.0", + "author": "Numigi", + "maintainer": "Numigi", + "website": "https://www.numigi.com", + "license": "LGPL-3", + "category": "Project", + "summary": "Autocomplete task descriptions from templates", + "depends": ["project"], + "data": [ + "security/ir.model.access.csv", + "views/project_task_views.xml", + "views/task_description_template_views.xml", + ], + "installable": True, +} diff --git a/project_task_description_template/i18n/fr.po b/project_task_description_template/i18n/fr.po new file mode 100644 index 00000000..bcf64a94 --- /dev/null +++ b/project_task_description_template/i18n/fr.po @@ -0,0 +1,104 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * project_task_description_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-11-22 13:35+0000\n" +"PO-Revision-Date: 2024-11-22 13:35+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: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__active +msgid "Active" +msgstr "Actif" + +#. module: project_task_description_template +#: model_terms:ir.ui.view,arch_db:project_task_description_template.project_task_description_template_search +msgid "Archived" +msgstr "Archivé" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__create_uid +msgid "Created by" +msgstr "Créé par" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__create_date +msgid "Created on" +msgstr "Créé le" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__description +msgid "Description" +msgstr "" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task__description_template_id +msgid "Description Template" +msgstr "Modèle de description" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__display_name +msgid "Display Name" +msgstr "Nom affiché" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__id +msgid "ID" +msgstr "" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template____last_update +msgid "Last Modified on" +msgstr "Dernière modification le" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__write_uid +msgid "Last Updated by" +msgstr "Dernière mise à jour par" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__write_date +msgid "Last Updated on" +msgstr "Dernière mise à jour le" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__name +msgid "Name" +msgstr "Nom" + +#. module: project_task_description_template +#: model:ir.model,name:project_task_description_template.model_project_task_description_template +msgid "Project Task Description Template" +msgstr "Modèles de description de tâches" + +#. module: project_task_description_template +#: model:ir.model.fields,field_description:project_task_description_template.field_project_task_description_template__sequence +msgid "Sequence" +msgstr "Séquence" + +#. module: project_task_description_template +#: model:ir.model,name:project_task_description_template.model_project_task +msgid "Task" +msgstr "Tâche" + +#. module: project_task_description_template +#: model_terms:ir.ui.view,arch_db:project_task_description_template.project_task_description_template_form +msgid "Task Description Template" +msgstr "Modèle de description de tâche" + +#. module: project_task_description_template +#: model:ir.actions.act_window,name:project_task_description_template.project_task_description_template_action +#: model:ir.ui.menu,name:project_task_description_template.project_task_description_template_menu +#: model_terms:ir.ui.view,arch_db:project_task_description_template.project_task_description_template_list +#: model_terms:ir.ui.view,arch_db:project_task_description_template.project_task_description_template_search +msgid "Task Description Templates" +msgstr "Modèles de description de tâches" diff --git a/project_task_description_template/models/__init__.py b/project_task_description_template/models/__init__.py new file mode 100644 index 00000000..a4e313f5 --- /dev/null +++ b/project_task_description_template/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import project_task +from . import project_task_description_template diff --git a/project_task_description_template/models/project_task.py b/project_task_description_template/models/project_task.py new file mode 100644 index 00000000..aebd2b8e --- /dev/null +++ b/project_task_description_template/models/project_task.py @@ -0,0 +1,18 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, fields, models + + +class ProjectTask(models.Model): + + _inherit = "project.task" + + description_template_id = fields.Many2one( + "project.task.description.template", ondelete="restrict" + ) + + @api.onchange("description_template_id") + def _onchange_description_template(self): + if self.description_template_id: + self.description = self.description_template_id.description diff --git a/project_task_description_template/models/project_task_description_template.py b/project_task_description_template/models/project_task_description_template.py new file mode 100644 index 00000000..58add8f7 --- /dev/null +++ b/project_task_description_template/models/project_task_description_template.py @@ -0,0 +1,16 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class ProjectTaskDescriptionTemplate(models.Model): + + _name = "project.task.description.template" + _description = "Project Task Description Template" + _order = "sequence" + + name = fields.Char(required=True) + description = fields.Html() + active = fields.Boolean(default=True) + sequence = fields.Integer() diff --git a/project_task_description_template/security/ir.model.access.csv b/project_task_description_template/security/ir.model.access.csv new file mode 100644 index 00000000..d10b0446 --- /dev/null +++ b/project_task_description_template/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_project_task_description_template_user,project_task_description_template_user,model_project_task_description_template,base.group_user,1,0,0,0 +access_project_task_description_template_manager,project_task_description_template_manager,model_project_task_description_template,project.group_project_manager,1,1,1,1 diff --git a/project_task_description_template/static/description/description_template_form.png b/project_task_description_template/static/description/description_template_form.png new file mode 100644 index 00000000..89fd2c2f Binary files /dev/null and b/project_task_description_template/static/description/description_template_form.png differ diff --git a/project_task_description_template/static/description/description_template_list.png b/project_task_description_template/static/description/description_template_list.png new file mode 100644 index 00000000..7491d504 Binary files /dev/null and b/project_task_description_template/static/description/description_template_list.png differ diff --git a/project_task_description_template/static/description/icon.png b/project_task_description_template/static/description/icon.png new file mode 100644 index 00000000..92a86b10 Binary files /dev/null and b/project_task_description_template/static/description/icon.png differ diff --git a/project_task_description_template/static/description/task_form.png b/project_task_description_template/static/description/task_form.png new file mode 100644 index 00000000..12c0ba2b Binary files /dev/null and b/project_task_description_template/static/description/task_form.png differ diff --git a/project_task_description_template/static/description/task_form_description_filled.png b/project_task_description_template/static/description/task_form_description_filled.png new file mode 100644 index 00000000..d763a5cc Binary files /dev/null and b/project_task_description_template/static/description/task_form_description_filled.png differ diff --git a/project_task_description_template/tests/__init__.py b/project_task_description_template/tests/__init__.py new file mode 100644 index 00000000..f1892a60 --- /dev/null +++ b/project_task_description_template/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_project_task diff --git a/project_task_description_template/tests/test_project_task.py b/project_task_description_template/tests/test_project_task.py new file mode 100644 index 00000000..bb2dbbc0 --- /dev/null +++ b/project_task_description_template/tests/test_project_task.py @@ -0,0 +1,20 @@ +# Copyright 2024-today Numigi and all its contributors (https://bit.ly/numigiens) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests import Form +from odoo.tests.common import TransactionCase + + +class TestProjectTask(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.template = cls.env["project.task.description.template"].create( + {"name": "My Template", "description": "Lorem Ipsum"} + ) + cls.task = cls.env["project.task"].create({"name": "My Task"}) + + def test_onchange_description_template(self): + with Form(self.task) as task_form: + task_form.description_template_id = self.template + assert self.task.description == self.template.description diff --git a/project_task_description_template/views/project_task_views.xml b/project_task_description_template/views/project_task_views.xml new file mode 100644 index 00000000..e33116e3 --- /dev/null +++ b/project_task_description_template/views/project_task_views.xml @@ -0,0 +1,15 @@ + + + + + Task form: Add description template + project.task + + + + + + + + + diff --git a/project_task_description_template/views/task_description_template_views.xml b/project_task_description_template/views/task_description_template_views.xml new file mode 100644 index 00000000..e8f21f31 --- /dev/null +++ b/project_task_description_template/views/task_description_template_views.xml @@ -0,0 +1,60 @@ + + + + + Task Description Template Form + project.task.description.template + +
+
+
+ + + + + + + + +
+
+
+ + + Task Description Template List + project.task.description.template + + + + + + + + + + + Task Description Template Search + project.task.description.template + + + + + + + + + + Task Description Templates + project.task.description.template + tree,form + + + + +