Skip to content

Commit

Permalink
TA#67341 [MIG][16.0] project_stage_allow_timesheet
Browse files Browse the repository at this point in the history
  • Loading branch information
rivo2302 committed Aug 29, 2024
1 parent f5d51ef commit d136d3e
Show file tree
Hide file tree
Showing 22 changed files with 386 additions and 0 deletions.
1 change: 1 addition & 0 deletions .docker_files/main/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"project_task_date_planned",
"project_task_full_text_search",
"project_type_advanced",
"project_stage_allow_timesheet"
],
"installable": True,
}
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ RUN gitoo install-all --conf_file /gitoo.yml --destination "${THIRD_PARTY_ADDONS

USER odoo

COPY project_stage_allow_timesheet mnt/extra-addons/project_stage_allow_timesheet
COPY project_task_date_planned /mnt/extra-addons/project_task_date_planned
COPY project_task_full_text_search /mnt/extra-addons/project_task_full_text_search
COPY project_type_advanced /mnt/extra-addons/project_type_advanced


COPY .docker_files/main /mnt/extra-addons/main
COPY .docker_files/odoo.conf /etc/odoo
33 changes: 33 additions & 0 deletions project_stage_allow_timesheet/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Project Stage Allow Timesheet
=============================

This module adds the notion of time sheet on project stages.
With this implementation, the field allow_timesheets on project is now readonly and it
is driven by the stage the project is in.


*This module automatically activates the feature for project_stage in the section. :* ``Project // General Settings``

.. image:: static/description/res_config_settings.png


*I go on the project stage configuration. I find an option to* ``Allow Timesheet`` *on tasks in this stage.*

.. image:: static/description/project_stage_form.png

*On the list view, the* ``Allow Timesheet`` *field is also visible.*

.. image:: static/description/project_stage_list.png

Additionally, the module implements two new constraints that avoid to move time sheets in a project that does not
allow time sheets.

*It is now forbidden to move a task with time sheets to a project that does not allow time sheets.*

.. image:: static/description/task_error.png



Contributors
------------
* Numigi (tm) and all its contributors (https://bit.ly/numigiens)
4 changes: 4 additions & 0 deletions project_stage_allow_timesheet/__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_stage_allow_timesheet/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/__init__.py#L4

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

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/__manifest__.py#L4

Statement seems to have no effect
"name": "Project Stage Allow Timesheet",
"summary": """
Allows to tell that a project stage is opened for timesheets.""",
"version": "16.0.1.0.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://bit.ly/numigi-com",
"license": "LGPL-3",
"category": "Project",
"depends": ["hr_timesheet"],
"data": [
"views/res_config_settings.xml",
"views/project_stage_views.xml",
"views/project_task_type_views.xml",
],
}
83 changes: 83 additions & 0 deletions project_stage_allow_timesheet/i18n/fr.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * project_stage_allow_timesheet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-29 19:37+0000\n"
"PO-Revision-Date: 2024-08-29 19:37+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_stage_allow_timesheet
#: model:ir.model.fields,field_description:project_stage_allow_timesheet.field_project_project_stage__allow_timesheet
msgid "Allow Timesheet"
msgstr "Autoriser les feuilles de temps"

#. module: project_stage_allow_timesheet
#: model:ir.model.fields,field_description:project_stage_allow_timesheet.field_project_task_type__allow_timesheet
msgid "Allow timesheets"
msgstr "Autoriser les feuilles de temps
#. module: project_stage_allow_timesheet
#: model:ir.model,name:project_stage_allow_timesheet.model_account_analytic_line
msgid "Analytic Line"
msgstr "Ligne analytique"

#. module: project_stage_allow_timesheet
#: model:ir.model.fields,help:project_stage_allow_timesheet.field_project_project__allow_timesheets
msgid "Depends if the project stage allows timesheet."
msgstr "Dépends si l'étape du projet permet les feuilles de temps"

#. module: project_stage_allow_timesheet
#: model:ir.model,name:project_stage_allow_timesheet.model_project_project
msgid "Project"
msgstr "Projet"

#. module: project_stage_allow_timesheet
#: model:ir.model,name:project_stage_allow_timesheet.model_project_project_stage
msgid "Project Stage"
msgstr "Étape du projet"

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

