""" Organizations serializers """ from rest_framework import serializers from .models import Department, Hospital, Location, MainSection, Organization, Patient, Staff, SubSection 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", "display_name", "display_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) localized_name = serializers.CharField(source="get_localized_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", "localized_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): if obj.report_to: return obj.report_to.get_localized_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, was_created, password = StaffService.create_user_for_staff( staff, role=role, request=self.context.get("request") ) # Send email if requested and user was created if was_created and password and 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, was_created, password = StaffService.create_user_for_staff( instance, role=role, request=self.context.get("request") ) # Send email if requested and user was created if was_created and password and 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() national_id = serializers.SerializerMethodField() national_id_masked = serializers.SerializerMethodField() class Meta: model = Patient fields = [ "id", "mrn", "national_id", "national_id_masked", "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_national_id(self, obj): request = self.context.get("request") if request and request.user and request.user.is_superuser: return obj.national_id return None def get_national_id_masked(self, obj): return obj.get_masked_national_id() 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) national_id_masked = serializers.CharField(source="get_masked_national_id", read_only=True) class Meta: model = Patient fields = ["id", "mrn", "full_name", "national_id_masked", "phone", "email", "primary_hospital_name", "status"] class LocationSerializer(serializers.ModelSerializer): """Location serializer for dropdown""" name = serializers.SerializerMethodField() class Meta: model = Location fields = ["id", "name"] def get_name(self, obj): """Return name based on current language""" from django.utils.translation import get_language lang = get_language() if lang == "ar" and obj.name_ar: return obj.name_ar return obj.name_en if obj.name_en else obj.name_ar class MainSectionSerializer(serializers.ModelSerializer): """MainSection serializer for dropdown""" name = serializers.SerializerMethodField() class Meta: model = MainSection fields = ["id", "name"] def get_name(self, obj): """Return name based on current language""" from django.utils.translation import get_language lang = get_language() if lang == "ar" and obj.name_ar: return obj.name_ar return obj.name_en if obj.name_en else obj.name_ar class SubSectionSerializer(serializers.ModelSerializer): """SubSection serializer for dropdown""" id = serializers.IntegerField(source="internal_id", read_only=True) name = serializers.SerializerMethodField() location_name = serializers.SerializerMethodField() main_section_name = serializers.SerializerMethodField() class Meta: model = SubSection fields = ["id", "name", "location", "main_section", "location_name", "main_section_name"] def get_name(self, obj): """Return name based on current language""" from django.utils.translation import get_language lang = get_language() if lang == "ar" and obj.name_ar: return obj.name_ar return obj.name_en if obj.name_en else obj.name_ar def get_location_name(self, obj): """Return location name based on current language""" from django.utils.translation import get_language lang = get_language() if lang == "ar" and obj.location.name_ar: return obj.location.name_ar return obj.location.name_en if obj.location.name_en else obj.location.name_ar def get_main_section_name(self, obj): """Return main section name based on current language""" from django.utils.translation import get_language lang = get_language() if lang == "ar" and obj.main_section.name_ar: return obj.main_section.name_ar return obj.main_section.name_en if obj.main_section.name_en else obj.main_section.name_ar