diff --git a/document_page_project_task/README.rst b/document_page_project_task/README.rst new file mode 100644 index 00000000000..7557812bb23 --- /dev/null +++ b/document_page_project_task/README.rst @@ -0,0 +1,267 @@ +========================== +Document Page Project Task +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:792f27beb9e30e02336420e9ffafb95a1a3027dc4b2ff368b4d350c683de3b01 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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%2Fknowledge-lightgray.png?logo=github + :target: https://github.com/OCA/knowledge/tree/16.0/document_page_project_task + :alt: OCA/knowledge +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/knowledge-16-0/knowledge-16-0-document_page_project_task + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/knowledge&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module extends the document page (wiki) functionality by allowing +you to link them directly to project tasks. + +Main Features +------------- + +- **Link Wiki Pages to Tasks**: Allows associating document pages to + specific project tasks +- **Automatic Project Filling**: When a task is selected, the related + project is automatically filled +- **Consistency Validation**: Ensures that the wiki page's project is + always the same as the linked task's project +- **Smart Filtering**: When a project is defined, only tasks from that + project are displayed for selection +- **Page Counter**: Displays the number of wiki pages linked to each + task directly in the task view + +Benefits +-------- + +- Organize project documentation hierarchically (Project → Task → Wiki) +- Keep documentation close to the work context (tasks) +- Avoid inconsistencies between projects and tasks through automatic + validations +- Quickly access documentation related to a specific task + +Dependencies +------------ + +This module requires: + +- ``document_page_project``: Module that links document pages to + projects +- ``project``: Odoo's project management module + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +This module does not require additional configuration after +installation. It works automatically once installed. + +Installation +------------ + +1. Go to the **Apps** menu +2. Remove the "Apps" filter if necessary +3. Search for "Document Page Project Task" +4. Click **Install** + +Prerequisites +------------- + +Make sure the following modules are installed: + +- **Project** (base project module) +- **Document Page Project** (links wiki pages to projects) + +The system will automatically install the necessary dependencies during +installation. + +Permissions +----------- + +The module uses the same access permissions as the base modules: + +- Users with access to **Projects** can view and create wiki pages + linked to tasks +- Users with access to **Documents/Knowledge** can manage wiki page + content + +No additional permission configuration is required. + +Usage +===== + +This guide explains how to use the Document Page Project Task module to +link wiki pages to project tasks. + +Create a Wiki Page from a Task +------------------------------ + +**Method 1: From the Task** + +1. Go to the **Projects** module +2. Open the desired project +3. Select a task +4. In the task view, locate the **Wiki Pages** button (book icon) +5. Click the button to see linked pages or create a new one +6. Click **Create** to add a new wiki page +7. The task and project will be automatically filled + +**Method 2: From the Wiki Page** + +1. Go to the **Knowledge** or **Documents** module +2. Create a new wiki page or edit an existing one +3. In the page form, you will see the fields: + + - **Project**: Select the project + - **Task**: Select the task (only tasks from the selected project + will be displayed) + +4. When you select a task, the project will be automatically filled +5. Save the page + +Automatic Behaviors +------------------- + +**Automatic Project Filling** + +When you select a task: + +- The **Project** field is automatically filled with the task's project +- This ensures consistency between task and project + +**Task Filtering** + +When a project is selected: + +- Only tasks from that project appear in the selection list +- This prevents selecting tasks from different projects + +**Consistency Validation** + +The system automatically validates that: + +- If a task is linked, the project must also be defined +- The wiki page's project must be the same as the linked task's project +- If you try to link a task to a different project, the system will + prevent the operation + +**Automatic Cleanup** + +When you change the project: + +- If the linked task does not belong to the new project, it is + automatically removed +- This maintains data consistency + +View Wiki Pages of a Task +------------------------- + +1. Access a project task +2. At the top of the form, you will see the **Wiki Pages** button with a + counter +3. The displayed number indicates how many wiki pages are linked to the + task +4. Click the button to see all linked pages + +Usage Examples +-------------- + +**Example 1: Requirements Documentation** + +1. Create a task "Define System Requirements" +2. From the task, create a wiki page "Functional Requirements" +3. Document the requirements in the wiki page +4. The page will be linked to the task and project + +**Example 2: Meeting Notes** + +1. Create a task "Planning Meeting" +2. Create a wiki page "Meeting Minutes" +3. Document the discussed points +4. The documentation will be organized and easy to find + +**Example 3: Technical Specifications** + +1. Create a task "Develop Module X" +2. Create a wiki page "Technical Specification" +3. Document the architecture and technical decisions +4. Keep the documentation close to the task work + +Tips +---- + +- Use wiki pages to maintain contextual documentation related to + specific tasks +- The page counter on the task helps quickly identify tasks with + documentation +- When creating a page from the task, fields are automatically filled, + saving time +- Organize project documentation hierarchically: Project → Task → Wiki + +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 `__: + + - Marcel Savegnago + +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. + +.. |maintainer-marcelsavegnago| image:: https://github.com/marcelsavegnago.png?size=40px + :target: https://github.com/marcelsavegnago + :alt: marcelsavegnago + +Current `maintainer `__: + +|maintainer-marcelsavegnago| + +This module is part of the `OCA/knowledge `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/document_page_project_task/__init__.py b/document_page_project_task/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/document_page_project_task/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/document_page_project_task/__manifest__.py b/document_page_project_task/__manifest__.py new file mode 100644 index 00000000000..92116923a9c --- /dev/null +++ b/document_page_project_task/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2025 Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +{ + "name": "Document Page Project Task", + "summary": "This module links document pages to project tasks", + "version": "16.0.1.0.0", + "category": "Project", + "author": "Escodoo, Odoo Community Association (OCA)", + "maintainers": ["marcelsavegnago"], + "website": "https://github.com/OCA/knowledge", + "license": "AGPL-3", + "depends": ["document_page_project"], + "data": ["views/document_page_views.xml", "views/project_task_views.xml"], + "installable": True, +} diff --git a/document_page_project_task/models/__init__.py b/document_page_project_task/models/__init__.py new file mode 100644 index 00000000000..6b90bf138ac --- /dev/null +++ b/document_page_project_task/models/__init__.py @@ -0,0 +1,2 @@ +from . import document_page +from . import project_task diff --git a/document_page_project_task/models/document_page.py b/document_page_project_task/models/document_page.py new file mode 100644 index 00000000000..ddcea42fcbd --- /dev/null +++ b/document_page_project_task/models/document_page.py @@ -0,0 +1,67 @@ +# Copyright 2025 Marcel Savegnago - Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError + + +class DocumentPage(models.Model): + _inherit = "document.page" + + task_id = fields.Many2one(string="Task", comodel_name="project.task") + + @api.onchange("task_id") + def _onchange_task_id(self): + """Fill the project_id field with the task's related project.""" + if self.task_id and self.task_id.project_id: + self.project_id = self.task_id.project_id + + @api.onchange("project_id") + def _onchange_project_id(self): + """Clear the task if the project is removed or changed and does not + match the task's project.""" + if self.task_id: + if not self.project_id or self.task_id.project_id != self.project_id: + self.task_id = False + + @api.constrains("task_id", "project_id") + def _check_task_project_consistency(self): + """Ensure that the project is the same as the task's project when a + task is defined.""" + for record in self: + # If there is a task, there must be a project + if record.task_id and not record.project_id: + raise ValidationError( + _( + "When a task is linked, the project must be defined. " + "Task '%(task)s' requires that the project be defined.", + task=record.task_id.name, + ) + ) + # If there is a task and project, they must be from the same project + if record.task_id and record.project_id: + if record.task_id.project_id != record.project_id: + raise ValidationError( + _( + "The wiki document's project must be the same as the " + "task's project. Task '%(task)s' belongs to project " + "'%(task_project)s', but the document is associated " + "with project '%(doc_project)s'.", + task=record.task_id.name, + task_project=record.task_id.project_id.name, + doc_project=record.project_id.name, + ) + ) + + @api.model + def default_get(self, fields_list): + """Fill the project_id when the wiki is created with default_task_id + in the context.""" + res = super().default_get(fields_list) + if "default_task_id" in self.env.context and "project_id" in fields_list: + task = self.env["project.task"].browse( + self.env.context.get("default_task_id") + ) + if task.exists() and task.project_id: + res["project_id"] = task.project_id.id + return res diff --git a/document_page_project_task/models/project_task.py b/document_page_project_task/models/project_task.py new file mode 100644 index 00000000000..1eabbb52ad6 --- /dev/null +++ b/document_page_project_task/models/project_task.py @@ -0,0 +1,18 @@ +# Copyright 2025 Marcel Savegnago - Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ProjectTask(models.Model): + _inherit = "project.task" + + document_page_ids = fields.One2many( + string="Wiki Pages", comodel_name="document.page", inverse_name="task_id" + ) + document_page_count = fields.Integer(compute="_compute_document_page_count") + + @api.depends("document_page_ids") + def _compute_document_page_count(self): + for rec in self: + rec.document_page_count = len(rec.document_page_ids) diff --git a/document_page_project_task/readme/CONFIGURE.md b/document_page_project_task/readme/CONFIGURE.md new file mode 100644 index 00000000000..8fa021c31b7 --- /dev/null +++ b/document_page_project_task/readme/CONFIGURE.md @@ -0,0 +1,24 @@ +This module does not require additional configuration after installation. It works automatically once installed. + +## Installation + +1. Go to the **Apps** menu +2. Remove the "Apps" filter if necessary +3. Search for "Document Page Project Task" +4. Click **Install** + +## Prerequisites + +Make sure the following modules are installed: +* **Project** (base project module) +* **Document Page Project** (links wiki pages to projects) + +The system will automatically install the necessary dependencies during installation. + +## Permissions + +The module uses the same access permissions as the base modules: +* Users with access to **Projects** can view and create wiki pages linked to tasks +* Users with access to **Documents/Knowledge** can manage wiki page content + +No additional permission configuration is required. diff --git a/document_page_project_task/readme/CONTRIBUTORS.md b/document_page_project_task/readme/CONTRIBUTORS.md new file mode 100644 index 00000000000..efe359c4713 --- /dev/null +++ b/document_page_project_task/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [ESCODOO](https://escodoo.com.br): + - Marcel Savegnago \<\> diff --git a/document_page_project_task/readme/DESCRIPTION.md b/document_page_project_task/readme/DESCRIPTION.md new file mode 100644 index 00000000000..2e69490c4a8 --- /dev/null +++ b/document_page_project_task/readme/DESCRIPTION.md @@ -0,0 +1,22 @@ +This module extends the document page (wiki) functionality by allowing you to link them directly to project tasks. + +## Main Features + +* **Link Wiki Pages to Tasks**: Allows associating document pages to specific project tasks +* **Automatic Project Filling**: When a task is selected, the related project is automatically filled +* **Consistency Validation**: Ensures that the wiki page's project is always the same as the linked task's project +* **Smart Filtering**: When a project is defined, only tasks from that project are displayed for selection +* **Page Counter**: Displays the number of wiki pages linked to each task directly in the task view + +## Benefits + +* Organize project documentation hierarchically (Project → Task → Wiki) +* Keep documentation close to the work context (tasks) +* Avoid inconsistencies between projects and tasks through automatic validations +* Quickly access documentation related to a specific task + +## Dependencies + +This module requires: +* `document_page_project`: Module that links document pages to projects +* `project`: Odoo's project management module diff --git a/document_page_project_task/readme/USAGE.md b/document_page_project_task/readme/USAGE.md new file mode 100644 index 00000000000..21ba5123dba --- /dev/null +++ b/document_page_project_task/readme/USAGE.md @@ -0,0 +1,87 @@ +This guide explains how to use the Document Page Project Task module to link wiki pages to project tasks. + +## Create a Wiki Page from a Task + +**Method 1: From the Task** + +1. Go to the **Projects** module +2. Open the desired project +3. Select a task +4. In the task view, locate the **Wiki Pages** button (book icon) +5. Click the button to see linked pages or create a new one +6. Click **Create** to add a new wiki page +7. The task and project will be automatically filled + +**Method 2: From the Wiki Page** + +1. Go to the **Knowledge** or **Documents** module +2. Create a new wiki page or edit an existing one +3. In the page form, you will see the fields: + * **Project**: Select the project + * **Task**: Select the task (only tasks from the selected project will be displayed) +4. When you select a task, the project will be automatically filled +5. Save the page + +## Automatic Behaviors + +**Automatic Project Filling** + +When you select a task: +* The **Project** field is automatically filled with the task's project +* This ensures consistency between task and project + +**Task Filtering** + +When a project is selected: +* Only tasks from that project appear in the selection list +* This prevents selecting tasks from different projects + +**Consistency Validation** + +The system automatically validates that: +* If a task is linked, the project must also be defined +* The wiki page's project must be the same as the linked task's project +* If you try to link a task to a different project, the system will prevent the operation + +**Automatic Cleanup** + +When you change the project: +* If the linked task does not belong to the new project, it is automatically removed +* This maintains data consistency + +## View Wiki Pages of a Task + +1. Access a project task +2. At the top of the form, you will see the **Wiki Pages** button with a counter +3. The displayed number indicates how many wiki pages are linked to the task +4. Click the button to see all linked pages + +## Usage Examples + +**Example 1: Requirements Documentation** + +1. Create a task "Define System Requirements" +2. From the task, create a wiki page "Functional Requirements" +3. Document the requirements in the wiki page +4. The page will be linked to the task and project + +**Example 2: Meeting Notes** + +1. Create a task "Planning Meeting" +2. Create a wiki page "Meeting Minutes" +3. Document the discussed points +4. The documentation will be organized and easy to find + +**Example 3: Technical Specifications** + +1. Create a task "Develop Module X" +2. Create a wiki page "Technical Specification" +3. Document the architecture and technical decisions +4. Keep the documentation close to the task work + +## Tips + +* Use wiki pages to maintain contextual documentation related to specific tasks +* The page counter on the task helps quickly identify tasks with documentation +* When creating a page from the task, fields are automatically filled, saving time +* Organize project documentation hierarchically: Project → Task → Wiki diff --git a/document_page_project_task/static/description/icon.png b/document_page_project_task/static/description/icon.png new file mode 100644 index 00000000000..3a0328b516c Binary files /dev/null and b/document_page_project_task/static/description/icon.png differ diff --git a/document_page_project_task/static/description/index.html b/document_page_project_task/static/description/index.html new file mode 100644 index 00000000000..0f2c6df3df2 --- /dev/null +++ b/document_page_project_task/static/description/index.html @@ -0,0 +1,600 @@ + + + + + +Document Page Project Task + + + +
+

