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']