HH/apps/accounts/serializers.py
2026-01-06 13:36:43 +03:00

263 lines
9.2 KiB
Python

"""
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,
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)