Document Page Project Task

+ + +

Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runboat

+

This module extends the document page (wiki) functionality by allowing +you to link them directly to project tasks.

+
+

Main Features

+
    +
  • Link Wiki Pages to Tasks: Allows associating document pages to +specific project tasks
  • +
  • Automatic Project Filling: When a task is selected, the related +project is automatically filled
  • +
  • Consistency Validation: Ensures that the wiki page’s project is +always the same as the linked task’s project
  • +
  • Smart Filtering: When a project is defined, only tasks from that +project are displayed for selection
  • +
  • Page Counter: Displays the number of wiki pages linked to each +task directly in the task view
  • +
+
+
+

Benefits

+
    +
  • Organize project documentation hierarchically (Project → Task → Wiki)
  • +
  • Keep documentation close to the work context (tasks)
  • +
  • Avoid inconsistencies between projects and tasks through automatic +validations
  • +
  • Quickly access documentation related to a specific task
  • +
+
+
+

Dependencies

+

This module requires:

+
    +
  • document_page_project: Module that links document pages to +projects
  • +
  • project: Odoo’s project management module
  • +
+

Table of contents

+ +
+

Configuration

+

This module does not require additional configuration after +installation. It works automatically once installed.

+
+
+
+

Installation

+
    +
  1. Go to the Apps menu
  2. +
  3. Remove the “Apps” filter if necessary
  4. +
  5. Search for “Document Page Project Task”
  6. +
  7. Click Install
  8. +
