feat: add discoverable rig catalog

This commit is contained in:
ik
2026-09-21 19:43:17 +07:00
parent 5c1a7ffa01
commit b4585cee7e
5 changed files with 58 additions and 8 deletions
+28 -4
View File
@@ -6,7 +6,7 @@ from sqlalchemy.orm import selectinload
from ..dependencies import Db
from ..models import Bait, CatchReport, Fish, ModerationStatus, Rig, Spot, TackleItem, Waterbody
from ..schemas import BaitOut, FishOut, PaginatedTackleItemOut, RigOut, TackleItemOut, WaterbodyOut
from ..schemas import BaitOut, FishOut, PaginatedRigOut, PaginatedTackleItemOut, RigOut, RigSummaryOut, TackleItemOut, WaterbodyOut
router = APIRouter()
@@ -34,6 +34,12 @@ def _item_missing_fields(item: TackleItem) -> list[str]:
) if value is None]
def _rig_missing_fields(rig: Rig) -> list[str]:
return [field for field, value in (
("source_url", rig.source_url), ("source_checked_at", rig.source_checked_at),
) if value is None]
@router.get("/api/v1/tackle/items", response_model=PaginatedTackleItemOut)
def tackle_items(
db: Db,
@@ -69,14 +75,32 @@ def tackle_item(item_id: UUID, db: Db) -> TackleItemOut:
return TackleItemOut.model_validate(item).model_copy(update={"missing_fields": _item_missing_fields(item)})
@router.get("/api/v1/tackle/rigs", response_model=PaginatedRigOut)
def tackle_rigs(
db: Db,
limit: int = Query(48, ge=1, le=100),
offset: int = Query(0, ge=0),
) -> PaginatedRigOut:
query = select(Rig).options(selectinload(Rig.components))
total = db.scalar(select(func.count(Rig.id))) or 0
rigs = list(db.scalars(query.order_by(Rig.name, Rig.id).offset(offset).limit(limit)))
return PaginatedRigOut(
items=[RigSummaryOut(
id=rig.id, name=rig.name, source_system=rig.source_system,
source_external_id=rig.source_external_id, source_url=rig.source_url,
source_checked_at=rig.source_checked_at, missing_fields=_rig_missing_fields(rig),
component_count=len(rig.components),
) for rig in rigs],
total=total, limit=limit, offset=offset,
)
@router.get("/api/v1/tackle/rigs/{rig_id}", response_model=RigOut)
def rig_detail(rig_id: UUID, db: Db) -> RigOut:
rig = db.scalar(select(Rig).options(selectinload(Rig.components)).where(Rig.id == rig_id))
if rig is None:
raise HTTPException(status_code=404, detail="rig not found")
missing = [field for field, value in (
("source_url", rig.source_url), ("source_checked_at", rig.source_checked_at),
) if value is None]
missing = _rig_missing_fields(rig)
return RigOut(
id=rig.id, name=rig.name, source_system=rig.source_system,
source_external_id=rig.source_external_id, source_url=rig.source_url,
+18
View File
@@ -63,6 +63,24 @@ class PaginatedTackleItemOut(BaseModel):
offset: int
class RigSummaryOut(BaseModel):
id: UUID
name: str
source_system: str | None
source_external_id: str | None
source_url: str | None
source_checked_at: datetime | None
missing_fields: list[str] = Field(default_factory=list)
component_count: int
class PaginatedRigOut(BaseModel):
items: list[RigSummaryOut]
total: int
limit: int
offset: int
class RigComponentOut(BaseModel):
id: UUID
role: str