[IMP] project_timesheet_holiday: improve feature timesheet created by time off

This commit prevent user write on time off timesheets and create timesheet
on time off tasks and add test for this feature.

task-2826265

Part-of: odoo/odoo#90744
This commit is contained in:
Kartik Chavda
2022-08-08 10:50:22 +02:00
parent aef440b38e
commit 25cd0cf3fc
4 changed files with 73 additions and 1 deletions
@@ -4,6 +4,7 @@
from . import res_company # has to be before hr_holidays to create needed columns on res.company
from . import account_analytic
from . import hr_holidays
from . import project_task
from . import res_config_settings
from . import resource_calendar_leaves
from . import hr_employee
@@ -10,8 +10,24 @@ class AccountAnalyticLine(models.Model):
holiday_id = fields.Many2one("hr.leave", string='Leave Request')
global_leave_id = fields.Many2one("resource.calendar.leaves", string="Global Time Off", ondelete='cascade')
task_id = fields.Many2one(domain="[('company_id', '=', company_id), ('project_id.allow_timesheets', '=', True),"
"('project_id', '=?', project_id), ('is_timeoff_task', '=', False)]")
@api.ondelete(at_uninstall=False)
def _unlink_except_linked_leave(self):
if any(line.holiday_id for line in self):
raise UserError(_('You cannot delete timesheets linked to time off. Please, cancel the time off instead.'))
raise UserError(_('You cannot delete timesheets that are linked to time off requests. Please cancel your time off request from the Time Off application instead.'))
@api.model_create_multi
def create(self, vals_list):
if not self.env.su:
task_ids = [vals['task_id'] for vals in vals_list if vals.get('task_id')]
has_timeoff_task = self.env['project.task'].search_count([('id', 'in', task_ids), ('is_timeoff_task', '=', True)], limit=1) > 0
if has_timeoff_task:
raise UserError(_('You cannot create timesheets for a task that is linked to a time off type. Please use the Time Off application to request new time off instead.'))
return super().create(vals_list)
def write(self, vals):
if not self.env.su and self.filtered('holiday_id'):
raise UserError(_('You cannot modify timesheets that are linked to time off requests. Please use the Time Off application to modify your time off requests instead.'))
return super().write(vals)
@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models, _
class Task(models.Model):
_inherit = 'project.task'
leave_types_count = fields.Integer(compute='_compute_leave_types_count')
is_timeoff_task = fields.Boolean("Is Time off Task", compute="_compute_is_timeoff_task", search="_search_is_timeoff_task")
def _compute_leave_types_count(self):
time_off_type_read_group = self.env['hr.leave.type']._read_group(
[('timesheet_task_id', 'in', self.ids)],
['timesheet_task_id'],
['timesheet_task_id'],
)
time_off_type_count_per_task = {res['timesheet_task_id'][0]: res['timesheet_task_id_count'] for res in time_off_type_read_group}
for task in self:
task.leave_types_count = time_off_type_count_per_task.get(task.id, 0)
def _compute_is_timeoff_task(self):
timeoff_tasks = self.filtered(lambda task: task.leave_types_count or task.company_id.leave_timesheet_task_id == task)
timeoff_tasks.is_timeoff_task = True
(self - timeoff_tasks).is_timeoff_task = False
def _search_is_timeoff_task(self, operator, value):
if operator not in ['=', '!='] or not isinstance(value, bool):
raise NotImplementedError(_('Operation not supported'))
leave_type_read_group = self.env['hr.leave.type']._read_group(
[('timesheet_task_id', '!=', False)],
['timesheet_task_ids:array_agg(timesheet_task_id)'],
[],
)
timeoff_task_ids = leave_type_read_group[0]['timesheet_task_ids'] if leave_type_read_group else []
if self.env.company.leave_timesheet_task_id:
timeoff_task_ids.append(self.env.company.leave_timesheet_task_id.id)
if operator == '!=':
value = not value
return [('id', 'in' if value else 'not in', timeoff_task_ids)]
@@ -7,6 +7,7 @@ from freezegun import freeze_time
from odoo import fields, SUPERUSER_ID
from odoo.exceptions import UserError
from odoo.tests import common, new_test_user
from odoo.addons.hr_timesheet.tests.test_timesheet import TestCommonTimesheet
import time
@@ -187,5 +188,19 @@ class TestTimesheetHolidays(TestCommonTimesheet):
('employee_id', '=', self.empl_employee.id),
])
# should not able to update timeoff timesheets
with self.assertRaises(UserError):
timesheets.with_user(self.empl_employee).write({'task_id': 4})
# should not able to create timesheet in timeoff task
with self.assertRaises(UserError):
self.env['account.analytic.line'].with_user(self.empl_employee).create({
'name': "my timesheet",
'project_id': self.internal_project.id,
'task_id': self.internal_task_leaves.id,
'date': '2021-10-04',
'unit_amount': 8.0,
})
self.assertEqual(len(timesheets.filtered('holiday_id')), 4, "4 timesheet should be linked to employee's timeoff")
self.assertEqual(len(timesheets.filtered('global_leave_id')), 1, '1 timesheet should be linked to global leave')