+
+
+

Prerequisites

+

Make sure the following modules are installed:

+
    +
  • Project (base project module)
  • +
  • Document Page Project (links wiki pages to projects)
  • +
+

The system will automatically install the necessary dependencies during +installation.

+
+
+

Permissions

+

The module uses the same access permissions as the base modules:

+
    +
  • Users with access to Projects can view and create wiki pages +linked to tasks
  • +
  • Users with access to Documents/Knowledge can manage wiki page +content
  • +
+

No additional permission configuration is required.

+
+

Usage

+

This guide explains how to use the Document Page Project Task module to +link wiki pages to project tasks.

+
+
+
+

Create a Wiki Page from a Task

+

Method 1: From the Task

+
    +
  1. Go to the Projects module
  2. +
  3. Open the desired project
  4. +
  5. Select a task
  6. +
  7. In the task view, locate the Wiki Pages button (book icon)
  8. +
  9. Click the button to see linked pages or create a new one
  10. +
  11. Click Create to add a new wiki page
  12. +
  13. The task and project will be automatically filled
  14. +
+

Method 2: From the Wiki Page

+
    +
  1. Go to the Knowledge or Documents module
  2. +
  3. Create a new wiki page or edit an existing one
  4. +
  5. In the page form, you will see the fields:
      +
    • Project: Select the project
    • +
    • Task: Select the task (only tasks from the selected project +will be displayed)
    • +
    +
  6. +
  7. When you select a task, the project will be automatically filled
  8. +
  9. Save the page
  10. +
