update: overhauled firmware ui. Added public flash page.
This commit is contained in:
@@ -52,10 +52,11 @@ def _generate_serial_number() -> str:
|
||||
def _ensure_unique_serial(db) -> str:
|
||||
"""Generate a serial number and verify it doesn't already exist in Firestore."""
|
||||
existing_sns = set()
|
||||
for doc in db.collection(COLLECTION).select(["device_id"]).stream():
|
||||
for doc in db.collection(COLLECTION).select(["serial_number"]).stream():
|
||||
data = doc.to_dict()
|
||||
if data.get("device_id"):
|
||||
existing_sns.add(data["device_id"])
|
||||
sn = data.get("serial_number") or data.get("device_id")
|
||||
if sn:
|
||||
existing_sns.add(sn)
|
||||
|
||||
for _ in range(100): # safety limit
|
||||
sn = _generate_serial_number()
|
||||
@@ -95,18 +96,40 @@ def _sanitize_dict(d: dict) -> dict:
|
||||
return result
|
||||
|
||||
|
||||
def _auto_upgrade_claimed(doc_ref, data: dict) -> dict:
|
||||
"""If the device has entries in user_list and isn't already claimed/decommissioned,
|
||||
upgrade mfg_status to 'claimed' automatically and return the updated data dict."""
|
||||
current_status = data.get("mfg_status", "")
|
||||
if current_status in ("claimed", "decommissioned"):
|
||||
return data
|
||||
user_list = data.get("user_list", []) or []
|
||||
if user_list:
|
||||
doc_ref.update({"mfg_status": "claimed"})
|
||||
data = dict(data)
|
||||
data["mfg_status"] = "claimed"
|
||||
return data
|
||||
|
||||
|
||||
def _doc_to_device(doc) -> DeviceInDB:
|
||||
"""Convert a Firestore document snapshot to a DeviceInDB model."""
|
||||
data = _sanitize_dict(doc.to_dict())
|
||||
"""Convert a Firestore document snapshot to a DeviceInDB model.
|
||||
|
||||
Also auto-upgrades mfg_status to 'claimed' if user_list is non-empty.
|
||||
"""
|
||||
raw = doc.to_dict()
|
||||
raw = _auto_upgrade_claimed(doc.reference, raw)
|
||||
data = _sanitize_dict(raw)
|
||||
return DeviceInDB(id=doc.id, **data)
|
||||
|
||||
|
||||
FLEET_STATUSES = {"sold", "claimed"}
|
||||
|
||||
|
||||
def list_devices(
|
||||
search: str | None = None,
|
||||
online_only: bool | None = None,
|
||||
subscription_tier: str | None = None,
|
||||
) -> list[DeviceInDB]:
|
||||
"""List devices with optional filters."""
|
||||
"""List fleet devices (sold + claimed only) with optional filters."""
|
||||
db = get_db()
|
||||
ref = db.collection(COLLECTION)
|
||||
query = ref
|
||||
@@ -118,6 +141,14 @@ def list_devices(
|
||||
results = []
|
||||
|
||||
for doc in docs:
|
||||
raw = doc.to_dict() or {}
|
||||
|
||||
# Only include sold/claimed devices in the fleet view.
|
||||
# Legacy devices without mfg_status are included to avoid breaking old data.
|
||||
mfg_status = raw.get("mfg_status")
|
||||
if mfg_status and mfg_status not in FLEET_STATUSES:
|
||||
continue
|
||||
|
||||
device = _doc_to_device(doc)
|
||||
|
||||
# Client-side filters
|
||||
@@ -128,7 +159,7 @@ def list_devices(
|
||||
search_lower = search.lower()
|
||||
name_match = search_lower in (device.device_name or "").lower()
|
||||
location_match = search_lower in (device.device_location or "").lower()
|
||||
sn_match = search_lower in (device.device_id or "").lower()
|
||||
sn_match = search_lower in (device.serial_number or "").lower()
|
||||
if not (name_match or location_match or sn_match):
|
||||
continue
|
||||
|
||||
|
||||
Reference in New Issue
Block a user