1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/project_holidays/models/project.py
2024-12-10 09:04:09 +07:00

127 lines
5.9 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.addons.project.models.project_task import CLOSED_STATES
from collections import defaultdict
class Task(models.Model):
_inherit = 'project.task'
leave_warning = fields.Char(compute='_compute_leave_warning', compute_sudo=True)
is_absent = fields.Boolean(
'Employees on Time Off', compute='_compute_leave_warning', search='_search_is_absent',
compute_sudo=True, readonly=True)
@api.depends_context('lang')
@api.depends('planned_date_begin', 'date_deadline', 'user_ids')
def _compute_leave_warning(self):
def group_by_leave(data):
mapping_leaves = defaultdict(list)
for item in data:
name = item['name']
for leave in item['leaves']:
leave_tuple = tuple(leave.items())
mapping_leaves[leave_tuple].append(name)
res = []
for leave_tuple, names in mapping_leaves.items():
leave_dict = dict(leave_tuple)
res.append({'names': names, 'leaves': leave_dict})
return res
# Avoid NewIds issue by browsing for self.ids.
tasks = self.with_context(prefetch_fields=False).browse(self.ids)
tasks.fetch(['user_ids', 'project_id', 'planned_date_begin', 'date_deadline', 'state'])
assigned_tasks = tasks.filtered(
lambda t: t.user_ids.employee_id
and t.project_id
and t.planned_date_begin
and t.date_deadline
and not t.state in CLOSED_STATES
)
(self - assigned_tasks).leave_warning = False
(self - assigned_tasks).is_absent = False
if not assigned_tasks:
return
min_date = min(assigned_tasks.mapped('planned_date_begin'))
date_from = min_date if min_date > fields.Datetime.today() else fields.Datetime.today()
leaves = self.env['hr.leave']._get_leave_interval(
date_from=date_from,
date_to=max(assigned_tasks.mapped('date_deadline')),
employee_ids=assigned_tasks.mapped('user_ids.employee_id')
)
for task in assigned_tasks:
leaves_parameters = {"validated": [], "requested": []}
# Gather leaves parameters for each employee
for employee in task.user_ids.employee_id:
task_leaves = leaves.get(employee.id)
if task_leaves:
employee_leaves = self.env['hr.leave']._get_leave_warning_parameters(
task_leaves, employee, task.planned_date_begin, task.date_deadline
)
for leave_type, leaves_for_employee in employee_leaves.items():
if not leaves_for_employee:
continue
leaves_parameters[leave_type].append(leaves_for_employee)
# Group leaves
for leave_type, leaves_for_employee in leaves_parameters.items():
leaves_parameters[leave_type] = group_by_leave(leaves_for_employee)
warning = ''
for leave_type, leaves_for_employee in leaves_parameters.items():
for leave in leaves_for_employee:
if leave["leaves"]:
if leave_type == 'validated':
if len(leave["names"]) == 1:
warning += _('%(names)s is on time off %(leaves)s. \n',
names=', '.join(leave["names"]),
leaves=self.env['hr.leave'].format_date_range_to_string(leave["leaves"]))
else:
warning += _('%(names)s are on time off %(leaves)s. \n',
names=', '.join(leave["names"]),
leaves=self.env['hr.leave'].format_date_range_to_string(leave["leaves"]))
else:
warning += _('%(names)s requested time off %(leaves)s. \n',
names=', '.join(leave["names"]),
leaves=self.env['hr.leave'].format_date_range_to_string(leave["leaves"]))
task.leave_warning = warning or False
task.is_absent = bool(warning)
return warning
@api.model
def _search_is_absent(self, operator, value):
if operator not in ['=', '!='] or not isinstance(value, bool):
raise NotImplementedError(_('Operation not supported'))
tasks = self.search([
('user_ids.employee_id', '!=', False),
('project_id', '!=', False),
('planned_date_begin', '!=', False),
('date_deadline', '!=', False),
('state', 'in', self.OPEN_STATES),
])
if not tasks:
return []
min_date = min(tasks.mapped('planned_date_begin'))
date_from = min_date if min_date > fields.Datetime.today() else fields.Datetime.today()
mapped_leaves = self.env['hr.leave']._get_leave_interval(
date_from=date_from,
date_to=max(tasks.mapped('date_deadline')),
employee_ids=tasks.mapped('user_ids.employee_id')
)
task_ids = []
for task in tasks:
employees = tasks.mapped('user_ids.employee_id')
for employee in employees:
if employee.id in mapped_leaves:
leaves = mapped_leaves[employee.id]
period = self.env['hr.leave']._group_leaves(leaves, employee, task.planned_date_begin, task.date_deadline)
if period:
task_ids.append(task.id)
if operator == '!=':
value = not value
return [('id', 'in' if value else 'not in', task_ids)]