hr_holidays_ru/models/hr_leave.py

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