feat(children): support soft delete child profiles
This commit is contained in:
@@ -88,3 +88,9 @@ export async function updateChild(
|
|||||||
data,
|
data,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteChild(childId: number): Promise<void> {
|
||||||
|
return request<void>(`/banban/children/${childId}`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,11 +42,29 @@ class ChildDAO(BaseDAO):
|
|||||||
async def get_by_id(self, child_id: int) -> Optional[Mapping]:
|
async def get_by_id(self, child_id: int) -> Optional[Mapping]:
|
||||||
return (
|
return (
|
||||||
await self.execute(
|
await self.execute(
|
||||||
"SELECT * FROM children WHERE child_id = :child_id",
|
"SELECT * FROM children WHERE child_id = :child_id AND status = 1",
|
||||||
{"child_id": child_id},
|
{"child_id": child_id},
|
||||||
)
|
)
|
||||||
).mappings().first()
|
).mappings().first()
|
||||||
|
|
||||||
|
async def get_by_parent(self, child_id: int, user_id: int) -> Optional[Mapping]:
|
||||||
|
return (
|
||||||
|
await self.execute(
|
||||||
|
"""
|
||||||
|
SELECT c.*
|
||||||
|
FROM children AS c
|
||||||
|
JOIN parent_child_relations AS pcr
|
||||||
|
ON pcr.child_id = c.child_id
|
||||||
|
WHERE c.child_id = :child_id
|
||||||
|
AND pcr.user_id = :user_id
|
||||||
|
AND c.status = 1
|
||||||
|
AND pcr.status = 1
|
||||||
|
LIMIT 1
|
||||||
|
""",
|
||||||
|
{"child_id": child_id, "user_id": user_id},
|
||||||
|
)
|
||||||
|
).mappings().first()
|
||||||
|
|
||||||
async def list_by_parent(self, user_id: int, limit: int = 20, cursor: int = None) -> list[Mapping]:
|
async def list_by_parent(self, user_id: int, limit: int = 20, cursor: int = None) -> list[Mapping]:
|
||||||
params = {"user_id": user_id, "limit": limit + 1}
|
params = {"user_id": user_id, "limit": limit + 1}
|
||||||
where = "pcr.user_id = :user_id AND pcr.status = 1 AND c.status = 1"
|
where = "pcr.user_id = :user_id AND pcr.status = 1 AND c.status = 1"
|
||||||
@@ -104,3 +122,41 @@ class ChildDAO(BaseDAO):
|
|||||||
{"child_id": child_id, "user_id": user_id},
|
{"child_id": child_id, "user_id": user_id},
|
||||||
)
|
)
|
||||||
return result.scalar_one_or_none() is not None
|
return result.scalar_one_or_none() is not None
|
||||||
|
|
||||||
|
async def soft_delete_for_parent(self, child_id: int, user_id: int) -> bool:
|
||||||
|
if not await self.has_access(child_id, user_id):
|
||||||
|
return False
|
||||||
|
|
||||||
|
await self.execute(
|
||||||
|
"""
|
||||||
|
UPDATE children
|
||||||
|
SET status = 0,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE child_id = :child_id
|
||||||
|
AND status = 1
|
||||||
|
""",
|
||||||
|
{"child_id": child_id},
|
||||||
|
)
|
||||||
|
await self.execute(
|
||||||
|
"""
|
||||||
|
UPDATE parent_child_relations
|
||||||
|
SET status = 0,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE child_id = :child_id
|
||||||
|
AND user_id = :user_id
|
||||||
|
AND status = 1
|
||||||
|
""",
|
||||||
|
{"child_id": child_id, "user_id": user_id},
|
||||||
|
)
|
||||||
|
await self.execute(
|
||||||
|
"""
|
||||||
|
UPDATE device_bindings
|
||||||
|
SET child_id = NULL,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE child_id = :child_id
|
||||||
|
AND owner_user_id = :user_id
|
||||||
|
AND status = 1
|
||||||
|
""",
|
||||||
|
{"child_id": child_id, "user_id": user_id},
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|||||||
@@ -72,8 +72,9 @@ async def get_child(
|
|||||||
request: Request,
|
request: Request,
|
||||||
current_user_id: int = Depends(get_current_user_id),
|
current_user_id: int = Depends(get_current_user_id),
|
||||||
) -> ChildResponse:
|
) -> ChildResponse:
|
||||||
|
del request
|
||||||
service = ChildService()
|
service = ChildService()
|
||||||
child = await service.get(child_id)
|
child = await service.get(child_id, current_user_id)
|
||||||
if not child:
|
if not child:
|
||||||
raise HTTPException(status_code=404, detail="child not found")
|
raise HTTPException(status_code=404, detail="child not found")
|
||||||
return ChildResponse(**child)
|
return ChildResponse(**child)
|
||||||
@@ -94,3 +95,16 @@ async def update_child(
|
|||||||
if not child:
|
if not child:
|
||||||
raise HTTPException(status_code=404, detail="child not found")
|
raise HTTPException(status_code=404, detail="child not found")
|
||||||
return ChildResponse(**child)
|
return ChildResponse(**child)
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/{child_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
async def delete_child(
|
||||||
|
child_id: int,
|
||||||
|
request: Request,
|
||||||
|
current_user_id: int = Depends(get_current_user_id),
|
||||||
|
) -> None:
|
||||||
|
del request
|
||||||
|
service = ChildService()
|
||||||
|
deleted = await service.delete(child_id, current_user_id)
|
||||||
|
if not deleted:
|
||||||
|
raise HTTPException(status_code=404, detail="child not found")
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ class ChildService(DatabaseServiceBase):
|
|||||||
finally:
|
finally:
|
||||||
await db_session.close()
|
await db_session.close()
|
||||||
|
|
||||||
async def get(self, child_id: int) -> Optional[Mapping]:
|
async def get(self, child_id: int, user_id: int) -> Optional[Mapping]:
|
||||||
db_session = await self.get_session()
|
db_session = await self.get_session()
|
||||||
try:
|
try:
|
||||||
dao = ChildDAO(db_session)
|
dao = ChildDAO(db_session)
|
||||||
return await dao.get_by_id(child_id)
|
return await dao.get_by_parent(child_id, user_id)
|
||||||
finally:
|
finally:
|
||||||
await db_session.close()
|
await db_session.close()
|
||||||
|
|
||||||
@@ -75,6 +75,21 @@ class ChildService(DatabaseServiceBase):
|
|||||||
raise PermissionError("No access to this child")
|
raise PermissionError("No access to this child")
|
||||||
await dao.update(child_id, child_name, child_gender, child_birthday)
|
await dao.update(child_id, child_name, child_gender, child_birthday)
|
||||||
await db_session.commit()
|
await db_session.commit()
|
||||||
return await self.get(child_id)
|
return await self.get(child_id, user_id)
|
||||||
|
finally:
|
||||||
|
await db_session.close()
|
||||||
|
|
||||||
|
async def delete(self, child_id: int, user_id: int) -> bool:
|
||||||
|
db_session = await self.get_session()
|
||||||
|
try:
|
||||||
|
dao = ChildDAO(db_session)
|
||||||
|
deleted = await dao.soft_delete_for_parent(child_id, user_id)
|
||||||
|
if not deleted:
|
||||||
|
return False
|
||||||
|
await db_session.commit()
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
await db_session.rollback()
|
||||||
|
raise
|
||||||
finally:
|
finally:
|
||||||
await db_session.close()
|
await db_session.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user