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#72216 [MIG][16.0] timesheet_task_project_no_change #55

Merged
merged 5 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .docker_files/main/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"depends": [
"hr_timesheet_project_parent_enhanced",
"project_timesheet_time_control_sheet",
"timesheet_task_project_no_change",
],
"installable": True,
}
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ USER odoo

COPY hr_timesheet_project_parent_enhanced /mnt/extra-addons/hr_timesheet_project_parent_enhanced
COPY project_timesheet_time_control_sheet /mnt/extra-addons/project_timesheet_time_control_sheet
COPY timesheet_task_project_no_change /mnt/extra-addons/timesheet_task_project_no_change

COPY .docker_files/main /mnt/extra-addons/main
COPY .docker_files/odoo.conf /etc/odoo
23 changes: 23 additions & 0 deletions timesheet_task_project_no_change/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Timesheet Task Project No Change
================================

Usage
-----

As a user of the **Project** module, when attempting to change the project of a task:

1. If timesheets have already been recorded on the task, a blocking message will appear:

.. image:: static/description/task_timesheet_error.png
:alt: Blocking error when task has timesheets

2. If timesheets have been recorded on a subtask, a similar blocking message will appear:

.. image:: static/description/subtask_timesheet_error.png
:alt: Blocking error when subtask has timesheets

3. In both cases, the task's project cannot be changed unless no timesheets exist for the task or its subtasks.

Contributors
------------
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
4 changes: 4 additions & 0 deletions timesheet_task_project_no_change/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 - today 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 timesheet_task_project_no_change/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

timesheet_task_project_no_change/__init__.py#L4

'.models' imported but unused (F401)
15 changes: 15 additions & 0 deletions timesheet_task_project_no_change/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2024 - today 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 timesheet_task_project_no_change/__manifest__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

timesheet_task_project_no_change/__manifest__.py#L4

Statement seems to have no effect
"name": "Timesheet Task Project No Change",
"version": "16.0.1.0.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://bit.ly/numigi-com",
"license": "LGPL-3",
"category": "Project",
"summary": "Prevent changing the project on a task with timesheets.",
"depends": ["hr_timesheet"],
"installable": True,
}
47 changes: 47 additions & 0 deletions timesheet_task_project_no_change/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * timesheet_task_project_no_change
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-12-03 11:49+0000\n"
"PO-Revision-Date: 2024-12-03 11:49+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: timesheet_task_project_no_change
#: model:ir.model,name:timesheet_task_project_no_change.model_project_task
msgid "Task"
msgstr "Tâche"

#. module: timesheet_task_project_no_change
#. odoo-python
#: code:addons/timesheet_task_project_no_change/models/project_task.py:0
#, python-format
msgid ""
"Timesheets have already been entered on a sub-task ({subtask}). In order to "
"modify the project of the parent task ({task}), there must be no time on the"
" parent task, nor on its child tasks."
msgstr ""
"Du temps a été saisi une des tâches enfant ({subtask}). Pour modifier le "
"projet de la tâche parente ({task}), il ne doit pas y avoir de temps saisi "
"sur celle-ci ou sur ses tâches enfants."

#. module: timesheet_task_project_no_change
#. odoo-python
#: code:addons/timesheet_task_project_no_change/models/project_task.py:0
#, python-format
msgid ""
"Timesheets have already been entered on this task ({task}). In order to "
"modify the project of this task, you may close the task and create another "
"in the target project."
msgstr ""
"Du temps a déjà été saisi sur la tâche ({task}). Pour modifier le projet de "
"la tâche, veuillez fermer celle-ci et en créer une nouvelle sur le projet "
"cible."
4 changes: 4 additions & 0 deletions timesheet_task_project_no_change/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 - today 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 timesheet_task_project_no_change/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

timesheet_task_project_no_change/models/__init__.py#L4

'.project_task' imported but unused (F401)
50 changes: 50 additions & 0 deletions timesheet_task_project_no_change/models/project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Copyright 2024 - today 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 ProjectTask(models.Model):
_inherit = "project.task"

def write(self, vals):
if "project_id" in vals:
project = self.env["project.project"].browse(vals["project_id"])
tasks_with_different_project = self.filtered(
lambda t: t.project_id != project
)

for task in tasks_with_different_project:
task._validate_no_timesheets()
task._validate_no_subtask_timesheets()

return super().write(vals)

def _validate_no_timesheets(self):
if self.sudo().timesheet_ids:
raise ValidationError(
_(
"Timesheets have already been entered on this task ({task}). "
"In order to modify the project of this task, you may "
"close the task and create another in the target project."
).format(task=self.display_name)
)

def _validate_no_subtask_timesheets(self):
timesheets = (
self.env["account.analytic.line"]
.sudo()
.search([("task_id.parent_id", "=", self.id)])
)

if timesheets:
raise ValidationError(
_(
"Timesheets have already been entered on a sub-task ({subtask}). "
"In order to modify the project of the parent task ({task}), there must "
"be no time on the parent task, nor on its child tasks."
).format(
task=self.display_name, subtask=timesheets[0].task_id.display_name
)
)
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 timesheet_task_project_no_change/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright 2024 - today 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 timesheet_task_project_no_change/tests/test_project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2024 - today 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 TestProjectTask(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 = cls.env["project.task"].create(
{"name": "Parent Task", "project_id": cls.project_a.id}
)
cls.subtask = cls.env["project.task"].create(
{
"name": "Child Task",
"project_id": cls.project_a.id,
"parent_id": cls.task.id,
}
)

def test_if_no_timesheet__project_can_be_changed(self):
self.task.project_id = self.project_b

def test_if_project_is_the_same__constraint_not_raised(self):
self._make_timesheet_line(self.task)
self.task.project_id = self.project_a

def test_if_task_has_timesheet__project_can_not_be_changed(self):
self._make_timesheet_line(self.task)
with pytest.raises(ValidationError):
self.task.project_id = self.project_b

def test_if_subtask_has_timesheet__project_can_not_be_changed(self):
self._make_timesheet_line(self.subtask)
with pytest.raises(ValidationError):
self.task.project_id = self.project_b

def _make_timesheet_line(self, task):
return self.env["account.analytic.line"].create(
{
"task_id": task.id,
"project_id": task.project_id.id,
"name": "/",
"employee_id": self.ref("hr.employee_admin"),
}
)
Loading