"""Doctor and Patient profile shells — Phase 13.0.""" from __future__ import annotations import uuid from sqlalchemy import Index, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.types import JSON from app.core.database import Base from app.models.base import ( ActorAuditMixin, OptimisticLockMixin, SoftDeleteMixin, TenantMixin, TimestampMixin, UUIDPrimaryKeyMixin, ) from app.models.types import GUID, LifecycleStatus, ProfileStatus class Doctor( Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin, SoftDeleteMixin, ActorAuditMixin, OptimisticLockMixin, ): """Doctor profile shell — links to Identity user ref only.""" __tablename__ = "doctors" user_id: Mapped[str] = mapped_column(String(100), nullable=False) clinic_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True) department_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True) code: Mapped[str] = mapped_column(String(50), nullable=False) display_name: Mapped[str] = mapped_column(String(255), nullable=False) specialty: Mapped[str | None] = mapped_column(String(100), nullable=True) license_number: Mapped[str | None] = mapped_column(String(100), nullable=True) status: Mapped[ProfileStatus] = mapped_column( default=ProfileStatus.ACTIVE, nullable=False ) contact: Mapped[dict | None] = mapped_column(JSON, nullable=True) metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True) __table_args__ = ( UniqueConstraint("tenant_id", "code", name="uq_doctors_tenant_code"), UniqueConstraint("tenant_id", "user_id", name="uq_doctors_tenant_user"), Index("ix_doctors_clinic", "tenant_id", "clinic_id"), Index("ix_doctors_tenant_deleted", "tenant_id", "is_deleted"), ) class Patient( Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin, SoftDeleteMixin, ActorAuditMixin, OptimisticLockMixin, ): """Patient profile shell — links to Identity user ref only.""" __tablename__ = "patients" user_id: Mapped[str] = mapped_column(String(100), nullable=False) code: Mapped[str] = mapped_column(String(50), nullable=False) display_name: Mapped[str] = mapped_column(String(255), nullable=False) status: Mapped[ProfileStatus] = mapped_column( default=ProfileStatus.ACTIVE, nullable=False ) date_of_birth: Mapped[str | None] = mapped_column(String(32), nullable=True) gender: Mapped[str | None] = mapped_column(String(32), nullable=True) contact: Mapped[dict | None] = mapped_column(JSON, nullable=True) emergency_contact: Mapped[dict | None] = mapped_column(JSON, nullable=True) metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True) __table_args__ = ( UniqueConstraint("tenant_id", "code", name="uq_patients_tenant_code"), UniqueConstraint("tenant_id", "user_id", name="uq_patients_tenant_user"), Index("ix_patients_tenant_deleted", "tenant_id", "is_deleted"), )