Files
minerops/backend/app/inventory/models.py
T

129 lines
4.0 KiB
Python

"""Pydantic contracts for the inventory domain."""
from datetime import datetime
from typing import Literal
from uuid import UUID
from pydantic import BaseModel, ConfigDict, Field, IPvAnyAddress
LifecycleStatus = Literal["active", "spare", "retired"]
class InventoryTag(BaseModel):
id: UUID
name: str
created_at: datetime
updated_at: datetime
class InventoryMinerSummary(BaseModel):
id: UUID
asset_id: str | None = None
current_mac: str | None = None
current_ip: str | None = None
model: str | None = None
lifecycle_status: LifecycleStatus
runtime_status: str
site_id: UUID | None = None
room_id: UUID | None = None
tags: list[InventoryTag] = Field(default_factory=list)
created_at: datetime
updated_at: datetime
last_seen_at: datetime | None = None
class InventoryMinerDetail(InventoryMinerSummary):
hostname: str | None = None
miner_sn: str | None = None
control_board_sn: str | None = None
psu_serial: str | None = None
firmware_version: str | None = None
notes: str | None = None
first_seen_at: datetime | None = None
class InventoryAssetIDHistoryEntry(BaseModel):
old_asset_id: str | None = None
new_asset_id: str
changed_at: datetime
changed_by: UUID
changed_by_display_name: str
class InventoryCreateRequest(BaseModel):
asset_id: str = Field(min_length=1, max_length=120)
current_mac: str | None = Field(default=None, max_length=64)
current_ip: IPvAnyAddress | None = None
hostname: str | None = Field(default=None, max_length=255)
miner_sn: str | None = Field(default=None, max_length=255)
control_board_sn: str | None = Field(default=None, max_length=255)
psu_serial: str | None = Field(default=None, max_length=255)
model: str | None = Field(default=None, max_length=255)
firmware_version: str | None = Field(default=None, max_length=255)
lifecycle_status: str = "active"
site_id: UUID | None = None
room_id: UUID | None = None
notes: str | None = None
tags: list[str] = Field(default_factory=list)
class InventoryMetadataUpdateRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
asset_id: str | None = Field(default=None, max_length=120)
miner_sn: str | None = Field(default=None, max_length=255)
psu_serial: str | None = Field(default=None, max_length=255)
model: str | None = Field(default=None, max_length=255)
notes: str | None = None
class InventoryUpdateRequest(BaseModel):
asset_id: str | None = Field(default=None, max_length=120)
current_mac: str | None = Field(default=None, max_length=64)
current_ip: IPvAnyAddress | None = None
hostname: str | None = Field(default=None, max_length=255)
miner_sn: str | None = Field(default=None, max_length=255)
control_board_sn: str | None = Field(default=None, max_length=255)
psu_serial: str | None = Field(default=None, max_length=255)
model: str | None = Field(default=None, max_length=255)
firmware_version: str | None = Field(default=None, max_length=255)
lifecycle_status: str | None = None
site_id: UUID | None = None
room_id: UUID | None = None
notes: str | None = None
tags: list[str] | None = None
class InventorySearchFilters(BaseModel):
query: str | None = None
asset_id: str | None = None
lifecycle_status: str | None = None
tags: list[str] = Field(default_factory=list)
limit: int = Field(default=100, ge=1, le=500)
offset: int = Field(default=0, ge=0)
class InventoryListMeta(BaseModel):
limit: int
offset: int
returned: int
class InventoryMinerListResponse(BaseModel):
data: list[InventoryMinerSummary]
meta: InventoryListMeta
error: None = None
class InventoryMinerDetailResponse(BaseModel):
data: InventoryMinerDetail
meta: dict[str, object] = Field(default_factory=dict)
error: None = None
class InventoryAssetIDHistoryResponse(BaseModel):
data: list[InventoryAssetIDHistoryEntry]
meta: dict[str, object] = Field(default_factory=dict)
error: None = None