From 81be161fae110fe2fe0506f15ed1771a66c39e4a Mon Sep 17 00:00:00 2001 From: Kartik Chavda Date: Sat, 13 Aug 2022 06:06:55 +0000 Subject: [PATCH] [IMP] {hr,sale}_timesheet: compute total time wo checking security rules Before this commit total time on timesheet for projects and invoices computed according to user's access to timesheet and security rules on account.analytic.line are quite complex. So, in this commit compute those fields with sudo to ease the perfomance of project and sale apps. task-2890184 closes odoo/odoo#99372 Related: odoo/enterprise#30950 Related: odoo/upgrade#3843 Signed-off-by: Xavier Bol (xbo) --- addons/hr_timesheet/models/project_project.py | 14 +------ .../views/project_project_views.xml | 3 +- addons/sale_timesheet/models/account_move.py | 6 ++- addons/sale_timesheet/models/sale_order.py | 41 ++++++++----------- 4 files changed, 22 insertions(+), 42 deletions(-) diff --git a/addons/hr_timesheet/models/project_project.py b/addons/hr_timesheet/models/project_project.py index c5b200f3396..4881dac58a8 100644 --- a/addons/hr_timesheet/models/project_project.py +++ b/addons/hr_timesheet/models/project_project.py @@ -20,11 +20,10 @@ class Project(models.Model): ) timesheet_ids = fields.One2many('account.analytic.line', 'project_id', 'Associated Timesheets') - timesheet_count = fields.Integer(compute="_compute_timesheet_count", groups='hr_timesheet.group_hr_timesheet_user') timesheet_encode_uom_id = fields.Many2one('uom.uom', related='company_id.timesheet_encode_uom_id') total_timesheet_time = fields.Integer( compute='_compute_total_timesheet_time', groups='hr_timesheet.group_hr_timesheet_user', - help="Total number of time (in the proper UoM) recorded in the project, rounded to the unit.") + help="Total number of time (in the proper UoM) recorded in the project, rounded to the unit.", compute_sudo=True) encode_uom_in_days = fields.Boolean(compute='_compute_encode_uom_in_days') is_internal_project = fields.Boolean(compute='_compute_is_internal_project', search='_search_is_internal_project') remaining_hours = fields.Float(compute='_compute_remaining_hours', string='Remaining Invoiced Time', compute_sudo=True) @@ -148,17 +147,6 @@ class Project(models.Model): total_time *= project.timesheet_encode_uom_id.factor project.total_timesheet_time = int(round(total_time)) - @api.depends('timesheet_ids') - def _compute_timesheet_count(self): - timesheet_read_group = self.env['account.analytic.line']._read_group( - [('project_id', 'in', self.ids)], - ['project_id'], - ['project_id'] - ) - timesheet_project_map = {project_info['project_id'][0]: project_info['project_id_count'] for project_info in timesheet_read_group} - for project in self: - project.timesheet_count = timesheet_project_map.get(project.id, 0) - @api.model_create_multi def create(self, vals_list): """ Create an analytic account if project allow timesheet and don't provide one diff --git a/addons/hr_timesheet/views/project_project_views.xml b/addons/hr_timesheet/views/project_project_views.xml index e5ea4bee6c5..bc362c4cb42 100644 --- a/addons/hr_timesheet/views/project_project_views.xml +++ b/addons/hr_timesheet/views/project_project_views.xml @@ -54,13 +54,12 @@ - -
+ diff --git a/addons/sale_timesheet/models/account_move.py b/addons/sale_timesheet/models/account_move.py index 2628bd326ac..dacc6d1f99c 100644 --- a/addons/sale_timesheet/models/account_move.py +++ b/addons/sale_timesheet/models/account_move.py @@ -11,9 +11,11 @@ class AccountMove(models.Model): _inherit = "account.move" timesheet_ids = fields.One2many('account.analytic.line', 'timesheet_invoice_id', string='Timesheets', readonly=True, copy=False) - timesheet_count = fields.Integer("Number of timesheets", compute='_compute_timesheet_count') + timesheet_count = fields.Integer("Number of timesheets", compute='_compute_timesheet_count', compute_sudo=True) timesheet_encode_uom_id = fields.Many2one('uom.uom', related='company_id.timesheet_encode_uom_id') - timesheet_total_duration = fields.Integer("Timesheet Total Duration", compute='_compute_timesheet_total_duration', help="Total recorded duration, expressed in the encoding UoM, and rounded to the unit") + timesheet_total_duration = fields.Integer("Timesheet Total Duration", + compute='_compute_timesheet_total_duration', compute_sudo=True, + help="Total recorded duration, expressed in the encoding UoM, and rounded to the unit") @api.depends('timesheet_ids', 'company_id.timesheet_encode_uom_id') def _compute_timesheet_total_duration(self): diff --git a/addons/sale_timesheet/models/sale_order.py b/addons/sale_timesheet/models/sale_order.py index 6537a7ebef7..558253a43e3 100644 --- a/addons/sale_timesheet/models/sale_order.py +++ b/addons/sale_timesheet/models/sale_order.py @@ -12,40 +12,31 @@ from odoo.tools import float_compare class SaleOrder(models.Model): _inherit = 'sale.order' - timesheet_ids = fields.Many2many('account.analytic.line', compute='_compute_timesheet_ids', string='Timesheet activities associated to this sale') - timesheet_count = fields.Float(string='Timesheet activities', compute='_compute_timesheet_ids', groups="hr_timesheet.group_hr_timesheet_user") + timesheet_count = fields.Float(string='Timesheet activities', compute='_compute_timesheet_count', groups="hr_timesheet.group_hr_timesheet_user") # override domain project_id = fields.Many2one(domain="[('pricing_type', '!=', 'employee_rate'), ('analytic_account_id', '!=', False), ('company_id', '=', company_id)]") timesheet_encode_uom_id = fields.Many2one('uom.uom', related='company_id.timesheet_encode_uom_id') - timesheet_total_duration = fields.Integer("Timesheet Total Duration", compute='_compute_timesheet_total_duration', help="Total recorded duration, expressed in the encoding UoM, and rounded to the unit") + timesheet_total_duration = fields.Integer("Timesheet Total Duration", compute='_compute_timesheet_total_duration', + help="Total recorded duration, expressed in the encoding UoM, and rounded to the unit", compute_sudo=True, + groups="hr_timesheet.group_hr_timesheet_user") - def _compute_timesheet_ids(self): - timesheet_groups = self.env['account.analytic.line'].sudo().read_group( - [('so_line', 'in', self.mapped('order_line').ids), ('project_id', '!=', False)], - ['so_line', 'ids:array_agg(id)'], - ['so_line']) - timesheets_per_sol = {group['so_line'][0]: (group['ids'], group['so_line_count']) for group in timesheet_groups} + def _compute_timesheet_count(self): + timesheets_per_so = { + group['order_id'][0]: group['order_id_count'] + for group in self.env['account.analytic.line']._read_group( + [('order_id', 'in', self.ids), ('project_id', '!=', False)], + ['order_id'], + ['order_id'] + ) + } for order in self: - timesheet_ids = [] - timesheet_count = 0 - for sale_line_id in order.order_line.filtered('is_service').ids: - list_timesheet_ids, count = timesheets_per_sol.get(sale_line_id, ([], 0)) - timesheet_ids.extend(list_timesheet_ids) - timesheet_count += count + order.timesheet_count = timesheets_per_so.get(order.id, 0) - order.update({ - 'timesheet_ids': self.env['account.analytic.line'].browse(timesheet_ids), - 'timesheet_count': timesheet_count, - }) - - @api.depends('company_id.project_time_mode_id', 'timesheet_ids', 'company_id.timesheet_encode_uom_id') + @api.depends('company_id.project_time_mode_id', 'company_id.timesheet_encode_uom_id', 'order_line.timesheet_ids') def _compute_timesheet_total_duration(self): - if not self.user_has_groups('hr_timesheet.group_hr_timesheet_user'): - self.update({'timesheet_total_duration': 0}) - return - group_data = self.env['account.analytic.line'].sudo()._read_group([ + group_data = self.env['account.analytic.line']._read_group([ ('order_id', 'in', self.ids) ], ['order_id', 'unit_amount'], ['order_id']) timesheet_unit_amount_dict = defaultdict(float)