[FIX] sale_timesheet: performance for project with a lot of tasks

closes odoo/odoo#33766

Signed-off-by: Nicolas Seinlet (nse) <nse@odoo.com>
This commit is contained in:
Toufik Ben Jaa
2019-06-03 08:19:50 +00:00
parent 15187da85a
commit a7649a3d86
@@ -82,12 +82,16 @@ class Project(models.Model):
#
# Time Repartition (per employee per billable types)
#
user_ids = self.env['project.task'].sudo().search_read([('project_id', 'in', self.ids), ('user_id', '!=', False)], ['user_id'])
user_ids = self.env['project.task'].sudo().read_group([('project_id', 'in', self.ids), ('user_id', '!=', False)], ['user_id'], ['user_id'])
user_ids = [user_id['user_id'][0] for user_id in user_ids]
employee_ids = self.env['res.users'].sudo().search_read([('id', 'in', user_ids)], ['employee_ids'])
# flatten the list of list
employee_ids = list(itertools.chain.from_iterable([employee_id['employee_ids'] for employee_id in employee_ids]))
employees = self.env['hr.employee'].sudo().browse(employee_ids) | self.env['account.analytic.line'].search([('project_id', 'in', self.ids)]).mapped('employee_id')
aal_employee_ids = self.env['account.analytic.line'].read_group([('project_id', 'in', self.ids), ('employee_id', '!=', False)], ['employee_id'], ['employee_id'])
employee_ids.extend(list(map(lambda x: x['employee_id'][0], aal_employee_ids)))
employees = self.env['hr.employee'].sudo().browse(employee_ids)
repartition_domain = [('project_id', 'in', self.ids), ('employee_id', '!=', False), ('timesheet_invoice_type', '!=', False)] # force billable type
repartition_data = self.env['account.analytic.line'].read_group(repartition_domain, ['employee_id', 'timesheet_invoice_type', 'unit_amount'], ['employee_id', 'timesheet_invoice_type'], lazy=False)
@@ -330,8 +334,14 @@ class Project(models.Model):
def _plan_prepare_actions(self, values):
actions = []
if len(self) == 1:
task_order_line_ids = []
# retrieve all the sale order line that we will need later below
if self.env.user.has_group('sales_team.group_sale_salesman') or self.env.user.has_group('sales_team.group_sale_salesman_all_leads'):
task_order_line_ids = self.env['project.task'].read_group([('project_id', '=', self.id), ('sale_line_id', '!=', False)], ['sale_line_id'], ['sale_line_id'])
task_order_line_ids = [ol['sale_line_id'][0] for ol in task_order_line_ids]
if self.env.user.has_group('sales_team.group_sale_salesman'):
if not self.sale_line_id and not self.tasks.mapped('sale_line_id'):
if not self.sale_line_id and not task_order_line_ids:
actions.append({
'label': _("Create a Sales Order"),
'type': 'action',
@@ -340,14 +350,19 @@ class Project(models.Model):
})
if self.env.user.has_group('sales_team.group_sale_salesman_all_leads'):
to_invoice_amount = values['dashboard']['profit'].get('to_invoice', False) # plan project only takes services SO line with timesheet into account
sale_orders = self.tasks.mapped('sale_line_id.order_id').filtered(lambda so: so.invoice_status == 'to invoice')
if to_invoice_amount and sale_orders:
if len(sale_orders) == 1:
sale_order_ids = self.env['sale.order.line'].read_group([('id', 'in', task_order_line_ids)], ['order_id'], ['order_id'])
sale_order_ids = [s['order_id'][0] for s in sale_order_ids]
sale_order_ids = self.env['sale.order'].search_read([('id', 'in', sale_order_ids), ('invoice_status', '=', 'to invoice')], ['id'])
sale_order_ids = list(map(lambda x: x['id'], sale_order_ids))
if to_invoice_amount and sale_order_ids:
if len(sale_order_ids) == 1:
actions.append({
'label': _("Create Invoice"),
'type': 'action',
'action_id': 'sale.action_view_sale_advance_payment_inv',
'context': json.dumps({'active_ids': sale_orders.ids, 'active_model': 'project.project'}),
'context': json.dumps({'active_ids': sale_order_ids, 'active_model': 'project.project'}),
})
else:
actions.append({
@@ -383,9 +398,13 @@ class Project(models.Model):
# if only one project, add it in the context as default value
tasks_domain = [('project_id', 'in', self.ids)]
tasks_context = self.env.context
tasks_projects = self.env['project.task'].sudo().search(tasks_domain).mapped('project_id')
if len(tasks_projects) == 1:
tasks_context = {**tasks_context, 'default_project_id': tasks_projects.id}
# filter out all the projects that have no tasks
task_projects_ids = self.env['project.task'].read_group([('project_id', 'in', self.ids)], ['project_id'], ['project_id'])
task_projects_ids = [p['project_id'][0] for p in task_projects_ids]
if len(task_projects_ids) == 1:
tasks_context = {**tasks_context, 'default_project_id': task_projects_ids[0]}
stat_buttons.append({
'name': _('Tasks'),
'count': sum(self.mapped('task_count')),
@@ -398,8 +417,13 @@ class Project(models.Model):
})
if self.env.user.has_group('sales_team.group_sale_salesman_all_leads'):
sale_orders = self.mapped('sale_line_id.order_id') | self.mapped(
'tasks.sale_order_id')
# read all the sale orders linked to the projects' tasks
task_so_ids = self.env['project.task'].search_read([
('project_id', 'in', self.ids), ('sale_order_id', '!=', False)
], ['sale_order_id'])
task_so_ids = [o['sale_order_id'][0] for o in task_so_ids]
sale_orders = self.mapped('sale_line_id.order_id') | self.env['sale.order'].browse(task_so_ids)
if sale_orders:
stat_buttons.append({
'name': _('Sales Orders'),
@@ -411,15 +435,20 @@ class Project(models.Model):
context={'create': False, 'edit': False, 'delete': False}
)
})
invoices = sale_orders.mapped('invoice_ids').filtered(lambda inv: inv.type == 'out_invoice')
if invoices:
invoice_ids = self.env['sale.order'].search_read([('id', 'in', sale_orders.ids)], ['invoice_ids'])
invoice_ids = list(itertools.chain(*[i['invoice_ids'] for i in invoice_ids]))
invoice_ids = self.env['account.invoice'].search_read([('id', 'in', invoice_ids), ('type', '=', 'out_invoice')], ['id'])
invoice_ids = list(map(lambda x: x['id'], invoice_ids))
if invoice_ids:
stat_buttons.append({
'name': _('Invoices'),
'count': len(invoices),
'count': len(invoice_ids),
'icon': 'fa fa-pencil-square-o',
'action': _to_action_data(
action=self.env.ref('account.action_invoice_tree1'),
domain=[('id', 'in', invoices.ids), ('type', '=', 'out_invoice')],
domain=[('id', 'in', invoice_ids), ('type', '=', 'out_invoice')],
context={'create': False, 'delete': False}
)
})