Skip to content

Commit

Permalink
[REF] hr_timesheet_begin_end: Make more extensible
Browse files Browse the repository at this point in the history
The separation of checks into separate methods is needed because I want
to disable one check in another module. This makes the module more
extensible.

The unit_amount_from_start_stop method also makes the module more
extensible.

I have also moved the onchange to the top of the file, according to the
OCA contribution guidelines.

Signed-off-by: Carmen Bianca BAKKER <[email protected]>
  • Loading branch information
carmenbianca committed Jun 28, 2024
1 parent 764a1c0 commit 0985b0d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 26 deletions.
75 changes: 49 additions & 26 deletions hr_timesheet_begin_end/models/account_analytic_line.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Copyright 2015 Camptocamp SA - Guewen Baconnier
# Copyright 2017 Tecnativa, S.L. - Luis M. Ontalba
# Copyright 2024 Coop IT Easy SC - Carmen Bianca BAKKER
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html

from datetime import timedelta
Expand All @@ -15,16 +16,14 @@ class AccountAnalyticLine(models.Model):
time_start = fields.Float(string="Begin Hour")
time_stop = fields.Float(string="End Hour")

@api.constrains("time_start", "time_stop", "unit_amount")
def _check_time_start_stop(self):
for line in self:
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
start = timedelta(hours=line.time_start)
stop = timedelta(hours=line.time_stop)
if stop < start:
value_to_html(line.time_start, None)
value_to_html(line.time_stop, None)
@api.onchange("time_start", "time_stop", "project_id")
def onchange_hours_start_stop(self):
self.unit_amount = self.unit_amount_from_start_stop()

def _validate_start_before_stop(self):
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
for line in self:
if line.time_stop < line.time_start:
raise exceptions.ValidationError(
_(
"The beginning hour (%(html_start)s) must "
Expand All @@ -35,7 +34,11 @@ def _check_time_start_stop(self):
"html_stop": value_to_html(line.time_stop, None),
}
)
hours = (stop - start).seconds / 3600

def _validate_unit_amount_equal_to_time_diff(self):
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
for line in self:
hours = line.unit_amount_from_start_stop()
rounding = self.env.ref("uom.product_uom_hour").rounding
if hours and float_compare(
hours, line.unit_amount, precision_rounding=rounding
Expand All @@ -50,16 +53,21 @@ def _check_time_start_stop(self):
"html_hours": value_to_html(hours, None),
}
)
# check if lines overlap
others = self.search(
[
("id", "!=", line.id),
("employee_id", "=", line.employee_id.id),
("date", "=", line.date),
("time_start", "<", line.time_stop),
("time_stop", ">", line.time_start),
]
)

def _overlap_domain(self):
self.ensure_one()
return [
("id", "!=", self.id),
("employee_id", "=", self.employee_id.id),
("date", "=", self.date),
("time_start", "<", self.time_stop),
("time_stop", ">", self.time_start),
]

def _validate_no_overlap(self):
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
for line in self:
others = self.search(line._overlap_domain())
if others:
message = _("Lines can't overlap:\n")
message += "\n".join(
Expand All @@ -74,13 +82,28 @@ def _check_time_start_stop(self):
)
raise exceptions.ValidationError(message)

@api.onchange("time_start", "time_stop")
def onchange_hours_start_stop(self):
start = timedelta(hours=self.time_start)
stop = timedelta(hours=self.time_stop)
@api.constrains("time_start", "time_stop", "unit_amount")
def _check_time_start_stop(self):
lines = self.filtered(lambda line: line.project_id)
lines._validate_start_before_stop()
lines._validate_unit_amount_equal_to_time_diff()
lines._validate_no_overlap()

@api.model
def _hours_from_start_stop(self, time_start, time_stop):
start = timedelta(hours=time_start)
stop = timedelta(hours=time_stop)
if stop < start:
return
self.unit_amount = (stop - start).seconds / 3600
# Invalid case, but return something sensible.
return 0
return (stop - start).seconds / 3600

def unit_amount_from_start_stop(self):
self.ensure_one()
# Don't handle non-timesheet lines.
if not self.project_id:
return 0
return self._hours_from_start_stop(self.time_start, self.time_stop)

def merge_timesheets(self): # pragma: no cover
"""This method is needed in case hr_timesheet_sheet is installed"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refactored the module to be more extensible.

0 comments on commit 0985b0d

Please sign in to comment.