Skip to content

Commit 1ff1e18

Browse files
committed
[REF] hr_timesheet_begin_end: Make more extensible
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]>
1 parent 80446c6 commit 1ff1e18

File tree

1 file changed

+45
-26
lines changed

1 file changed

+45
-26
lines changed

hr_timesheet_begin_end/models/account_analytic_line.py

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Copyright 2015 Camptocamp SA - Guewen Baconnier
22
# Copyright 2017 Tecnativa, S.L. - Luis M. Ontalba
3+
# Copyright 2024 Coop IT Easy SC - Carmen Bianca BAKKER
34
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
45

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

18-
@api.constrains("time_start", "time_stop", "unit_amount")
19-
def _check_time_start_stop(self):
20-
for line in self:
21-
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
22-
start = timedelta(hours=line.time_start)
23-
stop = timedelta(hours=line.time_stop)
24-
if stop < start:
25-
value_to_html(line.time_start, None)
26-
value_to_html(line.time_stop, None)
19+
@api.onchange("time_start", "time_stop")
20+
def onchange_hours_start_stop(self):
21+
self.unit_amount = self.unit_amount_from_start_stop()
2722

23+
def _validate_start_before_stop(self):
24+
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
25+
for line in self:
26+
if line.time_stop < line.time_start:
2827
raise exceptions.ValidationError(
2928
_(
3029
"The beginning hour (%(html_start)s) must "
@@ -35,7 +34,11 @@ def _check_time_start_stop(self):
3534
"html_stop": value_to_html(line.time_stop, None),
3635
}
3736
)
38-
hours = (stop - start).seconds / 3600
37+
38+
def _validate_unit_amount_equal_to_time_diff(self):
39+
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
40+
for line in self:
41+
hours = line.unit_amount_from_start_stop()
3942
rounding = self.env.ref("uom.product_uom_hour").rounding
4043
if hours and float_compare(
4144
hours, line.unit_amount, precision_rounding=rounding
@@ -50,16 +53,21 @@ def _check_time_start_stop(self):
5053
"html_hours": value_to_html(hours, None),
5154
}
5255
)
53-
# check if lines overlap
54-
others = self.search(
55-
[
56-
("id", "!=", line.id),
57-
("employee_id", "=", line.employee_id.id),
58-
("date", "=", line.date),
59-
("time_start", "<", line.time_stop),
60-
("time_stop", ">", line.time_start),
61-
]
62-
)
56+
57+
def _overlap_domain(self):
58+
self.ensure_one()
59+
return [
60+
("id", "!=", self.id),
61+
("employee_id", "=", self.employee_id.id),
62+
("date", "=", self.date),
63+
("time_start", "<", self.time_stop),
64+
("time_stop", ">", self.time_start),
65+
]
66+
67+
def _validate_no_overlap(self):
68+
value_to_html = self.env["ir.qweb.field.float_time"].value_to_html
69+
for line in self:
70+
others = self.search(line._overlap_domain())
6371
if others:
6472
message = _("Lines can't overlap:\n")
6573
message += "\n".join(
@@ -74,13 +82,24 @@ def _check_time_start_stop(self):
7482
)
7583
raise exceptions.ValidationError(message)
7684

77-
@api.onchange("time_start", "time_stop")
78-
def onchange_hours_start_stop(self):
79-
start = timedelta(hours=self.time_start)
80-
stop = timedelta(hours=self.time_stop)
85+
@api.constrains("time_start", "time_stop", "unit_amount")
86+
def _check_time_start_stop(self):
87+
self._validate_start_before_stop()
88+
self._validate_unit_amount_equal_to_time_diff()
89+
self._validate_no_overlap()
90+
91+
@api.model
92+
def _hours_from_start_stop(self, time_start, time_stop):
93+
start = timedelta(hours=time_start)
94+
stop = timedelta(hours=time_stop)
8195
if stop < start:
82-
return
83-
self.unit_amount = (stop - start).seconds / 3600
96+
# Invalid case, but return something sensible.
97+
return 0
98+
return (stop - start).seconds / 3600
99+
100+
def unit_amount_from_start_stop(self):
101+
self.ensure_one()
102+
return self._hours_from_start_stop(self.time_start, self.time_stop)
84103

85104
def merge_timesheets(self): # pragma: no cover
86105
"""This method is needed in case hr_timesheet_sheet is installed"""

0 commit comments

Comments
 (0)