""" Accounts serializers """ from django.contrib.auth import get_user_model from rest_framework import serializers from .models import ( AcknowledgementChecklistItem, AcknowledgementContent, Role, UserAcknowledgement, ) User = get_user_model() class UserSerializer(serializers.ModelSerializer): """User serializer""" roles = serializers.SerializerMethodField() hospital_name = serializers.CharField(source='hospital.name', read_only=True) department_name = serializers.CharField(source='department.name', read_only=True) class Meta: model = User fields = [ 'id', 'username', 'email', 'first_name', 'last_name', 'phone', 'employee_id', 'hospital', 'hospital_name', 'department', 'department_name', 'avatar', 'bio', 'language', 'is_active', 'roles', 'date_joined', 'created_at', 'updated_at' ] read_only_fields = ['id', 'date_joined', 'created_at', 'updated_at'] def get_roles(self, obj): """Get user roles""" return obj.get_role_names() class UserCreateSerializer(serializers.ModelSerializer): """User creation serializer with password""" password = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'}) password_confirm = serializers.CharField(write_only=True, required=True, style={'input_type': 'password'}) class Meta: model = User fields = [ 'username', 'email', 'password', 'password_confirm', 'first_name', 'last_name', 'phone', 'employee_id', 'hospital', 'department', 'language' ] def validate(self, attrs): """Validate passwords match""" if attrs['password'] != attrs['password_confirm']: raise serializers.ValidationError({"password": "Passwords do not match."}) return attrs def create(self, validated_data): """Create user with hashed password""" validated_data.pop('password_confirm') password = validated_data.pop('password') user = User.objects.create(**validated_data) user.set_password(password) user.save() return user class UserUpdateSerializer(serializers.ModelSerializer): """User update serializer (without password)""" class Meta: model = User fields = [ 'first_name', 'last_name', 'phone', 'employee_id', 'hospital', 'department', 'avatar', 'bio', 'language', 'is_active' ] class ChangePasswordSerializer(serializers.Serializer): """Change password serializer""" old_password = serializers.CharField(required=True, write_only=True) new_password = serializers.CharField(required=True, write_only=True) new_password_confirm = serializers.CharField(required=True, write_only=True) def validate(self, attrs): """Validate passwords""" if attrs['new_password'] != attrs['new_password_confirm']: raise serializers.ValidationError({"new_password": "Passwords do not match."}) return attrs def validate_old_password(self, value): """Validate old password""" user = self.context['request'].user if not user.check_password(value): raise serializers.ValidationError("Old password is incorrect.") return value class RoleSerializer(serializers.ModelSerializer): """Role serializer""" group_name = serializers.CharField(source='group.name', read_only=True) class Meta: model = Role fields = [ 'id', 'name', 'display_name', 'description', 'group', 'group_name', 'level', 'permissions', 'created_at', 'updated_at' ] read_only_fields = ['id', 'created_at', 'updated_at'] # ==================== Onboarding Serializers ==================== class ProvisionalUserSerializer(serializers.ModelSerializer): """Serializer for creating provisional users""" roles = serializers.ListField( child=serializers.CharField(), write_only=True, required=False, default=list, help_text="List of role names to assign" ) class Meta: model = User fields = [ 'email', 'first_name', 'last_name', 'phone', 'employee_id', 'hospital', 'department', 'language', 'roles' ] def create(self, validated_data): """Create provisional user""" roles = validated_data.pop('roles', []) user = User(**validated_data) user.is_provisional = True user.set_unusable_password() user.save() # Assign roles for role_name in roles: from .models import Role as RoleModel try: role = RoleModel.objects.get(name=role_name) user.groups.add(role.group) except RoleModel.DoesNotExist: pass return user class AcknowledgementContentSerializer(serializers.ModelSerializer): """Serializer for acknowledgement content""" role_display = serializers.CharField(source='get_role_display', read_only=True) class Meta: model = AcknowledgementContent fields = [ 'id', 'role', 'role_display', 'code', 'title_en', 'title_ar', 'description_en', 'description_ar', 'content_en', 'content_ar', 'icon', 'color', 'order', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['id', 'created_at', 'updated_at'] class AcknowledgementChecklistItemSerializer(serializers.ModelSerializer): """Serializer for checklist items""" role_display = serializers.CharField(source='get_role_display', read_only=True) content_title_en = serializers.CharField(source='content.title_en', read_only=True) content_title_ar = serializers.CharField(source='content.title_ar', read_only=True) class Meta: model = AcknowledgementChecklistItem fields = [ 'id', 'role', 'role_display', 'content', 'content_title_en', 'content_title_ar', 'code', 'text_en', 'text_ar', 'description_en', 'description_ar', 'is_required', 'order', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['id', 'created_at', 'updated_at'] class UserAcknowledgementSerializer(serializers.ModelSerializer): """Serializer for user acknowledgements""" user_email = serializers.CharField(source='user.email', read_only=True) user_name = serializers.CharField(source='user.get_full_name', read_only=True) checklist_item_text_en = serializers.CharField(source='checklist_item.text_en', read_only=True) checklist_item_text_ar = serializers.CharField(source='checklist_item.text_ar', read_only=True) checklist_item_code = serializers.CharField(source='checklist_item.code', read_only=True) class Meta: model = UserAcknowledgement fields = [ 'id', 'user', 'user_email', 'user_name', 'checklist_item', 'checklist_item_text_en', 'checklist_item_text_ar', 'checklist_item_code', 'is_acknowledged', 'acknowledged_at', 'signature', 'signature_ip', 'signature_user_agent', 'metadata', 'created_at', 'updated_at' ] read_only_fields = [ 'id', 'user', 'acknowledged_at', 'created_at', 'updated_at' ] class WizardProgressSerializer(serializers.Serializer): """Serializer for wizard progress""" current_step = serializers.IntegerField() completed_steps = serializers.ListField(child=serializers.IntegerField()) progress_percentage = serializers.FloatField() total_required_items = serializers.IntegerField() acknowledged_items = serializers.IntegerField() class AcknowledgeItemSerializer(serializers.Serializer): """Serializer for acknowledging checklist items""" checklist_item_id = serializers.UUIDField(required=True) signature = serializers.CharField(required=False, allow_blank=True) class AccountActivationSerializer(serializers.Serializer): """Serializer for account activation""" username = serializers.CharField( required=True, min_length=3, max_length=150, help_text="Desired username" ) password = serializers.CharField( required=True, min_length=8, write_only=True, style={'input_type': 'password'} ) password_confirm = serializers.CharField( required=True, write_only=True, style={'input_type': 'password'} ) signature = serializers.CharField( required=True, help_text="Digital signature data (base64 encoded)" ) def validate(self, attrs): """Validate passwords match""" if attrs['password'] != attrs['password_confirm']: raise serializers.ValidationError({"password": "Passwords do not match."}) # Check if username is available if User.objects.filter(username=attrs['username']).exists(): raise serializers.ValidationError({"username": "Username already taken."}) return attrs class ResendInvitationSerializer(serializers.Serializer): """Serializer for resending invitation""" user_id = serializers.UUIDField(required=True)