from pydantic import BaseModel, Field from typing import Optional, List from enum import Enum class BoardType(str, Enum): vesper = "vesper" vesper_plus = "vesper_plus" vesper_pro = "vesper_pro" chronos = "chronos" chronos_pro = "chronos_pro" agnus_mini = "agnus_mini" agnus = "agnus" BOARD_TYPE_LABELS = { "vesper": "Vesper", "vesper_plus": "Vesper Plus", "vesper_pro": "Vesper Pro", "chronos": "Chronos", "chronos_pro": "Chronos Pro", "agnus_mini": "Agnus Mini", "agnus": "Agnus", } # Family codes (BS + 4 chars = segment 1 of serial number) BOARD_FAMILY_CODES = { "vesper": "VSPR", "vesper_plus": "VSPR", "vesper_pro": "VSPR", "agnus": "AGNS", "agnus_mini": "AGNS", "chronos": "CRNS", "chronos_pro": "CRNS", } # Variant codes (3 chars = first part of segment 3 of serial number) BOARD_VARIANT_CODES = { "vesper": "STD", "vesper_plus": "PLS", "vesper_pro": "PRO", "agnus": "STD", "agnus_mini": "MIN", "chronos": "STD", "chronos_pro": "PRO", } class MfgStatus(str, Enum): manufactured = "manufactured" flashed = "flashed" provisioned = "provisioned" sold = "sold" claimed = "claimed" decommissioned = "decommissioned" class BatchCreate(BaseModel): board_type: BoardType board_version: str = Field( ..., pattern=r"^\d+(\.\d+)*$", description="SemVer-style version string, e.g. '1.0' or legacy '01'", ) quantity: int = Field(..., ge=1, le=100) class BatchResponse(BaseModel): batch_id: str serial_numbers: List[str] board_type: str board_version: str created_at: str class DeviceInventoryItem(BaseModel): id: str serial_number: str hw_type: str hw_version: str mfg_status: str mfg_batch_id: Optional[str] = None created_at: Optional[str] = None owner: Optional[str] = None assigned_to: Optional[str] = None device_name: Optional[str] = None class DeviceInventoryListResponse(BaseModel): devices: List[DeviceInventoryItem] total: int class DeviceStatusUpdate(BaseModel): status: MfgStatus note: Optional[str] = None class DeviceAssign(BaseModel): customer_email: str customer_name: Optional[str] = None class RecentActivityItem(BaseModel): serial_number: str hw_type: str mfg_status: str owner: Optional[str] = None updated_at: Optional[str] = None class ManufacturingStats(BaseModel): counts: dict recent_activity: List[RecentActivityItem]