Skip to content

Commit

Permalink
[REF] hr_timesheet_overtime: Add hours_worked field
Browse files Browse the repository at this point in the history
Signed-off-by: Carmen Bianca BAKKER <[email protected]>
  • Loading branch information
carmenbianca committed Jul 4, 2024
1 parent ab3ca34 commit ef2a7bb
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 36 deletions.
3 changes: 2 additions & 1 deletion hr_timesheet_overtime/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Timesheet/Contract - Overtime",
"version": "16.0.2.1.0",
"version": "16.0.3.0.0",
"category": "Human Resources",
"summary": "Overtime Calculation",
"author": "Coop IT Easy SC, Odoo Community Association (OCA)",
Expand All @@ -16,6 +16,7 @@
],
"data": [
"security/ir.model.access.csv",
"views/account_analytic_line_views.xml",
"views/hr_employee_view.xml",
"views/resource_view.xml",
"views/hr_timesheet_sheet_view.xml",
Expand Down
19 changes: 19 additions & 0 deletions hr_timesheet_overtime/migrations/16.0.3.0.0/post-upgrade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later


def migrate(cr, version):
# This is not strictly true, but it's the best way to populate the field
# with sensible data.
#
# TODO: Does this run upon module installation? This needs to be run on
# module installation as well.
cr.execute(
# Perfect symmetry is joyous
"""
UPDATE account_analytic_line
SET hours_worked=unit_amount
WHERE project_id IS NOT NULL
"""
)
1 change: 1 addition & 0 deletions hr_timesheet_overtime/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from . import account_analytic_line
from . import hr_employee
from . import hr_timesheet_sheet
from . import hr_timesheet_sheet_line
from . import resource_overtime
from . import resource_overtime_rate
44 changes: 23 additions & 21 deletions hr_timesheet_overtime/models/account_analytic_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,29 @@ class AnalyticLine(models.Model):

_inherit = "account.analytic.line"

@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
self._update_values(vals)
return super().create(vals_list)

def write(self, values):
if not self.env.context.get("create"): # sale module
self._update_values(values)
return super().write(values)

def _update_values(self, values):
"""
Update values if date or unit_amount fields have changed
"""
if "date" in values or "unit_amount" in values:
# TODO: self.date and self.unit_amount do not exist when called from
# create().
date = values.get("date", self.date)
unit_amount = values.get("unit_amount", self.unit_amount)
values["unit_amount"] = unit_amount * self.rate_for_date(date)
hours_worked = fields.Float(
default=0.0,
)
# Override to be a computed field.
unit_amount = fields.Float(
# We use a kind of custom name here because `hr_timesheet_begin_end`
# also overrides this, and the two compute methods are not necessarily
# compatible.
compute="_compute_unit_amount_from_hours",
store=True,
readonly=False,
# This triggers computation on creation. default=False and default=0 do
# not trigger computation.
default=None,
)

# TODO: should this also depend on resource.overtime.rate, somehow?
@api.depends("hours_worked", "date")
def _compute_unit_amount_from_hours(self):
# Do not compute/adjust the unit_amount of non-timesheets.
lines = self.filtered(lambda line: line.project_id)
for line in lines:
line.unit_amount = line.hours_worked * line.rate_for_date(line.date)

@api.model
def rate_for_date(self, date):
Expand Down
5 changes: 5 additions & 0 deletions hr_timesheet_overtime/models/hr_timesheet_sheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,8 @@ def _compute_timesheet_overtime_trimmed(self):
working_time = employee.get_working_time(start_date, end_date)
worked_time = sheet.get_worked_time(start_date, end_date)
sheet.timesheet_overtime_trimmed = worked_time - working_time

def _get_default_sheet_line(self, matrix, key):
result = super()._get_default_sheet_line(matrix, key)
result["hours_worked"] = sum(t.hours_worked for t in matrix[key])
return result
31 changes: 31 additions & 0 deletions hr_timesheet_overtime/models/hr_timesheet_sheet_line.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo import api, fields, models


class HrTimesheetSheetLineAbstract(models.AbstractModel):
_inherit = "hr_timesheet.sheet.line.abstract"

hours_worked = fields.Float(default=0.0)
unit_amount = fields.Float(
compute="_compute_unit_amount_from_hours", readonly=False
)

# TODO: this is basically identical to account.analytic.line. it's probably
# fine?
@api.depends("hours_worked", "date")
def _compute_unit_amount_from_hours(self):
for line in self:
line.unit_amount = line.hours_worked * self.env[
"account.analytic.line"
].rate_for_date(line.date)


class HrTimesheetSheetLine(models.TransientModel):
_inherit = "hr_timesheet.sheet.line"

@api.onchange("unit_amount", "hours_worked")
def onchange_unit_amount(self):
return super().onchange_unit_amount()
9 changes: 5 additions & 4 deletions hr_timesheet_overtime/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

/*
:Author: David Goodger ([email protected])
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
Expand Down Expand Up @@ -274,7 +275,7 @@
margin-left: 2em ;
margin-right: 2em }

pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
Expand All @@ -300,7 +301,7 @@
span.pre {
white-space: pre }

span.problematic {
span.problematic, pre.problematic {
color: red }

span.section-subtitle {
Expand Down Expand Up @@ -366,7 +367,7 @@ <h1 class="title">Timesheet/Contract - Overtime</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f303e3ad17e5d88c4ddf2a1baf816f420994d594a04db998c4fd2c1e9f1b2131
!! source digest: sha256:bde6f189b3da65ae6a23a4337c16402e0a29f4ebbb8dd39431f53c37a66249ef
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/coopiteasy/cie-timesheet/tree/16.0/hr_timesheet_overtime"><img alt="coopiteasy/cie-timesheet" src="https://img.shields.io/badge/github-coopiteasy%2Fcie--timesheet-lightgray.png?logo=github" /></a></p>
<p>Computes overtime hours according to employee’s contracts.</p>
Expand Down
21 changes: 11 additions & 10 deletions hr_timesheet_overtime/tests/test_overtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def setUpClass(cls):
"date": "2019-12-02",
"name": "-",
"sheet_id": cls.ts1.id,
"unit_amount": 10.0, # 1 hour overtime
"hours_worked": 10.0, # 1 hour overtime
"user_id": cls.employee1.user_id.id,
}
)
Expand All @@ -85,7 +85,7 @@ def setUpClass(cls):
"date": date(2019, 12, day),
"name": "-",
"sheet_id": cls.ts1.id,
"unit_amount": 9.0, # expected time
"hours_worked": 9.0, # expected time
"user_id": cls.employee1.user_id.id,
}
)
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_overtime_02(self):
"date": date(2019, 12, day),
"name": "-",
"sheet_id": ts2.id,
"unit_amount": 10.0, # 1 hour overtime
"hours_worked": 10.0, # 1 hour overtime
"user_id": self.employee1.user_id.id,
}
)
Expand All @@ -134,7 +134,7 @@ def test_overtime_02(self):
"date": date(2019, 12, day),
"name": "-",
"sheet_id": ts2.id,
"unit_amount": 9.0, # expected time
"hours_worked": 9.0, # expected time
"user_id": self.employee1.user_id.id,
}
)
Expand Down Expand Up @@ -182,7 +182,7 @@ def test_overtime_04(self):
"date": "2019-12-09",
"name": "-",
"sheet_id": ts2.id,
"unit_amount": 10.0, # 1 hour overtime
"hours_worked": 10.0, # 1 hour overtime
"user_id": self.employee1.user_id.id,
}
)
Expand All @@ -195,7 +195,7 @@ def test_overtime_04(self):
"date": date(2019, 12, day),
"name": "-",
"sheet_id": ts2.id,
"unit_amount": 9.0, # expected time
"hours_worked": 9.0, # expected time
"user_id": self.employee1.user_id.id,
}
)
Expand Down Expand Up @@ -256,7 +256,7 @@ def test_overtime_05(self):
"date": "2020-01-06",
"name": "-",
"sheet_id": self.ts2.id,
"unit_amount": 9.0, # expected time from previous contract
"hours_worked": 9.0, # expected time from previous contract
"user_id": self.employee1.user_id.id,
}
)
Expand All @@ -270,7 +270,7 @@ def test_overtime_05(self):
"date": date(2020, 1, day),
"name": "-",
"sheet_id": self.ts2.id,
"unit_amount": 4.0, # expected time from new contract
"hours_worked": 4.0, # expected time from new contract
"user_id": self.employee1.user_id.id,
}
)
Expand Down Expand Up @@ -301,7 +301,7 @@ def test_overtime_archived_timesheet(self):
"date": date(2019, 12, day),
"name": "-",
"sheet_id": ts2.id,
"unit_amount": 10.0, # 1 hour overtime
"hours_worked": 10.0, # 1 hour overtime
"user_id": self.employee1.user_id.id,
}
)
Expand Down Expand Up @@ -406,7 +406,8 @@ def test_stored_change_today(self):
("sheet_id", "=", self.ts1.id),
]
)
line.unit_amount = 10
line.hours_worked = 10
self.assertEqual(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)
Expand Down
89 changes: 89 additions & 0 deletions hr_timesheet_overtime/views/account_analytic_line_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>

<record id="hr_timesheet_line_tree" model="ir.ui.view">
<field name="name">account.analytic.line.tree.hr_timesheet</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_tree" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field
name="hours_worked"
widget="timesheet_uom"
decoration-danger="hours_worked &gt; 24 or hours_worked &lt; 0"
/>
</xpath>
</field>
</record>

<record id="view_hr_timesheet_line_pivot" model="ir.ui.view">
<field name="name">account.analytic.line.pivot</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_line_pivot" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field name="hours_worked" type="measure" widget="timesheet_uom" />
</xpath>
</field>
</record>

<record id="view_hr_timesheet_line_graph" model="ir.ui.view">
<field name="name">account.analytic.line.graph</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_line_graph" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field name="hours_worked" type="measure" widget="timesheet_uom" />
</xpath>
</field>
</record>

<record id="view_hr_timesheet_line_graph_my" model="ir.ui.view">
<field name="name">account.analytic.line.graph</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_line_graph_my" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field name="hours_worked" type="measure" widget="timesheet_uom" />
</xpath>
</field>
</record>

<record id="view_hr_timesheet_line_graph_all" model="ir.ui.view">
<field name="name">account.analytic.line.graph</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.view_hr_timesheet_line_graph_all" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field name="hours_worked" type="measure" widget="timesheet_uom" />
</xpath>
</field>
</record>

<record id="hr_timesheet_line_form" model="ir.ui.view">
<field name="name">account.analytic.line.form</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.hr_timesheet_line_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field
name="hours_worked"
widget="timesheet_uom"
decoration-danger="hours_worked &gt; 24"
/>
</xpath>
</field>
</record>

<record id="view_kanban_account_analytic_line" model="ir.ui.view">
<field name="name">account.analytic.line.kanban</field>
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="hr_timesheet.view_kanban_account_analytic_line" />
<field name="arch" type="xml">
<xpath expr="//field[@name='unit_amount']" position="before">
<field name="hours_worked" widget="timesheet_uom" />
</xpath>
</field>
</record>

</odoo>
33 changes: 33 additions & 0 deletions hr_timesheet_overtime/views/hr_timesheet_sheet_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,39 @@
/>
</xpath>

<!-- FIXME: this is presently broken. the summary page does not
compute unit_amount when changing hours_worked -->
<xpath expr="//field[@name='line_ids']" position="attributes">
<attribute name="field_value">hours_worked</attribute>
</xpath>

<xpath
expr="//field[@name='line_ids']/tree/field[@name='unit_amount']"
position="before"
>
<field name="hours_worked" widget="float_time" />
</xpath>


<xpath
expr="//field[@name='timesheet_ids']/tree/field[@name='unit_amount']"
position="before"
>
<field
name="hours_worked"
widget="float_time"
string="Hours Worked"
sum="Hours Worked"
/>
</xpath>

<xpath
expr="//field[@name='timesheet_ids']/form//field[@name='unit_amount']"
position="before"
>
<field name="hours_worked" widget="float_time" string="Hours Worked" />
</xpath>

</field>
</record>

Expand Down

0 comments on commit ef2a7bb

Please sign in to comment.