feat: emit case-status webhook on status change in PUT /api/cases/:case

This commit is contained in:
2026-05-16 17:10:30 +00:00
parent d87f9c5a5f
commit 6bdf9786ac

View File

@@ -20,7 +20,7 @@ sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "mcp-server" / "
import zipfile 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 fastapi.responses import FileResponse, StreamingResponse
from typing import Any, Literal from typing import Any, Literal
from pydantic import BaseModel from pydantic import BaseModel
@@ -44,7 +44,7 @@ from web.mcp_env_catalog import (
normalize_for_compare, normalize_for_compare,
) )
from web.progress_store import ProgressStore 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 ( from web.paperclip_client import (
COMPANIES as PAPERCLIP_COMPANIES, COMPANIES as PAPERCLIP_COMPANIES,
accept_interaction as pc_accept_interaction, accept_interaction as pc_accept_interaction,
@@ -1337,8 +1337,12 @@ async def api_case_get(case_number: str):
@app.put("/api/cases/{case_number}") @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.""" """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( result = await cases_tools.case_update(
case_number=case_number, case_number=case_number,
status=req.status, status=req.status,
@@ -1351,10 +1355,29 @@ async def api_case_update(case_number: str, req: CaseUpdateRequest):
expected_outcome=req.expected_outcome, expected_outcome=req.expected_outcome,
) )
try: try:
return json.loads(result) parsed = json.loads(result)
except json.JSONDecodeError: except json.JSONDecodeError:
raise HTTPException(404, result) 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") @app.delete("/api/cases")
async def api_case_delete(case_number: str, remove_files: bool = False): async def api_case_delete(case_number: str, remove_files: bool = False):