from pydantic import BaseModel, Field from typing import Optional, List from enum import Enum class BoardType(str, Enum): vs = "vs" # Vesper vp = "vp" # Vesper Plus vx = "vx" # Vesper Pro cb = "cb" # Chronos cp = "cp" # Chronos Pro am = "am" # Agnus Mini ab = "ab" # Agnus BOARD_TYPE_LABELS = { "vs": "Vesper", "vp": "Vesper Plus", "vx": "Vesper Pro", "cb": "Chronos", "cp": "Chronos Pro", "am": "Agnus Mini", "ab": "Agnus", } 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]