Skip to content

Commit

Permalink
hr_timesheet_overtime: Store computed values working_time and timeshe…
Browse files Browse the repository at this point in the history
…et_overtime

This is technically not very useful; these values will be recomputed
every time a new thing is timesheeted. However, it allows you to
aggregate all working hours and overtime hours when using 'group by' in
the timesheet tree view.

This change is extensively tested.

Signed-off-by: Carmen Bianca Bakker <carmen@coopiteasy.be>
  • Loading branch information
carmenbianca committed Jun 16, 2022
1 parent 56ca41d commit 070e906
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 1 deletion.
1 change: 1 addition & 0 deletions hr_timesheet_overtime/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"website": "https://coopiteasy.be",
"license": "AGPL-3",
"depends": [
"company_today",
"hr_timesheet_sheet",
"resource_work_time_from_contracts",
],
Expand Down
7 changes: 6 additions & 1 deletion hr_timesheet_overtime/models/hr_employee.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class HrEmployee(models.Model):
string="Total Overtime",
compute="_compute_total_overtime",
help="Total Overtime since Overtime Start Date",
store=True,
)
timesheet_sheet_ids = fields.One2many(
comodel_name="hr_timesheet.sheet",
Expand Down Expand Up @@ -76,7 +77,11 @@ def _compute_current_day_working_time(self):
employee.current_day_working_time = employee.get_working_time(current_day)

@api.multi
@api.depends("timesheet_sheet_ids.active")
@api.depends(
"initial_overtime",
"overtime_start_date",
"timesheet_sheet_ids.timesheet_overtime_trimmed",
)
def _compute_total_overtime(self):
"""
Computes total overtime since employee's overtime start date
Expand Down
45 changes: 45 additions & 0 deletions hr_timesheet_overtime/models/hr_timesheet_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class HrTimesheetSheet(models.Model):
"Working Hours",
compute="_compute_working_time",
help="Hours to work for the timesheet period",
store=True,
)
daily_overtime = fields.Float(
"Daily Overtime",
Expand All @@ -33,12 +34,14 @@ class HrTimesheetSheet(models.Model):
"Timesheet Overtime",
compute="_compute_timesheet_overtime",
help="Overtime for this timesheet period",
store=True,
)
timesheet_overtime_trimmed = fields.Float(
"Trimmed Timesheet Overtime",
compute="_compute_timesheet_overtime_trimmed",
help="Overtime for this timesheet period, from the employee's start date until"
" today",
store=True,
)
total_overtime = fields.Float(
"Overtime Total",
Expand Down Expand Up @@ -67,6 +70,25 @@ def get_worked_time(self, start_date, end_date=None):
return sum(line.unit_amount for line in aal)

@api.multi
@api.depends(
"active",
"date_start",
"date_end",
"employee_id",
"employee_id.contract_ids",
"employee_id.contract_ids.date_start",
"employee_id.contract_ids.date_end",
"employee_id.contract_ids.resource_calendar_id",
"employee_id.contract_ids.resource_calendar_id.attendance_ids",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.dayofweek",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.hour_from",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.hour_to",
"employee_id.resource_calendar_id",
"employee_id.resource_calendar_id.attendance_ids",
"employee_id.resource_calendar_id.attendance_ids.dayofweek",
"employee_id.resource_calendar_id.attendance_ids.hour_from",
"employee_id.resource_calendar_id.attendance_ids.hour_to",
)
def _compute_working_time(self):
for sheet in self:
sheet.working_time = sheet.employee_id.get_working_time(
Expand All @@ -85,11 +107,34 @@ def _compute_daily_overtime(self):
sheet.daily_overtime = worked_time - working_time

@api.multi
@api.depends("total_time", "working_time")
def _compute_timesheet_overtime(self):
for sheet in self:
sheet.timesheet_overtime = sheet.total_time - sheet.working_time

@api.multi
@api.depends(
"active",
"date_start",
"date_end",
"company_id.today",
"employee_id",
"employee_id.contract_ids",
"employee_id.contract_ids.date_end",
"employee_id.contract_ids.date_start",
"employee_id.contract_ids.resource_calendar_id",
"employee_id.contract_ids.resource_calendar_id.attendance_ids",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.dayofweek",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.hour_from",
"employee_id.contract_ids.resource_calendar_id.attendance_ids.hour_to",
"employee_id.overtime_start_date",
"employee_id.resource_calendar_id",
"employee_id.resource_calendar_id.attendance_ids",
"employee_id.resource_calendar_id.attendance_ids.dayofweek",
"employee_id.resource_calendar_id.attendance_ids.hour_from",
"employee_id.resource_calendar_id.attendance_ids.hour_to",
"timesheet_ids.unit_amount",
)
def _compute_timesheet_overtime_trimmed(self):
"""
Computes overtime for the timesheet period
Expand Down
82 changes: 82 additions & 0 deletions hr_timesheet_overtime/tests/test_overtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import date

from freezegun import freeze_time

from odoo.tests.common import SavepointCase


Expand Down Expand Up @@ -339,3 +341,83 @@ def test_overtime_archived_timesheet(self):
self.assertEqual(ts2.timesheet_overtime, 5)
self.assertEqual(ts2.total_overtime, 1)
self.assertEqual(self.employee1.total_overtime, 1)

# The subsequent tests verify whether the stored fields respond correctly to
# changing variables.

def test_stored_change_contract_date_start(self):
"""When contract_id.date_start is changed, adjust correctly."""
# These initial assertions are not repeated in subsequent tests.
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 1)
self.assertEqual(self.ts1.timesheet_overtime, 1)
self.assertEqual(self.ts1.total_overtime, 1)
self.assertEqual(self.ts1.working_time, 9 * 5)
self.contract1.date_start = date(2019, 12, 3)
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 10)
self.assertEqual(self.ts1.timesheet_overtime, 10)
self.assertEqual(self.ts1.total_overtime, 10)
self.assertEqual(self.ts1.working_time, 9 * 4)

