from pydantic import BaseModel, EmailStr, field_validator from typing import Optional, List from datetime import datetime from app.models.models import UserRole, ActivityType, NCLevel, NCType # Token class Token(BaseModel): access_token: str token_type: str class TokenData(BaseModel): email: Optional[str] = None # User class UserBase(BaseModel): email: EmailStr full_name: Optional[str] = None role: UserRole = UserRole.SUPERVISOR is_active: bool = True class UserCreate(UserBase): password: str class User(UserBase): id: int class Config: from_attributes = True # Project class ProjectBase(BaseModel): name: str code: str location: Optional[str] = None start_date: Optional[datetime] = None end_date: Optional[datetime] = None status: str = "active" parent_id: Optional[int] = None class ProjectCreate(ProjectBase): specialty_ids: Optional[List[int]] = [] contractor_ids: Optional[List[int]] = [] class Project(ProjectBase): id: int specialties: List['Specialty'] = [] contractors: List['Contractor'] = [] subprojects: List['Project'] = [] class Config: from_attributes = True # Specialty class SpecialtyBase(BaseModel): name: str class Specialty(SpecialtyBase): id: int class Config: from_attributes = True # Contractor class ContractorBase(BaseModel): name: str ruc: Optional[str] = None contact_name: Optional[str] = None email: Optional[EmailStr] = None phone: Optional[str] = None address: Optional[str] = None specialty_id: Optional[int] = None parent_id: Optional[int] = None is_active: bool = True @field_validator('ruc', 'contact_name', 'email', 'phone', 'address', 'specialty_id', 'parent_id', mode='before') @classmethod def empty_string_to_none(cls, v): if v == "": return None return v class ContractorCreate(ContractorBase): pass class ContractorUpdate(BaseModel): name: Optional[str] = None ruc: Optional[str] = None contact_name: Optional[str] = None email: Optional[EmailStr] = None phone: Optional[str] = None address: Optional[str] = None specialty_id: Optional[int] = None parent_id: Optional[int] = None is_active: Optional[bool] = None class Contractor(ContractorBase): id: int specialty: Optional[Specialty] = None subcontractors: List['Contractor'] = [] class Config: from_attributes = True # Evidence class EvidenceBase(BaseModel): file_path: str media_type: Optional[str] = None description: Optional[str] = None captured_at: Optional[datetime] = None transcription: Optional[str] = None transcription_status: str = "none" class Evidence(EvidenceBase): id: int activity_id: Optional[int] = None non_conformity_id: Optional[int] = None class Config: from_attributes = True class EvidenceUpdate(BaseModel): description: Optional[str] = None # Activity class ActivityBase(BaseModel): project_id: int specialty_id: int contractor_id: Optional[int] = None type: ActivityType = ActivityType.INSPECTION area: Optional[str] = None description: Optional[str] = None observations: Optional[str] = None audio_transcription: Optional[str] = None status: str = "completed" date: Optional[datetime] = None end_date: Optional[datetime] = None class ActivityUpdate(BaseModel): project_id: Optional[int] = None specialty_id: Optional[int] = None contractor_id: Optional[int] = None area: Optional[str] = None description: Optional[str] = None observations: Optional[str] = None status: Optional[str] = None date: Optional[datetime] = None end_date: Optional[datetime] = None class ActivityCreate(ActivityBase): pass # NonConformity class NonConformityBase(BaseModel): level: NCLevel = NCLevel.MINOR description: str status: str = "open" due_date: Optional[datetime] = None responsible_person: Optional[str] = None responsible_email: Optional[str] = None contractor_id: Optional[int] = None access_hash: Optional[str] = None action_checklist: Optional[List[dict]] = None nc_type: Optional[NCType] = None impact_description: Optional[str] = None closure_description: Optional[str] = None guest_actions: Optional[str] = None parent_id: Optional[int] = None class NonConformityCreate(NonConformityBase): activity_id: int class NonConformityUpdate(BaseModel): due_date: Optional[datetime] = None responsible_person: Optional[str] = None responsible_email: Optional[str] = None contractor_id: Optional[int] = None access_hash: Optional[str] = None action_checklist: Optional[List[dict]] = None nc_type: Optional[NCType] = None impact_description: Optional[str] = None closure_description: Optional[str] = None status: Optional[str] = None guest_actions: Optional[str] = None class NonConformity(NonConformityBase): id: int activity_id: int evidences: List[Evidence] = [] child_ncs: List['NonConformity'] = [] class Config: from_attributes = True class Activity(ActivityBase): id: int user_id: int project: Optional[Project] = None evidences: List[Evidence] = [] non_conformities: List[NonConformity] = [] class Config: from_attributes = True Contractor.model_rebuild()