260 lines
9.0 KiB
Python
260 lines
9.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
import logging
|
|
from datetime import datetime, timedelta, date
|
|
|
|
from odoo import models, fields, api
|
|
from odoo.addons.resource.models.utils import HOURS_PER_DAY
|
|
from odoo.tools.float_utils import float_round
|
|
from odoo.tools.translate import _
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
DEFAULT_DAYS = 7
|
|
|
|
|
|
class HolidayRequest(models.Model):
|
|
_inherit = "hr.leave"
|
|
|
|
def _get_duration(self, check_leave_type=True, resource_calendar=None):
|
|
if self.leave_type_request_unit == "c_day":
|
|
return self.employee_id.get_all_days_data(
|
|
self.date_from, self.date_to, self.holiday_status_id.exclude_holidays
|
|
)
|
|
else:
|
|
return super()._get_duration(check_leave_type, resource_calendar)
|
|
|
|
working_hours_display = fields.Float(
|
|
"Working hours",
|
|
help="Working hours amount in selected period",
|
|
compute="_compute_working_hours_display",
|
|
copy=False,
|
|
readonly=True,
|
|
)
|
|
|
|
@staticmethod
|
|
def compute_work_weekends(date_from, date_to, collection):
|
|
days = set()
|
|
|
|
for event in collection:
|
|
if (
|
|
date_from
|
|
and event.date_to < date_from.date()
|
|
or date_to
|
|
and event.date_from > date_to.date()
|
|
):
|
|
continue
|
|
|
|
start = max(event.date_from, date_from.date())
|
|
until = min(event.date_to, date_to.date())
|
|
|
|
if event.type_transfer_day == "is_workday":
|
|
for i in range((until - start + timedelta(1)).days):
|
|
today = start + timedelta(i)
|
|
days.add(today)
|
|
else:
|
|
for i in range((until - start + timedelta(1)).days):
|
|
today = start + timedelta(i)
|
|
# weekends check
|
|
if today.weekday() != 5 and today.weekday() != 6:
|
|
days.add(today)
|
|
return timedelta(len(days)).days
|
|
|
|
@api.depends("number_of_days", "date_from", "date_to")
|
|
def _compute_working_hours_display(self):
|
|
for holiday in self:
|
|
calendar = (
|
|
holiday.employee_id.resource_calendar_id
|
|
or self.env.user.company_id.resource_calendar_id
|
|
)
|
|
count_work_weekends = holiday.compute_work_weekends(
|
|
holiday.date_from,
|
|
holiday.date_to,
|
|
self.env["holidays.calendar.leaves"].search(
|
|
[
|
|
("type_transfer_day", "=", "is_workday"),
|
|
]
|
|
),
|
|
)
|
|
count_non_working_days = holiday.compute_work_weekends(
|
|
holiday.date_from,
|
|
holiday.date_to,
|
|
self.env["holidays.calendar.leaves"].search(
|
|
[
|
|
("type_transfer_day", "=", "is_day_off"),
|
|
]
|
|
),
|
|
)
|
|
count_holidays = holiday.compute_work_weekends(
|
|
holiday.date_from,
|
|
holiday.date_to,
|
|
self.env["holidays.calendar.leaves"].search(
|
|
[
|
|
("type_transfer_day", "=", "is_holiday"),
|
|
]
|
|
),
|
|
)
|
|
|
|
if holiday.date_from and holiday.date_to:
|
|
date_start = datetime(
|
|
year=holiday.date_from.year,
|
|
month=holiday.date_from.month,
|
|
day=holiday.date_from.day,
|
|
hour=0,
|
|
minute=0,
|
|
second=0,
|
|
)
|
|
date_end = datetime(
|
|
year=holiday.date_to.year,
|
|
month=holiday.date_to.month,
|
|
day=holiday.date_to.day,
|
|
hour=23,
|
|
minute=59,
|
|
second=59,
|
|
)
|
|
number_of_hours = calendar.get_work_hours_count(
|
|
date_start, date_end, compute_leaves=False
|
|
)
|
|
holiday.working_hours_display = number_of_hours + HOURS_PER_DAY * (
|
|
count_work_weekends - count_non_working_days - count_holidays
|
|
)
|
|
else:
|
|
holiday.working_hours_display = 0
|
|
|
|
@api.depends("number_of_hours_display", "number_of_days_display")
|
|
def _compute_duration_display(self):
|
|
for leave in self:
|
|
amount = (
|
|
float_round(leave.number_of_hours_display, precision_digits=2)
|
|
if leave.leave_type_request_unit == "hour"
|
|
else float_round(leave.number_of_days_display, precision_digits=2)
|
|
)
|
|
if leave.leave_type_request_unit == "c_day":
|
|
units = _("calendar day(s)")
|
|
elif leave.leave_type_request_unit == "hour":
|
|
units = _("hour(s)")
|
|
else:
|
|
units = _("working day(s)")
|
|
leave.duration_display = "%g %s" % (amount, units)
|
|
|
|
@staticmethod
|
|
def notify_before(leave):
|
|
"""Checks whether days_before_holidays is set, if it's not, use DEFAULT_DAYS"""
|
|
return leave.holiday_status_id.days_before_holidays or DEFAULT_DAYS
|
|
|
|
def _check_users_holidays(self):
|
|
"""
|
|
Method calls every day and checks the planned holidays.
|
|
If needed, an email notification to the responsible employee will be sent.
|
|
"""
|
|
leaves = self.env["hr.leave"].search(
|
|
[
|
|
("holiday_status_id.notify_before_start_holidays", "=", True),
|
|
("holiday_status_id.responsible_employee_to_notify_id", "!=", None),
|
|
("date_from", ">=", date.today()),
|
|
]
|
|
)
|
|
|
|
for leave in leaves:
|
|
days_before_holidays = self.notify_before(leave)
|
|
holidays_start_date = leave.date_from
|
|
|
|
if (
|
|
holidays_start_date - timedelta(days=days_before_holidays)
|
|
).date() == date.today():
|
|
template_name = "hr_holidays_ru.holidays_notification_template"
|
|
template = self.env.ref(template_name)
|
|
template.send_mail(leave.id)
|
|
|
|
@staticmethod
|
|
def append_number_by_type(leave, res):
|
|
if leave.leave_type_request_unit == "c_day":
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s : %.2f Calendar day(s)")
|
|
% (
|
|
leave.name or leave.holiday_status_id.name,
|
|
leave.number_of_days,
|
|
),
|
|
)
|
|
)
|
|
elif leave.leave_type_request_unit == "hour":
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s : %.2f hour(s)")
|
|
% (
|
|
leave.name or leave.holiday_status_id.name,
|
|
leave.number_of_hours_display,
|
|
),
|
|
)
|
|
)
|
|
else:
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s : %.2f Working day(s)")
|
|
% (
|
|
leave.name or leave.holiday_status_id.name,
|
|
leave.number_of_days,
|
|
),
|
|
)
|
|
)
|
|
|
|
@staticmethod
|
|
def append_number_by_type_without_short_name(leave, res):
|
|
if leave.holiday_type == "company":
|
|
target = leave.mode_company_id.name
|
|
elif leave.holiday_type == "department":
|
|
target = leave.department_id.name
|
|
elif leave.holiday_type == "category":
|
|
target = leave.category_id.name
|
|
else:
|
|
target = leave.employee_id.name
|
|
|
|
if leave.leave_type_request_unit == "c_day":
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s on %s : %.2f Calendar day(s)")
|
|
% (
|
|
target,
|
|
leave.holiday_status_id.name,
|
|
leave.number_of_days,
|
|
),
|
|
)
|
|
)
|
|
elif leave.leave_type_request_unit == "hour":
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s on %s : %.2f hour(s)")
|
|
% (
|
|
target,
|
|
leave.holiday_status_id.name,
|
|
leave.number_of_hours_display,
|
|
),
|
|
)
|
|
)
|
|
else:
|
|
res.append(
|
|
(
|
|
leave.id,
|
|
_("%s on %s : %.2f Working day(s)")
|
|
% (
|
|
target,
|
|
leave.holiday_status_id.name,
|
|
leave.number_of_days,
|
|
),
|
|
)
|
|
)
|
|
|
|
def name_get(self):
|
|
res = []
|
|
for leave in self:
|
|
if self.env.context.get("short_name"):
|
|
self.append_number_by_type(leave, res)
|
|
else:
|
|
self.append_number_by_type_without_short_name(leave, res)
|
|
return res
|