2023-07-11 12:14:08 +05:30
|
|
|
import calendar
|
2023-08-14 14:47:15 +05:30
|
|
|
from datetime import datetime, timedelta
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2024-08-05 14:22:44 +05:30
|
|
|
from django.apps import apps
|
2024-05-08 15:57:41 +05:30
|
|
|
from django.db.models import Q
|
|
|
|
|
|
2024-08-05 14:22:44 +05:30
|
|
|
from employee.models import Employee
|
|
|
|
|
from horilla.methods import get_horilla_model_class
|
|
|
|
|
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2023-08-14 14:47:15 +05:30
|
|
|
def calculate_requested_days(
|
|
|
|
|
start_date, end_date, start_date_breakdown, end_date_breakdown
|
|
|
|
|
):
|
2023-07-11 12:14:08 +05:30
|
|
|
if start_date == end_date:
|
2025-05-03 14:15:41 +05:30
|
|
|
return (
|
|
|
|
|
1
|
|
|
|
|
if start_date_breakdown == "full_day" and end_date_breakdown == "full_day"
|
|
|
|
|
else 0.5
|
|
|
|
|
)
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2025-05-03 14:15:41 +05:30
|
|
|
# Count full days between the two dates, excluding start and end
|
|
|
|
|
middle_days = (end_date - start_date).days - 1
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2025-05-03 14:15:41 +05:30
|
|
|
# Count start and end days
|
|
|
|
|
start_day_value = 1 if start_date_breakdown == "full_day" else 0.5
|
|
|
|
|
end_day_value = 1 if end_date_breakdown == "full_day" else 0.5
|
2023-08-14 14:47:15 +05:30
|
|
|
|
2025-05-03 14:15:41 +05:30
|
|
|
return middle_days + start_day_value + end_day_value
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2023-08-14 14:47:15 +05:30
|
|
|
|
2023-07-11 12:14:08 +05:30
|
|
|
def holiday_dates_list(holidays):
|
2023-08-14 14:47:15 +05:30
|
|
|
"""
|
2025-05-03 14:15:41 +05:30
|
|
|
:return: This function returns a list of all holiday dates.
|
2023-08-14 14:47:15 +05:30
|
|
|
"""
|
|
|
|
|
holiday_dates = []
|
|
|
|
|
for holiday in holidays:
|
|
|
|
|
holiday_start_date = holiday.start_date
|
2025-05-03 14:15:41 +05:30
|
|
|
holiday_end_date = holiday.end_date or holiday_start_date
|
|
|
|
|
holiday_dates.extend(
|
|
|
|
|
holiday_start_date + timedelta(i)
|
|
|
|
|
for i in range((holiday_end_date - holiday_start_date).days + 1)
|
|
|
|
|
)
|
2023-08-14 14:47:15 +05:30
|
|
|
return holiday_dates
|
|
|
|
|
|
2023-07-11 12:14:08 +05:30
|
|
|
|
2023-08-14 14:47:15 +05:30
|
|
|
def company_leave_dates_list(company_leaves, start_date):
|
|
|
|
|
"""
|
2025-05-03 14:15:41 +05:30
|
|
|
:return: This function returns a list of all company leave dates
|
|
|
|
|
"""
|
|
|
|
|
company_leave_dates = set()
|
|
|
|
|
year = start_date.year
|
2023-08-14 14:47:15 +05:30
|
|
|
for company_leave in company_leaves:
|
|
|
|
|
based_on_week = company_leave.based_on_week
|
|
|
|
|
based_on_week_day = company_leave.based_on_week_day
|
2025-05-03 14:15:41 +05:30
|
|
|
|
2023-08-14 14:47:15 +05:30
|
|
|
for month in range(1, 13):
|
2025-05-03 14:15:41 +05:30
|
|
|
month_calendar = calendar.monthcalendar(year, month)
|
|
|
|
|
|
|
|
|
|
if based_on_week is not None:
|
2023-08-14 14:47:15 +05:30
|
|
|
# Set Sunday as the first day of the week
|
|
|
|
|
calendar.setfirstweekday(6)
|
2024-07-12 12:31:50 +05:30
|
|
|
try:
|
2025-05-03 14:15:41 +05:30
|
|
|
week_days = [
|
|
|
|
|
day for day in month_calendar[int(based_on_week)] if day != 0
|
|
|
|
|
]
|
|
|
|
|
for day in week_days:
|
|
|
|
|
date = datetime(year, month, day)
|
|
|
|
|
if date.weekday() == int(based_on_week_day):
|
|
|
|
|
company_leave_dates.add(date.date())
|
2024-07-12 12:31:50 +05:30
|
|
|
except IndexError:
|
|
|
|
|
pass
|
2023-08-14 14:47:15 +05:30
|
|
|
else:
|
|
|
|
|
# Set Monday as the first day of the week
|
|
|
|
|
calendar.setfirstweekday(0)
|
|
|
|
|
for week in month_calendar:
|
|
|
|
|
if week[int(based_on_week_day)] != 0:
|
2025-05-03 14:15:41 +05:30
|
|
|
date = datetime(year, month, week[int(based_on_week_day)])
|
|
|
|
|
company_leave_dates.add(date.date())
|
|
|
|
|
|
|
|
|
|
return list(company_leave_dates)
|
2024-05-08 15:57:41 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_leave_day_attendance(employee, comp_id=None):
|
|
|
|
|
"""
|
|
|
|
|
This function returns a queryset of attendance on leave dates
|
|
|
|
|
"""
|
2024-08-05 14:22:44 +05:30
|
|
|
Attendance = get_horilla_model_class(app_label="attendance", model="attendance")
|
2024-06-27 14:49:05 +05:30
|
|
|
from leave.models import CompensatoryLeaveRequest
|
2024-05-08 15:57:41 +05:30
|
|
|
|
2024-06-27 14:49:05 +05:30
|
|
|
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
|
2024-05-08 15:57:41 +05:30
|
|
|
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:
|
2024-06-27 14:49:05 +05:30
|
|
|
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
|
2024-05-08 15:57:41 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
def attendance_days(employee, attendances):
|
|
|
|
|
"""
|
|
|
|
|
This function returns count of workrecord from the attendance
|
|
|
|
|
"""
|
|
|
|
|
attendance_days = 0
|
2024-09-03 17:16:58 +05:30
|
|
|
if apps.is_installed("attendance"):
|
|
|
|
|
from attendance.models import WorkRecords
|
|
|
|
|
|
|
|
|
|
for attendance in attendances:
|
|
|
|
|
if WorkRecords.objects.filter(
|
|
|
|
|
employee_id=employee, date=attendance.attendance_date
|
|
|
|
|
).exists():
|
|
|
|
|
work_record_type = (
|
|
|
|
|
WorkRecords.objects.filter(
|
|
|
|
|
employee_id=employee, date=attendance.attendance_date
|
|
|
|
|
)
|
|
|
|
|
.first()
|
|
|
|
|
.work_record_type
|
2024-05-08 15:57:41 +05:30
|
|
|
)
|
2024-09-03 17:16:58 +05:30
|
|
|
if work_record_type == "HDP":
|
|
|
|
|
attendance_days += 0.5
|
|
|
|
|
elif work_record_type == "FDP":
|
|
|
|
|
attendance_days += 1
|
2024-05-08 15:57:41 +05:30
|
|
|
return attendance_days
|
2024-06-27 14:49:05 +05:30
|
|
|
|
|
|
|
|
|
2024-08-05 14:22:44 +05:30
|
|
|
def filter_conditional_leave_request(request):
|
2024-06-27 14:49:05 +05:30
|
|
|
"""
|
2024-08-05 14:22:44 +05:30
|
|
|
Filters and returns LeaveRequest objects that have been conditionally approved by the previous sequence of approvals.
|
2024-06-27 14:49:05 +05:30
|
|
|
"""
|
2024-08-05 14:22:44 +05:30
|
|
|
approval_manager = Employee.objects.filter(employee_user_id=request.user).first()
|
|
|
|
|
leave_request_ids = []
|
|
|
|
|
if apps.is_installed("leave"):
|
|
|
|
|
from leave.models import LeaveRequest, LeaveRequestConditionApproval
|
|
|
|
|
|
|
|
|
|
multiple_approval_requests = LeaveRequestConditionApproval.objects.filter(
|
|
|
|
|
manager_id=approval_manager
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
multiple_approval_requests = None
|
|
|
|
|
for instance in multiple_approval_requests:
|
|
|
|
|
if instance.sequence > 1:
|
|
|
|
|
pre_sequence = instance.sequence - 1
|
|
|
|
|
leave_request_id = instance.leave_request_id
|
|
|
|
|
instance = LeaveRequestConditionApproval.objects.filter(
|
|
|
|
|
leave_request_id=leave_request_id, sequence=pre_sequence
|
|
|
|
|
).first()
|
|
|
|
|
if instance and instance.is_approved:
|
|
|
|
|
leave_request_ids.append(instance.leave_request_id.id)
|
|
|
|
|
else:
|
|
|
|
|
leave_request_ids.append(instance.leave_request_id.id)
|
|
|
|
|
return LeaveRequest.objects.filter(pk__in=leave_request_ids)
|