[FIX] hr_timesheet_sheet: total attendances & timesheets performances

For these function fields, bypassing the ORM, using a SQL query,
improves the execution time by 100 for a set of 80 timesheets
in a database with
 - 250K `hr.analytic.timesheet`
&
 - 250K `hr.attendance`.

These function fields depends on a one2many field which use
the SQL view `hr_timesheet_sheet_sheet_day`.

When performing `sheet.period_ids`, two SQL requests are performed,
 - the first just to know the ids in the sql view matching this sheet
 - the second to read the fields `total_attendance` & `total_timesheet`
and the request is performed on the entire set of lines of this view
(~250K lines in the observed use case)

while, when replaced by this SQL request, only one request is performed,
on a restricted set of lines, speeding up significantly the computation
of these computed fields for smaller sets of sheets.

opw-653447
This commit is contained in:
Denis Ledoux 2015-11-05 16:00:47 +01:00
parent 80c7209d2e
commit a23468c845
1 changed files with 17 additions and 11 deletions

View File

@ -41,18 +41,24 @@ class hr_timesheet_sheet(osv.osv):
""" Compute the attendances, analytic lines timesheets and differences between them
for all the days of a timesheet and the current day
"""
res = dict.fromkeys(ids, {
'total_attendance': 0.0,
'total_timesheet': 0.0,
'total_difference': 0.0,
})
cr.execute("""
SELECT sheet_id as id,
sum(total_attendance) as total_attendance,
sum(total_timesheet) as total_timesheet,
sum(total_difference) as total_difference
FROM hr_timesheet_sheet_sheet_day
WHERE sheet_id IN %s
GROUP BY sheet_id
""", (tuple(ids),))
res.update(dict((x.pop('id'), x) for x in cr.dictfetchall()))
res = {}
for sheet in self.browse(cr, uid, ids, context=context or {}):
res.setdefault(sheet.id, {
'total_attendance': 0.0,
'total_timesheet': 0.0,
'total_difference': 0.0,
})
for period in sheet.period_ids:
res[sheet.id]['total_attendance'] += period.total_attendance
res[sheet.id]['total_timesheet'] += period.total_timesheet
res[sheet.id]['total_difference'] += period.total_attendance - period.total_timesheet
return res
def check_employee_attendance_state(self, cr, uid, sheet_id, context=None):