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']))
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)
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:
177
177
'name': user_name,
179
179
'hours': {column_name:0.0 for column_name in column_names},
180
180
'contracts': {}, # contract_id: contract
183
183
column_name = TOTAL
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:
188
188
res[key]['contracts'][contract_id] = contracts_with_schedule_by_id[contract_id]
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:
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,
201
'departments': [department_id],
202
'hours': {column_name:0.0 for column_name in column_names},}
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)
209
if (department_id, has_schedule) not in res_department:
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,
216
'hours': {column_name:0.0 for column_name in column_names},}
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
190
223
# initialize totals
191
224
users_without_contract = []
192
225
with_fte = configuration.with_fte
207
240
# row total, percentages and fte for each row
208
for (user_id, has_schedule), u in res.items():
241
for (company_id, has_company_schedule), company in res_company.items():
242
company_available_hours = 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
251
department['fte'] = 0.0
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']:
258
u['hours'][TOTAL] = reduce(lambda x,y: x+y, u['hours'].values())
215
for column_name in column_names:
216
res_total['hours'][column_name] += u['hours'][column_name]
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() }
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
233
users_without_contract.append(u['name'])
235
for column_name in column_names:
236
res_nc_total['hours'][column_name] += u['hours'][column_name]
262
for column_name in column_names:
263
res_total['hours'][column_name] += u['hours'][column_name]
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() }
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
284
users_without_contract.append(u['name'])
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
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']):
299
company['fte'] = "%.1f" % company['fte']
238
301
# total average percentage
239
302
if total_available_hours: