feat: 支持先绑定设备后关联儿童档案
- 绑定模型新增 owner_user_id,支持 child_id 为空\n- 新增绑定后设置儿童接口 /bindings/{device_id}/child\n- 前端绑定页改为先绑设备后补充儿童\n- 补充数据库迁移脚本与 DAO 测试用例
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, status
|
||||
from pydantic import BaseModel
|
||||
@@ -19,7 +20,7 @@ logger = logging.getLogger("app.bindings")
|
||||
|
||||
class BindStartRequest(BaseModel):
|
||||
device_id: str
|
||||
child_id: int
|
||||
child_id: int | None = None
|
||||
|
||||
|
||||
class BindStartResponse(BaseModel):
|
||||
@@ -34,21 +35,21 @@ class BindConfirmRequest(BaseModel):
|
||||
|
||||
class BindConfirmResponse(BaseModel):
|
||||
device_id: str
|
||||
child_id: int
|
||||
child_id: int | None
|
||||
|
||||
|
||||
class BindingGetResponse(BaseModel):
|
||||
device_id: str
|
||||
child_id: int
|
||||
child_id: int | None
|
||||
status: int
|
||||
bound_at: str
|
||||
bound_at: datetime
|
||||
|
||||
|
||||
class BindHistoryItem(BaseModel):
|
||||
device_id: str
|
||||
child_id: int
|
||||
bound_at: str
|
||||
unbound_at: str | None
|
||||
child_id: int | None
|
||||
bound_at: datetime
|
||||
unbound_at: datetime | None
|
||||
|
||||
|
||||
class BindHistoryResponse(BaseModel):
|
||||
@@ -86,11 +87,15 @@ def confirm_bind(
|
||||
|
||||
class DirectBindRequest(BaseModel):
|
||||
device_id: str
|
||||
child_id: int
|
||||
child_id: int | None = None
|
||||
|
||||
|
||||
class DirectBindResponse(BaseModel):
|
||||
device_id: str
|
||||
child_id: int | None
|
||||
|
||||
|
||||
class BindSetChildRequest(BaseModel):
|
||||
child_id: int
|
||||
|
||||
|
||||
@@ -106,6 +111,22 @@ def direct_bind(
|
||||
return DirectBindResponse(**result)
|
||||
|
||||
|
||||
@router.patch("/{device_id}/child", response_model=DirectBindResponse)
|
||||
def set_binding_child(
|
||||
device_id: str,
|
||||
payload: BindSetChildRequest,
|
||||
request: Request,
|
||||
current_user_id: int = Depends(get_current_user_id),
|
||||
db=Depends(get_db_session),
|
||||
) -> DirectBindResponse:
|
||||
service = BindingService(db)
|
||||
try:
|
||||
result = service.set_binding_child(device_id=device_id, child_id=payload.child_id, user_id=current_user_id)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
return DirectBindResponse(**result)
|
||||
|
||||
|
||||
@router.get("/current", response_model=BindingGetResponse)
|
||||
def get_current_binding(
|
||||
request: Request,
|
||||
@@ -154,11 +175,9 @@ def get_bind_history(
|
||||
current_user_id: int = Depends(get_current_user_id),
|
||||
db=Depends(get_db_session),
|
||||
) -> BindHistoryResponse:
|
||||
from datetime import datetime
|
||||
|
||||
cursor_dt = datetime.fromisoformat(cursor) if cursor else None
|
||||
service = BindingService(db)
|
||||
rows, has_more = service.list_history(device_id, limit, cursor_dt)
|
||||
next_cursor = rows[-1]["bound_at"].isoformat() if has_more and rows else None
|
||||
items = [BindHistoryItem(**row) for row in rows]
|
||||
return BindHistoryResponse(items=items, total=len(items), next_cursor=next_cursor)
|
||||
return BindHistoryResponse(items=items, total=len(items), next_cursor=next_cursor)
|
||||
|
||||
Reference in New Issue
Block a user