Merge lp:~matt454357/openobject-addons/7.0-timesheet_timezone_fix into lp:openobject-addons/7.0

Proposed by Matt Taylor
Status: Needs review
Proposed branch: lp:~matt454357/openobject-addons/7.0-timesheet_timezone_fix
Merge into: lp:openobject-addons/7.0
Diff against target: 140 lines (+50/-20) (has conflicts)
1 file modified
hr_timesheet_sheet/hr_timesheet_sheet.py (+50/-20)
Text conflict in hr_timesheet_sheet/hr_timesheet_sheet.py
To merge this branch: bzr merge lp:~matt454357/openobject-addons/7.0-timesheet_timezone_fix
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+219614@code.launchpad.net

Description of the change

Issue 1: _default_date_from() and _default_date_to() needed to be shifted to the user's time zone. I do daily time sheets. I'm in the MST7DST time zone (-7). When my timesheet got created at the end of the day, it was defaulting to tomorrow's date.

Issue 2: _get_hr_timesheet_sheet() should attach sign_in and sign_out to today's timesheet. It needs to find today's timesheet based on the user's time zone. When my user's performed a sign_out, the database record did not get assigned to any timesheet, because no timesheet exists yet for tomorrow. I changed the SQL to compare attendance.name in the user's time zone.

Issue 3: View "hr_timesheet_sheet_sheet_day" is used to show timesheet summaries in several places. It was grouping some attendance records on the wrong timesheet, and coming up with the wrong total attendance.

To post a comment you must log in.

Unmerged revisions

9758. By Matt Taylor