#. module: project_stage_allow_timesheet
#: model:ir.model,name:project_stage_allow_timesheet.model_project_task_type
msgid "Task Stage"
msgstr "Étape de tâche"

#. module: project_stage_allow_timesheet
#: model:ir.model.fields,field_description:project_stage_allow_timesheet.field_project_project__allow_timesheets
msgid "Timesheets"
msgstr "Autoriser les feuilles de temps"

#. module: project_stage_allow_timesheet
#. odoo-python
#: code:addons/project_stage_allow_timesheet/models/account_analytic_line.py:0
#, python-format
msgid ""
"You can't link a time sheet line to a task if its project's stage does not "
"allow it. (Task: {}, Project: {}, Project Stage: {})"
msgstr ""
"Vous ne pouvez pas lier une ligne de feuille de temps à une tâche si l'étape du projet ne le permet pas."
"(Tâche : {}, Projet : {}, Étape du projet : {})"

#. module: project_stage_allow_timesheet
#. odoo-python
#: code:addons/project_stage_allow_timesheet/models/project_task.py:0
#, python-format
msgid ""
"You cannot move a task linked to a timesheet line in a project if itsstage "
"does not allow it. (Task: {}, Project: {}, Project Stage: {})"
msgstr ""
"Vous ne pouvez pas déplacer une tâche liée à une ligne de feuille de temps dans un projet si son étape ne le permet pas."
"(Tâche : {}, Projet : {}, Étape du projet : {})"
8 changes: 8 additions & 0 deletions project_stage_allow_timesheet/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# 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

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

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/models/__init__.py#L4

'.project' imported but unused (F401)
from . import project_stage

Check notice on line 5 in project_stage_allow_timesheet/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/models/__init__.py#L5

'.project_stage' imported but unused (F401)
from . import project_task

Check notice on line 6 in project_stage_allow_timesheet/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/models/__init__.py#L6

'.project_task' imported but unused (F401)
from . import project_task_type

Check notice on line 7 in project_stage_allow_timesheet/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/models/__init__.py#L7

'.project_task_type' imported but unused (F401)
from . import account_analytic_line

Check notice on line 8 in project_stage_allow_timesheet/models/__init__.py

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

project_stage_allow_timesheet/models/__init__.py#L8

'.account_analytic_line' imported but unused (F401)
36 changes: 36 additions & 0 deletions project_stage_allow_timesheet/models/account_analytic_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 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 threading
from odoo import api, models, _
from odoo.exceptions import ValidationError


class AccountAnalyticLine(models.Model):
_inherit = "account.analytic.line"

def _should_apply_constraints(self, env):
def _is_testing():
return getattr(threading.current_thread(), "testing", False)
return not _is_testing() or env.context.get(
"enable_project_stage_allow_timesheet_constraint"
)

@api.constrains("task_id")
def _check_task_project_allow_timesheet(self):
if not self._should_apply_constraints(self.env):
return

error_message = _(
"You can't link a time sheet line to a task if its project's stage"
" does not allow it. (Task: {}, Project: {}, Project Stage: {})"
)
for rec in self:
task = rec.task_id
project = rec.project_id
stage = project.stage_id
if task and project and stage and not stage.allow_timesheet:
message = error_message.format(
rec.display_name, project.display_name, stage.display_name
)
raise ValidationError(message)
19 changes: 19 additions & 0 deletions project_stage_allow_timesheet/models/project.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).

from odoo import fields, models, api


class Project(models.Model):

_inherit = 'project.project'

@api.depends('stage_id', 'stage_id.allow_timesheet')
def _compute_allow_timesheet(self):
for record in self:
record.allow_timesheets = record.stage_id.allow_timesheet

allow_timesheets = fields.Boolean(
readonly=True, compute="_compute_allow_timesheet", store=True,
help="Depends if the project stage allows timesheet."
)
12 changes: 12 additions & 0 deletions project_stage_allow_timesheet/models/project_stage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 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 fields, models


class ProjectStage(models.Model):
_inherit = 'project.project.stage'

allow_timesheet = fields.Boolean(
default=True,
)
41 changes: 41 additions & 0 deletions project_stage_allow_timesheet/models/project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@

