fix(inventory): envelope transfer responses and add defensive array guards in UI

This commit is contained in:
2026-09-23 22:46:07 +03:30
parent 856513b6d7
commit e560018273
4 changed files with 69 additions and 37 deletions
+12 -11
View File
@@ -74,7 +74,7 @@ def _to_transfer_out(t) -> dict:
# ---------------------------------------------------------------------------
# POST /inventory/project-transfers — Create inter-project transfer
# ---------------------------------------------------------------------------
@router.post("/inventory/project-transfers", status_code=201, response_model=ProjectTransferOut)
@router.post("/inventory/project-transfers", status_code=201)
async def create_transfer(
payload: ProjectTransferCreate,
ctx: ArrivalScope = Depends(arrivals_scope),
@@ -87,7 +87,7 @@ async def create_transfer(
caller_role=ctx.role,
transferred_by=ctx.display_name,
)
return _to_transfer_out(transfer)
return {"data": _to_transfer_out(transfer)}
# ---------------------------------------------------------------------------
@@ -108,13 +108,13 @@ async def list_transfers(
direction=direction,
status=status,
)
return [_to_transfer_out(t) for t in transfers]
return {"data": [_to_transfer_out(t) for t in transfers]}
# ---------------------------------------------------------------------------
# GET /inventory/project-transfers/{id} — Single transfer details
# ---------------------------------------------------------------------------
@router.get("/inventory/project-transfers/{transfer_id}", response_model=ProjectTransferOut)
@router.get("/inventory/project-transfers/{transfer_id}")
async def get_transfer(
transfer_id: uuid.UUID,
ctx: ArrivalScope = Depends(arrivals_scope),
@@ -124,13 +124,13 @@ async def get_transfer(
if ctx.role == "pm" and ctx.project_id is not None:
if transfer.from_project_id != ctx.project_id and transfer.to_project_id != ctx.project_id:
raise ForbiddenError("شما به این رکورد انتقال دسترسی ندارید")
return _to_transfer_out(transfer)
return {"data": _to_transfer_out(transfer)}
# ---------------------------------------------------------------------------
# PATCH /inventory/project-transfers/{id} — Edit in-transit transfer (source PM only)
# ---------------------------------------------------------------------------
@router.patch("/inventory/project-transfers/{transfer_id}", response_model=ProjectTransferOut)
@router.patch("/inventory/project-transfers/{transfer_id}")
async def update_transfer(
transfer_id: uuid.UUID,
payload: ProjectTransferUpdate,
@@ -144,7 +144,7 @@ async def update_transfer(
caller_project_id=ctx.project_id,
caller_role=ctx.role,
)
return _to_transfer_out(transfer)
return {"data": _to_transfer_out(transfer)}
# ---------------------------------------------------------------------------
@@ -156,12 +156,13 @@ async def delete_transfer(
ctx: ArrivalScope = Depends(arrivals_scope),
db: AsyncSession = Depends(get_db),
):
return await project_transfer_service.delete_project_transfer(
res = await project_transfer_service.delete_project_transfer(
db=db,
transfer_id=transfer_id,
caller_project_id=ctx.project_id,
caller_role=ctx.role,
)
return {"data": res}
# ---------------------------------------------------------------------------
@@ -181,13 +182,13 @@ async def pm_incoming_transfers(
direction="incoming",
status="in_transit",
)
return [_to_transfer_out(t) for t in transfers]
return {"data": [_to_transfer_out(t) for t in transfers]}
# ---------------------------------------------------------------------------
# POST /inventory/project-transfers/{id}/receive — Destination PM confirms arrival
# ---------------------------------------------------------------------------
@router.post("/inventory/project-transfers/{transfer_id}/receive", response_model=ProjectTransferOut)
@router.post("/inventory/project-transfers/{transfer_id}/receive")
async def receive_transfer(
transfer_id: uuid.UUID,
payload: ProjectTransferReceive,
@@ -202,4 +203,4 @@ async def receive_transfer(
caller_role=ctx.role,
received_by=ctx.display_name,
)
return _to_transfer_out(transfer)
return {"data": _to_transfer_out(transfer)}