import uuid from datetime import date, datetime from typing import Literal, Optional from pydantic import BaseModel, ConfigDict, Field StudyStatus = Literal["DRAFT", "ACTIVE", "CLOSED"] class StudyCreate(BaseModel): name: str = Field(min_length=1) code: str = Field(min_length=1) project_full_name: Optional[str] = None sponsor: Optional[str] = None protocol_no: Optional[str] = None lead_unit: Optional[str] = None principal_investigator: Optional[str] = None main_pm: Optional[str] = None research_analysis: Optional[str] = None research_product: Optional[str] = None control_product: Optional[str] = None indication: Optional[str] = None research_population: Optional[str] = None research_design: Optional[str] = None plan_start_date: Optional[date] = None plan_end_date: Optional[date] = None planned_site_count: Optional[int] = None planned_enrollment_count: Optional[int] = None enrollment_monthly_goal_note: Optional[str] = None enrollment_stage_breakdown: Optional[str] = None summary_note: Optional[str] = None objective_note: Optional[str] = None phase: Optional[str] = None status: StudyStatus = "DRAFT" visit_interval_days: Optional[int] = None visit_total: Optional[int] = None visit_window_start_offset: Optional[int] = None visit_window_end_offset: Optional[int] = None class StudyUpdate(BaseModel): code: Optional[str] = None name: Optional[str] = None project_full_name: Optional[str] = None sponsor: Optional[str] = None protocol_no: Optional[str] = None lead_unit: Optional[str] = None principal_investigator: Optional[str] = None main_pm: Optional[str] = None research_analysis: Optional[str] = None research_product: Optional[str] = None control_product: Optional[str] = None indication: Optional[str] = None research_population: Optional[str] = None research_design: Optional[str] = None plan_start_date: Optional[date] = None plan_end_date: Optional[date] = None planned_site_count: Optional[int] = None planned_enrollment_count: Optional[int] = None enrollment_monthly_goal_note: Optional[str] = None enrollment_stage_breakdown: Optional[str] = None summary_note: Optional[str] = None objective_note: Optional[str] = None phase: Optional[str] = None status: Optional[StudyStatus] = None is_locked: Optional[bool] = None visit_interval_days: Optional[int] = None visit_total: Optional[int] = None visit_window_start_offset: Optional[int] = None visit_window_end_offset: Optional[int] = None class StudyRead(BaseModel): id: uuid.UUID code: str name: str project_full_name: Optional[str] sponsor: Optional[str] protocol_no: Optional[str] lead_unit: Optional[str] principal_investigator: Optional[str] main_pm: Optional[str] research_analysis: Optional[str] research_product: Optional[str] control_product: Optional[str] indication: Optional[str] research_population: Optional[str] research_design: Optional[str] plan_start_date: Optional[date] plan_end_date: Optional[date] planned_site_count: Optional[int] planned_enrollment_count: Optional[int] enrollment_monthly_goal_note: Optional[str] enrollment_stage_breakdown: Optional[str] summary_note: Optional[str] objective_note: Optional[str] phase: Optional[str] status: StudyStatus is_locked: bool visit_interval_days: Optional[int] visit_total: Optional[int] visit_window_start_offset: Optional[int] visit_window_end_offset: Optional[int] created_by: Optional[uuid.UUID] created_at: datetime model_config = ConfigDict(from_attributes=True)