Merge lp:~zaber/openobject-addons/timesheet-tz into lp:openobject-addons/6.1
- timesheet-tz
- Merge into 6.1
Status: | Needs review | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~zaber/openobject-addons/timesheet-tz | ||||
Merge into: | lp:openobject-addons/6.1 | ||||
Diff against target: |
275 lines (+69/-37) 4 files modified
hr_attendance/hr_attendance.py (+7/-1) hr_attendance/wizard/hr_attendance_sign_in_out.py (+2/-2) hr_timesheet/wizard/hr_timesheet_sign_in_out.py (+3/-3) hr_timesheet_sheet/hr_timesheet_sheet.py (+57/-31) |
||||
To merge this branch: | bzr merge lp:~zaber/openobject-addons/timesheet-tz | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Core Team | Pending | ||
Review via email: mp+141836@code.launchpad.net |
Commit message
Description of the change
This fixes bug lp:943091 in 6.1. There were several timezone problems, so I tried to fix each one in a separate commit.
There could still be problems if two users from different timezones edit the same timesheet, but the current 6.1 timesheet modules are unusable because of timezone problems, so I think this is a big improvement.
- 7122. By Don Kirkby
-
[FIX] Use time zone for signing in and out of timesheets as part of bug lp:943091. Change hr_attendance.day field to use local date instead of UTC date.
- 7123. By Don Kirkby
-
[FIX] Use local time in total attendance calculation on timesheet as part of bug lp:943091.
- 7124. By Don Kirkby
-
[FIX] Store hours on hr_attendance because doing the timezone calculation in SQL was messy. Fixes timesheet by day view.
Unmerged revisions
- 7125. By Don Kirkby
-
[FIX] Use timezone in Sign in / sign out by project feature as part of bug lp:943091.
- 7124. By Don Kirkby
-
[FIX] Store hours on hr_attendance because doing the timezone calculation in SQL was messy. Fixes timesheet by day view.
- 7123. By Don Kirkby
-
[FIX] Use local time in total attendance calculation on timesheet as part of bug lp:943091.
- 7122. By Don Kirkby
-
[FIX] Use time zone for signing in and out of timesheets as part of bug lp:943091. Change hr_attendance.day field to use local date instead of UTC date.
- 7121. By Don Kirkby
-
[FIX] fix today button to use time zone as part of bug lp:943091.
Preview Diff
1 | === modified file 'hr_attendance/hr_attendance.py' | |||
2 | --- hr_attendance/hr_attendance.py 2012-01-31 13:36:57 +0000 | |||
3 | +++ hr_attendance/hr_attendance.py 2013-01-03 23:59:21 +0000 | |||
4 | @@ -20,6 +20,7 @@ | |||
5 | 20 | ############################################################################## | 20 | ############################################################################## |
6 | 21 | 21 | ||
7 | 22 | import time | 22 | import time |
8 | 23 | from datetime import datetime | ||
9 | 23 | 24 | ||
10 | 24 | from osv import fields, osv | 25 | from osv import fields, osv |
11 | 25 | from tools.translate import _ | 26 | from tools.translate import _ |
12 | @@ -48,7 +49,12 @@ | |||
13 | 48 | def _day_compute(self, cr, uid, ids, fieldnames, args, context=None): | 49 | def _day_compute(self, cr, uid, ids, fieldnames, args, context=None): |
14 | 49 | res = dict.fromkeys(ids, '') | 50 | res = dict.fromkeys(ids, '') |
15 | 50 | for obj in self.browse(cr, uid, ids, context=context): | 51 | for obj in self.browse(cr, uid, ids, context=context): |
17 | 51 | res[obj.id] = time.strftime('%Y-%m-%d', time.strptime(obj.name, '%Y-%m-%d %H:%M:%S')) | 52 | timestamp = datetime.strptime(obj.name, '%Y-%m-%d %H:%M:%S') |
18 | 53 | res[obj.id] = fields.date.context_today(self, | ||
19 | 54 | cr, | ||
20 | 55 | uid, | ||
21 | 56 | context=context, | ||
22 | 57 | timestamp=timestamp) | ||
23 | 52 | return res | 58 | return res |
24 | 53 | 59 | ||
25 | 54 | _columns = { | 60 | _columns = { |
26 | 55 | 61 | ||
27 | === modified file 'hr_attendance/wizard/hr_attendance_sign_in_out.py' | |||
28 | --- hr_attendance/wizard/hr_attendance_sign_in_out.py 2011-11-09 18:12:56 +0000 | |||
29 | +++ hr_attendance/wizard/hr_attendance_sign_in_out.py 2013-01-03 23:59:21 +0000 | |||
30 | @@ -162,7 +162,7 @@ | |||
31 | 162 | self.pool.get('hr.attendance').create(cr, uid, {'name': data['last_time'], 'action': 'sign_out', | 162 | self.pool.get('hr.attendance').create(cr, uid, {'name': data['last_time'], 'action': 'sign_out', |
32 | 163 | 'employee_id': emp_id}, context=context) | 163 | 'employee_id': emp_id}, context=context) |
33 | 164 | try: | 164 | try: |
35 | 165 | self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_in') | 165 | self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_in', context=context) |
36 | 166 | except: | 166 | except: |
37 | 167 | raise osv.except_osv(_('UserError'), _('A sign-in must be right after a sign-out !')) | 167 | raise osv.except_osv(_('UserError'), _('A sign-in must be right after a sign-out !')) |
38 | 168 | return {'type': 'ir.actions.act_window_close'} # To do: Return Success message | 168 | return {'type': 'ir.actions.act_window_close'} # To do: Return Success message |
39 | @@ -174,7 +174,7 @@ | |||
40 | 174 | raise osv.except_osv(_('UserError'), _('The Sign-in date must be in the past')) | 174 | raise osv.except_osv(_('UserError'), _('The Sign-in date must be in the past')) |
41 | 175 | self.pool.get('hr.attendance').create(cr, uid, {'name':data['last_time'], 'action':'sign_in', 'employee_id':emp_id}, context=context) | 175 | self.pool.get('hr.attendance').create(cr, uid, {'name':data['last_time'], 'action':'sign_in', 'employee_id':emp_id}, context=context) |
42 | 176 | try: | 176 | try: |
44 | 177 | self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_out') | 177 | self.pool.get('hr.employee').attendance_action_change(cr, uid, [emp_id], 'sign_out', context=context) |
45 | 178 | except: | 178 | except: |
46 | 179 | raise osv.except_osv(_('UserError'), _('A sign-out must be right after a sign-in !')) | 179 | raise osv.except_osv(_('UserError'), _('A sign-out must be right after a sign-in !')) |
47 | 180 | return {'type': 'ir.actions.act_window_close'} # To do: Return Success message | 180 | return {'type': 'ir.actions.act_window_close'} # To do: Return Success message |
48 | 181 | 181 | ||
49 | === modified file 'hr_timesheet/wizard/hr_timesheet_sign_in_out.py' | |||
50 | --- hr_timesheet/wizard/hr_timesheet_sign_in_out.py 2011-12-21 10:52:14 +0000 | |||
51 | +++ hr_timesheet/wizard/hr_timesheet_sign_in_out.py 2013-01-03 23:59:21 +0000 | |||
52 | @@ -91,7 +91,7 @@ | |||
53 | 91 | emp_obj = self.pool.get('hr.employee') | 91 | emp_obj = self.pool.get('hr.employee') |
54 | 92 | for data in self.browse(cr, uid, ids, context=context): | 92 | for data in self.browse(cr, uid, ids, context=context): |
55 | 93 | emp_id = data.emp_id.id | 93 | emp_id = data.emp_id.id |
57 | 94 | emp_obj.attendance_action_change(cr, uid, [emp_id], type='sign_out', dt=data.date) | 94 | emp_obj.attendance_action_change(cr, uid, [emp_id], type='sign_out', dt=data.date, context=context) |
58 | 95 | self._write(cr, uid, data, emp_id, context=context) | 95 | self._write(cr, uid, data, emp_id, context=context) |
59 | 96 | return {'type': 'ir.actions.act_window_close'} | 96 | return {'type': 'ir.actions.act_window_close'} |
60 | 97 | 97 | ||
61 | @@ -99,7 +99,7 @@ | |||
62 | 99 | emp_obj = self.pool.get('hr.employee') | 99 | emp_obj = self.pool.get('hr.employee') |
63 | 100 | for data in self.browse(cr, uid, ids, context=context): | 100 | for data in self.browse(cr, uid, ids, context=context): |
64 | 101 | emp_id = data.emp_id.id | 101 | emp_id = data.emp_id.id |
66 | 102 | emp_obj.attendance_action_change(cr, uid, [emp_id], type='action', dt=data.date) | 102 | emp_obj.attendance_action_change(cr, uid, [emp_id], type='action', dt=data.date, context=context) |
67 | 103 | self._write(cr, uid, data, emp_id, context=context) | 103 | self._write(cr, uid, data, emp_id, context=context) |
68 | 104 | return {'type': 'ir.actions.act_window_close'} | 104 | return {'type': 'ir.actions.act_window_close'} |
69 | 105 | 105 | ||
70 | @@ -156,7 +156,7 @@ | |||
71 | 156 | emp_obj = self.pool.get('hr.employee') | 156 | emp_obj = self.pool.get('hr.employee') |
72 | 157 | for data in self.browse(cr, uid, ids, context=context): | 157 | for data in self.browse(cr, uid, ids, context=context): |
73 | 158 | emp_id = data.emp_id.id | 158 | emp_id = data.emp_id.id |
75 | 159 | emp_obj.attendance_action_change(cr, uid, [emp_id], type = 'sign_in' ,dt=data.date or False) | 159 | emp_obj.attendance_action_change(cr, uid, [emp_id], type = 'sign_in' , context=context, dt=data.date or False) |
76 | 160 | return {'type': 'ir.actions.act_window_close'} | 160 | return {'type': 'ir.actions.act_window_close'} |
77 | 161 | 161 | ||
78 | 162 | def default_get(self, cr, uid, fields_list, context=None): | 162 | def default_get(self, cr, uid, fields_list, context=None): |
79 | 163 | 163 | ||
80 | === modified file 'hr_timesheet_sheet/hr_timesheet_sheet.py' | |||
81 | --- hr_timesheet_sheet/hr_timesheet_sheet.py 2012-08-31 10:45:03 +0000 | |||
82 | +++ hr_timesheet_sheet/hr_timesheet_sheet.py 2013-01-03 23:59:21 +0000 | |||
83 | @@ -46,8 +46,8 @@ | |||
84 | 46 | dom.insert(0 ,'|') | 46 | dom.insert(0 ,'|') |
85 | 47 | dom.append('&') | 47 | dom.append('&') |
86 | 48 | dom.append('&') | 48 | dom.append('&') |
89 | 49 | dom.append(('name', '>=', res6[id])) | 49 | dom.append(('day', '>=', res6[id])) |
90 | 50 | dom.append(('name', '<=', res6[id])) | 50 | dom.append(('day', '<=', res6[id])) |
91 | 51 | dom.append(('sheet_id', '=', id)) | 51 | dom.append(('sheet_id', '=', id)) |
92 | 52 | 52 | ||
93 | 53 | ids2 = obj.pool.get(self._obj).search(cr, user, dom, limit=self._limit) | 53 | ids2 = obj.pool.get(self._obj).search(cr, user, dom, limit=self._limit) |
94 | @@ -118,6 +118,10 @@ | |||
95 | 118 | """ | 118 | """ |
96 | 119 | context = context or {} | 119 | context = context or {} |
97 | 120 | attendance_obj = self.pool.get('hr.attendance') | 120 | attendance_obj = self.pool.get('hr.attendance') |
98 | 121 | now = fields.datetime.context_timestamp(cr, | ||
99 | 122 | uid, | ||
100 | 123 | datetime.now(), | ||
101 | 124 | context=context) | ||
102 | 121 | res = {} | 125 | res = {} |
103 | 122 | for sheet_id in ids: | 126 | for sheet_id in ids: |
104 | 123 | sheet = self.browse(cr, uid, sheet_id, context=context) | 127 | sheet = self.browse(cr, uid, sheet_id, context=context) |
105 | @@ -129,25 +133,17 @@ | |||
106 | 129 | total_attendance = {} | 133 | total_attendance = {} |
107 | 130 | for attendance in [att for att in attendances | 134 | for attendance in [att for att in attendances |
108 | 131 | if att.action in ('sign_in', 'sign_out')]: | 135 | if att.action in ('sign_in', 'sign_out')]: |
110 | 132 | day = attendance.name[:10] | 136 | day = attendance.day |
111 | 133 | if not total_attendance.get(day, False): | 137 | if not total_attendance.get(day, False): |
112 | 134 | total_attendance[day] = timedelta(seconds=0) | 138 | total_attendance[day] = timedelta(seconds=0) |
113 | 135 | 139 | ||
122 | 136 | attendance_in_time = datetime.strptime(attendance.name, '%Y-%m-%d %H:%M:%S') | 140 | total_attendance[day] += timedelta(hours=attendance.daily_hours) |
115 | 137 | attendance_interval = timedelta(hours=attendance_in_time.hour, | ||
116 | 138 | minutes=attendance_in_time.minute, | ||
117 | 139 | seconds=attendance_in_time.second) | ||
118 | 140 | if attendance.action == 'sign_in': | ||
119 | 141 | total_attendance[day] -= attendance_interval | ||
120 | 142 | else: | ||
121 | 143 | total_attendance[day] += attendance_interval | ||
123 | 144 | 141 | ||
124 | 145 | # if the delta is negative, it means that a sign out is missing | 142 | # if the delta is negative, it means that a sign out is missing |
125 | 146 | # in a such case, we want to have the time to the end of the day | 143 | # in a such case, we want to have the time to the end of the day |
126 | 147 | # for a past date, and the time to now for the current date | 144 | # for a past date, and the time to now for the current date |
127 | 148 | if total_attendance[day] < timedelta(0): | 145 | if total_attendance[day] < timedelta(0): |
128 | 149 | if day == date_current: | 146 | if day == date_current: |
129 | 150 | now = datetime.now() | ||
130 | 151 | total_attendance[day] += timedelta(hours=now.hour, | 147 | total_attendance[day] += timedelta(hours=now.hour, |
131 | 152 | minutes=now.minute, | 148 | minutes=now.minute, |
132 | 153 | seconds=now.second) | 149 | seconds=now.second) |
133 | @@ -275,13 +271,15 @@ | |||
134 | 275 | return True | 271 | return True |
135 | 276 | 272 | ||
136 | 277 | def date_today(self, cr, uid, ids, context=None): | 273 | def date_today(self, cr, uid, ids, context=None): |
137 | 274 | today = fields.date.context_today(self, cr, uid, context=context) | ||
138 | 275 | |||
139 | 278 | for sheet in self.browse(cr, uid, ids, context=context): | 276 | for sheet in self.browse(cr, uid, ids, context=context): |
144 | 279 | if datetime.today() <= datetime.strptime(sheet.date_from, '%Y-%m-%d'): | 277 | if today <= sheet.date_from: |
145 | 280 | self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from,}, context=context) | 278 | self.write(cr, uid, [sheet.id], {'date_current': sheet.date_from}, context=context) |
146 | 281 | elif datetime.now() >= datetime.strptime(sheet.date_to, '%Y-%m-%d'): | 279 | elif today >= sheet.date_to: |
147 | 282 | self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to,}, context=context) | 280 | self.write(cr, uid, [sheet.id], {'date_current': sheet.date_to}, context=context) |
148 | 283 | else: | 281 | else: |
150 | 284 | self.write(cr, uid, [sheet.id], {'date_current': time.strftime('%Y-%m-%d')}, context=context) | 282 | self.write(cr, uid, [sheet.id], {'date_current': today}, context=context) |
151 | 285 | return True | 283 | return True |
152 | 286 | 284 | ||
153 | 287 | def date_previous(self, cr, uid, ids, context=None): | 285 | def date_previous(self, cr, uid, ids, context=None): |
154 | @@ -314,7 +312,8 @@ | |||
155 | 314 | 312 | ||
156 | 315 | def check_sign(self, cr, uid, ids, typ, context=None): | 313 | def check_sign(self, cr, uid, ids, typ, context=None): |
157 | 316 | sheet = self.browse(cr, uid, ids, context=context)[0] | 314 | sheet = self.browse(cr, uid, ids, context=context)[0] |
159 | 317 | if not sheet.date_current == time.strftime('%Y-%m-%d'): | 315 | today = fields.date.context_today(self, cr, uid, context=context) |
160 | 316 | if not sheet.date_current == today: | ||
161 | 318 | raise osv.except_osv(_('Error !'), _('You cannot sign in/sign out from an other date than today')) | 317 | raise osv.except_osv(_('Error !'), _('You cannot sign in/sign out from an other date than today')) |
162 | 319 | return True | 318 | return True |
163 | 320 | 319 | ||
164 | @@ -477,7 +476,7 @@ | |||
165 | 477 | context = {} | 476 | context = {} |
166 | 478 | if 'date' in context: | 477 | if 'date' in context: |
167 | 479 | return context['date'] | 478 | return context['date'] |
169 | 480 | return time.strftime('%Y-%m-%d') | 479 | return fields.date.context_today(self, cr, uid, context=context) |
170 | 481 | 480 | ||
171 | 482 | def _sheet(self, cursor, user, ids, name, args, context=None): | 481 | def _sheet(self, cursor, user, ids, name, args, context=None): |
172 | 483 | sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') | 482 | sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') |
173 | @@ -519,7 +518,7 @@ | |||
174 | 519 | store={ | 518 | store={ |
175 | 520 | 'hr_timesheet_sheet.sheet': (_get_hr_timesheet_sheet, ['employee_id', 'date_from', 'date_to'], 10), | 519 | 'hr_timesheet_sheet.sheet': (_get_hr_timesheet_sheet, ['employee_id', 'date_from', 'date_to'], 10), |
176 | 521 | 'account.analytic.line': (_get_account_analytic_line, ['user_id', 'date'], 10), | 520 | 'account.analytic.line': (_get_account_analytic_line, ['user_id', 'date'], 10), |
178 | 522 | 'hr.analytic.timesheet': (lambda self,cr,uid,ids,context=None: ids, ['line_id'], 10), | 521 | 'hr.analytic.timesheet': (lambda self,cr,uid,ids,context=None: ids, None, 10), |
179 | 523 | }, | 522 | }, |
180 | 524 | ), | 523 | ), |
181 | 525 | } | 524 | } |
182 | @@ -573,8 +572,8 @@ | |||
183 | 573 | INNER JOIN resource_resource r | 572 | INNER JOIN resource_resource r |
184 | 574 | ON (e.resource_id = r.id) | 573 | ON (e.resource_id = r.id) |
185 | 575 | ON (a.employee_id = e.id) | 574 | ON (a.employee_id = e.id) |
188 | 576 | WHERE %(date_to)s >= date_trunc('day', a.name) | 575 | WHERE %(date_to)s >= a.day |
189 | 577 | AND %(date_from)s <= a.name | 576 | AND %(date_from)s <= a.day |
190 | 578 | AND %(user_id)s = r.user_id | 577 | AND %(user_id)s = r.user_id |
191 | 579 | GROUP BY a.id""", {'date_from': ts.date_from, | 578 | GROUP BY a.id""", {'date_from': ts.date_from, |
192 | 580 | 'date_to': ts.date_to, | 579 | 'date_to': ts.date_to, |
193 | @@ -586,16 +585,38 @@ | |||
194 | 586 | sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') | 585 | sheet_obj = self.pool.get('hr_timesheet_sheet.sheet') |
195 | 587 | res = {}.fromkeys(ids, False) | 586 | res = {}.fromkeys(ids, False) |
196 | 588 | for attendance in self.browse(cursor, user, ids, context=context): | 587 | for attendance in self.browse(cursor, user, ids, context=context): |
198 | 589 | date_to = datetime.strftime(datetime.strptime(attendance.name[0:10], '%Y-%m-%d'), '%Y-%m-%d %H:%M:%S') | 588 | timestamp = datetime.strptime(attendance.name, '%Y-%m-%d %H:%M:%S') |
199 | 589 | day = fields.date.context_today(self, | ||
200 | 590 | cursor, | ||
201 | 591 | user, | ||
202 | 592 | context=context, | ||
203 | 593 | timestamp=timestamp) | ||
204 | 590 | sheet_ids = sheet_obj.search(cursor, user, | 594 | sheet_ids = sheet_obj.search(cursor, user, |
206 | 591 | [('date_to', '>=', date_to), ('date_from', '<=', attendance.name), | 595 | [('date_to', '>=', day), ('date_from', '<=', day), |
207 | 592 | ('employee_id', '=', attendance.employee_id.id)], | 596 | ('employee_id', '=', attendance.employee_id.id)], |
208 | 593 | context=context) | 597 | context=context) |
209 | 594 | if sheet_ids: | 598 | if sheet_ids: |
210 | 595 | # [0] because only one sheet possible for an employee between 2 dates | 599 | # [0] because only one sheet possible for an employee between 2 dates |
211 | 596 | res[attendance.id] = sheet_obj.name_get(cursor, user, sheet_ids, context=context)[0] | 600 | res[attendance.id] = sheet_obj.name_get(cursor, user, sheet_ids, context=context)[0] |
212 | 597 | return res | 601 | return res |
214 | 598 | 602 | ||
215 | 603 | def _daily_hours(self, cr, uid, ids, name, args, context=None): | ||
216 | 604 | res = {}.fromkeys(ids, False) | ||
217 | 605 | for attendance in self.browse(cr, uid, ids, context=context): | ||
218 | 606 | day = attendance.day | ||
219 | 607 | attendance_in_time = fields.datetime.context_timestamp( | ||
220 | 608 | cr, | ||
221 | 609 | uid, | ||
222 | 610 | datetime.strptime(attendance.name, '%Y-%m-%d %H:%M:%S'), | ||
223 | 611 | context=context) | ||
224 | 612 | hours = (attendance_in_time.hour + | ||
225 | 613 | attendance_in_time.minute / 60.0 + | ||
226 | 614 | attendance_in_time.second / 3600.0) | ||
227 | 615 | if attendance.action == 'sign_in': | ||
228 | 616 | hours *= -1 | ||
229 | 617 | res[attendance.id] = hours | ||
230 | 618 | return res | ||
231 | 619 | |||
232 | 599 | _columns = { | 620 | _columns = { |
233 | 600 | 'sheet_id': fields.function(_sheet, string='Sheet', | 621 | 'sheet_id': fields.function(_sheet, string='Sheet', |
234 | 601 | type='many2one', relation='hr_timesheet_sheet.sheet', | 622 | type='many2one', relation='hr_timesheet_sheet.sheet', |
235 | @@ -603,7 +624,12 @@ | |||
236 | 603 | 'hr_timesheet_sheet.sheet': (_get_hr_timesheet_sheet, ['employee_id', 'date_from', 'date_to'], 10), | 624 | 'hr_timesheet_sheet.sheet': (_get_hr_timesheet_sheet, ['employee_id', 'date_from', 'date_to'], 10), |
237 | 604 | 'hr.attendance': (lambda self,cr,uid,ids,context=None: ids, ['employee_id', 'name', 'day'], 10), | 625 | 'hr.attendance': (lambda self,cr,uid,ids,context=None: ids, ['employee_id', 'name', 'day'], 10), |
238 | 605 | }, | 626 | }, |
240 | 606 | ) | 627 | ), |
241 | 628 | 'daily_hours': fields.function(_daily_hours, | ||
242 | 629 | type='float', | ||
243 | 630 | string='Daily Hours', | ||
244 | 631 | digits=(16,2), | ||
245 | 632 | store=True) | ||
246 | 607 | } | 633 | } |
247 | 608 | _defaults = { | 634 | _defaults = { |
248 | 609 | 'name': _get_default_date, | 635 | 'name': _get_default_date, |
249 | @@ -709,10 +735,10 @@ | |||
250 | 709 | ) union ( | 735 | ) union ( |
251 | 710 | select | 736 | select |
252 | 711 | -min(a.id) as id, | 737 | -min(a.id) as id, |
254 | 712 | a.name::date as name, | 738 | a.day::date as name, |
255 | 713 | s.id as sheet_id, | 739 | s.id as sheet_id, |
256 | 714 | 0.0 as total_timesheet, | 740 | 0.0 as total_timesheet, |
258 | 715 | SUM(((EXTRACT(hour FROM a.name) * 60) + EXTRACT(minute FROM a.name)) * (CASE WHEN a.action = 'sign_in' THEN -1 ELSE 1 END)) as total_attendance | 741 | SUM(a.daily_hours)*60 as total_attendance |
259 | 716 | from | 742 | from |
260 | 717 | hr_attendance a | 743 | hr_attendance a |
261 | 718 | LEFT JOIN (hr_timesheet_sheet_sheet s | 744 | LEFT JOIN (hr_timesheet_sheet_sheet s |
262 | @@ -721,10 +747,10 @@ | |||
263 | 721 | ON (e.resource_id = r.id) | 747 | ON (e.resource_id = r.id) |
264 | 722 | ON (s.user_id = r.user_id)) | 748 | ON (s.user_id = r.user_id)) |
265 | 723 | ON (a.employee_id = e.id | 749 | ON (a.employee_id = e.id |
268 | 724 | AND s.date_to >= date_trunc('day',a.name) | 750 | AND s.date_to >= a.day::date |
269 | 725 | AND s.date_from <= a.name) | 751 | AND s.date_from <= a.day::date) |
270 | 726 | WHERE action in ('sign_in', 'sign_out') | 752 | WHERE action in ('sign_in', 'sign_out') |
272 | 727 | group by a.name::date, s.id | 753 | group by a.day::date, s.id |
273 | 728 | )) AS foo | 754 | )) AS foo |
274 | 729 | GROUP BY name, sheet_id | 755 | GROUP BY name, sheet_id |
275 | 730 | )) AS bar""") | 756 | )) AS bar""") |