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