~laetitia-gangloff/acsone-addons/hr_utilization_group_by_report

« back to all changes in this revision

Viewing changes to hr_utilization/report/hr_utilization_report.py

  • Committer: Laetitia Gangloff
  • Date: 2013-06-11 12:16:06 UTC
  • Revision ID: laetitia.gangloff@acsone.eu-20130611121606-m3xkmhx12j8acx1u
hr_utilization: add group by department/company for the report

Show diffs side-by-side

added added

removed removed

Lines of Context:
152
152
        #       (which is the OpenErp default and the convention used in account_analytic_analysis)    
153
153
        # XXX: this query assumes all timesheets are entered in hours
154
154
        self.cr.execute("""
155
 
            select al.user_id, al.account_id, r.name, r.company_id, c.id, sum(al.unit_amount)
 
155
            select e.department_id, al.user_id, al.account_id, r.name, r.company_id, c.id, sum(al.unit_amount)
156
156
              from account_analytic_line al
157
157
              left join res_users u on u.id = al.user_id 
158
158
              left join resource_resource r on r.user_id = u.id
163
163
                      (c.date_end is null or al.date <= c.date_end)
164
164
              where al.journal_id = (select id from account_analytic_journal where type='general')
165
165
                and al.date >= %s and al.date <= %s
166
 
              group by al.user_id, al.account_id, r.name, r.company_id, c.id
 
166
              group by e.department_id, al.user_id, al.account_id, r.name, r.company_id, c.id
167
167
              order by r.name""", (data['period_start'], data['period_end']))
168
168
 
169
 
        res = {} # user_id: {'name':name,'columns':{column_name:hours}}
170
 
        for user_id, account_id, user_name, company_id, contract_id, hours in self.cr.fetchall():
171
 
            if contract_id in contracts_with_schedule_by_id:
172
 
                key = (user_id, True)
173
 
            else:
174
 
                key = (user_id, False)
 
169
        res = {} # (user_id, has_schedule): {'name':name,'columns':{column_name:hours}}
 
170
        res_company = {} # (company_id, has_schedule): {'name':name, users:[user_ids], departments: [departmen_ids],}
 
171
        res_department = {} # (department_id, has_schedule): {'name':name, users:[user_ids]}
 
172
        for department_id, user_id, account_id, user_name, company_id, contract_id, hours in self.cr.fetchall():
 
173
            has_schedule = contract_id in contracts_with_schedule_by_id
 
174
            key = (user_id, has_schedule)
175
175
            if key not in res:
176
176
                res[key] = {
177
177
                    'name': user_name,
179
179
                    'hours': {column_name:0.0 for column_name in column_names},
180
180
                    'contracts': {}, # contract_id: contract
181
181
                }
182
 
            if only_total:        
 
182
            if only_total:
183
183
                column_name = TOTAL
184
184
            else:
185
185
                column_name = account_id_column_name_map.get(account_id, OTHER)
186
186
            res[key]['hours'][column_name] += hours
187
 
            if contract_id in contracts_with_schedule_by_id:
 
187
            if has_schedule:
188
188
                res[key]['contracts'][contract_id] = contracts_with_schedule_by_id[contract_id]
189
 
                
 
189
 
 
190
            if not data['group_by_company']:
 
191
                company_id = (None, has_schedule)
 
192
            if not data['group_by_department']:
 
193
                department_id = (None, has_schedule)
 
194
            if (company_id, has_schedule) not in res_company:
 
195
                company_name = ''
 
196
                if company_id:
 
197
                    company_name = self.pool.get("res.company").browse(self.cr, self.uid, company_id).name
 
198
                res_company[(company_id, has_schedule)] = {
 
199
                                           'name': company_name,
 
200
                                           'users': [user_id],
 
201
                                           'departments': [department_id],
 
202
                                           'hours': {column_name:0.0 for column_name in column_names},}
 
203
            else:
 
204
                if user_id not in res_company[(company_id, has_schedule)]['users']:
 
205
                    res_company[(company_id, has_schedule)]['users'].append(user_id)
 
206
                if department_id not in res_company[(company_id, has_schedule)]['departments']:
 
207
                    res_company[(company_id, has_schedule)]['departments'].append(department_id)
 
208
 
 
209
            if (department_id, has_schedule) not in res_department:
 
210
                department_name = ''
 
211
                if department_id:
 
212
                    department_name = self.pool.get("hr.department").browse(self.cr, self.uid, department_id).name
 
213
                res_department[(department_id, has_schedule)] = {
 
214
                                                 'name': department_name,
 
215
                                                 'users': [user_id],
 
216
                                                 'hours': {column_name:0.0 for column_name in column_names},}
 
217
            else:
 
218
                if user_id not in res_department[(department_id, has_schedule)]['users']: 
 
219
                    res_department[(department_id, has_schedule)]['users'].append(user_id)
 
220
            res_department[(department_id, has_schedule)]['hours'][column_name] += hours
 
221
            res_company[(company_id, has_schedule)]['hours'][column_name] += hours
 
222
 
190
223
        # initialize totals
191
224
        users_without_contract = []
192
225
        with_fte = configuration.with_fte
205
238
        }
206
239
 
207
240
        # row total, percentages and fte for each row
208
 
        for (user_id, has_schedule), u in res.items():
