[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:
@@ -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>
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user