# 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 threading
from odoo import api, models, _
from odoo.exceptions import ValidationError


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

def _should_apply_constraints(self, env):
def _is_testing():
return getattr(threading.current_thread(), "testing", False)
return not _is_testing() or env.context.get(
"enable_project_stage_allow_timesheet_constraint"
)

@api.constrains("project_id")
def _check_project_move_allow_timesheet(self):
""" Check if a line is moved to another project,
the target project must allow time sheet """
if not self._should_apply_constraints(self.env):
return

error_message = _(
"You cannot move a task linked to a timesheet line in a project if its"
"stage does not allow it. (Task: {}, Project: {}, Project Stage: {})"
)

for rec in self:
project = rec.project_id
time_sheets = rec.timesheet_ids

if time_sheets and project and not project.allow_timesheets:
stage = project.stage_id
message = error_message.format(
rec.display_name, project.display_name, stage.display_name
)
raise ValidationError(message)
14 changes: 14 additions & 0 deletions project_stage_allow_timesheet/models/project_task_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# 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 fields, models


class ProjectTaskType(models.Model):

_inherit = 'project.task.type'

allow_timesheet = fields.Boolean(
string="Allow timesheets",
default=True,
)
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.
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_stage_allow_timesheet/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
55 changes: 55 additions & 0 deletions project_stage_allow_timesheet/tests/test_project_task.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 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.exceptions import ValidationError
from odoo.tests.common import TransactionCase


class TestTask(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
context = dict(
cls.env.context, enable_project_stage_allow_timesheet_constraint=True
)
cls.employee = cls.env["hr.employee"].create(
{"name": "Employee"}
)
cls.env = cls.env(context=context)
cls.project_stage_timesheet = cls.env["project.project.stage"].create(
{"name": "project_stage", "allow_timesheet": True}
)
cls.project_stage_no_timesheet = cls.env["project.project.stage"].create(
{"name": "project_stage_no_timesheet", "allow_timesheet": False}
)
cls.project_timesheet = cls.env["project.project"].create(
{"name": "tproject", "stage_id": cls.project_stage_timesheet.id}
)

cls.project_no_timesheet = cls.env["project.project"].create(
{"name": "tproject_no", "stage_id": cls.project_stage_no_timesheet.id}
)

cls.task_no_timesheet = cls.env["project.task"].create(
{"name": "tTask_no", "project_id": cls.project_no_timesheet.id}
)
cls.task_timesheet = cls.env["project.task"].create(
{"name": "tTask_no", "project_id": cls.project_timesheet.id}
)

cls.account_analytic_line = cls.env["account.analytic.line"].create(
{
"name": "line",
"task_id": cls.task_timesheet.id,
"project_id": cls.project_timesheet.id,
"employee_id": cls.employee.id
}
)

def test_whenTaskWithTimeSheetIsSetToProjectNoTimeSheet_thenRaiseError(self):
with self.assertRaises(ValidationError):
self.task_timesheet.project_id = self.project_no_timesheet

def test_whenAALMovedToProjectNoTimeSheet_thenRaiseError(self):
with self.assertRaises(ValidationError):
self.task_timesheet.project_id = self.project_no_timesheet.id
27 changes: 27 additions & 0 deletions project_stage_allow_timesheet/views/project_stage_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>

<odoo>

<record id="project_stage_allow_timesheet_tree" model="ir.ui.view">
<field name="name">Project stage: allow timesheet</field>
<field name="model">project.project.stage</field>
<field name="inherit_id" ref="project.project_project_stage_view_tree" />
<field type="xml" name="arch">
<field name="name" position="after">
<field name="allow_timesheet" />
</field>
</field>
</record>

<record id="project_project_stage_view_tree" model="ir.ui.view">
<field name="name">Project stage: allow timesheet</field>
<field name="model">project.project.stage</field>
<field name="inherit_id" ref="project.project_project_stage_view_form" />
<field type="xml" name="arch">
<field name="mail_template_id" position="after">
<field name="allow_timesheet" />
</field>
</field>
</record>

</odoo>
Loading

0 comments on commit d136d3e

Please sign in to comment.