Merge lp:~laetitia-gangloff/hr-timesheet/hr_attendance_analysis_externalise_contract_calendar_ into lp:~hr-core-editors/hr-timesheet/7.0

Proposed by Laetitia Gangloff (Acsone)
Status: Merged
Merged at revision: 62
Proposed branch: lp:~laetitia-gangloff/hr-timesheet/hr_attendance_analysis_externalise_contract_calendar_
Merge into: lp:~hr-core-editors/hr-timesheet/7.0
Diff against target: 343 lines (+62/-77)
2 files modified
hr_attendance_analysis/hr_attendance.py (+41/-52)
hr_attendance_analysis/wizard/print_calendar_report.py (+21/-25)
To merge this branch: bzr merge lp:~laetitia-gangloff/hr-timesheet/hr_attendance_analysis_externalise_contract_calendar_
Reviewer Review Type Date Requested Status
Yannick Vaucher @ Camptocamp code review, no tests Approve
Lorenzo Battistini (community) code review Approve
Guewen Baconnier @ Camptocamp Pending
Review via email: mp+195775@code.launchpad.net

This proposal supersedes a proposal from 2013-08-28.

Description of the change

In order to be able to use another calendar in some extension modules:
- rename get_active_contracts to get_reference_calendar and return the possible calendar attached to retrieve contract
- update code to take account of this change (_get_attendance_duration and print_calendar method)
- externalise store part of column in _store_rules to easily extends it

To post a comment you must log in.
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal

LGTM

review: Approve (code review, no test)
Revision history for this message
Lorenzo Battistini (elbati) wrote : Posted in a previous version of this proposal
review: Needs Fixing
Revision history for this message
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote : Posted in a previous version of this proposal

Oh right !
and all following lines are shifted.

Thank you for your review. I corrected this mistake.

Revision history for this message
Lorenzo Battistini (elbati) wrote : Posted in a previous version of this proposal

There are conflicts.

Your last commit
http://bazaar.launchpad.net/~laetitia-gangloff/hr-timesheet/hr_attendance_analysis_externalise_contract_calendar/revision/54
did a lot of changes

I suggest to revert to revision 53 and make the changes related to line 235 only.

Thanks

review: Needs Fixing
Revision history for this message
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal

There are still conflicts. Can you check ?

review: Needs Resubmitting
Revision history for this message
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote :

Sorry for the late resolution.

There is no more conflict (for the moment...).

Changes are :

- rename get_active_contracts to get_reference_calendar and return the possible calendar attached to retrieve contract
- update code to take account of this change (_get_attendance_duration and print_calendar method) -> there is many 'if' on same thing to avoid indentation problem, it can be correct in next version
- externalise store part of column in _store_rules to easily extends it
- add some context

Revision history for this message
Lorenzo Battistini (elbati) wrote :

Thanks Laetitia.
Just a little style fix:
at line 23 add spaces after ","

review: Needs Fixing
59. By Laetitia Gangloff (Acsone)

style fix

Revision history for this message
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote :

Hello,

I add spaces after "," at line 23

Revision history for this message
Lorenzo Battistini (elbati) :
review: Approve (code review)
Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

LGTM thanks

review: Approve (code review, no tests)
Revision history for this message
Pedro Manuel Baeza (pedro.baeza) wrote : Posted in a previous version of this proposal

This project is now hosted on https://github.com/OCA/hr-timesheet. Please move your proposal there. This guide may help you https://github.com/OCA/maintainers-tools/wiki/How-to-move-a-Merge-Proposal-to-GitHub

review: Needs Resubmitting
Revision history for this message
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote : Posted in a previous version of this proposal

I think, the state of this mp/branch is not correct.
The purpose of this mp, is already in hr-timesheet project at revision 62.

What is the best pratice to remove the mp and the branch ?

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : Posted in a previous version of this proposal

This one is set as Superseeded. Seems fine. No change needed.

Revision history for this message
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote : Posted in a previous version of this proposal

