dev #1
@@ -252,6 +252,40 @@ class BindingDAO(BaseDAO):
|
|||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def list_by_user(self, user_id: int, limit: int = 20, cursor: int = None) -> list[Mapping]:
|
||||||
|
params = {"user_id": user_id, "limit": limit + 1}
|
||||||
|
where = "db.owner_user_id = :user_id AND db.status = 1"
|
||||||
|
if cursor is not None:
|
||||||
|
where += " AND db.id < :cursor"
|
||||||
|
params["cursor"] = cursor
|
||||||
|
|
||||||
|
rows = (
|
||||||
|
self.db.execute(
|
||||||
|
text(
|
||||||
|
f"""
|
||||||
|
SELECT
|
||||||
|
db.id,
|
||||||
|
db.device_id,
|
||||||
|
db.child_id,
|
||||||
|
c.child_name,
|
||||||
|
db.status,
|
||||||
|
db.bound_at
|
||||||
|
FROM device_bindings AS db
|
||||||
|
LEFT JOIN children AS c
|
||||||
|
ON c.child_id = db.child_id
|
||||||
|
AND c.status = 1
|
||||||
|
WHERE {where}
|
||||||
|
ORDER BY db.id DESC
|
||||||
|
LIMIT :limit
|
||||||
|
"""
|
||||||
|
),
|
||||||
|
params,
|
||||||
|
)
|
||||||
|
.mappings()
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
return rows
|
||||||
|
|
||||||
def get_by_device(self, device_id: str, user_id: int) -> Optional[Mapping]:
|
def get_by_device(self, device_id: str, user_id: int) -> Optional[Mapping]:
|
||||||
return (
|
return (
|
||||||
self.db.execute(
|
self.db.execute(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
from fastapi import APIRouter, Depends, HTTPException, Query, Request, status
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -45,6 +45,20 @@ class BindingGetResponse(BaseModel):
|
|||||||
bound_at: datetime
|
bound_at: datetime
|
||||||
|
|
||||||
|
|
||||||
|
class BindingListItem(BaseModel):
|
||||||
|
device_id: str
|
||||||
|
child_id: int | None
|
||||||
|
child_name: str | None = None
|
||||||
|
status: int
|
||||||
|
bound_at: datetime
|
||||||
|
|
||||||
|
|
||||||
|
class BindingListResponse(BaseModel):
|
||||||
|
items: list[BindingListItem]
|
||||||
|
total: int
|
||||||
|
next_cursor: int | None = None
|
||||||
|
|
||||||
|
|
||||||
class BindHistoryItem(BaseModel):
|
class BindHistoryItem(BaseModel):
|
||||||
device_id: str
|
device_id: str
|
||||||
child_id: int | None
|
child_id: int | None
|
||||||
@@ -140,6 +154,30 @@ def get_current_binding(
|
|||||||
return binding
|
return binding
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("", response_model=BindingListResponse)
|
||||||
|
def list_bindings(
|
||||||
|
request: Request,
|
||||||
|
cursor: int | None = Query(default=None, ge=1),
|
||||||
|
limit: int = Query(default=20, ge=1, le=100),
|
||||||
|
current_user_id: int = Depends(get_current_user_id),
|
||||||
|
db=Depends(get_db_session),
|
||||||
|
) -> BindingListResponse:
|
||||||
|
service = BindingService(db)
|
||||||
|
rows, has_more = service.list_bindings(current_user_id, limit, cursor)
|
||||||
|
next_cursor = int(rows[-1]["id"]) if has_more and rows else None
|
||||||
|
items = [
|
||||||
|
BindingListItem(
|
||||||
|
device_id=row["device_id"],
|
||||||
|
child_id=row["child_id"],
|
||||||
|
child_name=row["child_name"],
|
||||||
|
status=row["status"],
|
||||||
|
bound_at=row["bound_at"],
|
||||||
|
)
|
||||||
|
for row in rows
|
||||||
|
]
|
||||||
|
return BindingListResponse(items=items, total=len(items), next_cursor=next_cursor)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{device_id}", response_model=BindingGetResponse)
|
@router.get("/{device_id}", response_model=BindingGetResponse)
|
||||||
def get_binding(
|
def get_binding(
|
||||||
device_id: str,
|
device_id: str,
|
||||||
|
|||||||
@@ -31,6 +31,12 @@ class BindingService:
|
|||||||
def get_current_binding(self, user_id: int) -> Optional[Mapping]:
|
def get_current_binding(self, user_id: int) -> Optional[Mapping]:
|
||||||
return self.dao.get_current_by_user(user_id)
|
return self.dao.get_current_by_user(user_id)
|
||||||
|
|
||||||
|
def list_bindings(self, user_id: int, limit: int = 20, cursor: int = None) -> tuple[list, bool]:
|
||||||
|
rows = self.dao.list_by_user(user_id, limit, cursor)
|
||||||
|
has_more = len(rows) > limit
|
||||||
|
rows = rows[:limit]
|
||||||
|
return rows, has_more
|
||||||
|
|
||||||
def direct_bind(self, device_id: str, child_id: int | None, user_id: int) -> Mapping:
|
def direct_bind(self, device_id: str, child_id: int | None, user_id: int) -> Mapping:
|
||||||
self.dao.direct_bind(device_id, child_id, user_id)
|
self.dao.direct_bind(device_id, child_id, user_id)
|
||||||
return {"device_id": device_id, "child_id": child_id}
|
return {"device_id": device_id, "child_id": child_id}
|
||||||
|
|||||||
Reference in New Issue
Block a user