# app/modules/loyalty/schemas/terminal_device.py """Pydantic schemas for terminal device pairing & management.""" from datetime import datetime from pydantic import BaseModel, ConfigDict, Field class TerminalDeviceCreate(BaseModel): """Pair a new terminal device. Issues a long-lived JWT shown once.""" store_id: int = Field(..., gt=0, description="Store the device is bound to") label: str = Field( ..., min_length=1, max_length=100, description="Merchant-facing name e.g. 'Counter 1'", ) class TerminalDeviceUpdate(BaseModel): """Update a paired device's label. Token is not affected.""" model_config = ConfigDict(from_attributes=True) label: str | None = Field(None, min_length=1, max_length=100) class TerminalDeviceRevoke(BaseModel): """Revoke a device's token, optionally with a reason for the audit log.""" reason: str | None = Field(None, max_length=255) class TerminalDeviceResponse(BaseModel): """Read view of a paired device. Never includes the JWT.""" model_config = ConfigDict(from_attributes=True) id: int merchant_id: int store_id: int store_name: str | None = None label: str status: str # active | revoked | expired expires_at: datetime last_seen_at: datetime | None = None last_seen_ip: str | None = None revoked_at: datetime | None = None revoked_by_id: int | None = None revoked_reason: str | None = None created_by_id: int | None = None created_at: datetime class TerminalDevicePairingResponse(TerminalDeviceResponse): """Returned by POST only. Carries the one-time setup token + QR PNG.""" setup_token: str = Field(..., description="The signed JWT — shown once") setup_payload: dict = Field( ..., description="Decoded {api_url, store_code, auth_token} payload encoded in the QR", ) qr_png_base64: str = Field( ..., description="Base64-encoded PNG of the setup QR (data:image/png;base64,...)", ) class TerminalDeviceListResponse(BaseModel): devices: list[TerminalDeviceResponse] total: int