import uuid from fastapi import APIRouter, status from app.api.deps import CurrentUser, SessionDep from app.schemas.person import PersonCreate, PersonRead from app.services import person_service, tree_service # Persons are nested under their tree (the tenant boundary). router = APIRouter(prefix="/trees", tags=["persons"]) @router.post( "/{tree_id}/persons", response_model=PersonRead, status_code=status.HTTP_201_CREATED, ) async def create_person( tree_id: uuid.UUID, data: PersonCreate, session: SessionDep, current: CurrentUser ) -> PersonRead: # get_tree enforces existence + view access; create_person enforces edit rights. tree = await tree_service.get_tree(session, viewer_id=current.id, tree_id=tree_id) person = await person_service.create_person( session, actor=current, tree=tree, given=data.given, surname=data.surname, gender=data.gender, is_living=data.is_living, privacy_setting=data.privacy, notes=data.notes, ) return PersonRead.model_validate(person) @router.get("/{tree_id}/persons", response_model=list[PersonRead]) async def list_persons( tree_id: uuid.UUID, session: SessionDep, current: CurrentUser, deleted: bool = False ) -> list[PersonRead]: tree = await tree_service.get_tree(session, viewer_id=current.id, tree_id=tree_id) if deleted: persons = await person_service.list_deleted_persons( session, viewer_id=current.id, tree=tree ) else: persons = await person_service.list_persons(session, viewer_id=current.id, tree=tree) return [PersonRead.model_validate(p) for p in persons] @router.delete("/{tree_id}/persons/{person_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_person( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, current: CurrentUser ) -> None: tree = await tree_service.get_tree(session, viewer_id=current.id, tree_id=tree_id) await person_service.delete_person(session, actor=current, tree=tree, person_id=person_id) @router.post("/{tree_id}/persons/{person_id}/restore", response_model=PersonRead) async def restore_person( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, current: CurrentUser ) -> PersonRead: tree = await tree_service.get_tree(session, viewer_id=current.id, tree_id=tree_id) person = await person_service.restore_person( session, actor=current, tree=tree, person_id=person_id ) return PersonRead.model_validate(person) @router.get("/{tree_id}/persons/{person_id}", response_model=PersonRead) async def get_person( tree_id: uuid.UUID, person_id: uuid.UUID, session: SessionDep, current: CurrentUser ) -> PersonRead: tree = await tree_service.get_tree(session, viewer_id=current.id, tree_id=tree_id) person = await person_service.get_person( session, viewer_id=current.id, tree=tree, person_id=person_id ) return PersonRead.model_validate(person)