[FIX] hr_timesheet_sheet.py - shift dates to user time zone

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hr_timesheet_sheet/hr_timesheet_sheet.py'
2--- hr_timesheet_sheet/hr_timesheet_sheet.py 2014-04-30 11:37:30 +0000
3+++ hr_timesheet_sheet/hr_timesheet_sheet.py 2014-05-14 22:46:33 +0000
4@@ -29,6 +29,7 @@
5 from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
6 from openerp.tools.translate import _
7 from openerp import netsvc
8+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
9
10 class hr_timesheet_sheet(osv.osv):
11 _name = "hr_timesheet_sheet.sheet"
12@@ -170,26 +171,31 @@
13 }
14
15 def _default_date_from(self, cr, uid, context=None):
16+ #FIXME: timesheet ranges of month, week and year don't respect the user timezone
17+ # timesheets will probably get created on the first day of the new range
18+ # for example, suppose a user is in +8 timezone, and creates a new timesheet at 07:59 local time
19+ # the default date_from will be for the previous range, rather than for the current range
20 user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
21 r = user.company_id and user.company_id.timesheet_range or 'month'
22 if r=='month':
23 return time.strftime('%Y-%m-01')
24 elif r=='week':
25- return (datetime.today() + relativedelta(weekday=0, days=-6)).strftime('%Y-%m-%d')
26+ return (datetime.today() + relativedelta(weekday=0, days=-6)).strftime(DEFAULT_SERVER_DATE_FORMAT)
27 elif r=='year':
28 return time.strftime('%Y-01-01')
29- return time.strftime('%Y-%m-%d')
30+ return fields.date.context_today(self, cr, uid, context)
31
32 def _default_date_to(self, cr, uid, context=None):
33+ #FIXME: timesheet ranges of month, week and year don't respect the user timezone
34 user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
35 r = user.company_id and user.company_id.timesheet_range or 'month'
36 if r=='month':
37- return (datetime.today() + relativedelta(months=+1,day=1,days=-1)).strftime('%Y-%m-%d')
38+ return (datetime.today() + relativedelta(months=+1,day=1,days=-1)).strftime(DEFAULT_SERVER_DATE_FORMAT)
39 elif r=='week':
40- return (datetime.today() + relativedelta(weekday=6)).strftime('%Y-%m-%d')
41+ return (datetime.today() + relativedelta(weekday=6)).strftime(DEFAULT_SERVER_DATE_FORMAT)
42 elif r=='year':
43 return time.strftime('%Y-12-31')
44- return time.strftime('%Y-%m-%d')
45+ return fields.date.context_today(self, cr, uid, context)
46
47 def _default_employee(self, cr, uid, context=None):
48 emp_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id','=',uid)], context=context)
49@@ -233,7 +239,7 @@
50 return []
51 if isinstance(ids, (long, int)):
52 ids = [ids]
53- return [(r['id'], _('Week ')+datetime.strptime(r['date_from'], '%Y-%m-%d').strftime('%U')) \
54+ return [(r['id'], _('Week ')+datetime.strptime(r['date_from'], DEFAULT_SERVER_DATE_FORMAT).strftime('%U')) \
55 for r in self.read(cr, uid, ids, ['date_from'],
56 context=context, load='_classic_write')]
57
58@@ -372,7 +378,7 @@
59 context = {}
60 if 'name' in context:
61 return context['name'] + time.strftime(' %H:%M:%S')
62- return time.strftime('%Y-%m-%d %H:%M:%S')
63+ return time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
64
65 def _get_hr_timesheet_sheet(self, cr, uid, ids, context=None):
66 attendance_ids = []
67@@ -384,8 +390,13 @@
68 INNER JOIN resource_resource r
69 ON (e.resource_id = r.id)
70 ON (a.employee_id = e.id)
71- WHERE %(date_to)s >= date_trunc('day', a.name)
72- AND %(date_from)s <= a.name
73+ LEFT JOIN ((
74+ SELECT u.id AS user_id, coalesce(p.tz, current_setting('TIMEZONE')) AS tz
75+ FROM res_users AS u
76+ LEFT JOIN res_partner AS p ON p.id=u.partner_id
77+ )) AS z ON z.user_id=r.user_id
78+ WHERE %(date_to)s >= date_trunc('day', a.name AT TIME ZONE 'UTC' AT TIME ZONE z.tz)
79+ AND %(date_from)s <= date_trunc('day', a.name AT TIME ZONE 'UTC' AT TIME ZONE z.tz)
80 AND %(user_id)s = r.user_id
81 GROUP BY a.id""", {'date_from': ts.date_from,
82 'date_to': ts.date_to,
83@@ -440,9 +451,20 @@
84 def _sheet(self, cursor, user, ids, name, args, context=None):
85 res = {}.fromkeys(ids, False)
86 for attendance in self.browse(cursor, user, ids, context=context):
87+<<<<<<< TREE
88 res[attendance.id] = self._get_current_sheet(
89 cursor, user, attendance.employee_id.id, attendance.name,
90 context=context)
91+=======
92+ local_day = fields.date.context_today(self, cursor, user, context, datetime.strptime(attendance.name, DEFAULT_SERVER_DATETIME_FORMAT))
93+ sheet_ids = sheet_obj.search(cursor, user,
94+ [('date_to', '>=', local_day), ('date_from', '<=', local_day),
95+ ('employee_id', '=', attendance.employee_id.id)],
96+ context=context)
97+ if sheet_ids:
98+ # [0] because only one sheet possible for an employee between 2 dates
99+ res[attendance.id] = sheet_obj.name_get(cursor, user, sheet_ids, context=context)[0]
100+>>>>>>> MERGE-SOURCE
101 return res
102
103 _columns = {
104@@ -555,17 +577,25 @@
105 group by l.date::date, s.id
106 ) union (
107 select
108- -min(a.id) as id,
109- a.name::date as name,
110- s.id as sheet_id,
111- 0.0 as total_timesheet,
112- 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
113- from
114- hr_attendance a
115- LEFT JOIN hr_timesheet_sheet_sheet s
116- ON s.id = a.sheet_id
117- WHERE action in ('sign_in', 'sign_out')
118- group by a.name::date, s.id
119+ -min(a.id) AS id,
120+ a.tzname::date AS name,
121+ s.id AS sheet_id,
122+ 0.0 AS total_timesheet,
123+ SUM(((EXTRACT(hour FROM a.tzname) * 60) + EXTRACT(minute FROM a.tzname)) * (CASE WHEN a.action = 'sign_in' THEN -1 ELSE 1 END)) as total_attendance
124+ FROM ((
125+ SELECT a.*, (a.name AT TIME ZONE 'UTC' AT TIME ZONE z.tz) AS tzname
126+ FROM hr_attendance as a
127+ LEFT JOIN ((
128+ SELECT e.id AS employee_id, coalesce(p.tz, current_setting('TIMEZONE')) AS tz
129+ FROM res_users AS u
130+ LEFT JOIN res_partner AS p ON p.id=u.partner_id
131+ LEFT JOIN resource_resource AS r ON r.user_id=u.id
132+ LEFT JOIN hr_employee AS e ON e.resource_id=r.id
133+ )) AS z ON z.employee_id=a.employee_id
134+ )) AS a
135+ LEFT JOIN hr_timesheet_sheet_sheet s ON s.id = a.sheet_id
136+ WHERE action IN ('sign_in', 'sign_out')
137+ GROUP BY a.tzname::date, s.id
138 )) AS foo
139 GROUP BY name, sheet_id
140 )) AS bar""")