Files
ihrm/leave/methods.py

230 lines
8.4 KiB
Python

import calendar
from datetime import datetime, timedelta
from django.db.models import Q
def calculate_requested_days(
start_date, end_date, start_date_breakdown, end_date_breakdown
):
if start_date == end_date:
if start_date_breakdown == "full_day" and end_date_breakdown == "full_day":
requested_days = 1
else:
requested_days = 0.5
else:
start_days = 0
end_days = 0
if start_date_breakdown != "full_day":
start_days = 0.5
if end_date_breakdown != "full_day":
end_days = 0.5
if start_date_breakdown == "full_day" and end_date_breakdown == "full_day":
requested_days = (end_date - start_date).days + start_days + end_days + 1
else:
if start_date_breakdown == "full_day" or end_date_breakdown == "full_day":
requested_days = (end_date - start_date).days + start_days + end_days
else:
requested_days = (
(end_date - start_date).days + start_days + end_days - 1
)
return requested_days
def leave_requested_dates(start_date, end_date):
"""
:return: this functions returns a list of dates from start date to end date.
"""
request_start_date = start_date
request_end_date = end_date
if request_end_date is None:
request_end_date = start_date
requested_days = request_end_date - request_start_date
requested_dates = []
for i in range(requested_days.days + 1):
date = request_start_date + timedelta(i)
requested_dates.append(date)
return requested_dates
def holiday_dates_list(holidays):
"""
:return: this functions returns a list of all holiday dates.
"""
holiday_dates = []
for holiday in holidays:
holiday_start_date = holiday.start_date
holiday_end_date = holiday.end_date
if holiday_end_date is None:
holiday_end_date = holiday_start_date
holiday_days = holiday_end_date - holiday_start_date
for i in range(holiday_days.days + 1):
date = holiday_start_date + timedelta(i)
holiday_dates.append(date)
return holiday_dates
def company_leave_dates_list(company_leaves, start_date):
"""
:return: This function returns a list of all company leave dates"""
company_leave_dates = []
for company_leave in company_leaves:
year = start_date.year
based_on_week = company_leave.based_on_week
based_on_week_day = company_leave.based_on_week_day
for month in range(1, 13):
if based_on_week != None:
# Set Sunday as the first day of the week
calendar.setfirstweekday(6)
month_calendar = calendar.monthcalendar(year, month)
try:
weeks = month_calendar[int(based_on_week)]
weekdays_in_weeks = [day for day in weeks if day != 0]
for day in weekdays_in_weeks:
date = datetime.strptime(
f"{year}-{month:02}-{day:02}", "%Y-%m-%d"
).date()
if (
date.weekday() == int(based_on_week_day)
and date not in company_leave_dates
):
company_leave_dates.append(date)
except IndexError:
pass
else:
# Set Monday as the first day of the week
calendar.setfirstweekday(0)
month_calendar = calendar.monthcalendar(year, month)
for week in month_calendar:
if week[int(based_on_week_day)] != 0:
date = datetime.strptime(
f"{year}-{month:02}-{week[int(based_on_week_day)]:02}",
"%Y-%m-%d",
).date()
if date not in company_leave_dates:
company_leave_dates.append(date)
return company_leave_dates
def get_leave_day_attendance(employee, comp_id=None):
"""
This function returns a queryset of attendance on leave dates
"""
from attendance.models import Attendance
from leave.models import CompensatoryLeaveRequest
attendances_to_exclude = Attendance.objects.none() # Empty queryset to start with
# Check for compensatory leave requests that are not rejected and not the current one
if (
CompensatoryLeaveRequest.objects.filter(employee_id=employee)
.exclude(Q(id=comp_id) | Q(status="rejected"))
.exists()
):
comp_leave_reqs = CompensatoryLeaveRequest.objects.filter(
employee_id=employee
).exclude(Q(id=comp_id) | Q(status="rejected"))
for req in comp_leave_reqs:
attendances_to_exclude |= req.attendance_id.all()
# Filter holiday attendance excluding the attendances in attendances_to_exclude
holiday_attendance = Attendance.objects.filter(
is_holiday=True, employee_id=employee, attendance_validated=True
).exclude(id__in=attendances_to_exclude.values_list("id", flat=True))
return holiday_attendance
def attendance_days(employee, attendances):
"""
This function returns count of workrecord from the attendance
"""
from payroll.models.models import WorkRecord
attendance_days = 0
for attendance in attendances:
if WorkRecord.objects.filter(
employee_id=employee, date=attendance.attendance_date
).exists():
work_record_type = (
WorkRecord.objects.filter(
employee_id=employee, date=attendance.attendance_date
)
.first()
.work_record_type
)
if work_record_type == "HDP":
attendance_days += 0.5
elif work_record_type == "FDP":
attendance_days += 1
return attendance_days
def is_holiday(date):
"""
Check if the given date is a holiday.
Args:
date (datetime.date): The date to check.
Returns:
Holiday or bool: The Holiday object if the date is a holiday, otherwise False.
"""
from leave.models import Holiday
holidays = Holiday.objects.all()
for holiday in holidays:
start_date = holiday.start_date
end_date = holiday.end_date
# Check if the date is within the range of the holiday dates
if start_date <= date <= end_date:
return holiday
# Check for recurring holidays
if holiday.recurring:
try:
# Create a new date object for comparison without the year
start_date_without_year = datetime(
year=date.year, month=start_date.month, day=start_date.day
).date()
end_date_without_year = datetime(
year=date.year, month=end_date.month, day=end_date.day
).date()
if start_date_without_year <= date <= end_date_without_year:
return holiday
except:
return False
return False
def is_company_leave(input_date):
"""
Check if the given date is a company leave.
Args:
input_date (datetime.date): The date to check.
Returns:
CompanyLeave or bool: The CompanyLeave object if the date is a company leave, otherwise False.
"""
from leave.models import CompanyLeave
# Calculate the week number within the month (1-5)
first_day_of_month = input_date.replace(day=1)
first_week_day = first_day_of_month.weekday() # Monday is 0 and Sunday is 6
adjusted_day = input_date.day + first_week_day
date_week_no = (adjusted_day - 1) // 7
# Calculate the weekday (1 for Monday to 7 for Sunday)
date_week_day = input_date.isoweekday() - 1
company_leaves = CompanyLeave.objects.all()
for company_leave in company_leaves:
week_no = (
company_leave.based_on_week
if not company_leave.based_on_week
else int(company_leave.based_on_week)
) # from 0 for the first week to 4 for the fifth week
week_day = int(
company_leave.based_on_week_day
) # from 0 to 6 for Monday to Sunday
if not week_no:
if date_week_day == week_day:
return company_leave
if date_week_no == week_no and date_week_day == week_day:
return company_leave
return False