Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TA#72203 [MIG][16.0] project_task_subtask_same_project #458

Open
wants to merge 4 commits into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .docker_files/main/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@
"project_task_editable_list_view",
"project_task_full_text_search",
"project_task_resource_type",
"project_time_range",
"project_task_stage_external_mail",
"project_task_subtask_same_project",
"project_time_range",
"project_track_end_date",
"project_type_advanced",
],
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ COPY project_task_editable_list_view /mnt/extra-addons/project_task_editable_lis
COPY project_task_full_text_search /mnt/extra-addons/project_task_full_text_search
COPY project_task_resource_type /mnt/extra-addons/project_task_resource_type
COPY project_task_stage_external_mail /mnt/extra-addons/project_task_stage_external_mail
COPY project_task_subtask_same_project /mnt/extra-addons/project_task_subtask_same_project
COPY project_time_range /mnt/extra-addons/project_time_range
COPY project_track_end_date /mnt/extra-addons/project_track_end_date
COPY project_type_advanced /mnt/extra-addons/project_type_advanced
Expand Down
22 changes: 22 additions & 0 deletions project_task_subtask_same_project/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
Project Task Subtask Same Project
=================================
Force the subtasks to be on the same project than its parent.


When attempting to assign a subtask to a task from a different project,
an error message is displayed

.. image:: static/description/subtask_in_different_project.png

Project Readonly on Subtask
---------------------------
On the form view of a subtask, the project is readonly.
The value is automatically propagated from the parent task.

.. image:: static/description/subtask_project_readonly.png



Contributors
------------
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
4 changes: 4 additions & 0 deletions project_task_subtask_same_project/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import models

Check notice on line 4 in project_task_subtask_same_project/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_task_subtask_same_project/__init__.py#L4

'.models' imported but unused (F401)
19 changes: 19 additions & 0 deletions project_task_subtask_same_project/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

{

Check warning on line 4 in project_task_subtask_same_project/__manifest__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_task_subtask_same_project/__manifest__.py#L4

Statement seems to have no effect
"name": "Project Task Subtask Same Project",
"version": "16.0.1.0.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://bit.ly/numigi-com",
"license": "LGPL-3",
"category": "Project",
"summary": "Constrain a subtask to be on the same project that its parent.",
"depends": ["project"],
"data": [
"data/res_config_data.xml",
"views/project_task_views.xml",
],
"installable": True,
}
12 changes: 12 additions & 0 deletions project_task_subtask_same_project/data/res_config_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<data>
<record model="res.config.settings" id="res_config_settings">
<field name="group_subtask_project" eval="1" />
</record>

<function model="res.config.settings" name="execute">
<value eval="[ref('res_config_settings')]" />
</function>
</data>
</odoo>
32 changes: 32 additions & 0 deletions project_task_subtask_same_project/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * project_task_subtask_same_project
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-27 10:44+0000\n"
"PO-Revision-Date: 2024-11-27 10:44+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"

#. module: project_task_subtask_same_project
#: model:ir.model,name:project_task_subtask_same_project.model_project_task
msgid "Task"
msgstr "Tâche"

#. module: project_task_subtask_same_project
#. odoo-python
#: code:addons/project_task_subtask_same_project/models/project_task.py:0
#, python-format
msgid ""
"The task {task} is in the project {task_project}. The subtask {subtask} must"
" be in the same project."
msgstr ""
"La tâche {task} est dans le projet {task_project}. La sous-tâche {subtask} "
"doit être dans le même projet."
4 changes: 4 additions & 0 deletions project_task_subtask_same_project/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import project_task

Check notice on line 4 in project_task_subtask_same_project/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_task_subtask_same_project/models/__init__.py#L4

'.project_task' imported but unused (F401)
37 changes: 37 additions & 0 deletions project_task_subtask_same_project/models/project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from odoo import models, _
from odoo.exceptions import ValidationError


class ProjectTaskSubtaskSameProject(models.Model):
_inherit = "project.task"

def _check_subtask_not_in_different_project(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @rivo2302
It would be preferable to use @api.constrains here instead of calling the check in the write() method.

subtasks = self.filtered(lambda t: t.parent_id)
for subtask in subtasks:
task = subtask.parent_id
if subtask.project_id != task.project_id:
raise ValidationError(
_(
"The task {task} is in the project {task_project}. "
"The subtask {subtask} must be in the same project."
).format(
task=task.display_name,
task_project=task.project_id.display_name,
subtask=subtask.display_name,
)
)

def write(self, vals):
"""
Propagate the value of the project to the subtask when it
is changed on the parent task.
"""
res = super().write(vals)
for task in self:
if task.child_ids and "project_id" in vals:
task.child_ids.write({"project_id": vals["project_id"]})
Copy link
Contributor

@majouda majouda Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @rivo2302
I tested this code, but it's not working.
I'm unsure whether to keep it or not since it's not mentioned in the README.
I don't understand how the unit tests are passing without any issues.
Could you please verify this?

task._check_subtask_not_in_different_project()
return res
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions project_task_subtask_same_project/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

from . import test_project_task
51 changes: 51 additions & 0 deletions project_task_subtask_same_project/tests/test_project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2024 Numigi (tm) and all its contributors (https://bit.ly/numigiens)
# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl).

import pytest
from odoo.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestProjectTaskSubTaskSameProject(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.project_a = cls.env["project.project"].create({"name": "projectA"})
cls.project_b = cls.env["project.project"].create({"name": "projectB"})
cls.task_parent = cls.env["project.task"].create(
{"name": "Task Parent", "project_id": cls.project_a.id}
)
cls.subtask_1 = cls.env["project.task"].create(
{
"name": "Task Child 1",
"project_id": cls.task_parent.project_id.id,
"parent_id": cls.task_parent.id,
"planned_hours": 1.0,
}
)
cls.subtask_2 = cls.env["project.task"].create(
{
"name": "Task Child 2",
"project_id": cls.task_parent.project_id.id,
"parent_id": cls.task_parent.id,
"planned_hours": 1.0,
}
)

def test_whenParentTaskChangeProject_thenSubTaskInheritNewProject(self):
"""
Given a parent task is on project A
And the subtasks are on project A too

When the parent task is changed to project B

Then the subtasks are changed to project B too.
"""
self.task_parent.project_id = self.project_b.id

assert self.subtask_1.project_id == self.project_b
assert self.subtask_2.project_id == self.project_b

def test_onUpdateSubtask_ifNotSameProject_raiseError(self):
with pytest.raises(ValidationError):
self.subtask_1.project_id = self.project_b
29 changes: 29 additions & 0 deletions project_task_subtask_same_project/views/project_task_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>

<record id="view_task_form2" model="ir.ui.view">
<field name="name">Project task: Project Readonly for Subtasks</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_form2"/>
<field name="arch" type="xml">
<field name="display_project_id" position="attributes">
<attribute name="attrs">{'readonly': [('parent_id', '!=', False)],'invisible': [('parent_id', '=', False)]}</attribute>
</field>
</field>
</record>

<record id="view_task_kanban" model="ir.ui.view">
<field name="name">Project task: Project Readonly for Subtasks Kanban</field>
<field name="model">project.task</field>
<field name="inherit_id" ref="project.view_task_kanban"/>
<field name="arch" type="xml">
<field name="project_id" position="after">
<field name="parent_id" invisible="1"/>
</field>
<field name="project_id" position="attributes">
<attribute name="attrs">{'readonly': [('parent_id', '!=', False)]}</attribute>
</field>
</field>
</record>

</odoo>
Loading