+
+
+

Automatic Behaviors

+

Automatic Project Filling

+

When you select a task:

+
    +
  • The Project field is automatically filled with the task’s project
  • +
  • This ensures consistency between task and project
  • +
+

Task Filtering

+

When a project is selected:

+
    +
  • Only tasks from that project appear in the selection list
  • +
  • This prevents selecting tasks from different projects
  • +
+

Consistency Validation

+

The system automatically validates that:

+
    +
  • If a task is linked, the project must also be defined
  • +
  • The wiki page’s project must be the same as the linked task’s project
  • +
  • If you try to link a task to a different project, the system will +prevent the operation
  • +
+

Automatic Cleanup

+

When you change the project:

+
    +
  • If the linked task does not belong to the new project, it is +automatically removed
  • +
  • This maintains data consistency
  • +
+
+
+

View Wiki Pages of a Task

+
    +
  1. Access a project task
  2. +
  3. At the top of the form, you will see the Wiki Pages button with a +counter
  4. +
  5. The displayed number indicates how many wiki pages are linked to the +task
  6. +
  7. Click the button to see all linked pages
  8. +
+
+
+

Usage Examples

+

Example 1: Requirements Documentation

+
    +
  1. Create a task “Define System Requirements”
  2. +
  3. From the task, create a wiki page “Functional Requirements”
  4. +
  5. Document the requirements in the wiki page
  6. +
  7. The page will be linked to the task and project
  8. +