def test_stored_change_contract_date_end(self):
"""When contract_id.date_end is changed, adjust correctly."""
self.contract1.date_end = date(2019, 12, 5)
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 10)
self.assertEqual(self.ts1.timesheet_overtime, 10)
self.assertEqual(self.ts1.total_overtime, 10)
self.assertEqual(self.ts1.working_time, 9 * 4)

def test_stored_change_attendance_hour_to(self):
"""When contract_id.resource_calendar_id.attendance_ids.hour_to is changed,
adjust correctly.
"""
self.contract1.resource_calendar_id.attendance_ids[0].hour_to = 17
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 2)
self.assertEqual(self.ts1.timesheet_overtime, 2)
self.assertEqual(self.ts1.total_overtime, 2)
self.assertEqual(self.ts1.working_time, 9 * 5 - 1)

def test_stored_change_attendance_hour_from(self):
"""When contract_id.resource_calendar_id.attendance_ids.hour_from is changed,
adjust correctly.
"""
self.contract1.resource_calendar_id.attendance_ids[0].hour_from = 10
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 2)
self.assertEqual(self.ts1.timesheet_overtime, 2)
self.assertEqual(self.ts1.total_overtime, 2)
self.assertEqual(self.ts1.working_time, 9 * 5 - 1)

def test_stored_change_initial_overtime(self):
"""When employee_id.initial_overtime is changed, adjust accordingly."""
self.employee1.initial_overtime = 1
self.assertEqual(self.ts1.total_overtime, 2)

def test_stored_change_overtime_start_date(self):
"""When employee_id.overtime_start_date is changed, adjust accordingly."""
self.employee1.overtime_start_date = date(2020, 1, 1)
# No matching records.
self.assertEqual(self.ts1.total_overtime, 0)

def test_stored_change_today(self):
"""When today is changed, adjust accordingly."""
# More hours of work in the week
line = self.env["account.analytic.line"].search(
[
("date", "=", "2019-12-4"),
("sheet_id", "=", self.ts1.id),
]
)
line.unit_amount = 10
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 2)
self.assertEqual(self.ts1.timesheet_overtime, 2)
self.assertEqual(self.ts1.total_overtime, 2)
self.assertEqual(self.ts1.working_time, 9 * 5)

# Time travel into the past before the overtime.
with freeze_time("2019-12-3"):
self.ts1.company_id.cron_update_today()
# Not affected by the extra overtime
self.assertEqual(self.ts1.timesheet_overtime_trimmed, 1)
self.assertEqual(self.ts1.total_overtime, 1)
self.assertEqual(self.ts1.working_time, 9 * 5)
# Affected by the extra overtime
self.assertEqual(self.ts1.timesheet_overtime, 2)
1 change: 1 addition & 0 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
git+https://github.com/coopiteasy/addons@12.0#subdirectory=setup/resource_work_time_from_contracts
git+https://github.com/coopiteasy/addons@12.0-today#subdirectory=setup/company_today

0 comments on commit 070e906

Please sign in to comment.