Merge lp:~openerp-groupes/hrself-addons/balance-report-optimization-oli into lp:hrself-addons
- balance-report-optimization-oli
- Merge into 6.0
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Groupe S | Pending | ||
Review via email: mp+84604@code.launchpad.net |
Commit message
Description of the change
- 639. By Olivier Ligot
-
[MERGE] Upstream merge
- 640. By Olivier Ligot
-
[FIX] _update_context: get employee from uid if not defined
- 641. By Olivier Ligot
-
[FIX] Get unit from precision when no balance for a given type
- 642. By Olivier Ligot
-
[REM] print statements
- 643. By Olivier Ligot
-
[REF] Don't use _ for public functions
- 644. By Olivier Ligot
-
[REM] today_balance field
- 645. By Olivier Ligot
-
[IMP] Define 2 balance tree views: one with date field and one without
- 646. By Olivier Ligot
-
[FIX] Employee has now the right to delete a balance
- 647. By Olivier Ligot
-
[FIX] Check allowed duration when start date equals end date and unit is day
- 648. By Olivier Ligot
-
[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
-
[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
-
[FIX] Check allowed duration when start date equals end date and unit is day
- 646. By Olivier Ligot
-
[FIX] Employee has now the right to delete a balance
- 645. By Olivier Ligot
-
[IMP] Define 2 balance tree views: one with date field and one without
- 644. By Olivier Ligot
-
[REM] today_balance field
- 643. By Olivier Ligot
-
[REF] Don't use _ for public functions
- 642. By Olivier Ligot
-
[REM] print statements
- 641. By Olivier Ligot
-
[FIX] Get unit from precision when no balance for a given type
- 640. By Olivier Ligot
-
[FIX] _update_context: get employee from uid if not defined
- 639. By Olivier Ligot
-
[MERGE] Upstream merge
Preview Diff
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 |