From c6b64112a1b03048b2925a14d8ff7787f3e87473 Mon Sep 17 00:00:00 2001 From: Marcel Savegnago Date: Thu, 6 Nov 2025 19:06:29 -0300 Subject: [PATCH] [ADD] document_page_project_task: add new module --- document_page_project_task/README.rst | 267 ++++++++ document_page_project_task/__init__.py | 1 + document_page_project_task/__manifest__.py | 16 + document_page_project_task/models/__init__.py | 2 + .../models/document_page.py | 67 ++ .../models/project_task.py | 18 + .../readme/CONFIGURE.md | 24 + .../readme/CONTRIBUTORS.md | 2 + .../readme/DESCRIPTION.md | 22 + document_page_project_task/readme/USAGE.md | 87 +++ .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 600 ++++++++++++++++++ document_page_project_task/tests/__init__.py | 2 + .../tests/test_document_page.py | 192 ++++++ .../tests/test_project_task.py | 70 ++ .../views/document_page_views.xml | 36 ++ .../views/project_task_views.xml | 24 + .../odoo/addons/document_page_project_task | 1 + setup/document_page_project_task/setup.py | 6 + 19 files changed, 1437 insertions(+) create mode 100644 document_page_project_task/README.rst create mode 100644 document_page_project_task/__init__.py create mode 100644 document_page_project_task/__manifest__.py create mode 100644 document_page_project_task/models/__init__.py create mode 100644 document_page_project_task/models/document_page.py create mode 100644 document_page_project_task/models/project_task.py create mode 100644 document_page_project_task/readme/CONFIGURE.md create mode 100644 document_page_project_task/readme/CONTRIBUTORS.md create mode 100644 document_page_project_task/readme/DESCRIPTION.md create mode 100644 document_page_project_task/readme/USAGE.md create mode 100644 document_page_project_task/static/description/icon.png create mode 100644 document_page_project_task/static/description/index.html create mode 100644 document_page_project_task/tests/__init__.py create mode 100644 document_page_project_task/tests/test_document_page.py create mode 100644 document_page_project_task/tests/test_project_task.py create mode 100644 document_page_project_task/views/document_page_views.xml create mode 100644 document_page_project_task/views/project_task_views.xml create mode 120000 setup/document_page_project_task/odoo/addons/document_page_project_task create mode 100644 setup/document_page_project_task/setup.py 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 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 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, +)