feat: add PATCH /projects/{id} for partial updates
- Added PATCH endpoint for projects (supports name and/or description)
- Added test_patch_project test case
- Verify folder_id already supported in POST /api/v1/projects/{project_id}/documents
This commit is contained in:
@@ -96,6 +96,36 @@ async def update_project(
|
|||||||
return ProjectResponse.model_validate(project)
|
return ProjectResponse.model_validate(project)
|
||||||
|
|
||||||
|
|
||||||
|
@router.patch("/{project_id}", response_model=ProjectResponse)
|
||||||
|
async def patch_project(
|
||||||
|
request: Request,
|
||||||
|
project_id: str,
|
||||||
|
payload: ProjectUpdate,
|
||||||
|
db: AsyncSession = Depends(get_db),
|
||||||
|
):
|
||||||
|
"""Partial update of project name and/or description."""
|
||||||
|
agent = await get_current_agent(request, db)
|
||||||
|
result = await db.execute(
|
||||||
|
select(Project).where(
|
||||||
|
Project.id == project_id,
|
||||||
|
Project.agent_id == agent.id,
|
||||||
|
Project.is_deleted == False,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
project = result.scalar_one_or_none()
|
||||||
|
if not project:
|
||||||
|
raise HTTPException(status_code=404, detail="Project not found")
|
||||||
|
|
||||||
|
if payload.name is not None:
|
||||||
|
project.name = payload.name
|
||||||
|
if payload.description is not None:
|
||||||
|
project.description = payload.description
|
||||||
|
project.updated_at = datetime.utcnow()
|
||||||
|
|
||||||
|
await db.flush()
|
||||||
|
return ProjectResponse.model_validate(project)
|
||||||
|
|
||||||
|
|
||||||
@router.delete("/{project_id}", status_code=204)
|
@router.delete("/{project_id}", status_code=204)
|
||||||
async def delete_project(
|
async def delete_project(
|
||||||
request: Request,
|
request: Request,
|
||||||
|
|||||||
@@ -62,6 +62,40 @@ async def test_update_project(client):
|
|||||||
assert response.json()["name"] == "Updated"
|
assert response.json()["name"] == "Updated"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_patch_project(client):
|
||||||
|
"""Test PATCH endpoint for partial project update."""
|
||||||
|
token = await get_token(client)
|
||||||
|
create_resp = await client.post(
|
||||||
|
"/api/v1/projects",
|
||||||
|
json={"name": "Original", "description": "Original desc"},
|
||||||
|
headers={"Authorization": f"Bearer {token}"}
|
||||||
|
)
|
||||||
|
proj_id = create_resp.json()["id"]
|
||||||
|
|
||||||
|
# PATCH name only
|
||||||
|
response = await client.patch(
|
||||||
|
f"/api/v1/projects/{proj_id}",
|
||||||
|
json={"name": "Patched Name"},
|
||||||
|
headers={"Authorization": f"Bearer {token}"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
assert data["name"] == "Patched Name"
|
||||||
|
assert data["description"] == "Original desc"
|
||||||
|
|
||||||
|
# PATCH description only
|
||||||
|
response = await client.patch(
|
||||||
|
f"/api/v1/projects/{proj_id}",
|
||||||
|
json={"description": "Patched desc"},
|
||||||
|
headers={"Authorization": f"Bearer {token}"}
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
data = response.json()
|
||||||
|
assert data["name"] == "Patched Name"
|
||||||
|
assert data["description"] == "Patched desc"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_soft_delete_project(client):
|
async def test_soft_delete_project(client):
|
||||||
token = await get_token(client)
|
token = await get_token(client)
|
||||||
|
|||||||
Reference in New Issue
Block a user