+

Example 2: Meeting Notes

+
    +
  1. Create a task “Planning Meeting”
  2. +
  3. Create a wiki page “Meeting Minutes”
  4. +
  5. Document the discussed points
  6. +
  7. The documentation will be organized and easy to find
  8. +
+

Example 3: Technical Specifications

+
    +
  1. Create a task “Develop Module X”
  2. +
  3. Create a wiki page “Technical Specification”
  4. +
  5. Document the architecture and technical decisions
  6. +
  7. Keep the documentation close to the task work
  8. +
+
+
+

Tips

+
    +
  • Use wiki pages to maintain contextual documentation related to +specific tasks
  • +
  • The page counter on the task helps quickly identify tasks with +documentation
  • +
  • When creating a page from the task, fields are automatically filled, +saving time
  • +
  • Organize project documentation hierarchically: Project → Task → Wiki
  • +
+
+

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 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.

+

Current maintainer:

+

marcelsavegnago

+

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

+

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

+
+
+ + diff --git a/document_page_project_task/tests/__init__.py b/document_page_project_task/tests/__init__.py new file mode 100644 index 00000000000..8a79e33d2ee --- /dev/null +++ b/document_page_project_task/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_project_task +from . import test_document_page diff --git a/document_page_project_task/tests/test_document_page.py b/document_page_project_task/tests/test_document_page.py new file mode 100644 index 00000000000..2a557875bda --- /dev/null +++ b/document_page_project_task/tests/test_document_page.py @@ -0,0 +1,192 @@ +# Copyright 2025 Marcel Savegnago - Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.exceptions import ValidationError +from odoo.tests import common + + +class TestDocumentPage(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.Page = cls.env["document.page"] + cls.Project = cls.env["project.project"] + cls.Task = cls.env["project.task"] + + cls.project1 = cls.Project.create({"name": "Project 1"}) + cls.project2 = cls.Project.create({"name": "Project 2"}) + cls.task1 = cls.Task.create({"name": "Task 1", "project_id": cls.project1.id}) + cls.task2 = cls.Task.create({"name": "Task 2", "project_id": cls.project2.id}) + + def test_onchange_task_id_fills_project(self): + """Test that when selecting a task, the project is automatically + filled.""" + page = self.Page.new({"name": "Test Page"}) + page.task_id = self.task1 + page._onchange_task_id() + + self.assertEqual( + page.project_id, + self.project1, + "The project should be automatically filled with the task's project", + ) + + def test_onchange_project_id_clears_task(self): + """Test that when changing the project to a different one, the task + is cleared.""" + page = self.Page.new( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + page.project_id = self.project2 + page._onchange_project_id() + + self.assertFalse( + page.task_id, + "The task should be cleared when the project changes to a different one", + ) + + def test_onchange_project_id_clears_task_when_removed(self): + """Test that when removing the project, the task is cleared.""" + page = self.Page.new( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + page.project_id = False + page._onchange_project_id() + + self.assertFalse( + page.task_id, + "The task should be cleared when the project is removed", + ) + + def test_default_get_with_task_in_context(self): + """Test that default_get fills the project when there is default_task_id + in the context.""" + context = {"default_task_id": self.task1.id} + fields_list = ["name", "project_id", "task_id"] + defaults = self.Page.with_context(**context).default_get(fields_list) + + self.assertEqual( + defaults.get("project_id"), + self.project1.id, + "The project_id should be filled with the task's project in context", + ) + self.assertEqual( + defaults.get("task_id"), + self.task1.id, + "The task_id should be filled with the task from context", + ) + + def test_constraint_task_project_consistency_valid(self): + """Test that the constraint allows task and project from the same + project.""" + page = self.Page.create( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + + # Should not raise an exception + self.assertTrue(page.exists()) + + def test_constraint_task_project_consistency_invalid(self): + """Test that the constraint prevents task and project from different + projects.""" + page = self.Page.create( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + + # Trying to change the project to a different one should raise + # ValidationError + with self.assertRaises(ValidationError): + page.project_id = self.project2 + + def test_constraint_task_project_consistency_no_task(self): + """Test that the constraint does not prevent when there is no task.""" + page = self.Page.create({"name": "Test Page", "project_id": self.project1.id}) + + # Should not raise an exception when there is no task + self.assertTrue(page.exists()) + + def test_constraint_task_project_consistency_no_project(self): + """Test that the constraint prevents when there is a task but no + project.""" + # Trying to create a page with a task but without a project should + # raise ValidationError + with self.assertRaises(ValidationError): + self.Page.create({"name": "Test Page", "task_id": self.task1.id}) + + def test_constraint_task_requires_project(self): + """Test that when removing the project when there is a task, it should + raise an error.""" + page = self.Page.create( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + + # Trying to remove the project when there is a task should raise + # ValidationError + with self.assertRaises(ValidationError): + page.project_id = False + + def test_create_page_with_task_sets_project(self): + """Test that when creating a page with a task, the project is set + automatically.""" + # Create page with task_id and project_id defined together + # (the onchange fills the project_id when task_id is defined in the + # form) + page = self.Page.create( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + + self.assertEqual( + page.project_id, + self.project1, + "The project should be the same as the task", + ) + self.assertEqual( + page.task_id, + self.task1, + "The task should be correctly associated", + ) + + def test_write_task_changes_project(self): + """Test that when changing the task, the project should be updated.""" + page = self.Page.create( + { + "name": "Test Page", + "task_id": self.task1.id, + "project_id": self.project1.id, + } + ) + + # Change the task - the project should be updated to match + page.write({"task_id": self.task2.id, "project_id": self.task2.project_id.id}) + + page.invalidate_recordset() + self.assertEqual( + page.project_id, + self.project2, + "The project should match the new task's project", + ) diff --git a/document_page_project_task/tests/test_project_task.py b/document_page_project_task/tests/test_project_task.py new file mode 100644 index 00000000000..38371858e22 --- /dev/null +++ b/document_page_project_task/tests/test_project_task.py @@ -0,0 +1,70 @@ +# Copyright 2025 Marcel Savegnago - Escodoo +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from odoo.tests import common + + +class TestProjectTask(common.TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + + cls.Page = cls.env["document.page"] + cls.Project = cls.env["project.project"] + cls.Task = cls.env["project.task"] + + cls.project = cls.Project.create({"name": "Test Project"}) + cls.task = cls.Task.create({"name": "Test Task", "project_id": cls.project.id}) + cls.default_page = cls.Page.create({"name": "My page"}) + + def test_page_count(self): + """Test the page counter on the task.""" + self.assertEqual( + self.task.document_page_count, + 0, + "Initial page count should be zero", + ) + + # Set task_id and project_id together (the onchange fills project_id) + self.default_page.write( + {"task_id": self.task.id, "project_id": self.task.project_id.id} + ) + self.task._compute_document_page_count() + + self.assertEqual( + self.task.document_page_count, + 1, + "After associating task to document, the count should be one", + ) + self.assertIn( + self.default_page, + self.task.document_page_ids, + "The page should be in the list of document pages for the task", + ) + + def test_page_count_multiple_pages(self): + """Test the counter with multiple pages.""" + page2 = self.Page.create( + { + "name": "Second page", + "task_id": self.task.id, + "project_id": self.task.project_id.id, + } + ) + page3 = self.Page.create( + { + "name": "Third page", + "task_id": self.task.id, + "project_id": self.task.project_id.id, + } + ) + + self.task._compute_document_page_count() + + self.assertEqual( + self.task.document_page_count, + 2, + "Count should be two with two pages associated", + ) + self.assertIn(page2, self.task.document_page_ids) + self.assertIn(page3, self.task.document_page_ids) diff --git a/document_page_project_task/views/document_page_views.xml b/document_page_project_task/views/document_page_views.xml new file mode 100644 index 00000000000..7f727988cec --- /dev/null +++ b/document_page_project_task/views/document_page_views.xml @@ -0,0 +1,36 @@ + + + + document.page.form - document_page_project_task + document.page + + + + + + + + + Task Wiki + document.page + [('type','=','content'), ('task_id', '=', active_id)] + { + 'default_type': 'content', + 'default_task_id': active_id} + tree,form + + + +

+ Click to create a new web page. +

+
+
+
diff --git a/document_page_project_task/views/project_task_views.xml b/document_page_project_task/views/project_task_views.xml new file mode 100644 index 00000000000..24b8d815f76 --- /dev/null +++ b/document_page_project_task/views/project_task_views.xml @@ -0,0 +1,24 @@ + + + + project.task.form - document_page_project_task + project.task + + +
+ +
+
+
+
diff --git a/setup/document_page_project_task/odoo/addons/document_page_project_task b/setup/document_page_project_task/odoo/addons/document_page_project_task new file mode 120000 index 00000000000..9f6ff89a3aa --- /dev/null +++ b/setup/document_page_project_task/odoo/addons/document_page_project_task @@ -0,0 +1 @@ +../../../../document_page_project_task \ No newline at end of file diff --git a/setup/document_page_project_task/setup.py b/setup/document_page_project_task/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/document_page_project_task/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)