# backend/schemas.py from pydantic import BaseModel from typing import Optional, List, Literal from datetime import datetime # === Equipment Type === class EquipmentTypeBase(BaseModel): name: str class EquipmentTypeCreate(EquipmentTypeBase): pass class EquipmentTypeRead(EquipmentTypeBase): id: int class Config: from_attributes = True # === Component === class ComponentBase(BaseModel): name: str description: Optional[str] = None class ComponentCreate(ComponentBase): oborud_id: int class ComponentRead(ComponentBase): id: int class Config: from_attributes = True # === Consumable === class ConsumableBase(BaseModel): name: str description: Optional[str] = None class ConsumableCreate(ConsumableBase): oborud_id: int class ConsumableRead(ConsumableBase): id: int class Config: from_attributes = True # === Owner === class OwnerBase(BaseModel): name: str class OwnerCreate(OwnerBase): pass class OwnerRead(OwnerBase): id: int class Config: from_attributes = True # === Oborud === class OborudBase(BaseModel): invNumber: Optional[int] = None nazvanie: str raspologenie: Optional[str] = None numberppasu: Optional[str] = None kolichestvo: Optional[int] = None aud_id: Optional[int] = None type_id: Optional[int] = None owner_id: Optional[int] = None class OborudCreate(OborudBase): pass class OborudUpdate(BaseModel): invNumber: Optional[int] = None nazvanie: Optional[str] = None raspologenie: Optional[str] = None numberppasu: Optional[str] = None kolichestvo: Optional[int] = None aud_id: Optional[int] = None type_id: Optional[int] = None owner_id: Optional[int] = None class OborudRead(OborudBase): id: int type: Optional[EquipmentTypeRead] = None owner: Optional[OwnerRead] = None components: List[ComponentRead] = [] consumables: List[ConsumableRead] = [] class Config: from_attributes = True # === Auditory === class AuditoryBase(BaseModel): audnazvanie: str class AuditoryCreate(AuditoryBase): pass class AuditoryRead(AuditoryBase): id: int class Config: from_attributes = True # === Zametka === class ZametkaBase(BaseModel): txtzam: str rmdt: Optional[datetime] = None class ZametkaCreate(ZametkaBase): pass class ZametkaRead(ZametkaBase): id: int created_date: Optional[datetime] = None class Config: from_attributes = True # === Auth/User === class Token(BaseModel): access_token: str token_type: str = "bearer" class TokenData(BaseModel): username: Optional[str] = None role: Optional[str] = None Role = Literal["admin", "editor", "viewer"] class UserBase(BaseModel): username: str role: Role = "viewer" class UserCreate(UserBase): password: str class UserRead(UserBase): id: int class Config: from_attributes = True class UserRoleUpdate(BaseModel): role: Role # === Inspection System === # InspectionSession class InspectionSessionBase(BaseModel): aud_id: Optional[int] = None class InspectionSessionCreate(InspectionSessionBase): pass class InspectionSessionRead(InspectionSessionBase): id: int user_id: int started_at: datetime completed_at: Optional[datetime] = None class Config: from_attributes = True # InspectionRecord class InspectionRecordRead(BaseModel): id: int session_id: int oborud_id: int checked_at: datetime oborud: Optional[OborudRead] = None class Config: from_attributes = True # UnknownBarcode class UnknownBarcodeRead(BaseModel): id: int session_id: int barcode: str scanned_at: datetime class Config: from_attributes = True # Ответ на сканирование class CheckBarcodeResponse(BaseModel): status: Literal["found", "not_found"] equipment: Optional[OborudRead] = None message: str # Статистика сессии class InspectionSessionStats(BaseModel): session: InspectionSessionRead total_expected: int # всего оборудования (в аудитории или всего) total_checked: int # проверено уникальных позиций total_unknown: int # неизвестных штрихкодов progress_percent: float # Детальный отчёт class InspectionDetailReport(BaseModel): records: List[InspectionRecordRead] unknown_barcodes: List[UnknownBarcodeRead]