Merge lp:~laetitia-gangloff/hr-timesheet/hr_attendance_analysis_externalise_contract_calendar_ into lp:~hr-core-editors/hr-timesheet/7.0
- hr_attendance_analysis_externalise_contract_calendar_
- Merge into 7.0
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_ |
Related bugs: |
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.
Commit message
Description of the change
In order to be able to use another calendar in some extension modules:
- rename get_active_
- update code to take account of this change (_get_attendanc
- externalise store part of column in _store_rules to easily extends it
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal | # |
Lorenzo Battistini (elbati) wrote : Posted in a previous version of this proposal | # |
Looking at the whole code of
http://
line 235 is always False
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.
Lorenzo Battistini (elbati) wrote : Posted in a previous version of this proposal | # |
There are conflicts.
Your last commit
http://
did a lot of changes
I suggest to revert to revision 53 and make the changes related to line 235 only.
Thanks
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal | # |
There are still conflicts. Can you check ?
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote : | # |
Sorry for the late resolution.
There is no more conflict (for the moment...).
Changes are :
- rename get_active_
- update code to take account of this change (_get_attendanc
- externalise store part of column in _store_rules to easily extends it
- add some context
Lorenzo Battistini (elbati) wrote : | # |
Thanks Laetitia.
Just a little style fix:
at line 23 add spaces after ","
- 59. By Laetitia Gangloff (Acsone)
-
style fix
Laetitia Gangloff (Acsone) (laetitia-gangloff) wrote : | # |
Hello,
I add spaces after "," at line 23
Lorenzo Battistini (elbati) : | # |
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : | # |
LGTM thanks
Pedro Manuel Baeza (pedro.baeza) wrote : Posted in a previous version of this proposal | # |
This project is now hosted on https:/
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 ?
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.
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
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'] |
LGTM