209
 
            # row total
 
241
        for (company_id, has_company_schedule), company in res_company.items():
 
242
            company_available_hours = 0.0
 
243
            if with_fte:
 
244
                company['fte'] = 0.0
210
245
            if not only_total:
211
 
                u['hours'][TOTAL] = reduce(lambda x,y: x+y, u['hours'].values())
 
246
                company['hours'][TOTAL] = reduce(lambda x,y: x+y, company['hours'].values())
 
247
            for (department_id, has_department_schedule), department in res_department.items():
 
248
                if department_id in company['departments']:
 
249
                    department_available_hours = 0.0
 
250
                    if with_fte:
 
251
                        department['fte'] = 0.0
 
252
                    if not only_total:
 
253
                        department['hours'][TOTAL] = reduce(lambda x,y: x+y, department['hours'].values())
 
254
                    for (user_id, has_schedule), u in res.items():
 
255
                        if user_id in department['users'] and user_id in company['users']:
 
256
                            # row total
 
257
                            if not only_total:
 
258
                                u['hours'][TOTAL] = reduce(lambda x,y: x+y, u['hours'].values())
212
259
 
213
 
            if has_schedule:
214
 
                # column totals
215
 
                for column_name in column_names:
216
 
                    res_total['hours'][column_name] += u['hours'][column_name]
217
 
                # percentage
218
 
                available_hours = self.get_total_planned_working_hours(data['period_start'], data['period_end'], u['contracts'].values())
219
 
                total_available_hours += available_hours
220
 
                u['pct'] = { column_name: hours/available_hours for column_name, hours in u['hours'].items() }
221
 
                # fte
222
 
                if with_fte:
223
 
                    company = company_obj.browse(self.cr, self.uid, [u['company_id']])[0]
224
 
                    if company.fulltime_calendar_id:
225
 
                        fte_available_hours = self.get_planned_working_hours(company.fulltime_calendar_id, data['period_start'], data['period_end'])
226
 
                        fte = available_hours / fte_available_hours
227
 
                        res_total['fte'] += fte
228
 
                        u['fte'] = "%.1f" % fte
229
 
                    else:
230
 
                        u['fte'] = NA
231
 
                        fte_with_na = True
232
 
            else:
233
 
                users_without_contract.append(u['name'])
234
 
                # column totals
235
 
                for column_name in column_names:
236
 
                    res_nc_total['hours'][column_name] += u['hours'][column_name]
 
260
                            if has_schedule:
 
261
                                # column totals
 
262
                                for column_name in column_names:
 
263
                                    res_total['hours'][column_name] += u['hours'][column_name]
 
264
                                # percentage
 
265
                                available_hours = self.get_total_planned_working_hours(data['period_start'], data['period_end'], u['contracts'].values())
 
266
                                total_available_hours += available_hours
 
267
                                company_available_hours += available_hours
 
268
                                department_available_hours += available_hours
 
269
                                u['pct'] = { column_name: hours/available_hours for column_name, hours in u['hours'].items() }
 
270
                                # fte
 
271
                                if with_fte:
 
272
                                    company_u = company_obj.browse(self.cr, self.uid, [u['company_id']])[0]
 
273
                                    if company_u.fulltime_calendar_id:
 
274
                                        fte_available_hours = self.get_planned_working_hours(company_u.fulltime_calendar_id, data['period_start'], data['period_end'])
 
275
                                        fte = available_hours / fte_available_hours
 
276
                                        res_total['fte'] += fte
 
277
                                        company['fte'] += fte
 
278
                                        department['fte'] += fte
 
279
                                        u['fte'] = "%.1f" % fte
 
280
                                    else:
 
281
                                        u['fte'] = NA
 
282
                                        fte_with_na = True
 
283
                            else:
 
284
                                users_without_contract.append(u['name'])
 
285
                                # column totals
 
286
                                for column_name in column_names:
 
287
                                    res_nc_total['hours'][column_name] += u['hours'][column_name]
 
288
                    if has_company_schedule and has_department_schedule:
 
289
                        department['pct'] = { column_name: hours/department_available_hours for column_name, hours in department['hours'].items() }
 
290
                        if with_fte and fte_with_na and not(department['fte']):
 
291
                            department['fte'] = NA
 
292
                        else:
 
293
                            department['fte'] = "%.1f" % department['fte']
 
294
            if has_company_schedule:
 
295
                company['pct'] = { column_name: hours/company_available_hours for column_name, hours in company['hours'].items() }
 
296
                if with_fte and fte_with_na and not(company['fte']):
 
297
                    company['fte'] = NA
 
298
                else:
 
299
                    company['fte'] = "%.1f" % company['fte']
237
300
 
238
301
        # total average percentage
239
302
        if total_available_hours:
249
312
 
250
313
        # set data in context for report
251
314
        data['res'] = res
 
315
        data['res_department'] = res_department
 
316
        data['res_company'] = res_company
252
317
        data['res_total'] = res_total
253
318
        data['res_nc_total'] = res_nc_total
254
319
        data['users_without_contract'] = users_without_contract
264
329
                           'hr.utilization.print',
265
330
                           rml='addons/hr_utilization/report/hr_utilization_report.mako',
266
331
                           parser=hr_utilization_report)
267
 
 
268
 
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
 
332
 
 
333
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: