HH/apps/organizations/serializers.py

247 lines
9.5 KiB
Python

"""
Organizations serializers
"""
from rest_framework import serializers
from .models import Department, Hospital, Organization, Patient, Staff
class OrganizationSerializer(serializers.ModelSerializer):
"""Organization serializer"""
hospitals_count = serializers.SerializerMethodField()
class Meta:
model = Organization
fields = [
'id', 'name', 'name_ar', 'code', 'address', 'city',
'phone', 'email', 'website', 'status', 'license_number',
'logo', 'hospitals_count', 'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_hospitals_count(self, obj):
"""Get count of hospitals in this organization"""
return obj.hospitals.count()
class HospitalSerializer(serializers.ModelSerializer):
"""Hospital serializer"""
organization_name = serializers.CharField(source='organization.name', read_only=True)
departments_count = serializers.SerializerMethodField()
class Meta:
model = Hospital
fields = [
'id', 'organization', 'organization_name', 'name', 'name_ar', 'code',
'address', 'city', 'phone', 'email', 'status',
'license_number', 'capacity', 'departments_count',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_departments_count(self, obj):
"""Get count of departments in this hospital"""
return obj.departments.count()
class DepartmentSerializer(serializers.ModelSerializer):
"""Department serializer"""
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
parent_name = serializers.CharField(source='parent.name', read_only=True)
manager_name = serializers.SerializerMethodField()
class Meta:
model = Department
fields = [
'id', 'hospital', 'hospital_name', 'name', 'name_ar', 'code',
'parent', 'parent_name', 'manager', 'manager_name',
'phone', 'email', 'location', 'status',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_manager_name(self, obj):
"""Get manager full name"""
if obj.manager:
return obj.manager.get_full_name()
return None
class StaffSerializer(serializers.ModelSerializer):
"""Staff serializer"""
hospital_name = serializers.CharField(source='hospital.name', read_only=True)
department_name_display = serializers.CharField(source='department.name', read_only=True)
department_name = serializers.CharField(read_only=True)
full_name = serializers.CharField(source='get_full_name', read_only=True)
org_info = serializers.CharField(source='get_org_info', read_only=True)
user_email = serializers.EmailField(source='user.email', read_only=True, allow_null=True)
has_user_account = serializers.BooleanField(read_only=True)
report_to_name = serializers.SerializerMethodField()
direct_reports_count = serializers.SerializerMethodField()
# User creation fields (write-only)
create_user = serializers.BooleanField(write_only=True, required=False, default=False)
user_username = serializers.CharField(write_only=True, required=False, allow_blank=True)
user_password = serializers.CharField(write_only=True, required=False, allow_blank=True)
send_email = serializers.BooleanField(write_only=True, required=False, default=True)
class Meta:
model = Staff
fields = [
'id', 'user', 'name', 'first_name', 'last_name', 'first_name_ar', 'last_name_ar',
'full_name', 'org_info', 'staff_type', 'job_title',
'license_number', 'specialization', 'employee_id',
'email', 'phone',
'hospital', 'hospital_name', 'department', 'department_name', 'department_name_display',
'location', 'section', 'subsection', 'country', 'gender',
'report_to', 'report_to_name', 'direct_reports_count',
'user_email', 'has_user_account', 'status',
'created_at', 'updated_at',
'create_user', 'user_username', 'user_password', 'send_email'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_report_to_name(self, obj):
"""Get manager (report_to) full name"""
if obj.report_to:
return obj.report_to.get_full_name()
return None
def get_direct_reports_count(self, obj):
"""Get count of direct reports"""
return obj.direct_reports.count()
def to_representation(self, instance):
"""Customize representation"""
data = super().to_representation(instance)
data['has_user_account'] = instance.user is not None
return data
def create(self, validated_data):
"""Create staff with optional user account"""
# Extract user creation fields
create_user = validated_data.pop('create_user', False)
user_username = validated_data.pop('user_username', '')
user_password = validated_data.pop('user_password', '')
send_email = validated_data.pop('send_email', True)
# Create staff instance
staff = Staff.objects.create(**validated_data)
# Optionally create user account
if create_user and not staff.user:
from .services import StaffService
# Determine role based on staff_type
role = StaffService.get_staff_type_role(staff.staff_type)
# Create user account
try:
user, password = StaffService.create_user_for_staff(
staff,
role=role,
request=self.context.get('request')
)
# Send email if requested
if send_email and self.context.get('request'):
try:
StaffService.send_credentials_email(
staff,
password,
self.context['request']
)
except Exception as e:
# Log but don't fail if email sending fails
pass
except ValueError as e:
# If user creation fails, still return the staff
pass
return staff
def update(self, instance, validated_data):
"""Update staff with optional user account creation"""
# Extract user creation fields
create_user = validated_data.pop('create_user', False)
user_username = validated_data.pop('user_username', '')
user_password = validated_data.pop('user_password', '')
send_email = validated_data.pop('send_email', True)
# Update staff fields
for attr, value in validated_data.items():
setattr(instance, value)
instance.save()
# Optionally create user account if it doesn't exist
if create_user and not instance.user:
from .services import StaffService
# Determine role based on staff_type
role = StaffService.get_staff_type_role(instance.staff_type)
try:
user, password = StaffService.create_user_for_staff(
instance,
role=role,
request=self.context.get('request')
)
# Send email if requested
if send_email and self.context.get('request'):
try:
StaffService.send_credentials_email(
instance,
password,
self.context['request']
)
except Exception as e:
pass
except ValueError as e:
pass
return instance
class PatientSerializer(serializers.ModelSerializer):
"""Patient serializer"""
primary_hospital_name = serializers.CharField(source='primary_hospital.name', read_only=True)
full_name = serializers.CharField(source='get_full_name', read_only=True)
age = serializers.SerializerMethodField()
class Meta:
model = Patient
fields = [
'id', 'mrn', 'national_id', 'first_name', 'last_name',
'first_name_ar', 'last_name_ar', 'full_name',
'date_of_birth', 'age', 'gender',
'phone', 'email', 'address', 'city',
'primary_hospital', 'primary_hospital_name', 'status',
'created_at', 'updated_at'
]
read_only_fields = ['id', 'created_at', 'updated_at']
def get_age(self, obj):
"""Calculate patient age"""
if obj.date_of_birth:
from datetime import date
today = date.today()
return today.year - obj.date_of_birth.year - (
(today.month, today.day) < (obj.date_of_birth.month, obj.date_of_birth.day)
)
return None
class PatientListSerializer(serializers.ModelSerializer):
"""Simplified patient serializer for list views"""
full_name = serializers.CharField(source='get_full_name', read_only=True)
primary_hospital_name = serializers.CharField(source='primary_hospital.name', read_only=True)
class Meta:
model = Patient
fields = [
'id', 'mrn', 'full_name', 'phone', 'email',
'primary_hospital_name', 'status'
]