From 6bdf9786acd54b8c3e3ac4a4085f53bd639b2731 Mon Sep 17 00:00:00 2001 From: Chaim Date: Sat, 16 May 2026 17:10:30 +0000 Subject: [PATCH] feat: emit case-status webhook on status change in PUT /api/cases/:case --- web/app.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/web/app.py b/web/app.py index cb58178..27d3173 100644 --- a/web/app.py +++ b/web/app.py @@ -20,7 +20,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "mcp-server" / " import zipfile -from fastapi import FastAPI, File, Form, HTTPException, UploadFile +from fastapi import BackgroundTasks, FastAPI, File, Form, HTTPException, UploadFile from fastapi.responses import FileResponse, StreamingResponse from typing import Any, Literal from pydantic import BaseModel @@ -44,7 +44,7 @@ from web.mcp_env_catalog import ( normalize_for_compare, ) from web.progress_store import ProgressStore -from web.paperclip_api import pc_request +from web.paperclip_api import emit_case_status_webhook, pc_request from web.paperclip_client import ( COMPANIES as PAPERCLIP_COMPANIES, accept_interaction as pc_accept_interaction, @@ -1337,8 +1337,12 @@ async def api_case_get(case_number: str): @app.put("/api/cases/{case_number}") -async def api_case_update(case_number: str, req: CaseUpdateRequest): +async def api_case_update(case_number: str, req: CaseUpdateRequest, background_tasks: BackgroundTasks): """Update case details.""" + # Capture old status before the update so we can detect changes. + existing = await db.get_case_by_number(case_number) + old_status = (existing or {}).get("status", "") + result = await cases_tools.case_update( case_number=case_number, status=req.status, @@ -1351,10 +1355,29 @@ async def api_case_update(case_number: str, req: CaseUpdateRequest): expected_outcome=req.expected_outcome, ) try: - return json.loads(result) + parsed = json.loads(result) except json.JSONDecodeError: raise HTTPException(404, result) + # Emit webhook when status changes (fire-and-forget via BackgroundTasks). + new_status = req.status + if new_status and old_status != new_status: + prefix = case_number[:1] + company_id = ( + PAPERCLIP_COMPANIES["licensing"] if prefix == "1" + else PAPERCLIP_COMPANIES["betterment"] if prefix in ("8", "9") + else None + ) + background_tasks.add_task( + emit_case_status_webhook, + case_number=case_number, + old_status=old_status, + new_status=new_status, + company_id=company_id, + ) + + return parsed + @app.delete("/api/cases") async def api_case_delete(case_number: str, remove_files: bool = False):