307 lines
14 KiB
Python
307 lines
14 KiB
Python
from rest_framework import serializers
|
|
from ..models import (
|
|
Employee, Department, Schedule, ScheduleAssignment,
|
|
TimeEntry, PerformanceReview, TrainingRecord
|
|
)
|
|
|
|
|
|
class BaseSerializer(serializers.ModelSerializer):
|
|
"""Base serializer with common functionality"""
|
|
|
|
class Meta:
|
|
fields = ['id']
|
|
read_only_fields = ['created_at', 'updated_at']
|
|
|
|
|
|
class DepartmentSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Department model"""
|
|
manager_name = serializers.CharField(source='manager.get_full_name', read_only=True)
|
|
employee_count = serializers.IntegerField(read_only=True)
|
|
|
|
class Meta:
|
|
model = Department
|
|
fields = [
|
|
'department_id', 'name', 'description', 'code', 'manager',
|
|
'manager_name', 'budget', 'location', 'phone', 'email',
|
|
'is_active', 'employee_count', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['department_id', 'employee_count', 'created_at', 'updated_at']
|
|
|
|
|
|
class EmployeeSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Employee model"""
|
|
department_name = serializers.CharField(source='department.name', read_only=True)
|
|
supervisor_name = serializers.CharField(source='supervisor.get_full_name', read_only=True)
|
|
employment_status_display = serializers.CharField(source='get_employment_status_display', read_only=True)
|
|
|
|
class Meta:
|
|
model = Employee
|
|
fields = [
|
|
'employee_id', 'employee_number', 'user', 'department', 'department_name',
|
|
'job_title', 'employment_status', 'employment_status_display',
|
|
'hire_date', 'termination_date', 'supervisor', 'supervisor_name',
|
|
'salary', 'hourly_rate', 'fte', 'is_active', 'emergency_contact_name',
|
|
'emergency_contact_phone', 'emergency_contact_relationship',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['employee_id', 'employee_number', 'created_at', 'updated_at']
|
|
|
|
|
|
class ScheduleSerializer(serializers.ModelSerializer):
|
|
"""Serializer for Schedule model"""
|
|
created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True)
|
|
|
|
class Meta:
|
|
model = Schedule
|
|
fields = [
|
|
'schedule_id', 'name', 'description', 'start_date', 'end_date',
|
|
'is_published', 'created_by', 'created_by_name', 'notes',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['schedule_id', 'created_at', 'updated_at']
|
|
|
|
|
|
class ScheduleAssignmentSerializer(serializers.ModelSerializer):
|
|
"""Serializer for ScheduleAssignment model"""
|
|
employee_name = serializers.CharField(source='employee.user.get_full_name', read_only=True)
|
|
schedule_name = serializers.CharField(source='schedule.name', read_only=True)
|
|
shift_type_display = serializers.CharField(source='get_shift_type_display', read_only=True)
|
|
duration_hours = serializers.FloatField(read_only=True)
|
|
|
|
class Meta:
|
|
model = ScheduleAssignment
|
|
fields = [
|
|
'assignment_id', 'schedule', 'schedule_name', 'employee', 'employee_name',
|
|
'date', 'start_time', 'end_time', 'duration_hours', 'shift_type',
|
|
'shift_type_display', 'location', 'notes', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['assignment_id', 'duration_hours', 'created_at', 'updated_at']
|
|
|
|
|
|
class TimeEntrySerializer(serializers.ModelSerializer):
|
|
"""Serializer for TimeEntry model"""
|
|
employee_name = serializers.CharField(source='employee.user.get_full_name', read_only=True)
|
|
entry_type_display = serializers.CharField(source='get_entry_type_display', read_only=True)
|
|
hours_worked = serializers.FloatField(read_only=True)
|
|
|
|
class Meta:
|
|
model = TimeEntry
|
|
fields = [
|
|
'entry_id', 'employee', 'employee_name', 'date', 'clock_in_time',
|
|
'clock_out_time', 'break_start_time', 'break_end_time',
|
|
'hours_worked', 'entry_type', 'entry_type_display', 'notes',
|
|
'approved_by', 'approved_date', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['entry_id', 'hours_worked', 'created_at', 'updated_at']
|
|
|
|
|
|
class PerformanceReviewSerializer(serializers.ModelSerializer):
|
|
"""Serializer for PerformanceReview model"""
|
|
employee_name = serializers.CharField(source='employee.user.get_full_name', read_only=True)
|
|
reviewer_name = serializers.CharField(source='reviewer.get_full_name', read_only=True)
|
|
review_type_display = serializers.CharField(source='get_review_type_display', read_only=True)
|
|
|
|
class Meta:
|
|
model = PerformanceReview
|
|
fields = [
|
|
'review_id', 'employee', 'employee_name', 'reviewer', 'reviewer_name',
|
|
'review_period_start', 'review_period_end', 'review_date',
|
|
'review_type', 'review_type_display', 'overall_rating',
|
|
'goals_achievements', 'strengths', 'areas_for_improvement',
|
|
'development_plan', 'comments', 'is_final', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['review_id', 'created_at', 'updated_at']
|
|
|
|
|
|
class TrainingRecordSerializer(serializers.ModelSerializer):
|
|
"""Serializer for TrainingRecord model"""
|
|
employee_name = serializers.CharField(source='employee.user.get_full_name', read_only=True)
|
|
training_type_display = serializers.CharField(source='get_training_type_display', read_only=True)
|
|
status_display = serializers.CharField(source='get_status_display', read_only=True)
|
|
|
|
class Meta:
|
|
model = TrainingRecord
|
|
fields = [
|
|
'record_id', 'employee', 'employee_name', 'training_name',
|
|
'training_type', 'training_type_display', 'provider',
|
|
'start_date', 'completion_date', 'expiration_date',
|
|
'hours', 'cost', 'status', 'status_display', 'certificate_number',
|
|
'notes', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['record_id', 'created_at', 'updated_at']
|
|
|
|
|
|
class HRStatsSerializer(serializers.Serializer):
|
|
"""Serializer for HR statistics"""
|
|
total_employees = serializers.IntegerField()
|
|
active_employees = serializers.IntegerField()
|
|
new_hires_this_month = serializers.IntegerField()
|
|
terminations_this_month = serializers.IntegerField()
|
|
attendance_rate = serializers.FloatField()
|
|
overtime_hours = serializers.FloatField()
|
|
training_completion_rate = serializers.FloatField()
|
|
department_breakdown = serializers.DictField()
|
|
employment_status_breakdown = serializers.DictField()
|
|
|
|
|
|
class ClockInOutSerializer(serializers.Serializer):
|
|
"""Serializer for clock in/out operations"""
|
|
employee_id = serializers.IntegerField()
|
|
action = serializers.ChoiceField(choices=['CLOCK_IN', 'CLOCK_OUT', 'BREAK_START', 'BREAK_END'])
|
|
notes = serializers.CharField(required=False, allow_blank=True)
|
|
|
|
def validate_employee_id(self, value):
|
|
"""Validate that the employee exists"""
|
|
try:
|
|
Employee.objects.get(id=value)
|
|
return value
|
|
except Employee.DoesNotExist:
|
|
raise serializers.ValidationError("Invalid employee ID.")
|
|
|
|
|
|
class ScheduleCreateSerializer(serializers.Serializer):
|
|
"""Serializer for creating schedules"""
|
|
name = serializers.CharField()
|
|
description = serializers.CharField(required=False, allow_blank=True)
|
|
start_date = serializers.DateField()
|
|
end_date = serializers.DateField()
|
|
assignments = serializers.ListField(
|
|
child=serializers.DictField(),
|
|
min_length=1
|
|
)
|
|
notes = serializers.CharField(required=False, allow_blank=True)
|
|
|
|
def validate(self, data):
|
|
"""Validate schedule data"""
|
|
if data['end_date'] <= data['start_date']:
|
|
raise serializers.ValidationError("End date must be after start date.")
|
|
return data
|
|
|
|
def validate_assignments(self, value):
|
|
"""Validate schedule assignments"""
|
|
for assignment in value:
|
|
required_fields = ['employee_id', 'date', 'start_time', 'end_time', 'shift_type']
|
|
for field in required_fields:
|
|
if field not in assignment:
|
|
raise serializers.ValidationError(f"Assignment missing required field: {field}")
|
|
return value
|
|
|
|
|
|
class PerformanceReviewCreateSerializer(serializers.Serializer):
|
|
"""Serializer for creating performance reviews"""
|
|
employee_id = serializers.IntegerField()
|
|
review_period_start = serializers.DateField()
|
|
review_period_end = serializers.DateField()
|
|
review_type = serializers.CharField()
|
|
overall_rating = serializers.IntegerField(min_value=1, max_value=5)
|
|
goals_achievements = serializers.CharField()
|
|
strengths = serializers.CharField()
|
|
areas_for_improvement = serializers.CharField()
|
|
development_plan = serializers.CharField()
|
|
comments = serializers.CharField(required=False, allow_blank=True)
|
|
|
|
def validate(self, data):
|
|
"""Validate review data"""
|
|
if data['review_period_end'] <= data['review_period_start']:
|
|
raise serializers.ValidationError("Review period end must be after start.")
|
|
return data
|
|
|
|
|
|
class TrainingRecordCreateSerializer(serializers.Serializer):
|
|
"""Serializer for creating training records"""
|
|
employee_id = serializers.IntegerField()
|
|
training_name = serializers.CharField()
|
|
training_type = serializers.CharField()
|
|
provider = serializers.CharField()
|
|
start_date = serializers.DateField()
|
|
hours = serializers.IntegerField(min_value=1)
|
|
cost = serializers.DecimalField(max_digits=10, decimal_places=2, required=False)
|
|
notes = serializers.CharField(required=False, allow_blank=True)
|
|
|
|
|
|
# Salary and Document Management Serializers
|
|
|
|
class SalaryInformationSerializer(serializers.ModelSerializer):
|
|
"""Serializer for SalaryInformation model"""
|
|
employee_name = serializers.CharField(source='employee.get_full_name', read_only=True)
|
|
employee_id_display = serializers.CharField(source='employee.employee_id', read_only=True)
|
|
currency_display = serializers.CharField(source='get_currency_display', read_only=True)
|
|
payment_frequency_display = serializers.CharField(source='get_payment_frequency_display', read_only=True)
|
|
total_salary = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
|
|
|
|
class Meta:
|
|
model = 'hr.SalaryInformation'
|
|
fields = [
|
|
'id', 'employee', 'employee_name', 'employee_id_display',
|
|
'basic_salary', 'housing_allowance', 'transportation_allowance',
|
|
'food_allowance', 'other_allowances', 'total_salary',
|
|
'currency', 'currency_display', 'payment_frequency', 'payment_frequency_display',
|
|
'bank_name', 'account_number', 'iban', 'swift_code',
|
|
'effective_date', 'end_date', 'is_active',
|
|
'created_by', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'total_salary', 'created_at', 'updated_at']
|
|
|
|
|
|
class SalaryAdjustmentSerializer(serializers.ModelSerializer):
|
|
"""Serializer for SalaryAdjustment model"""
|
|
employee_name = serializers.CharField(source='employee.get_full_name', read_only=True)
|
|
adjustment_type_display = serializers.CharField(source='get_adjustment_type_display', read_only=True)
|
|
previous_salary_amount = serializers.DecimalField(source='previous_salary.total_salary', max_digits=10, decimal_places=2, read_only=True)
|
|
new_salary_amount = serializers.DecimalField(source='new_salary.total_salary', max_digits=10, decimal_places=2, read_only=True)
|
|
approved_by_name = serializers.CharField(source='approved_by.get_full_name', read_only=True, allow_null=True)
|
|
|
|
class Meta:
|
|
model = 'hr.SalaryAdjustment'
|
|
fields = [
|
|
'id', 'employee', 'employee_name', 'previous_salary', 'previous_salary_amount',
|
|
'new_salary', 'new_salary_amount', 'adjustment_type', 'adjustment_type_display',
|
|
'adjustment_date', 'amount_change', 'percentage_change', 'reason',
|
|
'approved_by', 'approved_by_name', 'approval_date',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'amount_change', 'percentage_change', 'created_at', 'updated_at']
|
|
|
|
|
|
class DocumentRequestSerializer(serializers.ModelSerializer):
|
|
"""Serializer for DocumentRequest model"""
|
|
employee_name = serializers.CharField(source='employee.get_full_name', read_only=True)
|
|
document_type_display = serializers.CharField(source='get_document_type_display', read_only=True)
|
|
language_display = serializers.CharField(source='get_language_display', read_only=True)
|
|
delivery_method_display = serializers.CharField(source='get_delivery_method_display', read_only=True)
|
|
status_display = serializers.CharField(source='get_status_display', read_only=True)
|
|
is_urgent = serializers.BooleanField(read_only=True)
|
|
is_overdue = serializers.BooleanField(read_only=True)
|
|
processed_by_name = serializers.CharField(source='processed_by.get_full_name', read_only=True, allow_null=True)
|
|
|
|
class Meta:
|
|
model = 'hr.DocumentRequest'
|
|
fields = [
|
|
'id', 'document_number', 'employee', 'employee_name',
|
|
'document_type', 'document_type_display', 'custom_document_name',
|
|
'language', 'language_display', 'purpose', 'addressee',
|
|
'delivery_method', 'delivery_method_display', 'delivery_email',
|
|
'delivery_address', 'required_by_date', 'include_salary',
|
|
'status', 'status_display', 'is_urgent', 'is_overdue',
|
|
'generated_document', 'processed_by', 'processed_by_name',
|
|
'processed_at', 'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'document_number', 'is_urgent', 'is_overdue', 'created_at', 'updated_at']
|
|
|
|
|
|
class DocumentTemplateSerializer(serializers.ModelSerializer):
|
|
"""Serializer for DocumentTemplate model"""
|
|
document_type_display = serializers.CharField(source='get_document_type_display', read_only=True)
|
|
language_display = serializers.CharField(source='get_language_display', read_only=True)
|
|
|
|
class Meta:
|
|
model = 'hr.DocumentTemplate'
|
|
fields = [
|
|
'id', 'name', 'description', 'document_type', 'document_type_display',
|
|
'language', 'language_display', 'template_content', 'header_content',
|
|
'footer_content', 'available_placeholders', 'css_styles',
|
|
'is_active', 'is_default', 'requires_approval',
|
|
'created_at', 'updated_at'
|
|
]
|
|
read_only_fields = ['id', 'created_at', 'updated_at']
|