-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[IMP] project_workload_timesheet: Link timesheet lines with workload …
…units Compute remaining time for unit Add quick timesheet buttons Handle unit done status Report unfinished unit at sheet validation
- Loading branch information
1 parent
f70d849
commit 8420905
Showing
6 changed files
with
356 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
from . import account_analytic_line | ||
from . import hr_timesheet_sheet | ||
from . import project_workload_unit |
65 changes: 65 additions & 0 deletions
65
project_workload_timesheet/models/account_analytic_line.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
# Copyright 2024 Akretion (https://www.akretion.com). | ||
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import _, api, fields, models | ||
from odoo.exceptions import UserError, ValidationError | ||
|
||
|
||
from odoo.addons.project_workload.models.project_task_workload import week_name | ||
|
||
|
||
class AccountAnalyticLine(models.Model): | ||
_inherit = "account.analytic.line" | ||
|
||
workload_unit_id = fields.Many2one( | ||
comodel_name="project.workload.unit", | ||
string="Workload Unit", | ||
readonly=False, | ||
compute="_compute_workload_unit_id", | ||
store=True, | ||
domain="[" | ||
"('week', '=', week), " | ||
"('user_id', '=', user_id), " | ||
"('project_id', '=', project_id), " | ||
"('task_id', '=', task_id)" | ||
"]", | ||
) | ||
|
||
week = fields.Char( | ||
string="Week", | ||
compute="_compute_week", | ||
help="Week number of the year", | ||
) | ||
|
||
@api.depends("date") | ||
def _compute_week(self): | ||
for record in self: | ||
record.week = week_name(record.date) | ||
|
||
@api.depends("task_id", "date", "user_id") | ||
def _compute_workload_unit_id(self): | ||
for record in self: | ||
if not record.project_id or not record.task_id: | ||
record.workload_unit_id = False | ||
continue | ||
available_workload_units = self.env["project.workload.unit"].search( | ||
record._get_available_workload_units_domain() | ||
) | ||
if ( | ||
not record.workload_unit_id | ||
or record.workload_unit_id not in available_workload_units | ||
): | ||
record.workload_unit_id = ( | ||
available_workload_units[0] | ||
if len(available_workload_units) > 0 | ||
else False | ||
) | ||
|
||
def _get_available_workload_units_domain(self): | ||
return [ | ||
("project_id", "=", self.project_id.id), | ||
("task_id", "=", self.task_id.id), | ||
("week", "=", self.week), | ||
("user_id", "=", self.user_id.id), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,22 +2,89 @@ | |
# @author Florian Mounier <[email protected]> | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
from odoo import api, fields, models | ||
|
||
|
||
class ProjectWorkloadUnit(models.Model): | ||
_inherit = "project.workload.unit" | ||
|
||
sheet_id = fields.Many2one("hr_timesheet.sheet") | ||
timesheet_ids = fields.One2many( | ||
"account.analytic.line", | ||
"workload_unit_id", | ||
"Timesheets", | ||
help="The timesheets (normally one) in which the workload is timesheeted", | ||
) | ||
priority = fields.Selection(related="task_id.priority") | ||
|
||
def action_add(self): | ||
timesheeted_hours = fields.Float( | ||
"Timesheeted Hours", | ||
compute="_compute_timesheeted_hours", | ||
help="The hours timesheeted on this workload", | ||
) | ||
remaining_hours = fields.Float( | ||
"Remaining Hours", | ||
compute="_compute_remaining_hours", | ||
help="The remaining hours to timesheet on this workload (can be negative)", | ||
) | ||
progress = fields.Float( | ||
"Progress", | ||
compute="_compute_progress", | ||
help="The progress of the task", | ||
) | ||
done = fields.Boolean( | ||
"Done", | ||
) | ||
task_stage_id = fields.Many2one( | ||
related="task_id.stage_id", string="Task Stage", readonly=False | ||
) | ||
|
||
@api.depends("timesheet_ids.unit_amount") | ||
def _compute_timesheeted_hours(self): | ||
for record in self: | ||
record.timesheeted_hours = sum(record.timesheet_ids.mapped("unit_amount")) | ||
|
||
@api.depends("hours", "timesheeted_hours") | ||
def _compute_progress(self): | ||
for record in self: | ||
if record.hours: | ||
record.progress = 100 * record.timesheeted_hours / record.hours | ||
else: | ||
record.progress = 0 | ||
|
||
@api.depends("hours", "timesheeted_hours", "done") | ||
def _compute_remaining_hours(self): | ||
for record in self: | ||
if record.done: | ||
record.remaining_hours = 0 | ||
else: | ||
record.remaining_hours = record.hours - record.timesheeted_hours | ||
|
||
def action_add_to_timesheet(self): | ||
sheet_id = self.env.context.get("current_sheet_id") | ||
if not sheet_id: | ||
return | ||
sheet = self.env["hr_timesheet.sheet"].browse(sheet_id) | ||
return sheet._add_line_from_unit(self) | ||
|
||
def action_timesheet_time(self): | ||
sheet_id = self.env.context.get("current_sheet_id") | ||
if not sheet_id: | ||
return | ||
sheet = self.env["hr_timesheet.sheet"].browse(sheet_id) | ||
if not sheet or not sheet.current: | ||
return | ||
time = self.env.context.get("time", 0) / 60 | ||
|
||
timesheet = self.timesheet_ids.filtered( | ||
lambda t: t.date == fields.Date.today() | ||
) or sheet._add_line_from_unit(self) | ||
timesheet.unit_amount += time | ||
return True | ||
|
||
def action_timesheet_done(self): | ||
self.done = True | ||
pass | ||
|
||
def _get_timesheeting_task(self): | ||
# For overrides | ||
return self.task_id |
Oops, something went wrong.