1
1
# Copyright 2015 Camptocamp SA - Guewen Baconnier
2
2
# Copyright 2017 Tecnativa, S.L. - Luis M. Ontalba
3
+ # Copyright 2024 Coop IT Easy SC - Carmen Bianca BAKKER
3
4
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
4
5
5
6
from datetime import timedelta
@@ -15,16 +16,16 @@ class AccountAnalyticLine(models.Model):
15
16
time_start = fields .Float (string = "Begin Hour" )
16
17
time_stop = fields .Float (string = "End Hour" )
17
18
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 (
22
+ self .time_start , self .time_stop
23
+ )
27
24
25
+ def _validate_start_before_stop (self ):
26
+ value_to_html = self .env ["ir.qweb.field.float_time" ].value_to_html
27
+ for line in self :
28
+ if line .time_stop < line .time_start :
28
29
raise exceptions .ValidationError (
29
30
_ (
30
31
"The beginning hour (%(html_start)s) must "
@@ -35,7 +36,11 @@ def _check_time_start_stop(self):
35
36
"html_stop" : value_to_html (line .time_stop , None ),
36
37
}
37
38
)
38
- hours = (stop - start ).seconds / 3600
39
+
40
+ def _validate_unit_amount_equal_to_time_diff (self ):
41
+ value_to_html = self .env ["ir.qweb.field.float_time" ].value_to_html
42
+ for line in self :
43
+ hours = line .unit_amount_from_start_stop (line .time_start , line .time_stop )
39
44
rounding = self .env .ref ("uom.product_uom_hour" ).rounding
40
45
if hours and float_compare (
41
46
hours , line .unit_amount , precision_rounding = rounding
@@ -50,16 +55,21 @@ def _check_time_start_stop(self):
50
55
"html_hours" : value_to_html (hours , None ),
51
56
}
52
57
)
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
- )
58
+
59
+ def _overlap_domain (self ):
60
+ self .ensure_one ()
61
+ return [
62
+ ("id" , "!=" , self .id ),
63
+ ("employee_id" , "=" , self .employee_id .id ),
64
+ ("date" , "=" , self .date ),
65
+ ("time_start" , "<" , self .time_stop ),
66
+ ("time_stop" , ">" , self .time_start ),
67
+ ]
68
+
69
+ def _validate_no_overlap (self ):
70
+ value_to_html = self .env ["ir.qweb.field.float_time" ].value_to_html
71
+ for line in self :
72
+ others = self .search (line ._overlap_domain ())
63
73
if others :
64
74
message = _ ("Lines can't overlap:\n " )
65
75
message += "\n " .join (
@@ -74,13 +84,25 @@ def _check_time_start_stop(self):
74
84
)
75
85
raise exceptions .ValidationError (message )
76
86
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 )
87
+ @api .constrains ("time_start" , "time_stop" , "unit_amount" )
88
+ def _check_time_start_stop (self ):
89
+ self ._validate_start_before_stop ()
90
+ self ._validate_unit_amount_equal_to_time_diff ()
91
+ self ._validate_no_overlap ()
92
+
93
+ @api .model
94
+ def _hours_from_start_stop (self , time_start , time_stop ):
95
+ start = timedelta (hours = time_start )
96
+ stop = timedelta (hours = time_stop )
81
97
if stop < start :
82
- return
83
- self .unit_amount = (stop - start ).seconds / 3600
98
+ # Invalid case, but return something sensible.
99
+ return 0
100
+ return (stop - start ).seconds / 3600
101
+
102
+ @api .model
103
+ def unit_amount_from_start_stop (self , time_start , time_stop , ** kwargs ):
104
+ # kwargs may be used to extend this method.
105
+ return self ._hours_from_start_stop (time_start , time_stop )
84
106
85
107
def merge_timesheets (self ): # pragma: no cover
86
108
"""This method is needed in case hr_timesheet_sheet is installed"""
0 commit comments