Merge lp:~openerp-groupes/hrself-addons/balance-report-optimization-oli into lp:hrself-addons

Proposed by tfr (Openerp) on 2011-12-06
Status: Needs review
Proposed branch: lp:~openerp-groupes/hrself-addons/balance-report-optimization-oli
Merge into: lp:hrself-addons
Diff against target: 874 lines (+334/-299)
5 files modified
hrself_holidays/hrself_holidays.py (+281/-232)
hrself_holidays/security/ir.model.access.csv (+1/-1)
hrself_holidays/security/leave_request_security.xml (+12/-0)
hrself_holidays/view/hrself_holidays_view.xml (+35/-13)
hrself_holidays/wizard/hrself_report_wizard.py (+5/-53)
To merge this branch: bzr merge lp:~openerp-groupes/hrself-addons/balance-report-optimization-oli
Reviewer Review Type Date Requested Status
OpenERP Groupe S 2011-12-06 Pending
Review via email: mp+84604@code.launchpad.net
To post a comment you must log in.
639. By Olivier Ligot on 2011-12-06

[MERGE] Upstream merge

640. By Olivier Ligot on 2011-12-07

[FIX] _update_context: get employee from uid if not defined

641. By Olivier Ligot on 2011-12-07

[FIX] Get unit from precision when no balance for a given type

642. By Olivier Ligot on 2011-12-07

[REM] print statements

643. By Olivier Ligot on 2011-12-07

[REF] Don't use _ for public functions

644. By Olivier Ligot on 2011-12-07

[REM] today_balance field

645. By Olivier Ligot on 2011-12-07

[IMP] Define 2 balance tree views: one with date field and one without

646. By Olivier Ligot on 2011-12-07

[FIX] Employee has now the right to delete a balance

647. By Olivier Ligot on 2011-12-07

[FIX] Check allowed duration when start date equals end date and unit is day

648. By Olivier Ligot on 2011-12-07

[FIX] Get unit from precision when no balance for a given type

The previous implementation was wrong as it used a shared dict, which caused
the unit to be set for each leave type!!!

Unmerged revisions

648. By Olivier Ligot on 2011-12-07

[FIX] Get unit from precision when no balance for a given type

The previous implementation was wrong as it used a shared dict, which caused
the unit to be set for each leave type!!!

647. By Olivier Ligot on 2011-12-07

[FIX] Check allowed duration when start date equals end date and unit is day

646. By Olivier Ligot on 2011-12-07

[FIX] Employee has now the right to delete a balance

645. By Olivier Ligot on 2011-12-07

[IMP] Define 2 balance tree views: one with date field and one without

644. By Olivier Ligot on 2011-12-07

[REM] today_balance field

643. By Olivier Ligot on 2011-12-07

[REF] Don't use _ for public functions

642. By Olivier Ligot on 2011-12-07

[REM] print statements

641. By Olivier Ligot on 2011-12-07

[FIX] Get unit from precision when no balance for a given type

640. By Olivier Ligot on 2011-12-07

[FIX] _update_context: get employee from uid if not defined

639. By Olivier Ligot on 2011-12-06

