feat: add Fleet operations view

This commit is contained in:
lussierj committed 2026-08-11 17:37:36 +00:00
1 parent c6d01df31c
commit 786a1ab910
12 files changed
+1062 -148

No files matched your search

+89 -4
View File
@@ -43,16 +43,24 @@ class StubInventoryService:
self.history_result: list[InventoryAssetIDHistoryEntry] = []
self.history_error: Exception | None = None
self.history_miner_id: UUID | None = None
self.include_location_details = False
self.location_options = {"sites": [], "rooms": []}
def search_miners(
self,
filters: InventorySearchFilters,
*,
include_location_details: bool = False,
) -> list[InventoryMinerSummary]:
self.search_filters = filters
self.include_location_details = include_location_details
if self.search_error is not None:
raise self.search_error
return self.search_result
def list_location_filter_options(self):
return self.location_options
def create_miner(
self,
request: InventoryCreateRequest,
@@ -110,10 +118,10 @@ def miner_summary(miner_id: UUID | None = None) -> InventoryMinerSummary:
def miner_detail(miner_id: UUID | None = None) -> InventoryMinerDetail:
summary = miner_summary(miner_id)
values = miner_summary(miner_id).model_dump()
values["miner_sn"] = "MINER-001"
return InventoryMinerDetail(
**summary.model_dump(),
miner_sn="MINER-001",
**values,
control_board_sn="CB-001",
psu_serial="PSU-001",
)
@@ -410,10 +418,77 @@ class InventoryRouterTests(unittest.TestCase):
self.assertEqual(body["data"][0]["asset_id"], "ASSET-001")
self.assertEqual(
body["meta"],
{"limit": 100, "offset": 0, "returned": 1},
{"limit": 100, "offset": 0, "returned": 1,
"location_options": {"sites": [], "rooms": []}},
)
self.assertIsNone(body["error"])
def test_list_projection_and_location_permission_are_explicit(self):
miner_id = uuid4()
site_id = uuid4()
room_id = uuid4()
position_id = uuid4()
self.service.search_result = [
InventoryMinerSummary(
id=miner_id,
asset_id="FLEET-001",
model="M50",
miner_sn="SN-001",
lifecycle_status="active",
runtime_status="online",
site_id=site_id,
site_name="North Site",
room_id=room_id,
room_name="Room A",
location_position_id=position_id,
rack_label="Rack 1",
shelf_label="Shelf 2",
position_index=3,
observed_at=datetime.now(timezone.utc),
hashrate_ths=120.0,
power_w=3400.0,
chip_temp_max_c=72.0,
hash_stable=True,
created_at=datetime.now(timezone.utc),
updated_at=datetime.now(timezone.utc),
)
]
self.service.location_options = {
"sites": [{"id": site_id, "name": "North Site"}],
"rooms": [{"id": room_id, "site_id": site_id, "name": "Room A"}],
}
self.authenticate(("miners.view", "locations.view"))
response = self.client.get("/api/inventory/miners")
data = response.json()["data"][0]
self.assertEqual(response.status_code, 200)
self.assertEqual(data["miner_sn"], "SN-001")
self.assertEqual(data["location_position_id"], str(position_id))
self.assertEqual(data["hashrate_ths"], 120.0)
self.assertTrue(self.service.include_location_details)
self.assertEqual(
response.json()["meta"]["location_options"]["sites"][0]["name"],
"North Site",
)
self.authenticate(("miners.view",))
self.service.search_result = [miner_summary(miner_id)]
response = self.client.get("/api/inventory/miners")
data = response.json()["data"][0]
self.assertIsNone(data["site_id"])
self.assertIsNone(data["room_id"])
self.assertIsNone(data["location_position_id"])
self.assertEqual(response.json()["meta"]["location_options"], {"sites": [], "rooms": []})
self.assertFalse(self.service.include_location_details)
def test_location_filters_require_locations_view(self):
self.authenticate(("miners.view",))
response = self.client.get(
"/api/inventory/miners", params={"site_id": str(uuid4())}
)
self.assertEqual(response.status_code, 403)
self.assertIsNone(self.service.search_filters)
def test_empty_list_returns_successful_empty_collection(self):
self.authenticate()
@@ -432,6 +507,11 @@ class InventoryRouterTests(unittest.TestCase):
("query", "M50"),
("asset_id", "ASSET-001"),
("lifecycle_status", "spare"),
("model", "M50"),
("runtime_status", "offline"),
("repair", "active"),
("operational_state", "repair"),
("problems", "true"),
("tags", "Priority"),
("tags", "Repair"),
("limit", "25"),
@@ -445,6 +525,11 @@ class InventoryRouterTests(unittest.TestCase):
self.assertEqual(filters.query, "M50")
self.assertEqual(filters.asset_id, "ASSET-001")
self.assertEqual(filters.lifecycle_status, "spare")
self.assertEqual(filters.model, "M50")
self.assertEqual(filters.runtime_status, "offline")
self.assertEqual(filters.repair, "active")
self.assertEqual(filters.operational_state, "repair")
self.assertTrue(filters.problems)
self.assertEqual(filters.tags, ["Priority", "Repair"])
self.assertEqual(filters.limit, 25)
self.assertEqual(filters.offset, 50)