""" Linux BenchTools - Peripheral Schemas """ from pydantic import BaseModel, Field from typing import Optional, List, Dict, Any from datetime import date, datetime # ======================================== # BASE SCHEMAS # ======================================== class PeripheralBase(BaseModel): """Base schema for peripherals""" nom: str = Field(..., min_length=1, max_length=255) type_principal: str = Field(..., min_length=1, max_length=100) sous_type: Optional[str] = Field(None, max_length=100) marque: Optional[str] = Field(None, max_length=100) modele: Optional[str] = Field(None, max_length=255) fabricant: Optional[str] = Field(None, max_length=255) produit: Optional[str] = Field(None, max_length=255) numero_serie: Optional[str] = Field(None, max_length=255) ean_upc: Optional[str] = Field(None, max_length=50) # Achat boutique: Optional[str] = Field(None, max_length=255) date_achat: Optional[date] = None prix: Optional[float] = Field(None, ge=0) devise: Optional[str] = Field("EUR", max_length=10) garantie_duree_mois: Optional[int] = Field(None, ge=0) garantie_expiration: Optional[date] = None # Évaluation rating: Optional[float] = Field(0.0, ge=0, le=5) # Stock quantite_totale: Optional[int] = Field(1, ge=0) quantite_disponible: Optional[int] = Field(1, ge=0) seuil_alerte: Optional[int] = Field(0, ge=0) # Métadonnées etat: Optional[str] = Field("Neuf", max_length=50) localisation: Optional[str] = Field(None, max_length=255) proprietaire: Optional[str] = Field(None, max_length=100) tags: Optional[str] = None # JSON string # Documentation description: Optional[str] = None # Description courte synthese: Optional[str] = None # Synthèse complète markdown cli: Optional[str] = None # DEPRECATED: Sortie CLI (lsusb -v) filtrée cli_yaml: Optional[str] = None # Données structurées CLI au format YAML cli_raw: Optional[str] = None # Sortie CLI brute (Markdown) specifications: Optional[str] = None # Spécifications techniques (Markdown) notes: Optional[str] = None # Notes libres (Markdown) # Linux device_path: Optional[str] = Field(None, max_length=255) sysfs_path: Optional[str] = Field(None, max_length=500) vendor_id: Optional[str] = Field(None, max_length=20) product_id: Optional[str] = Field(None, max_length=20) usb_device_id: Optional[str] = Field(None, max_length=20) iManufacturer: Optional[str] = None # USB manufacturer string iProduct: Optional[str] = None # USB product string class_id: Optional[str] = Field(None, max_length=20) driver_utilise: Optional[str] = Field(None, max_length=100) modules_kernel: Optional[str] = None # JSON string udev_rules: Optional[str] = None identifiant_systeme: Optional[str] = None # Installation installation_auto: Optional[bool] = False driver_requis: Optional[str] = None firmware_requis: Optional[str] = None paquets_necessaires: Optional[str] = None # JSON string commandes_installation: Optional[str] = None problemes_connus: Optional[str] = None solutions: Optional[str] = None compatibilite_noyau: Optional[str] = Field(None, max_length=100) # Connectivité interface_connexion: Optional[str] = Field(None, max_length=100) connecte_a: Optional[str] = Field(None, max_length=255) consommation_electrique_w: Optional[float] = Field(None, ge=0) # Localisation physique location_id: Optional[int] = None location_details: Optional[str] = Field(None, max_length=500) location_auto: Optional[bool] = True # Appareil complet is_complete_device: Optional[bool] = False device_type: Optional[str] = Field(None, max_length=50) linked_device_id: Optional[int] = None device_id: Optional[int] = None # Données spécifiques caracteristiques_specifiques: Optional[Dict[str, Any]] = None class PeripheralCreate(PeripheralBase): """Schema for creating a peripheral""" pass class PeripheralUpdate(BaseModel): """Schema for updating a peripheral (all fields optional)""" nom: Optional[str] = Field(None, min_length=1, max_length=255) type_principal: Optional[str] = Field(None, min_length=1, max_length=100) sous_type: Optional[str] = Field(None, max_length=100) marque: Optional[str] = Field(None, max_length=100) modele: Optional[str] = Field(None, max_length=255) fabricant: Optional[str] = Field(None, max_length=255) produit: Optional[str] = Field(None, max_length=255) numero_serie: Optional[str] = Field(None, max_length=255) ean_upc: Optional[str] = Field(None, max_length=50) boutique: Optional[str] = Field(None, max_length=255) date_achat: Optional[date] = None prix: Optional[float] = Field(None, ge=0) devise: Optional[str] = Field(None, max_length=10) garantie_duree_mois: Optional[int] = Field(None, ge=0) garantie_expiration: Optional[date] = None rating: Optional[float] = Field(None, ge=0, le=5) quantite_totale: Optional[int] = Field(None, ge=0) quantite_disponible: Optional[int] = Field(None, ge=0) seuil_alerte: Optional[int] = Field(None, ge=0) etat: Optional[str] = Field(None, max_length=50) localisation: Optional[str] = Field(None, max_length=255) proprietaire: Optional[str] = Field(None, max_length=100) tags: Optional[str] = None notes: Optional[str] = None device_path: Optional[str] = Field(None, max_length=255) vendor_id: Optional[str] = Field(None, max_length=20) product_id: Optional[str] = Field(None, max_length=20) usb_device_id: Optional[str] = Field(None, max_length=20) iManufacturer: Optional[str] = None iProduct: Optional[str] = None connecte_a: Optional[str] = Field(None, max_length=255) location_id: Optional[int] = None location_details: Optional[str] = Field(None, max_length=500) is_complete_device: Optional[bool] = None device_type: Optional[str] = Field(None, max_length=50) linked_device_id: Optional[int] = None device_id: Optional[int] = None caracteristiques_specifiques: Optional[Dict[str, Any]] = None class PeripheralSummary(BaseModel): """Summary schema for peripheral lists""" id: int nom: str type_principal: str sous_type: Optional[str] marque: Optional[str] modele: Optional[str] etat: str rating: float prix: Optional[float] en_pret: bool is_complete_device: bool quantite_disponible: int thumbnail_url: Optional[str] = None class Config: from_attributes = True class PeripheralDetail(PeripheralBase): """Detailed schema with all information""" id: int date_creation: datetime date_modification: Optional[datetime] en_pret: bool pret_actuel_id: Optional[int] prete_a: Optional[str] class Config: from_attributes = True class PeripheralListResponse(BaseModel): """Paginated list response""" items: List[PeripheralSummary] total: int page: int page_size: int total_pages: int # ======================================== # PHOTO SCHEMAS # ======================================== class PeripheralPhotoBase(BaseModel): """Base schema for peripheral photos""" description: Optional[str] = None is_primary: Optional[bool] = False class PeripheralPhotoCreate(PeripheralPhotoBase): """Schema for creating a photo""" peripheral_id: int filename: str stored_path: str mime_type: Optional[str] size_bytes: Optional[int] class PeripheralPhotoSchema(PeripheralPhotoBase): """Full photo schema""" id: int peripheral_id: int filename: str stored_path: str thumbnail_path: Optional[str] mime_type: Optional[str] size_bytes: Optional[int] uploaded_at: datetime class Config: from_attributes = True # ======================================== # DOCUMENT SCHEMAS # ======================================== class PeripheralDocumentBase(BaseModel): """Base schema for peripheral documents""" doc_type: str = Field(..., max_length=50) # manual, warranty, invoice, datasheet, other description: Optional[str] = None class PeripheralDocumentCreate(PeripheralDocumentBase): """Schema for creating a document""" peripheral_id: int filename: str stored_path: str mime_type: Optional[str] size_bytes: Optional[int] class PeripheralDocumentSchema(PeripheralDocumentBase): """Full document schema""" id: int peripheral_id: int filename: str stored_path: str mime_type: Optional[str] size_bytes: Optional[int] uploaded_at: datetime class Config: from_attributes = True # ======================================== # LINK SCHEMAS # ======================================== class PeripheralLinkBase(BaseModel): """Base schema for peripheral links""" link_type: str = Field(..., max_length=50) # manufacturer, support, drivers, documentation, custom label: str = Field(..., min_length=1, max_length=255) url: str class PeripheralLinkCreate(PeripheralLinkBase): """Schema for creating a link""" peripheral_id: int class PeripheralLinkSchema(PeripheralLinkBase): """Full link schema""" id: int peripheral_id: int class Config: from_attributes = True # ======================================== # LOAN SCHEMAS # ======================================== class LoanBase(BaseModel): """Base schema for loans""" emprunte_par: str = Field(..., min_length=1, max_length=255) email_emprunteur: Optional[str] = Field(None, max_length=255) telephone: Optional[str] = Field(None, max_length=50) date_pret: date date_retour_prevue: date caution_montant: Optional[float] = Field(None, ge=0) etat_depart: Optional[str] = Field(None, max_length=50) raison_pret: Optional[str] = None notes: Optional[str] = None class LoanCreate(LoanBase): """Schema for creating a loan""" peripheral_id: int class LoanReturn(BaseModel): """Schema for returning a loan""" date_retour_effectif: date etat_retour: Optional[str] = Field(None, max_length=50) problemes_retour: Optional[str] = None caution_rendue: bool = True notes: Optional[str] = None class LoanSchema(LoanBase): """Full loan schema""" id: int peripheral_id: int date_retour_effectif: Optional[date] statut: str caution_rendue: bool etat_retour: Optional[str] problemes_retour: Optional[str] created_by: Optional[str] rappel_envoye: bool date_rappel: Optional[datetime] class Config: from_attributes = True # ======================================== # LOCATION SCHEMAS # ======================================== class LocationBase(BaseModel): """Base schema for locations""" nom: str = Field(..., min_length=1, max_length=255) type: str = Field(..., max_length=50) # root, piece, placard, tiroir, etagere, meuble, boite parent_id: Optional[int] = None description: Optional[str] = None ordre_affichage: Optional[int] = 0 class LocationCreate(LocationBase): """Schema for creating a location""" pass class LocationUpdate(BaseModel): """Schema for updating a location""" nom: Optional[str] = Field(None, min_length=1, max_length=255) type: Optional[str] = Field(None, max_length=50) parent_id: Optional[int] = None description: Optional[str] = None ordre_affichage: Optional[int] = None class LocationSchema(LocationBase): """Full location schema""" id: int image_path: Optional[str] qr_code_path: Optional[str] class Config: from_attributes = True class LocationTreeNode(LocationSchema): """Location with children for tree view""" children: List['LocationTreeNode'] = [] class Config: from_attributes = True # ======================================== # HISTORY SCHEMAS # ======================================== class PeripheralHistorySchema(BaseModel): """Peripheral location history schema""" id: int peripheral_id: int from_location_id: Optional[int] to_location_id: Optional[int] from_device_id: Optional[int] to_device_id: Optional[int] action: str timestamp: datetime notes: Optional[str] user: Optional[str] class Config: from_attributes = True