[FIX] hr_work_entry: make _error_checking faster
Calls to `_error_checking()` would look for every work entries between 2 dates, even if we were only modifying one employee's. Because of that the leave creation on big production database would take a long time. Now the method allows for filtering to the employees. task-3142610 closes odoo/odoo#110987 X-original-commit: f54b7c34bc89140e2d31f0b602911ec9cda3ed0d Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com> Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import itertools
|
||||
from psycopg2 import OperationalError
|
||||
|
||||
from odoo import api, fields, models, tools, _
|
||||
from odoo.osv import expression
|
||||
|
||||
|
||||
class HrWorkEntry(models.Model):
|
||||
@@ -182,18 +183,22 @@ class HrWorkEntry(models.Model):
|
||||
if 'active' in vals:
|
||||
vals['state'] = 'draft' if vals['active'] else 'cancelled'
|
||||
|
||||
with self._error_checking(skip=skip_check):
|
||||
employee_ids = self.employee_id.ids
|
||||
if 'employee_id' in vals and vals['employee_id']:
|
||||
employee_ids += vals['employee_id']
|
||||
with self._error_checking(skip=skip_check, employee_ids=employee_ids):
|
||||
return super(HrWorkEntry, self).write(vals)
|
||||
|
||||
def unlink(self):
|
||||
with self._error_checking():
|
||||
employee_ids = self.employee_id.ids
|
||||
with self._error_checking(employee_ids=employee_ids):
|
||||
return super().unlink()
|
||||
|
||||
def _reset_conflicting_state(self):
|
||||
self.filtered(lambda w: w.state == 'conflict').write({'state': 'draft'})
|
||||
|
||||
@contextmanager
|
||||
def _error_checking(self, start=None, stop=None, skip=False):
|
||||
def _error_checking(self, start=None, stop=None, skip=False, employee_ids=False):
|
||||
"""
|
||||
Context manager used for conflicts checking.
|
||||
When exiting the context manager, conflicts are checked
|
||||
@@ -209,11 +214,14 @@ class HrWorkEntry(models.Model):
|
||||
start = start or min(self.mapped('date_start'), default=False)
|
||||
stop = stop or max(self.mapped('date_stop'), default=False)
|
||||
if not skip and start and stop:
|
||||
work_entries = self.sudo().with_context(hr_work_entry_no_check=True).search([
|
||||
domain = [
|
||||
('date_start', '<', stop),
|
||||
('date_stop', '>', start),
|
||||
('state', 'not in', ('validated', 'cancelled')),
|
||||
])
|
||||
]
|
||||
if employee_ids:
|
||||
domain = expression.AND([domain, [('employee_id', 'in', list(employee_ids))]])
|
||||
work_entries = self.sudo().with_context(hr_work_entry_no_check=True).search(domain)
|
||||
work_entries._reset_conflicting_state()
|
||||
yield
|
||||
except OperationalError:
|
||||
|
||||
@@ -169,7 +169,10 @@ Contracts:
|
||||
|
||||
start = min(self.mapped('date_from') + [fields.Datetime.from_string(vals.get('date_from', False)) or datetime.max])
|
||||
stop = max(self.mapped('date_to') + [fields.Datetime.from_string(vals.get('date_to', False)) or datetime.min])
|
||||
with self.env['hr.work.entry']._error_checking(start=start, stop=stop, skip=skip_check):
|
||||
employee_ids = self.employee_id.ids
|
||||
if 'employee_id' in vals and vals['employee_id']:
|
||||
employee_ids += vals['employee_id']
|
||||
with self.env['hr.work.entry']._error_checking(start=start, stop=stop, skip=skip_check, employee_ids=employee_ids):
|
||||
return super().write(vals)
|
||||
|
||||
@api.model_create_multi
|
||||
@@ -178,13 +181,14 @@ Contracts:
|
||||
stop_dates = [v.get('date_to') for v in vals_list if v.get('date_to')]
|
||||
if any(vals.get('holiday_type', 'employee') == 'employee' and not vals.get('multi_employee', False) and not vals.get('employee_id', False) for vals in vals_list):
|
||||
raise ValidationError(_("There is no employee set on the time off. Please make sure you're logged in the correct company."))
|
||||
with self.env['hr.work.entry']._error_checking(start=min(start_dates, default=False), stop=max(stop_dates, default=False)):
|
||||
employee_ids = {v['employee_id'] for v in vals_list if v.get('employee_id')}
|
||||
with self.env['hr.work.entry']._error_checking(start=min(start_dates, default=False), stop=max(stop_dates, default=False), employee_ids=employee_ids):
|
||||
return super().create(vals_list)
|
||||
|
||||
def action_confirm(self):
|
||||
start = min(self.mapped('date_from'), default=False)
|
||||
stop = max(self.mapped('date_to'), default=False)
|
||||
with self.env['hr.work.entry']._error_checking(start=start, stop=stop):
|
||||
with self.env['hr.work.entry']._error_checking(start=start, stop=stop, employee_ids=self.employee_id.ids):
|
||||
return super().action_confirm()
|
||||
|
||||
def _get_leaves_on_public_holiday(self):
|
||||
|
||||
Reference in New Issue
Block a user