Super !
Thank you, I set the branch has abandonned.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hr_attendance_analysis/hr_attendance.py'
2--- hr_attendance_analysis/hr_attendance.py 2013-08-30 10:27:51 +0000
3+++ hr_attendance_analysis/hr_attendance.py 2013-11-25 08:22:35 +0000
4@@ -127,7 +127,9 @@
5 res.append((start_datetime, precision))
6 return res
7
8- def get_active_contracts(self, cr, uid, employee_id, date=datetime.now().strftime('%Y-%m-%d')):
9+ def get_reference_calendar(self, cr, uid, employee_id, date=None, context=None):
10+ if date is None:
11+ date = fields.date.context_today(self, cr, uid, context=context)
12 contract_pool = self.pool.get('hr.contract')
13 active_contract_ids= contract_pool.search(cr, uid, [
14 '&',
15@@ -145,12 +147,15 @@
16 '&',
17 ('trial_date_end', '!=', False),
18 ('trial_date_end', '>=', date),
19- ])
20+ ], context=context)
21 if len(active_contract_ids) > 1:
22- employee = self.pool.get('hr.employee').browse(cr,uid,employee_id)
23+ employee = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context)
24 raise orm.except_orm(_('Error'), _(
25 'Too many active contracts for employee %s'
26 ) % employee.name)
27+ if active_contract_ids:
28+ contract = contract_pool.browse(cr, uid, active_contract_ids[0], context=context)
29+ return contract.working_hours
30 return active_contract_ids
31
32 def _ceil_rounding(self, rounding, datetime):
33@@ -165,10 +170,9 @@
34
35 def _get_attendance_duration(self, cr, uid, ids, field_name, arg, context=None):
36 res = {}
37- contract_pool = self.pool.get('hr.contract')
38 resource_pool = self.pool.get('resource.resource')
39 attendance_pool = self.pool.get('resource.calendar.attendance')
40- precision = self.pool.get('res.users').browse(cr, uid, uid).company_id.working_time_precision
41+ precision = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.working_time_precision
42 # 2012.10.16 LF FIX : Get timezone from context
43 active_tz = pytz.timezone(context.get("tz","UTC") if context else "UTC")
44 str_now = datetime.strftime(datetime.now(), '%Y-%m-%d %H:%M:%S')
45@@ -176,7 +180,7 @@
46 duration = 0.0
47 outside_calendar_duration = 0.0
48 inside_calendar_duration = 0.0
49- attendance = self.browse(cr, uid, attendance_id)
50+ attendance = self.browse(cr, uid, attendance_id, context=context)
51 res[attendance.id] = {}
52 # 2012.10.16 LF FIX : Attendance in context timezone
53 attendance_start = datetime.strptime(
54@@ -188,9 +192,9 @@
55 if attendance.action == 'sign_in':
56 next_attendance_ids = self.search(cr, uid, [
57 ('employee_id', '=', attendance.employee_id.id),
58- ('name', '>', attendance.name)], order='name')
59+ ('name', '>', attendance.name)], order='name', context=context)
60 if next_attendance_ids:
61- next_attendance = self.browse(cr, uid, next_attendance_ids[0])
62+ next_attendance = self.browse(cr, uid, next_attendance_ids[0], context=context)
63 if next_attendance.action == 'sign_in':
64 # 2012.10.16 LF FIX : Attendance in context timezone
65 raise orm.except_orm(_('Error'), _(
66@@ -206,19 +210,18 @@
67 duration = round(duration / precision) * precision
68 res[attendance.id]['duration'] = duration
69 res[attendance.id]['end_datetime'] = next_attendance_date
70- # If contract is not specified: working days = 24/7
71+ # If calendar is not specified: working days = 24/7
72 res[attendance.id]['inside_calendar_duration'] = duration
73 res[attendance.id]['outside_calendar_duration'] = 0.0
74
75- active_contract_ids = self.get_active_contracts(
76- cr, uid, attendance.employee_id.id, date=str_now[:10])
77+ reference_calendar = self.get_reference_calendar(
78+ cr, uid, attendance.employee_id.id, date=str_now[:10], context=context)
79
80- if active_contract_ids and next_attendance_ids:
81- contract = contract_pool.browse(cr, uid, active_contract_ids[0])
82- if contract.working_hours:
83+ if reference_calendar and next_attendance_ids:
84+ if reference_calendar:
85 # TODO applicare prima arrotondamento o tolleranza?
86- if contract.working_hours.attendance_rounding:
87- float_attendance_rounding = float(contract.working_hours.attendance_rounding)
88+ if reference_calendar.attendance_rounding:
89+ float_attendance_rounding = float(reference_calendar.attendance_rounding)
90 rounded_start_hour = self._ceil_rounding(
91 float_attendance_rounding, attendance_start)
92 rounded_stop_hour = self._floor_rounding(
93@@ -243,7 +246,7 @@
94
95 res[attendance.id]['inside_calendar_duration'] = 0.0
96 res[attendance.id]['outside_calendar_duration'] = 0.0
97- calendar_id = contract.working_hours.id
98+ calendar_id = reference_calendar.id
99 intervals_within = 0
100
101 # split attendance in intervals = precision
102@@ -273,7 +276,7 @@
103 ('calendar_id','=',calendar_id),
104 ('hour_to','>=',centered_attendance_hour),
105 ('hour_from','<=',centered_attendance_hour),
106- ])
107+ ], context=context)
108 if len(matched_schedule_ids) > 1:
109 raise orm.except_orm(_('Error'),
110 _('Wrongly configured working schedule with id %s') % str(calendar_id))
111@@ -281,7 +284,7 @@
112 intervals_within += 1
113 # sign in tolerance
114 if intervals_within == 1:
115- calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0])
116+ calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0], context=context)
117 attendance_start_hour = (
118 attendance_start.hour + attendance_start.minute / 60.0
119 + attendance_start.second / 60.0 / 60.0
120@@ -302,7 +305,7 @@
121 attendance_stop.hour + attendance_stop.minute / 60.0
122 + attendance_stop.second / 60.0 / 60.0
123 )
124- calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0])
125+ calendar_attendance = attendance_pool.browse(cr, uid, matched_schedule_ids[0], context=context)
126 if attendance_stop_hour <= (
127 calendar_attendance.hour_to and
128 (attendance_stop_hour - (calendar_attendance.hour_to -
129@@ -321,13 +324,13 @@
130 res[attendance.id]['inside_calendar_duration'],
131 res[attendance.id]['duration'])
132
133- if contract.working_hours.overtime_rounding:
134+ if reference_calendar.overtime_rounding:
135 if res[attendance.id]['outside_calendar_duration']:
136 overtime = res[attendance.id]['outside_calendar_duration']
137- if contract.working_hours.overtime_rounding_tolerance:
138+ if reference_calendar.overtime_rounding_tolerance:
139 overtime = self.time_sum(overtime,
140- contract.working_hours.overtime_rounding_tolerance)
141- float_overtime_rounding = float(contract.working_hours.overtime_rounding)
142+ reference_calendar.overtime_rounding_tolerance)
143+ float_overtime_rounding = float(reference_calendar.overtime_rounding)
144 res[attendance.id]['outside_calendar_duration'] = math.floor(
145 overtime * float_overtime_rounding) / float_overtime_rounding
146
147@@ -337,7 +340,7 @@
148 attendance_ids = []
149 attendance_pool = self.pool.get('hr.attendance')
150 for contract in self.pool.get('hr.contract').browse(cr, uid, ids, context=context):
151- att_ids = attendance_pool.search(cr, uid, [('employee_id', '=', contract.employee_id.id)])
152+ att_ids = attendance_pool.search(cr, uid, [('employee_id', '=', contract.employee_id.id)], context=context)
153 for att_id in att_ids:
154 if att_id not in attendance_ids:
155 attendance_ids.append(att_id)
156@@ -348,7 +351,7 @@
157 attendance_pool = self.pool.get('hr.attendance')
158 contract_pool = self.pool.get('hr.contract')
159 for calendar in self.pool.get('resource.calendar').browse(cr, uid, ids, context=context):
160- contract_ids = contract_pool.search(cr, uid, [('working_hours', '=', calendar.id)])
161+ contract_ids = contract_pool.search(cr, uid, [('working_hours', '=', calendar.id)], context=context)
162 att_ids = attendance_pool._get_by_contracts(cr, uid, contract_ids, context=None)
163 for att_id in att_ids:
164 if att_id not in attendance_ids:
165@@ -375,45 +378,31 @@
166 ('employee_id', '=', attendance.employee_id.id),
167 ('name', '<', attendance.name),
168 ('action', '=', 'sign_in'),
169- ], order='name')
170+ ], order='name', context=context)
171 if previous_attendance_ids and previous_attendance_ids[len(previous_attendance_ids) - 1] not in attendance_ids:
172 attendance_ids.append(previous_attendance_ids[len(previous_attendance_ids) - 1])
173 return attendance_ids
174
175 _inherit = "hr.attendance"
176
177+ _store_rules = {
178+ 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20),
179+ 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20),
180+ 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20),
181+ 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20),
182+ }
183+
184 _columns = {
185 'duration': fields.function(_get_attendance_duration, method=True, multi='duration', string="Attendance duration",
186- store={
187- 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20),
188- 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20),
189- 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20),
190- 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20),
191- }
192- ),
193+ store=_store_rules),
194 'end_datetime': fields.function(_get_attendance_duration, method=True, multi='duration', type="datetime", string="End date time",
195- store={
196- 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20),
197- 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20),
198- 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20),
199- 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20),
200- }),
201+ store=_store_rules),
202 'outside_calendar_duration': fields.function(_get_attendance_duration, method=True, multi='duration',
203 string="Overtime",
204- store={
205- 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20),
206- 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20),
207- 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20),
208- 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20),
209- }),
210+ store=_store_rules),
211 'inside_calendar_duration': fields.function(_get_attendance_duration, method=True, multi='duration',
212 string="Duration within working schedule",
213- store={
214- 'hr.attendance': (_get_attendances, ['name', 'action', 'employee_id'], 20),
215- 'hr.contract': (_get_by_contracts, ['employee_id', 'date_start', 'date_end', 'trial_date_start', 'trial_date_end', 'working_hours'], 20),
216- 'resource.calendar': (_get_by_calendars, ['attendance_ids'], 20),
217- 'resource.calendar.attendance': (_get_by_calendar_attendances, ['dayofweek', 'date_from', 'hour_from', 'hour_to', 'calendar_id'], 20),
218- }),
219+ store=_store_rules),
220 }
221
222
223
224=== modified file 'hr_attendance_analysis/wizard/print_calendar_report.py'
225--- hr_attendance_analysis/wizard/print_calendar_report.py 2013-07-16 07:39:48 +0000
226+++ hr_attendance_analysis/wizard/print_calendar_report.py 2013-11-25 08:22:35 +0000
227@@ -55,7 +55,7 @@
228 'year': lambda * a: datetime.now().year,
229 'from_date': lambda * a: (datetime.now()-timedelta(30)).strftime('%Y-%m-%d'),
230 'to_date': lambda * a: datetime.now().strftime('%Y-%m-%d'),
231- 'employee_ids': lambda s, cr, uid, c: s.pool.get('hr.employee').search(cr, uid, []),
232+ 'employee_ids': lambda s, cr, uid, c: s.pool.get('hr.employee').search(cr, uid, [], context=None),
233 }
234
235 _name = "attendance_analysis.wizard.calendar_report"
236@@ -74,12 +74,11 @@
237 if context is None:
238 context = {}
239 attendance_pool = self.pool.get('hr.attendance')
240- contract_pool = self.pool.get('hr.contract')
241 holidays_pool = self.pool.get('hr.holidays')
242
243 days_by_employee = {}
244
245- form = self.read(cr, uid, ids)[0]
246+ form = self.read(cr, uid, ids, context=context)[0]
247 from_date = datetime.strptime(form['from_date'], '%Y-%m-%d')
248 to_date = datetime.strptime(form['to_date'], '%Y-%m-%d')
249 if from_date > to_date:
250@@ -97,7 +96,7 @@
251 current_total_attendances = 0.0
252 current_total_overtime = 0.0
253 current_total_leaves = 0.0
254- current_total_due = 24.0 # If contract is not specified: working days = 24/7
255+ current_total_due = 24.0 # If calendar is not specified: working days = 24/7
256 current_total_inside_calendar = 0.0
257 str_current_date = current_date.strftime('%Y-%m-%d')
258 days_by_employee[employee_id][str_current_date] = {
259@@ -121,9 +120,9 @@
260 ('name','>=',str_current_date_beginning),
261 ('name','<=',str_current_date_end),
262 ('action','=','sign_in'),
263- ])
264+ ], context=context)
265 # computing attendance totals
266- for attendance in attendance_pool.browse(cr, uid, attendance_ids):
267+ for attendance in attendance_pool.browse(cr, uid, attendance_ids, context=context):
268 current_total_attendances = attendance_pool.time_sum(
269 current_total_attendances,attendance.duration)
270 current_total_overtime = attendance_pool.time_sum(current_total_overtime,
271@@ -135,7 +134,7 @@
272 #printing up to 4 attendances
273 if len(attendance_ids) < 5:
274 count = 1
275- for attendance in sorted(attendance_pool.browse(cr, uid, attendance_ids),
276+ for attendance in sorted(attendance_pool.browse(cr, uid, attendance_ids, context=context),
277 key=lambda x: x['name']):
278 days_by_employee[employee_id][str_current_date][
279 'signin_'+str(count)] = attendance.name[11:16]
280@@ -152,14 +151,13 @@
281 'overtime'
282 ] = current_total_overtime
283
284- active_contract_ids = attendance_pool.get_active_contracts(
285- cr, uid, int(employee_id), date=str_current_date)
286+ reference_calendar = attendance_pool.get_reference_calendar(
287+ cr, uid, int(employee_id), date=str_current_date, context=context)
288 # computing due total
289- if active_contract_ids:
290- contract = contract_pool.browse(cr, uid, active_contract_ids[0])
291- if contract.working_hours and contract.working_hours.attendance_ids:
292+ if reference_calendar:
293+ if reference_calendar.attendance_ids:
294 current_total_due = 0.0
295- for calendar_attendance in contract.working_hours.attendance_ids:
296+ for calendar_attendance in reference.attendance_ids:
297 if ((
298 not calendar_attendance.dayofweek
299 or int(calendar_attendance.dayofweek) == current_date.weekday()
300@@ -200,8 +198,8 @@
301 ('date_to', '>', str_current_date_end),
302 ('state', '=', 'validate'),
303 ('employee_id', '=', int(employee_id)),
304- ])
305- for holiday in holidays_pool.browse(cr, uid, holidays_ids):
306+ ], context=context)
307+ for holiday in holidays_pool.browse(cr, uid, holidays_ids, context=context):
308 date_from = datetime.strptime(holiday.date_from, '%Y-%m-%d %H:%M:%S')
309 date_to = datetime.strptime(holiday.date_to, '%Y-%m-%d %H:%M:%S')
310 # if beginned before today
311@@ -230,10 +228,9 @@
312 ] = attendance_pool.time_difference(
313 current_total_inside_calendar, due_minus_leaves)
314
315- if active_contract_ids:
316- contract = contract_pool.browse(cr, uid, active_contract_ids[0])
317- if contract.working_hours and contract.working_hours.leave_rounding:
318- float_rounding = float(contract.working_hours.leave_rounding)
319+ if reference_calendar:
320+ if reference_calendar.leave_rounding:
321+ float_rounding = float(reference_calendar.leave_rounding)
322 days_by_employee[employee_id][str_current_date][
323 'negative'
324 ] = math.floor(
325@@ -272,13 +269,12 @@
326 days_by_employee[employee_id][str_date]['due'])
327
328 # computing overtime types
329- active_contract_ids = attendance_pool.get_active_contracts(
330- cr, uid, int(employee_id), date=str_date)
331- if active_contract_ids:
332- contract = contract_pool.browse(cr, uid, active_contract_ids[0])
333- if contract.working_hours and contract.working_hours.overtime_type_ids:
334+ reference_calendar = attendance_pool.get_reference_calendar(
335+ cr, uid, int(employee_id), date=str_date, context=context)
336+ if reference_calendar:
337+ if reference_calendar.overtime_type_ids:
338 sorted_types = sorted(
339- contract.working_hours.overtime_type_ids,
340+ reference_calendar.overtime_type_ids,
341 key=lambda k: k.sequence)
342 current_overtime = days_by_employee[employee_id][
343 str_date]['overtime']