[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) <xbo@odoo.com>
This commit is contained in:
Kartik Chavda
2023-03-30 15:08:48 +02:00
parent 533e0451aa
commit 81be161fae
4 changed files with 22 additions and 42 deletions
+1 -13
View File
@@ -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
@@ -54,13 +54,12 @@
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="allow_timesheets" invisible="1"/>
<field name="timesheet_count" invisible="1"/>
<field name="remaining_hours" invisible="1"/>
<field name="encode_uom_in_days" invisible="1"/>
<field name="allocated_hours" invisible="1"/>
</field>
<xpath expr="//div[hasclass('o_kanban_manage_view')]" position="inside">
<div role="menuitem" t-if="record.allow_timesheets.raw_value and record.timesheet_count and record.timesheet_count.raw_value" groups="hr_timesheet.group_hr_timesheet_user">
<div role="menuitem" t-if="record.allow_timesheets.raw_value" groups="hr_timesheet.group_hr_timesheet_user">
<a name="action_project_timesheets" type="object">Timesheets</a>
</div>
</xpath>
+4 -2
View File
@@ -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):
+16 -25
View File
@@ -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)