Files
ihrm/horilla_api/api_serializers/leave/serializers.py

505 lines
15 KiB
Python

from rest_framework import serializers
from leave.models import *
from leave.forms import calculate_requested_days, cal_effective_requested_days
from employee.models import Employee
def leave_Validations(self, data):
start_date = data.get("start_date")
end_date = data.get("end_date")
start_date_breakdown = (
data.get("start_date_breakdown")
if data.get("start_date_breakdown") is not None
else "full_day"
)
end_date_breakdown = (
data.get("end_date_breakdown")
if data.get("end_date_breakdown") is not None
else "full_day"
)
employee = data.get("employee_id")
leave_type_id = data.get("leave_type_id")
attachment = data.get("attachment")
available_leave = (
AvailableLeave.objects.filter(
leave_type_id=leave_type_id, employee_id=employee
)[0]
if AvailableLeave.objects.filter(
leave_type_id=leave_type_id, employee_id=employee
).exists()
else None
)
if not available_leave:
raise serializers.ValidationError(
f"Employee is not assigned with leave type {leave_type_id}."
)
requested_days = calculate_requested_days(
start_date, end_date, start_date_breakdown, end_date_breakdown
)
effective_requested_days = cal_effective_requested_days(
start_date=start_date,
end_date=end_date,
leave_type_id=leave_type_id,
requested_days=requested_days,
)
total_leave_days = (
available_leave.available_days + available_leave.carryforward_days
)
errors = {}
# checking if there is any requested days is overlapping with the existing leave request
leave_requests = employee.leaverequest_set.filter(
start_date__lte=end_date, end_date__gte=start_date
)
if self.instance:
leave_requests = leave_requests.exclude(id=self.instance.id)
if leave_requests:
raise serializers.ValidationError(
"There is already a leave request for this date range."
)
# checking if the end date is less than the start date
if not start_date <= end_date:
errors["end_date"] = ["End date should not be less than start date."]
if start_date == end_date and start_date_breakdown != end_date_breakdown:
raise serializers.ValidationError(
"There is a mismatch in the breakdown of the start date and end date."
)
if not effective_requested_days <= total_leave_days:
raise serializers.ValidationError("Employee doesn't have enough leave days..")
if leave_type_id.require_attachment == "yes" and attachment == None:
errors["attachment"] = ["This field is required."]
if errors:
raise serializers.ValidationError(errors)
class GetAvailableLeaveTypeSerializer(serializers.ModelSerializer):
leave_type_id = serializers.SerializerMethodField()
icon = serializers.SerializerMethodField()
class Meta:
model = AvailableLeave
fields = [
"id",
"leave_type_id",
"icon",
"available_days",
"carryforward_days",
"total_leave_days",
]
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
def get_icon(self, obj):
try:
return obj.leave_type_id.icon.url
except:
return None
class GetAvailableLeaveTypeSerializer(serializers.ModelSerializer):
leave_type_id = serializers.SerializerMethodField()
icon = serializers.SerializerMethodField()
total_leave_days = serializers.SerializerMethodField()
class Meta:
model = AvailableLeave
fields = [
"id",
"leave_type_id",
"icon",
"available_days",
"carryforward_days",
"total_leave_days",
]
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
def get_icon(self, obj):
try:
return obj.leave_type_id.icon.url
except:
return None
def get_total_leave_days(self, obj):
return obj.available_days + obj.carryforward_days
class userLeaveRequestGetAllSerilaizer(serializers.ModelSerializer):
leave_type_id = serializers.SerializerMethodField()
class Meta:
model = LeaveRequest
exclude = [
"requested_date",
"description",
"attachment",
"approved_available_days",
"approved_carryforward_days",
"created_at",
"reject_reason",
"employee_id",
"created_by",
]
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
class UserLeaveRequestGetSerilaizer(serializers.ModelSerializer):
leave_type_id = serializers.SerializerMethodField()
class Meta:
model = LeaveRequest
exclude = [
"requested_date",
"approved_available_days",
"approved_carryforward_days",
"created_at",
"reject_reason",
"employee_id",
"created_by",
]
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
class LeaveRequestCreateUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = LeaveRequest
fields = [
"employee_id",
"leave_type_id",
"start_date",
"start_date_breakdown",
"end_date",
"end_date_breakdown",
"description",
"attachment",
]
def validate(self, data):
leave_Validations(self, data)
return data
class UpdateLeaveRequestSerializer(serializers.ModelSerializer):
class Meta:
model = LeaveRequest
fields = [
"start_date",
"start_date_breakdown",
"end_date",
"end_date_breakdown",
"description",
"attachment",
]
def validate(self, data):
leave_Validations(self, data)
return data
class LeaveTypeGetCreateSerilaizer(serializers.ModelSerializer):
class Meta:
model = LeaveType
fields = "__all__"
def validate(self, data):
reset = data.get("reset")
reset_based = data.get("reset_based")
reset_month = data.get("reset_month")
reset_day = data.get("reset_day")
reset_weekday = data.get("reset_weekday")
carryforward_type = data.get("carryforward_type")
carryforward_max = data.get("carryforward_max")
if reset == True:
if reset_based == None:
raise serializers.ValidationError(
{"reset_based": ["This field is required."]}
)
elif reset_based == "yearly" and reset_month == None:
raise serializers.ValidationError(
{"reset_month": ["This field is required."]}
)
elif reset_based in ["yearly", "monthly"] and reset_day == "":
raise serializers.ValidationError(
{"reset_day": ["This field is required."]}
)
elif reset_based == "weekly" and reset_weekday == None:
raise serializers.ValidationError(
{"reset_weekday": ["This field is required."]}
)
# elif carryforward_type in ['carryforward', 'carryforward expire'] and carryforward_max
return data
class LeaveTypeAllGetSerializer(serializers.ModelSerializer):
class Meta:
model = LeaveType
fields = ["id", "name", "icon"]
class LeaveAllocationRequestCreateSerializer(serializers.ModelSerializer):
requested_days = serializers.FloatField(required=True)
class Meta:
model = LeaveAllocationRequest
fields = [
"leave_type_id",
"employee_id",
"requested_days",
"created_by",
"description",
"attachment",
]
class AssignLeaveCreateSerializer(serializers.Serializer):
leave_type_ids = serializers.PrimaryKeyRelatedField(
many=True, queryset=LeaveType.objects.all()
)
employee_ids = serializers.PrimaryKeyRelatedField(
many=True, queryset=Employee.objects.all()
)
def validate_leave_type_ids(self, value):
if not value:
raise serializers.ValidationError(
{"leave_type_ids": ["This field is required."]}
)
return value
def validate_employee_ids(self, value):
if not value:
raise serializers.ValidationError(
{"employee_ids": ["This field is required."]}
)
return value
class AssignLeaveGetSerializer(serializers.ModelSerializer):
employee_id = serializers.SerializerMethodField()
leave_type_id = serializers.SerializerMethodField()
class Meta:
model = AvailableLeave
exclude = ["reset_date", "expired_date"]
def get_employee_id(self, obj):
employee = obj.employee_id
if employee:
return EmployeeGetSerializer(employee).data
return None
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
class EmployeeGetSerializer(serializers.ModelSerializer):
full_name = serializers.SerializerMethodField()
class Meta:
model = Employee
fields = ["id", "full_name", "employee_profile", "badge_id"]
def get_full_name(self, obj):
return obj.get_full_name()
class AvailableLeaveUpdateSerializer(serializers.ModelSerializer):
available_days = serializers.FloatField(required=True)
class Meta:
model = AvailableLeave
fields = ["available_days", "carryforward_days"]
class LeaveRequestGetAllSerilaizer(serializers.ModelSerializer):
employee_id = serializers.SerializerMethodField()
leave_type_id = serializers.SerializerMethodField()
multiple_approve = serializers.SerializerMethodField()
class Meta:
model = LeaveRequest
exclude = [
"requested_date",
"description",
"attachment",
"approved_available_days",
"approved_carryforward_days",
"created_at",
"reject_reason",
"created_by",
]
def get_employee_id(self, obj):
employee = obj.employee_id
if employee:
return EmployeeGetSerializer(employee).data
return None
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
def get_multiple_approve(self, obj):
approvals = LeaveRequestConditionApproval.objects.filter(leave_request_id=obj)
employee = self.context["request"].user.employee_get
if approvals and obj.status == "requested":
is_approved = approvals.filter(is_approved=True)
count = f"{is_approved.count()} / {approvals.count()}"
is_approved = (
True if is_approved.filter(manager_id=employee).exists() else False
)
return {"count": count, "is_approved": is_approved}
return None
class LeaveRequestGetSerilaizer(serializers.ModelSerializer):
employee_id = serializers.SerializerMethodField()
leave_type_id = serializers.SerializerMethodField()
multiple_approve = serializers.SerializerMethodField()
class Meta:
model = LeaveRequest
exclude = [
"requested_date",
"approved_available_days",
"approved_carryforward_days",
"created_at",
"reject_reason",
"created_by",
]
def get_employee_id(self, obj):
employee = obj.employee_id
if employee:
return EmployeeGetSerializer(employee).data
return None
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
def get_multiple_approve(self, obj):
approvals = LeaveRequestConditionApproval.objects.filter(leave_request_id=obj)
employee = self.context["request"].user.employee_get
if approvals and obj.status == "requested":
is_approved = approvals.filter(is_approved=True)
count = f"{is_approved.count()} / {approvals.count()}"
is_approved = (
True if is_approved.filter(manager_id=employee).exists() else False
)
return {"count": count, "is_approved": is_approved}
return None
class LeaveAllocationRequestSerilaizer(serializers.ModelSerializer):
class Meta:
model = LeaveAllocationRequest
exclude = [
"requested_date",
"status",
"created_by",
"created_at",
"reject_reason",
]
class LeaveAllocationRequestGetSerializer(serializers.ModelSerializer):
employee_id = serializers.SerializerMethodField()
leave_type_id = serializers.SerializerMethodField()
created_by = serializers.SerializerMethodField()
class Meta:
model = LeaveAllocationRequest
exclude = ["requested_date", "created_at", "reject_reason"]
def get_employee_id(self, obj):
employee = obj.employee_id
if employee:
return EmployeeGetSerializer(employee).data
return None
def get_leave_type_id(self, obj):
if obj.leave_type_id:
return LeaveTypeAllGetSerializer(obj.leave_type_id).data
return None
def get_created_by(self, obj):
created_by = obj.created_by
if created_by:
return EmployeeGetSerializer(created_by).data
return None
class CompanyLeaveSerializer(serializers.ModelSerializer):
class Meta:
model = CompanyLeave
exclude = ["company_id"]
class HoildaySerializer(serializers.ModelSerializer):
class Meta:
model = Holiday
exclude = ["company_id"]
def validate(self, data):
start_date = data.get("start_date")
end_date = data.get("end_date")
if end_date and not start_date <= end_date:
raise serializers.ValidationError(
{"end_date": ["End date should not be less than start date."]}
)
return data
class LeaveRequestApproveSerializer(serializers.ModelSerializer):
class Meta:
model = LeaveRequest
fields = []
def validate(self, data):
leave_request = self.instance
if leave_request.status != "requested":
raise serializers.ValidationError("Nothing to approve.")
employee_id = leave_request.employee_id
leave_type_id = leave_request.leave_type_id
available_leave = AvailableLeave.objects.get(
leave_type_id=leave_type_id, employee_id=employee_id
)
total_available_leave = (
available_leave.available_days + available_leave.carryforward_days
)
if not total_available_leave >= leave_request.requested_days:
raise serializers.ValidationError(
f"{employee_id} dont have enough leave days to approve the request.."
)
data["available_leave"] = available_leave
return data