from pydantic import BaseModel, EmailStr, Field from typing import Optional, List from datetime import datetime # User Schemas class UserBase(BaseModel): username: str email: Optional[EmailStr] = None full_name: Optional[str] = None role: str = "mechanic" class UserCreate(UserBase): password: str class UserUpdate(BaseModel): username: Optional[str] = None email: Optional[EmailStr] = None full_name: Optional[str] = None role: Optional[str] = None class UserPasswordUpdate(BaseModel): current_password: str new_password: str class AdminPasswordUpdate(BaseModel): new_password: str class UserLogin(BaseModel): username: str password: str class User(UserBase): id: int is_active: bool created_at: datetime class Config: from_attributes = True class Token(BaseModel): access_token: str token_type: str user: User # API Token Schemas class APITokenCreate(BaseModel): description: Optional[str] = None class APIToken(BaseModel): id: int description: Optional[str] = None is_active: bool last_used_at: Optional[datetime] = None created_at: datetime class Config: from_attributes = True class APITokenWithValue(APIToken): token: str # Checklist Schemas class ChecklistBase(BaseModel): name: str description: Optional[str] = None ai_mode: str = "off" scoring_enabled: bool = True logo_url: Optional[str] = None class ChecklistCreate(ChecklistBase): pass class ChecklistUpdate(ChecklistBase): is_active: Optional[bool] = None class Checklist(ChecklistBase): id: int max_score: int is_active: bool created_by: int created_at: datetime class Config: from_attributes = True # Question Schemas class QuestionBase(BaseModel): section: Optional[str] = None text: str type: str points: int = 1 options: Optional[dict] = None order: int = 0 allow_photos: bool = True max_photos: int = 3 requires_comment_on_fail: bool = False class QuestionCreate(QuestionBase): checklist_id: int class QuestionUpdate(QuestionBase): pass class Question(QuestionBase): id: int checklist_id: int created_at: datetime class Config: from_attributes = True # Inspection Schemas class InspectionBase(BaseModel): or_number: Optional[str] = None work_order_number: Optional[str] = None vehicle_plate: str vehicle_brand: Optional[str] = None vehicle_model: Optional[str] = None vehicle_km: Optional[int] = None client_name: Optional[str] = None class InspectionCreate(InspectionBase): checklist_id: int class InspectionUpdate(BaseModel): vehicle_brand: Optional[str] = None vehicle_model: Optional[str] = None vehicle_km: Optional[int] = None signature_data: Optional[str] = None status: Optional[str] = None class Inspection(InspectionBase): id: int checklist_id: int mechanic_id: int score: int max_score: int percentage: float flagged_items_count: int status: str started_at: datetime completed_at: Optional[datetime] = None class Config: from_attributes = True # Answer Schemas class AnswerBase(BaseModel): answer_value: str status: str = "ok" comment: Optional[str] = None is_flagged: bool = False class AnswerCreate(AnswerBase): inspection_id: int question_id: int class AnswerUpdate(AnswerBase): pass class Answer(AnswerBase): id: int inspection_id: int question_id: int points_earned: int ai_analysis: Optional[dict] = None created_at: datetime class Config: from_attributes = True # MediaFile Schemas class MediaFileBase(BaseModel): caption: Optional[str] = None order: int = 0 class MediaFileCreate(MediaFileBase): file_type: str = "image" class MediaFile(MediaFileBase): id: int answer_id: int file_path: str file_type: str uploaded_at: datetime class Config: from_attributes = True # Response Schemas class ChecklistWithQuestions(Checklist): questions: List[Question] = [] class AnswerWithMedia(Answer): media_files: List[MediaFile] = [] question: Question class InspectionDetail(Inspection): checklist: ChecklistWithQuestions mechanic: User answers: List[AnswerWithMedia] = [] # AI Configuration Schemas class AIConfigurationBase(BaseModel): provider: str # openai, gemini api_key: str model_name: str class AIConfigurationCreate(AIConfigurationBase): pass class AIConfigurationUpdate(BaseModel): provider: Optional[str] = None api_key: Optional[str] = None model_name: Optional[str] = None is_active: Optional[bool] = None class AIConfiguration(AIConfigurationBase): id: int is_active: bool created_at: datetime class Config: from_attributes = True class AIModelInfo(BaseModel): id: str name: str provider: str description: Optional[str] = None