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)