[MERGE] Upstream merge

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hrself_holidays/hrself_holidays.py'
2--- hrself_holidays/hrself_holidays.py 2011-12-02 10:20:44 +0000
3+++ hrself_holidays/hrself_holidays.py 2011-12-07 15:08:24 +0000
4@@ -82,14 +82,17 @@
5 _description = "Types of holidays"
6
7 def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
8- """Redefined to search only types applicables for an employee and a period.
9+ """
10+ Redefined to search only types applicables for an employee and a period.
11 If context contains activity_context_id (or employee_id and date_from to calculates it), returns only compatible type.
12 Else returns super.search result
13 """
14-
15 if not context:
16 context = {}
17+
18 ids = super(hrself_holidays_type, self).search(cr, uid, args, offset, limit, order, context, count)
19+ if count:
20+ return ids
21 result = ids
22 activity_context_id = context.get('activity_context_id')
23 if not activity_context_id:
24@@ -129,37 +132,6 @@
25 return employee_ids[0]
26 return False
27
28- def get_initialization_duration_for_employee(self, cr, uid, ids, context):
29- """Returns the initialization duration of a leave type for the employee. Only for the current year and activity context.
30- Duration is in hours or days (defined by leave type).
31- Requires employee_id, date_from and activity_context of the leave in context:
32- {'employee_id':employee_id, 'date_from':date_from, 'activity_context':activity_context}
33- @return: dictionary {leave_type: duration}
34- """
35- max_leaves = dict.fromkeys(ids, 0)
36- employee_id = context.get('employee_id')
37- # calculation of initializations at the date of leave request
38- # if leave request has no date_from yet, using today
39- self._update_context(cr, uid, context=context)
40- date_from = context.get('date_from')
41- activity_context_id = context.get('activity_context')
42- current_year = hrself_datetime.to_date(date_from).year
43- start_of_year = hrself_datetime.to_string(datetime.date(current_year, 1, 1))
44- for leave_type in self.browse(cr, uid, ids, context):
45- initialization_object = self.pool.get('hrself.holidays.request.initialization')
46- initialization_ids = initialization_object.search(cr, uid, [
47- ('type_id', '=', leave_type.id), ('employee_id', '=', employee_id),
48- ('date_from', '>=', start_of_year), ('date_from', '<=', date_from)],
49- order='date_from desc')
50- duration = 0
51- if initialization_ids:
52- for initialization in initialization_object.browse(cr, uid, initialization_ids, context=context):
53- if initialization.activity_context_id.is_compatible(activity_context_id):
54- duration = initialization.duration
55- break
56- max_leaves[leave_type.id] = duration
57- return max_leaves
58-
59 def get_remaining_leaves_for_employee(self, cr, uid, ids, context=None, remaining_date_to=None):
60 """Returns the remaining number of leaves for the employee by leave type. Only for the current year and activity context.
61 Context must contain employee_id, date_from and activity_context of the leave:
62@@ -169,10 +141,9 @@
63 remaining_date_to is end of year by default, can be used to specify an end date period for calculation of remaining leaves.
64 @return: dictionary {leave_type: duration}
65 """
66- result = {}
67- values = self.compute_values(cr, uid, ids, context=context, remaining_date_to=remaining_date_to)
68- for key, value in values.iteritems():
69- result[key] = value['remaining_leaves']
70+ result = dict.fromkeys(ids, 0)
71+ for type in self.browse(cr, uid, ids, context=context):
72+ result[type.id] = type.remaining_leaves
73 return result
74
75 def _update_context(self, cr, uid, context=None):
76@@ -181,46 +152,33 @@
77 if not employee_id:
78 employee_id = self._user_employee(cr, uid, context)
79 context['employee_id'] = employee_id
80- date_from = context.get('date_from')
81- if not date_from:
82- date_from = datetime.date.today()
83- context['date_from']=date_from
84+ date_to = context.get('date_to')
85+ if not date_to:
86+ date_to = datetime.date.today()
87+ context['date_to'] = date_to
88 if not context.get('activity_context') and employee_id:
89 services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
90- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_from, context=context)
91+ activities = services.get_theoretical_activities(cr, uid, employee_id, date_to, date_to, context=context)
92 if activities:
93 context['activity_context'] = activities[0]['activity_context']
94
95- def compute_values(self, cr, uid, ids, context, remaining_date_to=None):
96- """Compute values of remaining_leaves and unit functional fields."""
97- return self._compute(cr, uid, ids, None, None, context=context, remaining_date_to=remaining_date_to)
98-
99 def _compute(self, cr, uid, ids, field_name, arg, context, remaining_date_to=None):
100 """Method signature conformed to functional field."""
101- result = dict.fromkeys(ids, {'unit': None, 'remaining_leaves': 0})
102+ if not context:
103+ context = {}
104 self._update_context(cr, uid, context=context)
105- remaining_leaves = self.get_initialization_duration_for_employee(cr, uid, ids, context)
106- date_from = context.get('date_from')
107- current_year = hrself_datetime.to_date(date_from).year
108- start_of_year = hrself_datetime.to_string(datetime.date(current_year, 1, 1))
109- if remaining_date_to:
110- date_to = remaining_date_to
111- else:
112- date_to = hrself_datetime.to_string(datetime.date(current_year, 12, 31))
113- activity_context_id = context.get('activity_context')
114- leave_object = self.pool.get('hrself.holidays.request.leave')
115- for leave_type in self.browse(cr, uid, ids, context):
116- leave_ids = leave_object.search(cr, uid, [
117- ('type_id', '=', leave_type.id), ('employee_id', '=', context.get('employee_id')),
118- ('date_from', '>=', start_of_year), ('date_to', '<=', date_to),
119- ('state', 'in', [STATE_CONFIRMED, STATE_APPROVED] ), ('activity_context_id','=', activity_context_id) ])
120- remaining_leaves[leave_type.id] -= sum(leave.duration for leave in leave_object.browse(cr, uid, leave_ids))
121- precision_id = leave_type.precision_id_for_context(activity_context_id)
122- if precision_id:
123- result[leave_type.id] = {
124- 'remaining_leaves': remaining_leaves[leave_type.id],
125- 'unit': self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id).unit,
126- }
127+ result = {}
128+ for type_id in ids:
129+ result[type_id] = {'unit': None, 'remaining_leaves': 0}
130+ balance_object = self.pool.get('hrself.holidays.balance')
131+ balance_ids = balance_object.get_employee_balance_ids(cr, uid, context.get('employee_id'), ids, context.get('date_to'), context=context)
132+ for balance in balance_object.browse(cr, uid, balance_ids, context=context):
133+ result[balance.type_id.id] = {'unit' : balance.unit, 'remaining_leaves' : balance.end_year_balance}
134+ for type_id in ids:
135+ if result[type_id]['unit'] is None:
136+ precision_id = self.precision_id_for_context(cr, uid, [type_id], context.get('activity_context'))
137+ if precision_id:
138+ result[type_id]['unit'] = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id).unit
139 return result
140
141 _columns = {
142@@ -503,41 +461,33 @@
143 ], 'Generate source'),
144 }
145
146+ def _get_activity_context(self, cr, uid, date_from, employee_id, type_id, context=None):
147+ """Get the activity context."""
148+ services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
149+ #TODO: verify that get_theoretical_activities don't crash if arguments are None
150+ activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_from, context=context)
151+ if activities:
152+ activity_context_id = activities[0]['activity_context']
153+ precision_id = self.pool.get('hrself.holidays.type').precision_id_for_context(cr, uid, [type_id], activity_context_id)
154+ return self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id, context=context).activity_context_id.id
155+ return False
156+
157 def write(self, cr, uid, ids, vals, context=None):
158 """Redefining write to add activity context """
159 for initialization in self.browse(cr, uid, ids, context=context):
160 date_from = vals.get('date_from', initialization.date_from)
161 employee_id = initialization.employee_id.id
162- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
163- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_from, context=context)
164- if activities:
165- activity_context_id = activities[0]['activity_context']
166- type_id = self.browse(cr, uid, ids[0], context=context).type_id.id
167- precision_id = self.pool.get('hrself.holidays.type').precision_id_for_context(cr, uid, [type_id], activity_context_id)
168- vals['activity_context_id'] = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id, context=context).activity_context_id.id
169- # test if new duration > number of days/hours already taken
170- context = {'employee_id':employee_id, 'date_from':date_from, 'activity_context':activity_context_id}
171- old_duration_dic = initialization.type_id.get_initialization_duration_for_employee(context)
172- remaining_dic = initialization.type_id.get_remaining_leaves_for_employee(context)
173- remaining = remaining_dic[initialization.type_id.id]
174- old_duration = old_duration_dic[initialization.type_id.id]
175- days_taken = old_duration - remaining
176- new_duration = vals.get('duration', initialization.duration)
177- if new_duration < days_taken:
178- raise osv.except_osv(_('Error !'), _( 'Duration must be greater than days/hours already taken.\n Days/Hours taken: %s') % (str(days_taken)))
179+ type_id = vals.get('type_id', initialization.type_id.id)
180+ vals['activity_context_id'] = self._get_activity_context(cr, uid, date_from, employee_id, type_id)
181 return super(hrself_holidays_request_initialization, self).write(cr, uid, ids, vals, context=context)
182
183 def create(self, cr, uid, vals, context=None):
184 """Redefining create to add activity context """
185 if not 'activity_context_id' in vals:
186- date_from = vals['date_from']
187- employee_id = int(vals['employee_id'])
188- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
189- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_from, context=context)
190- if activities:
191- activity_context_id = activities[0]['activity_context']
192- precision_id = self.pool.get('hrself.holidays.type').precision_id_for_context(cr, uid, [vals['type_id']], activity_context_id)
193- vals['activity_context_id'] = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id, context=context).activity_context_id.id
194+ date_from = vals.get('date_from')
195+ employee_id = int(vals.get('employee_id'))
196+ type_id = int(vals.get('type_id'))
197+ vals['activity_context_id'] = self._get_activity_context(cr, uid, date_from, employee_id, type_id)
198 return super(hrself_holidays_request_initialization, self).create(cr, uid, vals, context=context)
199
200 _defaults = {
201@@ -572,10 +522,46 @@
202 return False
203 return True
204
205+ def _check_balance_positive(self, cr, uid, ids, context=None):
206+ """Check that final balance is not below zero.
207+ """
208+ balance_obj = self.pool.get('hrself.holidays.balance')
209+ for request in self.browse(cr, uid, ids, context=context):
210+ balance_obj.update_balance(cr, uid, request.employee_id.id, request.type_id.id, request.activity_context_id.id,
211+ request.date_from, context=context)
212+ if not balance_obj.check_all_balance_positive(cr, uid, request.employee_id.id, request.type_id.id, request.activity_context_id.id, request.date_from, context=context):
213+ return False
214+ return True
215+
216+ def _check_unicity(self, cr, uid, ids, context=None):
217+ for init in self.browse(cr, uid, ids, context=context):
218+ init_ids = self.search(cr, uid, [('employee_id', '=', init.employee_id.id),
219+ ('date_from', '=', init.date_from),
220+ ('type_id', '=', init.type_id.id)], context=context)
221+ if len(init_ids) > 1:
222+ return False
223+ return True
224+
225 _constraints = [
226 (_check_duration, _('Duration must be greater than 0 !'), ['duration']),
227+ (_check_unicity, _('Cannot create two initialization for the same employee for the same type at the same date'), ['duration', 'type', 'employee_id']),
228 (_check_type_activity_context, _('This type is not compatible with activity context of employee'), ['type']),
229+ (_check_balance_positive, _('The balance at the end of the year cannot be below zero'), ['duration']), #TODO: review message
230 ]
231+
232+ def unlink(self, cr, uid, ids, context=None):
233+ #Likely to be optimized
234+ balance_obj = self.pool.get('hrself.holidays.balance')
235+ for request_data in self.read(cr, uid, ids, ['employee_id', 'type_id', 'activity_context_id', 'date_from'],context=context):
236+ date_from = request_data['date_from']
237+ employee_id = request_data['employee_id'][0]
238+ type_id = request_data['type_id'][0]
239+ activity_context_id = request_data['activity_context_id'][0]
240+ res = super(hrself_holidays_request_initialization, self).unlink(cr, uid, [request_data['id']], context=context)
241+ balance_obj.update_balance(cr, uid, employee_id, type_id, activity_context_id, date_from, context=context)
242+ if not balance_obj.check_all_balance_positive(cr, uid, employee_id, type_id, activity_context_id, date_from, context=context):
243+ raise osv.except_osv(_('Warning!'), _('You cannot delete this initialization. Otherwise the remaining leaves for %s would be negative.' % request_data['employee_id'][1]))
244+ return res
245
246 hrself_holidays_request_initialization()
247
248@@ -721,14 +707,35 @@
249 if not self._disable_checks(cr, uid, leave_request.type_id.id, activity_context_id) and not (leave_request.duration > 0):
250 return False
251 return True
252+
253+ def _check_am_pm(self, cr, uid, ids, context=None):
254+ for leave in self.browse(cr, uid, ids, context=context):
255+ if leave.date_to != leave.date_from and leave.am_pm != AM_PM_ALL_DAY:
256+ return False
257+ return True
258
259 _constraints = [
260 (_check_duration, _('Duration must be greater than 0 !'), ['duration']),
261- (_check_mandatory_reason, _('Type of holiday requires a reason'), ['reason']),
262+ (_check_am_pm, _('The leave last more then one day, you should select all day'), ['am_pm']),
263 (_check_limit_date, _check_limit_date_message, ['date_to']),
264 (_check_minimum_date, _check_minimum_date_message, ['date_from']),
265+ (_check_mandatory_reason, _('Type of holiday requires a reason'), ['reason']),
266 (_check_type_activity_context, _('This type is not compatible with activity context of employee'), ['type']),
267 ]
268+
269+ #this function is use cause of the stupid web client that doesn't send the right values
270+ def onchange_unit(self, cr, uid, ids, employee_id, date_from, date_to, type_id, unit, am_pm, context=None):
271+ """Action to execute when the user changes the unit."""
272+ result = {}
273+ if employee_id and date_from and date_to and type_id:
274+ services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
275+ activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
276+ allowed_unit = self._duration(cr, uid, type_id, am_pm, activities)['value']['unit']
277+ if unit <> allowed_unit:
278+ result['warning'] = {'title': _('Warning'), 'message': _('You cannot change the unit.')}
279+ result['value'] = {'unit': allowed_unit}
280+ return result
281+
282
283 def write(self, cr, uid, ids, values, context=None):
284 """Redefined write to check constraints."""
285@@ -752,7 +759,7 @@
286 old_date_to = hrself_datetime.to_date(leave.date_to)
287 new_date_to = _to_date(values.get('date_to'), old_date_to)
288 if (new_date_from != old_date_from) or (new_date_to != old_date_to):
289- on_change = self._onchange_date_type(cr, uid, [leave.id], leave.employee_id.id, new_date_from, new_date_to, leave.type_id.id, leave.am_pm, context)
290+ on_change = self.onchange_date_type(cr, uid, [leave.id], leave.employee_id.id, new_date_from, new_date_to, leave.type_id.id, leave.am_pm, context)
291 warning = on_change.get('warning')
292 if warning:
293 logger.warning(warning['message'])
294@@ -764,106 +771,53 @@
295 write_ids.append(leave.id)
296 return super(hrself_holidays_request_leave, self).write(cr, uid, write_ids, values, context=context)
297
298- def onchange_employee_id(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
299- """Action to execute when the user changes employee_id."""
300- return self._onchange_date_type(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
301-
302- def onchange_date_from(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
303- """Action to execute when the user changes date_from."""
304- return self._onchange_dates_am_pm(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
305-
306- def onchange_date_to(self, cr, uid, ids, employee_id, date_to, date_from, type_id, am_pm, context):
307+ def onchange_date(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context=None):
308 """Action to execute when the user changes date_to."""
309- return self._onchange_dates_am_pm(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
310-
311- def onchange_type(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
312- """Action to execute when the user changes the type."""
313- return self._onchange_date_type(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
314+ if not date_from or not date_to:
315+ return {}
316+
317+ if date_from > date_to:
318+ message = _('The start date (%s) must be smaller or equal to the end date (%s)!') % (date_from, date_to)
319+ return {'warning' : {'title': _('Invalid dates'), 'message': message}}
320+ return self.onchange_date_type(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
321
322 def _disable_checks(self, cr, uid, type_id, activity_context_id):
323 """Disable checks?"""
324- result = False
325- if type_id and activity_context_id:
326- precision_id = self.pool.get('hrself.holidays.type').browse(cr, uid, type_id).precision_id_for_context(activity_context_id)
327- if precision_id:
328- prestation_code = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id).prestation_code_id
329- if prestation_code and prestation_code.gross_leave:
330- result = True
331- return result
332-
333- def onchange_duration(self, cr, uid, ids, employee_id, date_from, date_to, type_id, duration, unit, am_pm, context=None):
334- """Action to execute when the user changes the duration."""
335- result = {}
336- if employee_id and date_from and date_to:
337- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
338- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
339- if not self._disable_checks(cr, uid, type_id, activities and activities[0] and activities[0]['activity_context']):
340- allowed_duration = self._duration(cr, uid, type_id, am_pm, activities)['value']['duration']
341- if unit == hrself.TIME_UNIT_HOUR and date_from == date_to:
342- if duration > allowed_duration:
343- result['warning'] = {
344- 'title': _('Warning'),
345- 'message': _('The leave request duration is greater than allowed. \n You have %d %s(s) left.') %
346- (allowed_duration, hrself.TIME_UNITS_DICT[unit])
347- }
348- result['value'] = {'duration': allowed_duration}
349- elif duration <> allowed_duration:
350- result['warning'] = {'title': _('Warning'), 'message': _('You cannot change the duration.')}
351- result['value'] = {'duration': allowed_duration}
352- return result
353-
354- def onchange_unit(self, cr, uid, ids, employee_id, date_from, date_to, type_id, unit, am_pm, context=None):
355- """Action to execute when the user changes the unit."""
356- result = {}
357- date_from = date_from or fields.date.today()
358- date_to = date_to or fields.date.today()
359- if employee_id:
360- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
361- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
362- allowed_unit = self._duration(cr, uid, type_id, am_pm, activities)['value']['unit']
363- if unit <> allowed_unit:
364- result['warning'] = {'title': _('Warning'), 'message': _('You cannot change the unit.')}
365- result['value'] = {'unit': allowed_unit}
366- return result
367-
368- def _onchange_dates_am_pm(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
369- """Action to execute when the user changes dates (from or to) or the AM PM indicator."""
370- result = {}
371- if am_pm != AM_PM_ALL_DAY and date_from != date_to:
372- am_pm = AM_PM_ALL_DAY
373- result['warning'] = {'title': _('Warning'), 'message': _('You cannot set AM or PM when start date is not equal to end date.')}
374- result.update(self._onchange_date_type(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context))
375- result['value']['am_pm'] = am_pm
376- return result
377-
378- def onchange_am_pm(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
379- """Action to execute when the user changes the AM PM indicator."""
380- return self._onchange_dates_am_pm(cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context)
381-
382- def _onchange_date_type(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context):
383+ if not type_id or not activity_context_id:
384+ return False
385+
386+ precision_id = self.pool.get('hrself.holidays.type').browse(cr, uid, type_id).precision_id_for_context(activity_context_id)
387+ if precision_id:
388+ prestation_code = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id).prestation_code_id
389+ if prestation_code and prestation_code.gross_leave:
390+ result = True
391+
392+ return False
393+
394+ def onchange_date_type(self, cr, uid, ids, employee_id, date_from, date_to, type_id, am_pm, context=None):
395 """Action to execute when the user changes a date (from or to) or the type."""
396 result = {}
397 activities = None
398- if date_from and date_to:
399- if date_from > date_to:
400- message = _('The start date (%s) must be smaller or equal to the end date (%s)!') % (date_from, date_to)
401+ if not (date_from and date_to and type_id and employee_id):
402+ return result
403+
404+
405+ services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
406+ activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
407+ if not self._disable_checks(cr, uid, type_id, activities and activities[0] and activities[0]['activity_context']):
408+ present = False
409+ absence_days = set()
410+ for activity in activities:
411+ if activity['presence_absence'] == 'A':
412+ date = hrself_datetime.to_string(hrself_datetime.to_date(activity['date']))
413+ absence_days.add(date)
414+ elif activity['presence_absence'] == 'P':
415+ present = True
416+ if not present:
417+ message = _('You cannot take leave on absence days: ') + ', '.join(absence_days)
418 result['warning'] = {'title': _('Invalid dates'), 'message': message}
419- elif employee_id and type_id:
420- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
421- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
422- if not self._disable_checks(cr, uid, type_id, activities and activities[0] and activities[0]['activity_context']):
423- presence_days = []
424- absence_days = []
425- for activity in activities:
426- date = hrself_datetime.to_string(hrself_datetime.to_date(activity['date']))
427- if activity['presence_absence'] == 'A' and date not in absence_days:
428- absence_days.append(date)
429- elif activity['presence_absence'] == 'P' and date not in presence_days:
430- presence_days.append(date)
431- if not presence_days:
432- message = _('You cannot take leave on absence days: ') + ', '.join(absence_days)
433- result['warning'] = {'title': _('Invalid dates'), 'message': message}
434- result.update(self._duration(cr, uid, type_id, am_pm, activities))
435+
436+ result.update(self._duration(cr, uid, type_id, am_pm, activities))
437 return result
438
439 def _duration(self, cr, uid, type_id, am_pm, activities):
440@@ -893,7 +847,7 @@
441 duration = duration_in_hour
442 else:
443 type = self.pool.get('hrself.holidays.type').browse (cr, uid, type_id)
444- message = _('No precision defined for the holidays type named %s identified by %d') % (type.name , type.id)
445+ message = _('No precision defined for the holidays type named %s identified by %d, please contact your administrator') % (type.name , type.id)
446 result['warning'] = {'title': _('No precision'), 'message': message}
447 result['value'] = {
448 'duration': duration,
449@@ -919,40 +873,22 @@
450 if activity_context_id:
451 leave_request.write({'activity_context_id': activity_context_id})
452
453- def _check_balance(self, cr, uid, ids):
454- """Check balance limit if override is not allowed.
455- Returns the number of remaining days or hours.
456- @rtype: int
457- """
458-
459- for leave_request in self.browse(cr, uid, ids):
460- if leave_request.activity_context_id:
461- activity_context_id = leave_request.activity_context_id.id
462- precision_id = leave_request.type_id.precision_id_for_context(activity_context_id)
463- type_precision = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id)
464- if not type_precision.is_unlimited :
465- context = {
466- 'employee_id': leave_request.employee_id.id,
467- 'date_from': leave_request.date_from,
468- 'activity_context': activity_context_id,
469- }
470- remaining_dic = leave_request.type_id.get_remaining_leaves_for_employee(context)
471- remaining = remaining_dic[leave_request.type_id.id]
472- if leave_request.duration > remaining:
473- return (remaining, hrself.TIME_UNITS_DICT[leave_request.unit])
474- return None
475-
476 def _check_allowed_duration(self, cr, uid, ids, context=None):
477- """Check that the leave request duration is not greater than allowed.
478- For the moment, only takes into account leaves
479- where date from is equal to date to.
480- :return: (allowed duration, unit)
481- :rtype: (int, str)"""
482+ """
483+ Check that the leave request duration is not greater than allowed.
484+ For the moment, only takes into account leaves
485+ where date from is equal to date to.
486+ :return: (allowed duration, unit)
487+ :rtype: (int, str)
488+ """
489 for leave in self.browse(cr, uid, ids, context=context):
490 date_from = leave.date_from
491 date_to = leave.date_to
492+ employee_id = leave.employee_id.id
493+ services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
494+ activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
495 if date_from == date_to:
496- employee_id = leave.employee_id.id
497+
498 search_ids = self.search(cr, uid, [
499 ('employee_id', '=', employee_id),
500 '|', ('state', '=', STATE_APPROVED), ('state', '=', STATE_CONFIRMED),
501@@ -968,16 +904,18 @@
502 # then the service will already decrease the allowed duration.
503 # Otherwise, we have to decrease it ourselves.
504 if search_leave.state == STATE_CONFIRMED or not type_precision.prestation_code_id:
505- if search_leave.unit == hrself.TIME_UNIT_HOUR:
506- already_taken += search_leave.duration
507- else:
508- already_taken += search_leave.duration_in_hour
509- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
510- activities = services.get_theoretical_activities(cr, uid, employee_id, date_from, date_to, context=context)
511+ already_taken += search_leave.duration_in_hour
512+
513 max_duration = self._duration(cr, uid, leave.type_id.id, AM_PM_ALL_DAY, activities)['value']['duration_in_hour']
514 allowed_duration = max(round(max_duration - already_taken, 2), 0.0)
515- if leave.duration > allowed_duration:
516+ if leave.duration_in_hour > allowed_duration:
517 return (allowed_duration, hrself.TIME_UNIT_HOUR_LABEL)
518+ elif leave.unit != hrself.TIME_UNIT_HOUR:
519+ compute_duration = self._duration(cr, uid, leave.type_id.id, leave.am_pm, activities).get('value', {}).get('duration', -1)
520+ disable_check = self._disable_checks(cr, uid, leave.type_id.id, leave.activity_context_id.id)
521+ if leave.duration != compute_duration and not disable_check:
522+ return (compute_duration, hrself.TIME_UNIT_DAY_LABEL)
523+
524 return False
525
526 def _check_priority(self, cr, uid, ids, context=None):
527@@ -1062,13 +1000,9 @@
528 if self._overlap(cr, uid, ids):
529 raise osv.except_osv(_('Warning!'), _('One of the leave request you want to confirm is overlapping an existing one.'))
530
531- remaining = self._check_balance(cr, uid, ids)
532- if remaining :
533- raise osv.except_osv(_('Warning!'), _('The leave request duration is greater than balance. \n You have %d %s(s) left.') % remaining)
534-
535 allowed = self._check_allowed_duration(cr, uid, ids, context=context)
536 if allowed :
537- raise osv.except_osv(_('Warning!'), _('The leave request duration is greater than allowed. \n You have %.2f %s(s) left.') % allowed)
538+ raise osv.except_osv(_('Warning!'), _('The leave request duration is different than allowed. \n %.2f %s(s) is allowed.') % allowed)
539
540 for leave_request in self.browse(cr, uid, ids, context=context):
541 type_name = self._check_priority(cr, uid, ids, context)
542@@ -1079,6 +1013,16 @@
543 workflow_id = leave_request._get_workflow_id()
544 self._create_workflow(cr, uid, leave_request.id, workflow_id)
545 self.write(cr, uid, [leave_request.id], {'state': STATE_CONFIRMED})
546+
547+ self.pool.get('hrself.holidays.balance').update_balance(cr, uid, leave_request.employee_id.id,
548+ leave_request.type_id.id, leave_request.activity_context_id.id,
549+ leave_request.date_to, context=context)
550+ #Polish error message
551+ if not self.pool.get('hrself.holidays.balance').check_all_balance_positive(cr, uid, leave_request.employee_id.id,
552+ leave_request.type_id.id, leave_request.activity_context_id.id,
553+ leave_request.date_to, context=context ):
554+ raise osv.except_osv(_('Warning!'), _('The leave request duration is greater than balance.'))
555+
556 return True
557
558 def _transfer_to_approver(self, cr, uid, ids):
559@@ -1139,7 +1083,12 @@
560
561 def refuse(self, cr, uid, ids, context=None):
562 """Action executed when a leave request is refused"""
563- return self._change_state(cr, uid, ids, STATE_REFUSED, context=context)
564+ result = self._change_state(cr, uid, ids, STATE_REFUSED, context=context)
565+ for leave_request in self.browse(cr, uid, ids, context=context):
566+ self.pool.get('hrself.holidays.balance').update_balance(cr, uid, leave_request.employee_id.id,
567+ leave_request.type_id.id, leave_request.activity_context_id.id,
568+ leave_request.date_to, context=context)
569+ return result
570
571 def cancel(self, cr, uid, ids, context=None):
572 """Action executed when a leave request is cancelled"""
573@@ -1449,8 +1398,108 @@
574 'type_id': fields.many2one('hrself.holidays.type', 'Leave Type', required=True),
575 'unit': fields.selection(hrself.TIME_UNITS, 'Time unit', required=True),
576 'initial_value': fields.float('Initial value', required=True),
577- 'today_balance': fields.float('Balance (Today)', required=True),
578 'end_year_balance': fields.float('Balance (End of the year)', required=True),
579+ 'date' : fields.date("Date of the balance", required=True),
580 }
581+
582+ def check_all_balance_positive(self, cr, uid, employee_id, type_id, activity_context_id, date, context=None):
583+ precision_id = self.pool.get('hrself.holidays.type').precision_id_for_context(cr, uid, [type_id], activity_context_id)
584+ type_precision = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id)
585+ if type_precision.is_unlimited :
586+ return True
587+
588+ balance_ids = self.get_balance_ids(cr, uid, employee_id, type_id, date, context=context)
589+ for balance in self.browse(cr, uid, balance_ids, context=context):
590+ if balance.end_year_balance < 0:
591+ return False
592+ return True
593+
594+ def get_balance_ids(self, cr, uid, employee_id, type_id, effective_date, context=None):
595+ current_year = hrself_datetime.to_date(effective_date).year
596+ start_of_year = hrself_datetime.to_string(datetime.date(current_year, 1, 1))
597+ return self.search(cr, uid, [('employee_id', '=', employee_id), ('type_id', '=', type_id), ('date', '<=', effective_date), ('date', '>=', start_of_year)], order='date desc', context=context)
598+
599+ def get_all_balance_ids(self, cr, uid, employee_ids, date, context=None):
600+ """ Get the balance at a given date for an employee and all leave types."""
601+ sql = "SELECT DISTINCT ON (employee_id, type_id) id, employee_id, type_id, date " + \
602+ "FROM hrself_holidays_balance WHERE date <= '%s' AND employee_id in %%s ORDER BY employee_id, type_id, date DESC;" % date
603+ cr.execute(sql, (tuple(employee_ids),))
604+ return [r[0] for r in cr.fetchall()]
605+
606+ def get_employee_balance_ids(self, cr, uid, employee_id, type_ids, date, context=None):
607+ """ Get the balance at a given date for an employee and leave types."""
608+ sql = "SELECT DISTINCT ON (employee_id, type_id) id, employee_id, type_id, date " + \
609+ "FROM hrself_holidays_balance WHERE date <= '%s' AND employee_id = %s AND type_id in %%s " % (date, employee_id) + \
610+ "ORDER BY employee_id, type_id, date DESC;"
611+ cr.execute(sql, (tuple(type_ids),))
612+ return [r[0] for r in cr.fetchall()]
613+
614+ def update_balance(self, cr, uid, employee_id, type_id, activity_context_id, date, context=None):
615+ """
616+ Update balance after a modification of a initialization or a leave
617+ is_init : False, mean the modification come from a leave modification
618+ True mean the modification come from a leave modification
619+ """
620+ year = hrself_datetime.to_date(date).year
621+ self._delete_balance(cr, uid, employee_id, type_id, date, context=context)
622+ self._create_balance(cr, uid, employee_id, type_id, date, activity_context_id, context)
623+ self.compute_all_balance(cr, uid, employee_id, type_id, activity_context_id, year, context)
624+
625+ def _delete_balance(self, cr, uid, employee_id, type_id, date, context=None):
626+ year = hrself_datetime.to_date(date).year
627+ start_of_year = hrself_datetime.to_string(datetime.date(year, 1, 1))
628+ end_of_year = hrself_datetime.to_string(datetime.date(year, 12, 31))
629+ balance_ids = self.search(cr, uid, [('employee_id', '=', employee_id), ('type_id', '=', type_id), ('date', '<=', end_of_year), ('date', '>=', start_of_year)], context=context)
630+ self.unlink(cr, uid, balance_ids, context=context)
631+
632+ def _create_balance(self, cr, uid, employee_id, type_id, date, activity_context_id, context=None):
633+ year = hrself_datetime.to_date(date).year
634+ start_of_year = hrself_datetime.to_string(datetime.date(year, 1, 1))
635+ end_of_year = hrself_datetime.to_string(datetime.date(year, 12, 31))
636+
637+ init_obj = self.pool.get('hrself.holidays.request.initialization')
638+ init_request_ids = init_obj.search(cr, uid, [('employee_id', '=', employee_id), ('type_id', '=', type_id), ('date_from', '<=', end_of_year), ('date_from', '>=', start_of_year)], context=context)
639+ precision_id = self.pool.get('hrself.holidays.type').precision_id_for_context(cr, uid, [type_id], activity_context_id)
640+ unit = self.pool.get('hrself.holidays.type.precision').browse(cr, uid, precision_id, context=context).unit
641+ data = {
642+ 'employee_id' : employee_id,
643+ 'type_id' : type_id,
644+ 'unit' : unit,
645+ 'end_year_balance' : 0,
646+ }
647+ for init_request in init_obj.browse(cr, uid, init_request_ids, context=context):
648+ data.update({
649+ 'initial_value' : init_request.duration,
650+ 'date' : init_request.date_from,
651+ })
652+ self.create(cr, uid, data, context=context)
653+ #If there is no balance the 1st january, create one with initiatl value = 0
654+ balance_ids = self.search(cr, uid, [('employee_id', '=', employee_id), ('type_id', '=', type_id), ('date', '=', start_of_year)] ,context=context)
655+ if not balance_ids:
656+ data.update({
657+ 'initial_value' : 0,
658+ 'date' : start_of_year,
659+ })
660+ self.create(cr, uid, data, context=context)
661+
662+ def compute_all_balance(self, cr, uid, employee_id, type_id, activity_context_id, year, context=None):
663+ leave_object = self.pool.get('hrself.holidays.request.leave')
664+
665+ start_of_year = hrself_datetime.to_string(datetime.date(year, 1, 1))
666+ end_of_year = hrself_datetime.to_string(datetime.date(year, 12, 31))
667+ end_of_period_year = hrself_datetime.to_string(datetime.date(year + 1, 1, 1))
668+ balance_domain = [('type_id', '=', type_id), ('employee_id', '=', employee_id), ('date', '<=', end_of_year), ('date', '>=', start_of_year)]
669+ leave_domain = [('type_id', '=', type_id), ('employee_id', '=', employee_id),
670+ ('date_from', '>=', start_of_year), ('state', 'in', [STATE_CONFIRMED, STATE_APPROVED])]
671+
672+ balance_ids = self.search(cr, uid, balance_domain, order='date asc', context=context)
673+ balances = self.browse(cr, uid, balance_ids, context=context)
674+ for i in xrange(0, len(balance_ids)):
675+ date_end = i < len(balances) - 1 and balances[i+1].date or end_of_period_year
676+ domain = list(leave_domain)
677+ domain.append(('date_to', '<', date_end))
678+ leave_ids = leave_object.search(cr, uid, domain, context=context)
679+ remaining_leaves = balances[i].initial_value - sum(leave.duration for leave in leave_object.browse(cr, uid, leave_ids))
680+ self.write(cr, uid, balances[i].id, {'end_year_balance' : remaining_leaves }, context=context)
681
682 hrself_holidays_balance()
683
684=== modified file 'hrself_holidays/security/ir.model.access.csv'
685--- hrself_holidays/security/ir.model.access.csv 2011-12-05 15:00:14 +0000
686+++ hrself_holidays/security/ir.model.access.csv 2011-12-07 15:08:24 +0000
687@@ -33,7 +33,7 @@
688 "access_hrself_holidays_calendar_proxy","hrself.holidays.calendar.proxy","model_hrself_holidays_calendar_proxy","base.group_user",1,1,1,1
689 "access_hrself_holidays_calendar_proxy_config","hrself.holidays.calendar.proxy.config","model_hrself_holidays_calendar_proxy_config","base.group_user",1,0,0,0
690 "access_hrself_holidays_theoretical_activity","hrself.holidays.theoretical.activity","model_hrself_holidays_theoretical_activity","base.group_user",1,1,1,1
691-"access_hrself_holidays_balance","hrself.holidays.balance","model_hrself_holidays_balance","base.group_user",1,1,1,0
692+"access_hrself_holidays_balance","hrself.holidays.balance","model_hrself_holidays_balance","base.group_user",1,1,1,1
693 "access_email_template","email.template employee","email_template.model_email_template","base.group_user",1,0,0,0
694 "access_email_template_account_system","email_template.account employee","email_template.model_email_template_account","base.group_user",1,0,0,0
695 "access_email_template_account_system","email_template.account hrself manager","email_template.model_email_template_account","hrself.group_hr_admin_hrself",1,1,0,0
696
697=== modified file 'hrself_holidays/security/leave_request_security.xml'
698--- hrself_holidays/security/leave_request_security.xml 2011-08-26 14:25:55 +0000
699+++ hrself_holidays/security/leave_request_security.xml 2011-12-07 15:08:24 +0000
700@@ -89,6 +89,18 @@
701 </field>
702 <field name="groups" eval="[(6, 0, [ref('base.group_hr_user'), ref('hrself.group_hr_approver')])]"/>
703 </record>
704+
705+ <record id="ir_rule_functionaladmincannotdeletenotdraftleaverequest0" model="ir.rule">
706+ <field name="model_id" ref="hrself_holidays.model_hrself_holidays_request_leave"/>
707+ <field name="domain_force">[('state', 'in', ('Draft'))]</field>
708+ <field name="name">Functional Admin cannot delete not draft Leave request</field>
709+ <field eval="0" name="global"/>
710+ <field eval="[(6,0,[ref('base.group_hr_manager')])]" name="groups"/>
711+ <field eval="1" name="perm_unlink"/>
712+ <field eval="0" name="perm_write"/>
713+ <field eval="0" name="perm_read"/>
714+ <field eval="0" name="perm_create"/>
715+ </record>
716
717 </data>
718 </openerp>
719
720=== modified file 'hrself_holidays/view/hrself_holidays_view.xml'
721--- hrself_holidays/view/hrself_holidays_view.xml 2011-11-29 15:58:54 +0000
722+++ hrself_holidays/view/hrself_holidays_view.xml 2011-12-07 15:08:24 +0000
723@@ -36,8 +36,8 @@
724 <field name="type_id"/>
725 <field name="unit"/>
726 <field name="initial_value"/>
727- <field name="today_balance"/>
728 <field name="end_year_balance"/>
729+ <field name="date" />
730 </form>
731 </field>
732 </record>
733@@ -52,8 +52,23 @@
734 <field name="type_id"/>
735 <field name="unit"/>
736 <field name="initial_value"/>
737- <field name="today_balance"/>
738- <field name="end_year_balance"/>
739+ <field name="end_year_balance"/>
740+ </tree>
741+ </field>
742+ </record>
743+
744+ <record model="ir.ui.view" id="hrself_holidays_balance_complete_tree_view">
745+ <field name="name">hrself.holidays.balance.tree</field>
746+ <field name="model">hrself.holidays.balance</field>
747+ <field name="type">tree</field>
748+ <field name="arch" type="xml">
749+ <tree string="Leave Balances">
750+ <field name="employee_id"/>
751+ <field name="type_id"/>
752+ <field name="unit"/>
753+ <field name="initial_value"/>
754+ <field name="end_year_balance"/>
755+ <field name="date" />
756 </tree>
757 </field>
758 </record>
759@@ -65,11 +80,18 @@
760 <field name="search_view_id" eval="hrself_holidays_balance_filter_view"/>
761 </record>
762
763+ <record model="ir.actions.act_window" id="hrself_holidays_balance_complete_action">
764+ <field name="res_model">hrself.holidays.balance</field>
765+ <field name="view_type">form</field>
766+ <field name="view_id" eval="hrself_holidays_balance_complete_tree_view"/>
767+ <field name="search_view_id" eval="hrself_holidays_balance_filter_view"/>
768+ </record>
769+
770 <menuitem
771 name="Leave Balances"
772 parent="menu_open_request_holidays"
773 id="hrself_holidays_balance_menu"
774- action="hrself_holidays_balance_action"
775+ action="hrself_holidays_balance_complete_action"
776 groups = "-base.group_hr_manager,base.group_erp_manager,hrself.group_hr_admin_hrself"
777 sequence="50"
778 />
779@@ -204,15 +226,15 @@
780 <field name="arch" type="xml">
781 <form string="Leave Request">
782 <group col="6" colspan="4">
783- <field name="employee_id" on_change="onchange_employee_id(employee_id,date_from,date_to,type_id,am_pm,context)"/>
784- <field name="date_from" on_change="onchange_date_from(employee_id,date_from,date_to,type_id,am_pm,context)"/>
785- <field name="date_to" required="1" on_change="onchange_date_to(employee_id,date_to,date_from,type_id,am_pm,context)"/>
786- <field name="type_id" default_focus="1" on_change="onchange_type(employee_id,date_from,date_to,type_id,am_pm,context)" context="{'employee_id': employee_id, 'date_from': date_from, 'date_to': date_to}" attrs="{'readonly': ['|', ('date_from', '=', False), ('employee_id', '=', False)]}"/>
787- <field name="duration" on_change="onchange_duration(employee_id,date_from,date_to,type_id,duration,unit,am_pm,context)"/>
788- <field name="unit" on_change="onchange_unit(employee_id,date_from,date_to,type_id,unit,am_pm,context)"/>
789- <field name="reason_id" domain="[('type_id', '=', type_id)]"/>
790- <field name="name"/>
791- <field name="am_pm" on_change="onchange_am_pm(employee_id,date_from,date_to,type_id,am_pm,context)"/>
792+ <field name="employee_id" on_change="onchange_date_type(employee_id,date_from,date_to,type_id,am_pm, context)" />
793+ <field name="date_from" on_change="onchange_date(employee_id,date_from,date_to,type_id,am_pm, context)" />
794+ <field name="date_to" required="1" on_change="onchange_date(employee_id,date_from,date_to,type_id,am_pm, context)" />
795+ <field name="type_id" default_focus="1" on_change="onchange_date_type(employee_id,date_from,date_to,type_id,am_pm, context)" context="{'employee_id': employee_id, 'date_from': date_from, 'date_to': date_to}" attrs="{'readonly': [('employee_id', '=', False)]}" />
796+ <field name="duration"/>
797+ <field name="unit" on_change="onchange_unit(employee_id,date_from,date_to,type_id,am_pm, context)" />
798+ <field name="reason_id" domain="[('type_id', '=', type_id)]" />
799+ <field name="name" />
800+ <field name="am_pm" on_change="onchange_date_type(employee_id,date_from,date_to,type_id,am_pm, context)"/>
801 <!-- Duration (in hour) is visible when the unit is day.
802 So the opposite is: duration (in hour) is invisible when the unit is not day. -->
803 <field name="duration_in_hour" attrs="{'invisible': [('unit', '!=', 1)]}"/>
804
805=== modified file 'hrself_holidays/wizard/hrself_report_wizard.py'
806--- hrself_holidays/wizard/hrself_report_wizard.py 2011-12-01 13:46:13 +0000
807+++ hrself_holidays/wizard/hrself_report_wizard.py 2011-12-07 15:08:24 +0000
808@@ -137,61 +137,13 @@
809
810 def print_report(self, cr, uid, ids, context=None):
811 """Print the report."""
812- type_object = self.pool.get('hrself.holidays.type')
813+ year = datetime.date.today().year
814+ end_of_year = to_string(datetime.date(year, 12, 31))
815 balance_object = self.pool.get('hrself.holidays.balance')
816- activity_context_object = self.pool.get('hrself.activity.context')
817 wizard = self.browse(cr, uid, ids[0], context=context)
818- end_year = datetime.date(datetime.date.today().year, 12, 31)
819- balance_ids = []
820- employee_object = self.pool.get('hr.employee')
821- employee_ids = []
822- employee_object = self.pool.get('hr.employee')
823- for employee in wizard.employee_ids:
824- employee_ids.append(employee.id)
825- activity_context_ids = employee_object.get_today_activity_context_id(cr, uid, employee_ids, context=context)
826- end_year_activity_context_ids = employee_object.get_one_day_activity_context_id(cr, uid, employee_ids, end_year, context=context)
827- for employee in wizard.employee_ids:
828- balance_context = {
829- 'employee_id': employee.id,
830- }
831- remaining_date_to = datetime.date.today()
832- #employee_activity_context = employee.get_today_activity_context_id(context)
833- activity_context_id = activity_context_ids[employee.id]
834- if activity_context_id:
835- context['activity_context_id']= activity_context_id
836- type_ids = type_object.search(cr, uid, [], context=context)
837- del context['activity_context_id']
838- today_balances = type_object.compute_values(cr, uid, type_ids, context=balance_context, remaining_date_to=remaining_date_to)
839- services = self.pool.get('hrself.services').hrself_holidays_service(cr, uid, context=context)
840- #activities = services.get_theoretical_activities(cr, uid, employee.id, end_year, end_year, context=context)
841- end_year_activity_context_id = end_year_activity_context_ids[employee.id]
842- if end_year_activity_context_id:
843- balance_context['activity_context'] = end_year_activity_context_id
844- end_year_balances = type_object.get_remaining_leaves_for_employee(cr, uid, type_ids, context=balance_context)
845- for type in type_object.browse(cr, uid, type_ids, context=context):
846- initial_value = type.get_initialization_duration_for_employee(context=balance_context)[type.id]
847- search_ids = balance_object.search(cr, uid, [('employee_id', '=', employee.id), ('type_id', '=', type.id)], context=context)
848- if search_ids:
849- balance_object.write(cr, uid, search_ids, {
850- 'unit': today_balances[type.id]['unit'],
851- 'initial_value': initial_value,
852- 'today_balance': today_balances[type.id]['remaining_leaves'],
853- 'end_year_balance': end_year_balances.get(type.id, 0),
854- }, context=context)
855- balance_id = search_ids[0]
856- else:
857- balance_id = balance_object.create(cr, uid, {
858- 'employee_id': employee.id,
859- 'type_id': type.id,
860- 'unit': today_balances[type.id]['unit'],
861- 'initial_value': initial_value,
862- 'today_balance': today_balances[type.id]['remaining_leaves'],
863- 'end_year_balance': end_year_balances.get(type.id, 0),
864- }, context=context)
865- balance_ids.append(balance_id)
866- else:
867- raise osv.except_osv(_('Warning!'), _('Unable to find activity context for employee %s %s (id: %d).') % (employee.name, employee.first_name, employee.id))
868-
869+ employee_ids = [employee.id for employee in wizard.employee_ids]
870+ balance_ids = balance_object.get_all_balance_ids(cr, uid, employee_ids, end_of_year, context=context)
871+
872 model_data_object = self.pool.get('ir.model.data')
873 model_data_id = model_data_object._get_id(cr, uid, 'hrself_holidays', 'hrself_holidays_balance_action')
874 window_id = model_data_object.browse(cr, uid, model_data_id, context=context).res_id

Subscribers

People subscribed via source and target branches

to all changes: