From e37c7f1247902a0bad5d9473251b68ee6790cbaf Mon Sep 17 00:00:00 2001 From: Wesley Oliveira Date: Tue, 3 Mar 2026 08:47:19 -0300 Subject: [PATCH 1/2] [ADD] shared_custom_stages: add new module --- .../odoo/addons/shared_custom_stages | 1 + setup/shared_custom_stages/setup.py | 6 + shared_custom_stages/README.rst | 75 +++ shared_custom_stages/__init__.py | 1 + shared_custom_stages/__manifest__.py | 19 + shared_custom_stages/models/__init__.py | 5 + .../models/helpdesk_ticket.py | 9 + shared_custom_stages/models/project_task.py | 9 + .../models/shared_custom_stage.py | 38 ++ .../models/shared_stage_mixin.py | 20 + .../models/unified_task_ticket.py | 121 +++++ shared_custom_stages/pyproject.toml | 3 + shared_custom_stages/readme/CONTRIBUTORS.rst | 3 + shared_custom_stages/readme/DESCRIPTION.rst | 4 + shared_custom_stages/readme/USAGE.rst | 6 + .../security/ir.model.access.csv | 4 + .../security/shared_custom_stage_security.xml | 16 + .../static/description/icon.png | Bin 0 -> 2873 bytes .../static/description/index.html | 433 ++++++++++++++++++ shared_custom_stages/tests/__init__.py | 1 + .../tests/test_unified_task_ticket.py | 100 ++++ .../views/shared_custom_stage_views.xml | 73 +++ .../views/unified_task_ticket_views.xml | 66 +++ 23 files changed, 1013 insertions(+) create mode 120000 setup/shared_custom_stages/odoo/addons/shared_custom_stages create mode 100644 setup/shared_custom_stages/setup.py create mode 100644 shared_custom_stages/README.rst create mode 100644 shared_custom_stages/__init__.py create mode 100644 shared_custom_stages/__manifest__.py create mode 100644 shared_custom_stages/models/__init__.py create mode 100644 shared_custom_stages/models/helpdesk_ticket.py create mode 100644 shared_custom_stages/models/project_task.py create mode 100644 shared_custom_stages/models/shared_custom_stage.py create mode 100644 shared_custom_stages/models/shared_stage_mixin.py create mode 100644 shared_custom_stages/models/unified_task_ticket.py create mode 100644 shared_custom_stages/pyproject.toml create mode 100644 shared_custom_stages/readme/CONTRIBUTORS.rst create mode 100644 shared_custom_stages/readme/DESCRIPTION.rst create mode 100644 shared_custom_stages/readme/USAGE.rst create mode 100644 shared_custom_stages/security/ir.model.access.csv create mode 100644 shared_custom_stages/security/shared_custom_stage_security.xml create mode 100644 shared_custom_stages/static/description/icon.png create mode 100644 shared_custom_stages/static/description/index.html create mode 100644 shared_custom_stages/tests/__init__.py create mode 100644 shared_custom_stages/tests/test_unified_task_ticket.py create mode 100644 shared_custom_stages/views/shared_custom_stage_views.xml create mode 100644 shared_custom_stages/views/unified_task_ticket_views.xml diff --git a/setup/shared_custom_stages/odoo/addons/shared_custom_stages b/setup/shared_custom_stages/odoo/addons/shared_custom_stages new file mode 120000 index 0000000..bf92e46 --- /dev/null +++ b/setup/shared_custom_stages/odoo/addons/shared_custom_stages @@ -0,0 +1 @@ +../../../../shared_custom_stages \ No newline at end of file diff --git a/setup/shared_custom_stages/setup.py b/setup/shared_custom_stages/setup.py new file mode 100644 index 0000000..28c57bb --- /dev/null +++ b/setup/shared_custom_stages/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) diff --git a/shared_custom_stages/README.rst b/shared_custom_stages/README.rst new file mode 100644 index 0000000..9628968 --- /dev/null +++ b/shared_custom_stages/README.rst @@ -0,0 +1,75 @@ +============================ +Shared Custom Stages Unified +============================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:1bd85f0e92a40d3e822f25aaee54894a58d8195cbff24e032641c5e3512d9af7 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-Escodoo%2Fproject--addons-lightgray.png?logo=github + :target: https://github.com/Escodoo/project-addons/tree/16.0/shared_custom_stages + :alt: Escodoo/project-addons + +|badge1| |badge2| |badge3| + +This module centralizes custom stages for Project Tasks and Helpdesk Tickets +into a single management system. It features a unified Kanban view where all +stages remain visible as columns, allowing drag and drop tasks and tickets +between stages. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +* Go to Project > Configuration > Custom Stages. +* Define your stages and set the default stage. +* Navigate to Project > Tasks > Unified Tasks to view and manage all records in a consolidated Kanban interface. +* You can drag tickets and tasks across any column to update their stage. + +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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Escodoo + +Contributors +~~~~~~~~~~~~ + +* `Escodoo `_: + + * Wesley Oliveira + +Maintainers +~~~~~~~~~~~ + +This module is part of the `Escodoo/project-addons `_ project on GitHub. + +You are welcome to contribute. diff --git a/shared_custom_stages/__init__.py b/shared_custom_stages/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/shared_custom_stages/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/shared_custom_stages/__manifest__.py b/shared_custom_stages/__manifest__.py new file mode 100644 index 0000000..c1b1313 --- /dev/null +++ b/shared_custom_stages/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2026 - TODAY, Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Shared Custom Stages Unified", + "summary": "Shared Custom Stages Unified", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "Escodoo", + "website": "https://github.com/Escodoo/project-addons", + "depends": ["project", "helpdesk_mgmt"], + "data": [ + "security/ir.model.access.csv", + "security/shared_custom_stage_security.xml", + "views/shared_custom_stage_views.xml", + "views/unified_task_ticket_views.xml", + ], + "installable": True, +} diff --git a/shared_custom_stages/models/__init__.py b/shared_custom_stages/models/__init__.py new file mode 100644 index 0000000..283ddce --- /dev/null +++ b/shared_custom_stages/models/__init__.py @@ -0,0 +1,5 @@ +from . import shared_custom_stage +from . import shared_stage_mixin +from . import helpdesk_ticket +from . import project_task +from . import unified_task_ticket diff --git a/shared_custom_stages/models/helpdesk_ticket.py b/shared_custom_stages/models/helpdesk_ticket.py new file mode 100644 index 0000000..505bf4b --- /dev/null +++ b/shared_custom_stages/models/helpdesk_ticket.py @@ -0,0 +1,9 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class HelpdeskTicket(models.Model): + _inherit = ["helpdesk.ticket", "shared.stage.mixin"] + _name = "helpdesk.ticket" diff --git a/shared_custom_stages/models/project_task.py b/shared_custom_stages/models/project_task.py new file mode 100644 index 0000000..9759682 --- /dev/null +++ b/shared_custom_stages/models/project_task.py @@ -0,0 +1,9 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ProjectTask(models.Model): + _inherit = ["project.task", "shared.stage.mixin"] + _name = "project.task" diff --git a/shared_custom_stages/models/shared_custom_stage.py b/shared_custom_stages/models/shared_custom_stage.py new file mode 100644 index 0000000..cb58cbb --- /dev/null +++ b/shared_custom_stages/models/shared_custom_stage.py @@ -0,0 +1,38 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class SharedCustomStage(models.Model): + _name = "shared.custom.stage" + _description = "Shared Custom Stage" + _order = "sequence, id" + + name = fields.Char(required=True, translate=True) + sequence = fields.Integer(default=10) + active = fields.Boolean(default=True) + company_id = fields.Many2one( + comodel_name="res.company", + string="Company", + index=True, + ) + is_default = fields.Boolean(string="Default Stage", default=False) + + @api.constrains("is_default", "company_id") + def _check_single_default(self): + for record in self: + if record.is_default: + domain = [("is_default", "=", True), ("id", "!=", record.id)] + if record.company_id: + domain.append(("company_id", "=", record.company_id.id)) + else: + domain.append(("company_id", "=", False)) + + if self.search_count(domain) > 0: + raise ValidationError(_("There can only be one default stage.")) + + @api.model + def _read_group_stage_ids(self, stages, domain, order): + return self.search([], order=order) diff --git a/shared_custom_stages/models/shared_stage_mixin.py b/shared_custom_stages/models/shared_stage_mixin.py new file mode 100644 index 0000000..b0c8809 --- /dev/null +++ b/shared_custom_stages/models/shared_stage_mixin.py @@ -0,0 +1,20 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class SharedStageMixin(models.AbstractModel): + _name = "shared.stage.mixin" + _description = "Shared Stage Mixin" + + custom_stage_id = fields.Many2one( + comodel_name="shared.custom.stage", + string="Custom Stage", + group_expand="_read_group_custom_stage_ids", + tracking=True, + index=True, + ) + + def _read_group_custom_stage_ids(self, stages, domain, order): + return self.env["shared.custom.stage"].search([], order=order) diff --git a/shared_custom_stages/models/unified_task_ticket.py b/shared_custom_stages/models/unified_task_ticket.py new file mode 100644 index 0000000..2acb628 --- /dev/null +++ b/shared_custom_stages/models/unified_task_ticket.py @@ -0,0 +1,121 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models, tools + + +class UnifiedTaskTicket(models.Model): + _name = "unified.task.ticket" + _description = "Unified Task and Ticket View" + _auto = False + _order = "id desc" + + name = fields.Char(string="Title", readonly=True) + icon = fields.Char(string="Display Icon", readonly=True) + res_model = fields.Selection( + [ + ("project.task", "Task"), + ("helpdesk.ticket", "Ticket"), + ], + string="Type", + readonly=True, + ) + res_id = fields.Integer(string="Resource ID", readonly=True) + user_id = fields.Many2one( + comodel_name="res.users", + string="Assigned To", + readonly=True, + ) + company_id = fields.Many2one( + comodel_name="res.company", + string="Company", + readonly=True, + ) + custom_stage_id = fields.Many2one( + comodel_name="shared.custom.stage", + string="Stage", + group_expand="_read_group_custom_stage_ids", + ) + + def _read_group_custom_stage_ids(self, stages, domain, order): + return self.env["shared.custom.stage"].search([], order=order) + + def init(self): + tools.drop_view_if_exists(self.env.cr, self._table) + self.env.cr.execute( + f""" + CREATE OR REPLACE VIEW {self._table} AS ( + SELECT + t.id AS id, + t.id AS res_id, + 'project.task' AS res_model, + 'fa-tasks' AS icon, + t.name AS name, + ( + SELECT user_id + FROM project_task_user_rel + WHERE task_id = t.id LIMIT 1 + ) AS user_id, + t.company_id AS company_id, + COALESCE( + t.custom_stage_id, + ( + SELECT s.id + FROM shared_custom_stage s + WHERE s.is_default = true + AND (s.company_id = t.company_id OR s.company_id IS NULL) + ORDER BY s.company_id DESC + LIMIT 1 + ) + ) AS custom_stage_id + FROM project_task t + + UNION ALL + + SELECT + h.id + 1000000 AS id, + h.id AS res_id, + 'helpdesk.ticket' AS res_model, + 'fa-ticket' AS icon, + h.name AS name, + h.user_id AS user_id, + h.company_id AS company_id, + COALESCE( + h.custom_stage_id, + ( + SELECT s.id + FROM shared_custom_stage s + WHERE s.is_default = true + AND (s.company_id = h.company_id OR s.company_id IS NULL) + ORDER BY s.company_id DESC + LIMIT 1 + ) + ) AS custom_stage_id + FROM helpdesk_ticket h + ) + """ + ) + + def write(self, vals): + # pylint: disable=method-required-super + if "custom_stage_id" in vals: + for record in self: + original_record = ( + self.env[record.res_model].sudo().browse(record.res_id) + ) + original_record.write( + { + "custom_stage_id": vals["custom_stage_id"], + } + ) + return True + + def action_open_record(self): + self.ensure_one() + return { + "type": "ir.actions.act_window", + "res_model": self.res_model, + "res_id": self.res_id, + "view_mode": "form", + "target": "current", + } diff --git a/shared_custom_stages/pyproject.toml b/shared_custom_stages/pyproject.toml new file mode 100644 index 0000000..4231d0c --- /dev/null +++ b/shared_custom_stages/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/shared_custom_stages/readme/CONTRIBUTORS.rst b/shared_custom_stages/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..2f9bd6d --- /dev/null +++ b/shared_custom_stages/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Escodoo `_: + + * Wesley Oliveira diff --git a/shared_custom_stages/readme/DESCRIPTION.rst b/shared_custom_stages/readme/DESCRIPTION.rst new file mode 100644 index 0000000..c4691d4 --- /dev/null +++ b/shared_custom_stages/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module centralizes custom stages for Project Tasks and Helpdesk Tickets +into a single management system. It features a unified Kanban view where all +stages remain visible as columns, allowing drag and drop tasks and tickets +between stages. diff --git a/shared_custom_stages/readme/USAGE.rst b/shared_custom_stages/readme/USAGE.rst new file mode 100644 index 0000000..10c771a --- /dev/null +++ b/shared_custom_stages/readme/USAGE.rst @@ -0,0 +1,6 @@ +To use this module, you need to: + +* Go to Project > Configuration > Custom Stages. +* Define your stages and set the default stage. +* Navigate to Project > Tasks > Unified Tasks to view and manage all records in a consolidated Kanban interface. +* You can drag tickets and tasks across any column to update their stage. diff --git a/shared_custom_stages/security/ir.model.access.csv b/shared_custom_stages/security/ir.model.access.csv new file mode 100644 index 0000000..6e5ecf6 --- /dev/null +++ b/shared_custom_stages/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_shared_custom_stage_user,shared.custom.stage.user,model_shared_custom_stage,project.group_project_user,1,0,0,0 +access_shared_custom_stage_admin,shared.custom.stage.admin,model_shared_custom_stage,project.group_project_manager,1,1,1,1 +access_unified_task_ticket_user,unified.task.ticket.user,model_unified_task_ticket,project.group_project_user,1,1,0,0 diff --git a/shared_custom_stages/security/shared_custom_stage_security.xml b/shared_custom_stages/security/shared_custom_stage_security.xml new file mode 100644 index 0000000..06ad84e --- /dev/null +++ b/shared_custom_stages/security/shared_custom_stage_security.xml @@ -0,0 +1,16 @@ + + + + Shared Custom Stage Multi-Company + + + ["|", ("company_id", "=", False), ("company_id", "in", company_ids)] + + + + + Unified Task Ticket Multi-Company + + [("company_id", "in", company_ids)] + + diff --git a/shared_custom_stages/static/description/icon.png b/shared_custom_stages/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..12ab0051e3b9ac413f0f0016b7cff54f02fc763e GIT binary patch literal 2873 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 XXqTGI$C0NT00000NkvXXu0mjf?G|(} literal 0 HcmV?d00001 diff --git a/shared_custom_stages/static/description/index.html b/shared_custom_stages/static/description/index.html new file mode 100644 index 0000000..9fbd797 --- /dev/null +++ b/shared_custom_stages/static/description/index.html @@ -0,0 +1,433 @@ + + + + + + +Shared Custom Stages Unified + + + +
+

Shared Custom Stages Unified

+ + +

Beta License: AGPL-3 Escodoo/project-addons

+

This module centralizes custom stages for Project Tasks and Helpdesk Tickets +into a single management system. It features a unified Kanban view where all +stages remain visible as columns, allowing drag and drop tasks and tickets +between stages.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  • Go to Project > Configuration > Custom Stages.
  • +
  • Define your stages and set the default stage.
  • +
  • Navigate to Project > Tasks > Unified Tasks to view and manage all records in a consolidated Kanban interface.
  • +
  • You can drag tickets and tasks across any column to update their stage.
  • +
+
+
+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Escodoo
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the Escodoo/project-addons project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/shared_custom_stages/tests/__init__.py b/shared_custom_stages/tests/__init__.py new file mode 100644 index 0000000..4584e93 --- /dev/null +++ b/shared_custom_stages/tests/__init__.py @@ -0,0 +1 @@ +from . import test_unified_task_ticket diff --git a/shared_custom_stages/tests/test_unified_task_ticket.py b/shared_custom_stages/tests/test_unified_task_ticket.py new file mode 100644 index 0000000..794ba85 --- /dev/null +++ b/shared_custom_stages/tests/test_unified_task_ticket.py @@ -0,0 +1,100 @@ +# Copyright 2026 - TODAY, Wesley Oliveira +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestUnifiedTaskTicket(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.company = cls.env.ref("base.main_company") + cls.user = cls.env.user + + cls.default_stage = cls.env["shared.custom.stage"].create( + { + "name": "Default Stage", + "is_default": True, + "company_id": cls.company.id, + "sequence": 1, + } + ) + cls.other_stage = cls.env["shared.custom.stage"].create( + { + "name": "Other Stage", + "is_default": False, + "company_id": cls.company.id, + "sequence": 2, + } + ) + + cls.project = cls.env["project.project"].create({"name": "Test Project"}) + cls.task = cls.env["project.task"].create( + { + "name": "Test Task", + "project_id": cls.project.id, + } + ) + + cls.team = cls.env["helpdesk.ticket.team"].create({"name": "Test Team"}) + cls.ticket = cls.env["helpdesk.ticket"].create( + { + "name": "Test Ticket", + "team_id": cls.team.id, + "description": "Test Ticket", + } + ) + + def test_search_data(self): + """Ensure both tasks and tickets appear in the view with correct icons""" + self.env["unified.task.ticket"].flush_model() + + task_view = self.env["unified.task.ticket"].search( + [("res_model", "=", "project.task"), ("res_id", "=", self.task.id)] + ) + ticket_view = self.env["unified.task.ticket"].search( + [("res_model", "=", "helpdesk.ticket"), ("res_id", "=", self.ticket.id)] + ) + + self.assertTrue(task_view.exists()) + self.assertEqual(task_view.name, "Test Task") + self.assertEqual(task_view.icon, "fa-tasks") + + self.assertTrue(ticket_view.exists()) + self.assertEqual(ticket_view.name, "Test Ticket") + self.assertEqual(ticket_view.icon, "fa-ticket") + + def test_default_stage(self): + """Ensure the view shows the default stage when no custom_stage_id is set""" + self.task.write({"custom_stage_id": False}) + self.env["unified.task.ticket"].flush_model() + + view_record = self.env["unified.task.ticket"].search( + [("res_model", "=", "project.task"), ("res_id", "=", self.task.id)] + ) + + self.assertEqual(view_record.custom_stage_id.id, self.default_stage.id) + + def test_change_stage_id(self): + """Ensure writing to the view updates the actual underlying record""" + view_record = self.env["unified.task.ticket"].search( + [("res_model", "=", "project.task"), ("res_id", "=", self.task.id)] + ) + + view_record.write({"custom_stage_id": self.other_stage.id}) + + self.assertEqual(self.task.custom_stage_id.id, self.other_stage.id) + + def test_action_open_record(self): + """Ensure the action returns the correct dictionary for navigation""" + view_record = self.env["unified.task.ticket"].search( + [("res_model", "=", "helpdesk.ticket"), ("res_id", "=", self.ticket.id)] + ) + + action = view_record.action_open_record() + + self.assertEqual(action["res_model"], "helpdesk.ticket") + self.assertEqual(action["res_id"], self.ticket.id) + self.assertEqual(action["view_mode"], "form") + self.assertEqual(action["type"], "ir.actions.act_window") diff --git a/shared_custom_stages/views/shared_custom_stage_views.xml b/shared_custom_stages/views/shared_custom_stage_views.xml new file mode 100644 index 0000000..bab979d --- /dev/null +++ b/shared_custom_stages/views/shared_custom_stage_views.xml @@ -0,0 +1,73 @@ + + + + + shared.custom.stage.tree + shared.custom.stage + + + + + + + + + + + + + shared.custom.stage.form + shared.custom.stage + +
+ + +
+
+ + + + + + + + + + +
+
+
+
+ + + Custom Stages + shared.custom.stage + tree,form + + + +
diff --git a/shared_custom_stages/views/unified_task_ticket_views.xml b/shared_custom_stages/views/unified_task_ticket_views.xml new file mode 100644 index 0000000..4007a25 --- /dev/null +++ b/shared_custom_stages/views/unified_task_ticket_views.xml @@ -0,0 +1,66 @@ + + + + + unified.task.ticket.kanban + unified.task.ticket + + + + + + + +
+
+
+ + + +
+
+ + + +
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+ + + Unified Tasks + unified.task.ticket + kanban,tree + + + +
From 36779af2f580cea5214edc0886adcca26481078c Mon Sep 17 00:00:00 2001 From: Wesley Oliveira Date: Tue, 3 Mar 2026 08:50:38 -0300 Subject: [PATCH 2/2] [IMP] project-addons: copier update --- .copier-answers.yml | 10 ++-- .eslintrc.yml | 1 + .gitattributes | 1 + .github/workflows/pre-commit.yml | 19 ++++++-- .github/workflows/stale.yml | 4 +- .github/workflows/test.yml | 19 ++++++-- .gitignore | 14 ++++++ .pre-commit-config.yaml | 58 ++++++++++++++++++----- .pylintrc | 81 ++++++++++++++++---------------- .pylintrc-mandatory | 62 ++++++++++++------------ README.md | 4 +- 11 files changed, 173 insertions(+), 100 deletions(-) create mode 100644 .gitattributes diff --git a/.copier-answers.yml b/.copier-answers.yml index 1b96b61..d8a033e 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,8 +1,9 @@ # Do NOT update manually; changes here will be overwritten by Copier -_commit: v1.14.2 +_commit: v1.39 _src_path: https://github.com/oca/oca-addons-repo-template.git ci: GitHub -dependency_installation_mode: PIP +convert_readme_fragments_to_markdown: false +enable_checklog_odoo: false generate_requirements_txt: true github_check_license: true github_ci_extra_env: {} @@ -11,6 +12,7 @@ github_enable_makepot: true github_enable_stale_action: true github_enforce_dev_status_compatibility: true include_wkhtmltopdf: false +odoo_test_flavor: Both odoo_version: 16.0 org_name: Escodoo org_slug: Escodoo @@ -19,6 +21,6 @@ repo_description: Escodoo add-ons used to extend or customize Odoo Project app f repo_name: Escodoo Project Addons repo_slug: project-addons repo_website: https://github.com/Escodoo/project-addons -travis_apt_packages: [] -travis_apt_sources: [] +use_pyproject_toml: false +use_ruff: false diff --git a/.eslintrc.yml b/.eslintrc.yml index 9429bc6..fed88d7 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -22,6 +22,7 @@ globals: odoo: readonly openerp: readonly owl: readonly + luxon: readonly # Styling is handled by Prettier, so we only need to enable AST rules; # see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..e0d5668 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +test-requirements.txt merge=union diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 23e6e58..43b82fe 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -13,11 +13,15 @@ jobs: pre-commit: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: 'pip' + cache-dependency-path: '.pre-commit-config.yaml' - name: Get python version run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} @@ -25,6 +29,15 @@ jobs: run: pip install pre-commit - name: Run pre-commit run: pre-commit run --all-files --show-diff-on-failure --color=always + env: + # Consider valid a PR that changes README fragments but doesn't + # change the README.rst file itself. It's not really a problem + # because the bot will update it anyway after merge. This way, we + # lower the barrier for functional contributors that want to fix the + # readme fragments, while still letting developers get README + # auto-generated (which also helps functionals when using runboat). + # DOCS https://pre-commit.com/#temporarily-disabling-hooks + SKIP: oca-gen-addon-readme - name: Check that all files generated by pre-commit are in git run: | newfiles="$(git ls-files --others --exclude-from=.gitignore)" diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1693a12..fa17fcd 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Stale PRs and issues policy - uses: actions/stale@v4 + uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # General settings. @@ -48,7 +48,7 @@ jobs: # * Issues that are pending more information # * Except Issues marked as "no stale" - name: Needs more information stale issues policy - uses: actions/stale@v4 + uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} ascending: true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c56534e..175beac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest name: Detect unreleased dependencies steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - run: | for reqfile in requirements.txt test-requirements.txt ; do if [ -f ${reqfile} ] ; then @@ -36,13 +36,13 @@ jobs: matrix: include: - container: ghcr.io/oca/oca-ci/py3.10-odoo16.0:latest - makepot: "true" name: test with Odoo - container: ghcr.io/oca/oca-ci/py3.10-ocb16.0:latest name: test with OCB + makepot: "true" services: postgres: - image: postgres:12.0 + image: postgres:12 env: POSTGRES_USER: odoo POSTGRES_PASSWORD: odoo @@ -50,7 +50,7 @@ jobs: ports: - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: persist-credentials: false - name: Install addons and dependencies @@ -63,7 +63,16 @@ jobs: run: oca_init_test_database - name: Run tests run: oca_run_tests - - uses: codecov/codecov-action@v1 + - name: Upload screenshots from JS tests + uses: actions/upload-artifact@v4 + if: ${{ failure() }} + with: + name: Screenshots of failed JS tests - ${{ matrix.name }}${{ join(matrix.include) }} + path: /tmp/odoo_tests/${{ env.PGDATABASE }} + if-no-files-found: ignore + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} - name: Update .pot files run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }} if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'Escodoo' }} diff --git a/.gitignore b/.gitignore index 9c283fd..6ec07a0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ __pycache__/ *.py[cod] /.venv /.pytest_cache +/.ruff_cache # C extensions *.so @@ -24,6 +25,19 @@ var/ *.egg *.eggs +# Windows installers +*.msi + +# Debian packages +*.deb + +# Redhat packages +*.rpm + +# MacOS packages +*.dmg +*.pkg + # Installer logs pip-log.txt pip-delete-this-directory.txt diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 68cf65c..34d92d1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,13 +5,19 @@ exclude: | # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| # We don't want to mess with tool-generated files - .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| + .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/|^eslint.config.cjs|^prettier.config.cjs| # Maybe reactivate this when all README files include prettier ignore tags? ^README\.md$| # Library files can have extraneous formatting (even minimized) /static/(src/)?lib/| # Repos using Sphinx to generate docs don't need prettying ^docs/_templates/.*\.html$| + # Don't bother non-technical authors with formatting issues in docs + readme/.*\.(rst|md)$| + # Ignore build and dist directories in addons + /build/|/dist/| + # Ignore test files in addons + /tests/samples/.*| # You don't usually want a bot to modify your legal texts (LICENSE.*|COPYING.*) default_language_version: @@ -33,12 +39,27 @@ repos: language: fail files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools - rev: 4cd2b852214dead80822e93e6749b16f2785b2fe + rev: f9b919b9868143135a9c9cb03021089cabba8223 hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons - id: oca-fix-manifest-website args: ["https://github.com/Escodoo/project-addons"] + - id: oca-gen-addon-readme + args: + - --addons-dir=. + - --branch=16.0 + - --org-name=Escodoo + - --repo-name=project-addons + - --if-source-changed + - --keep-source-digest + - repo: https://github.com/OCA/odoo-pre-commit-hooks + rev: v0.0.25 + hooks: + - id: oca-checks-odoo-module + - id: oca-checks-po + args: + - --disable=po-pretty-format - repo: https://github.com/myint/autoflake rev: v1.6.1 hooks: @@ -54,25 +75,36 @@ repos: rev: 22.8.0 hooks: - id: black - - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.7.1 + - repo: local hooks: - id: prettier name: prettier (with plugin-xml) + entry: prettier + args: + - --write + - --list-different + - --ignore-unknown + types: [text] + files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ + language: node additional_dependencies: - "prettier@2.7.1" - "@prettier/plugin-xml@2.2.0" - args: - - --plugin=@prettier/plugin-xml - files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ - - repo: https://github.com/pre-commit/mirrors-eslint - rev: v8.24.0 + - repo: local hooks: - id: eslint - verbose: true + name: eslint + entry: eslint args: - --color - --fix + verbose: true + types: [javascript] + language: node + additional_dependencies: + - "eslint@8.24.0" + - "eslint-plugin-jsdoc@" + - "globals@" - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.3.0 hooks: @@ -109,7 +141,7 @@ repos: - --settings=. exclude: /__init__\.py$ - repo: https://github.com/acsone/setuptools-odoo - rev: 3.1.8 + rev: 3.3.2 hooks: - id: setuptools-odoo-make-default - id: setuptools-odoo-get-requirements @@ -119,13 +151,13 @@ repos: - --header - "# generated from manifests external_dependencies" - repo: https://github.com/PyCQA/flake8 - rev: 3.9.2 + rev: 5.0.0 hooks: - id: flake8 name: flake8 additional_dependencies: ["flake8-bugbear==21.9.2"] - repo: https://github.com/OCA/pylint-odoo - rev: 7.0.2 + rev: v8.0.19 hooks: - id: pylint_odoo name: pylint with optional checks diff --git a/.pylintrc b/.pylintrc index f7b431b..3f3c511 100644 --- a/.pylintrc +++ b/.pylintrc @@ -5,12 +5,12 @@ load-plugins=pylint_odoo score=n [ODOOLINT] -readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" -manifest_required_authors=Escodoo -manifest_required_keys=license -manifest_deprecated_keys=description,active -license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=16.0 +readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest-required-authors=Escodoo +manifest-required-keys=license +manifest-deprecated-keys=description,active +license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 +valid-odoo-versions=16.0 [MESSAGES CONTROL] disable=all @@ -25,19 +25,25 @@ disable=all enable=anomalous-backslash-in-string, api-one-deprecated, api-one-multi-together, - assignment-from-none, - attribute-deprecated, class-camelcase, - dangerous-default-value, dangerous-view-replace-wo-priority, - development-status-allowed, duplicate-id-csv, - duplicate-key, duplicate-xml-fields, duplicate-xml-record-id, eval-referenced, - eval-used, incoherent-interpreter-exec-perm, + openerp-exception-warning, + redundant-modulename-xml, + relative-import, + rst-syntax-error, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + assignment-from-none, + attribute-deprecated, + dangerous-default-value, + development-status-allowed, + duplicate-key, + eval-used, license-allowed, manifest-author-string, manifest-deprecated-key, @@ -48,73 +54,68 @@ enable=anomalous-backslash-in-string, method-inverse, method-required-super, method-search, - openerp-exception-warning, pointless-statement, pointless-string-statement, print-used, redundant-keyword-arg, - redundant-modulename-xml, reimported, - relative-import, return-in-init, - rst-syntax-error, sql-injection, too-few-format-args, translation-field, translation-required, unreachable, use-vim-comment, - wrong-tabs-instead-of-spaces, - xml-syntax-error, - attribute-string-redundant, character-not-valid-in-resource-link, - consider-merging-classes-inherited, - context-overridden, create-user-wo-reset-password, dangerous-filter-wo-user, dangerous-qweb-replace-wo-priority, deprecated-data-xml-node, deprecated-openerp-xml-node, duplicate-po-message-definition, - except-pass, file-not-used, + missing-newline-extrafiles, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + str-format-used, + unnecessary-utf8-coding-comment, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + attribute-string-redundant, + consider-merging-classes-inherited, + context-overridden, + except-pass, invalid-commit, manifest-maintainers-list, - missing-newline-extrafiles, missing-readme, missing-return, odoo-addons-relative-import, - old-api7-method-defined, - po-msgstr-variables, - po-syntax-error, renamed-field-parameter, resource-not-exist, - str-format-used, test-folder-imported, translation-contains-variable, translation-positional-used, - unnecessary-utf8-coding-comment, website-manifest-key-not-valid-uri, - xml-attribute-translatable, - xml-deprecated-qweb-directive, - xml-deprecated-tree-attribute, external-request-timeout, - # messages that do not cause the lint step to fail - consider-merging-classes-inherited, + missing-manifest-dependency, + too-complex,, create-user-wo-reset-password, dangerous-filter-wo-user, - deprecated-module, file-not-used, - invalid-commit, - missing-manifest-dependency, missing-newline-extrafiles, - missing-readme, no-utf8-coding-comment, - odoo-addons-relative-import, old-api7-method-defined, + unnecessary-utf8-coding-comment, + # messages that do not cause the lint step to fail + consider-merging-classes-inherited, + deprecated-module, + invalid-commit, + missing-readme, + odoo-addons-relative-import, redefined-builtin, - too-complex, - unnecessary-utf8-coding-comment + manifest-external-assets [REPORTS] diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory index 07a91c9..783ade3 100644 --- a/.pylintrc-mandatory +++ b/.pylintrc-mandatory @@ -4,12 +4,12 @@ load-plugins=pylint_odoo score=n [ODOOLINT] -readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" -manifest_required_authors=Escodoo -manifest_required_keys=license -manifest_deprecated_keys=description,active -license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=16.0 +readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" +manifest-required-authors=Escodoo +manifest-required-keys=license +manifest-deprecated-keys=description,active +license-allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 +valid-odoo-versions=16.0 [MESSAGES CONTROL] disable=all @@ -17,19 +17,25 @@ disable=all enable=anomalous-backslash-in-string, api-one-deprecated, api-one-multi-together, - assignment-from-none, - attribute-deprecated, class-camelcase, - dangerous-default-value, dangerous-view-replace-wo-priority, - development-status-allowed, duplicate-id-csv, - duplicate-key, duplicate-xml-fields, duplicate-xml-record-id, eval-referenced, - eval-used, incoherent-interpreter-exec-perm, + openerp-exception-warning, + redundant-modulename-xml, + relative-import, + rst-syntax-error, + wrong-tabs-instead-of-spaces, + xml-syntax-error, + assignment-from-none, + attribute-deprecated, + dangerous-default-value, + development-status-allowed, + duplicate-key, + eval-used, license-allowed, manifest-author-string, manifest-deprecated-key, @@ -40,56 +46,50 @@ enable=anomalous-backslash-in-string, method-inverse, method-required-super, method-search, - openerp-exception-warning, pointless-statement, pointless-string-statement, print-used, redundant-keyword-arg, - redundant-modulename-xml, reimported, - relative-import, return-in-init, - rst-syntax-error, sql-injection, too-few-format-args, translation-field, translation-required, unreachable, use-vim-comment, - wrong-tabs-instead-of-spaces, - xml-syntax-error, - attribute-string-redundant, character-not-valid-in-resource-link, - consider-merging-classes-inherited, - context-overridden, create-user-wo-reset-password, dangerous-filter-wo-user, dangerous-qweb-replace-wo-priority, deprecated-data-xml-node, deprecated-openerp-xml-node, duplicate-po-message-definition, - except-pass, file-not-used, + missing-newline-extrafiles, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + str-format-used, + unnecessary-utf8-coding-comment, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + attribute-string-redundant, + consider-merging-classes-inherited, + context-overridden, + except-pass, invalid-commit, manifest-maintainers-list, - missing-newline-extrafiles, missing-readme, missing-return, odoo-addons-relative-import, - old-api7-method-defined, - po-msgstr-variables, - po-syntax-error, renamed-field-parameter, resource-not-exist, - str-format-used, test-folder-imported, translation-contains-variable, translation-positional-used, - unnecessary-utf8-coding-comment, website-manifest-key-not-valid-uri, - xml-attribute-translatable, - xml-deprecated-qweb-directive, - xml-deprecated-tree-attribute, external-request-timeout [REPORTS] diff --git a/README.md b/README.md index 93a9220..068b266 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ + +# Escodoo Project Addons [![Pre-commit Status](https://github.com/Escodoo/project-addons/actions/workflows/pre-commit.yml/badge.svg?branch=16.0)](https://github.com/Escodoo/project-addons/actions/workflows/pre-commit.yml?query=branch%3A16.0) [![Build Status](https://github.com/Escodoo/project-addons/actions/workflows/test.yml/badge.svg?branch=16.0)](https://github.com/Escodoo/project-addons/actions/workflows/test.yml?query=branch%3A16.0) @@ -7,8 +9,6 @@ -# Escodoo Project Addons - Escodoo add-ons used to extend or customize Odoo Project app functions.