Merge pull request 'feat(mcp): FU-14 GAP-48 פרוסה 2 — envelope אחיד ל-11 משפחות-כלים' (#77) from fix/fu14-gap48-envelope-rest into main
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m5s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 2m5s
This commit was merged in pull request #77.
This commit is contained in:
67
web/app.py
67
web/app.py
@@ -1896,7 +1896,9 @@ async def api_case_create(req: CaseCreateRequest):
|
||||
appeal_subtype=req.appeal_subtype,
|
||||
proceeding_type=req.proceeding_type,
|
||||
)
|
||||
parsed = json.loads(result)
|
||||
# GAP-48: case_create now returns the {status,data,message} envelope; unwrap
|
||||
# to the case object so the existing gitea/appeal_subtype/paperclip wiring works.
|
||||
parsed = envelope_unwrap(json.loads(result))
|
||||
|
||||
# Auto-create Paperclip project for the new case. case_create may have
|
||||
# auto-derived appeal_subtype from the case-number prefix; prefer the
|
||||
@@ -1998,10 +2000,10 @@ async def api_case_git_status(case_number: str):
|
||||
async def api_case_get(case_number: str):
|
||||
"""Get full case details including documents."""
|
||||
result = await cases_tools.case_get(case_number)
|
||||
try:
|
||||
return json.loads(result)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(404, result)
|
||||
parsed = json.loads(result)
|
||||
if isinstance(parsed, dict) and parsed.get("status") == "error": # GAP-48
|
||||
raise HTTPException(404, parsed.get("message") or result)
|
||||
return envelope_unwrap(parsed)
|
||||
|
||||
|
||||
@app.put("/api/cases/{case_number}")
|
||||
@@ -2030,10 +2032,10 @@ async def api_case_update(case_number: str, req: CaseUpdateRequest, background_t
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(422, str(exc))
|
||||
try:
|
||||
parsed = json.loads(result)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(404, result)
|
||||
parsed = json.loads(result)
|
||||
if isinstance(parsed, dict) and parsed.get("status") == "error": # GAP-48
|
||||
raise HTTPException(404, parsed.get("message") or result)
|
||||
parsed = envelope_unwrap(parsed)
|
||||
|
||||
# Paperclip sync: update project name when title changes (fire-and-forget).
|
||||
old_title = (existing or {}).get("title", "")
|
||||
@@ -2075,9 +2077,9 @@ async def api_case_delete(case_number: str, remove_files: bool = False):
|
||||
FK ON DELETE CASCADE; audit_log rows nullify their case_id.
|
||||
Pass `remove_files=true` to also rm -rf the on-disk case directory."""
|
||||
result = await cases_tools.case_delete(case_number, remove_files)
|
||||
data = json.loads(result)
|
||||
data = envelope_unwrap(json.loads(result)) # GAP-48
|
||||
if not data.get("deleted"):
|
||||
raise HTTPException(404, data.get("reason", f"תיק {case_number} לא נמצא"))
|
||||
raise HTTPException(404, data.get("message") or data.get("reason") or f"תיק {case_number} לא נמצא")
|
||||
return data
|
||||
|
||||
|
||||
@@ -2085,10 +2087,10 @@ async def api_case_delete(case_number: str, remove_files: bool = False):
|
||||
async def api_case_status(case_number: str):
|
||||
"""Get full workflow status for a case."""
|
||||
result = await workflow_tools.workflow_status(case_number)
|
||||
try:
|
||||
return json.loads(result)
|
||||
except json.JSONDecodeError:
|
||||
raise HTTPException(404, result)
|
||||
parsed = json.loads(result)
|
||||
if isinstance(parsed, dict) and parsed.get("status") == "error": # GAP-48
|
||||
raise HTTPException(404, parsed.get("message") or result)
|
||||
return envelope_unwrap(parsed)
|
||||
|
||||
|
||||
@app.get("/api/search")
|
||||
@@ -2176,7 +2178,7 @@ async def api_case_template(case_number: str):
|
||||
async def api_processing_status():
|
||||
"""Get overall processing status."""
|
||||
result = await workflow_tools.processing_status()
|
||||
return json.loads(result)
|
||||
return envelope_unwrap(json.loads(result)) # GAP-48
|
||||
|
||||
|
||||
@app.get("/api/system/diagnostics")
|
||||
@@ -2965,10 +2967,10 @@ async def api_precedent_attach(case_number: str, req: PrecedentCreateRequest):
|
||||
chair_note=req.chair_note,
|
||||
pdf_document_id=req.pdf_document_id,
|
||||
)
|
||||
data = json.loads(result)
|
||||
if data.get("error"):
|
||||
raise HTTPException(404, data["error"])
|
||||
return data
|
||||
parsed = json.loads(result) # GAP-48
|
||||
if parsed.get("status") == "error":
|
||||
raise HTTPException(404, parsed.get("message") or "")
|
||||
return envelope_unwrap(parsed)
|
||||
|
||||
|
||||
@app.post("/api/cases/{case_number}/precedents/upload-pdf")
|
||||
@@ -3022,10 +3024,10 @@ async def api_precedent_upload_pdf(
|
||||
async def api_precedent_list(case_number: str):
|
||||
"""List all precedents attached to a case, grouped client-side by section_id."""
|
||||
result = await precedents_tools.precedent_list(case_number)
|
||||
data = json.loads(result)
|
||||
if isinstance(data, dict) and data.get("error"):
|
||||
raise HTTPException(404, data["error"])
|
||||
return data
|
||||
parsed = json.loads(result) # GAP-48
|
||||
if isinstance(parsed, dict) and parsed.get("status") == "error":
|
||||
raise HTTPException(404, parsed.get("message") or "")
|
||||
return envelope_unwrap(parsed)
|
||||
|
||||
|
||||
@app.delete("/api/precedents/{precedent_id}")
|
||||
@@ -3034,9 +3036,10 @@ async def api_precedent_delete(precedent_id: str):
|
||||
in the documents table — orphaned references nullify via FK
|
||||
ON DELETE SET NULL — so we keep the audit trail of the file."""
|
||||
result = await precedents_tools.precedent_remove(precedent_id)
|
||||
data = json.loads(result)
|
||||
if data.get("error"):
|
||||
raise HTTPException(400, data["error"])
|
||||
parsed = json.loads(result) # GAP-48
|
||||
if parsed.get("status") == "error":
|
||||
raise HTTPException(400, parsed.get("message") or "")
|
||||
data = envelope_unwrap(parsed)
|
||||
if not data.get("deleted"):
|
||||
raise HTTPException(404, "לא נמצא")
|
||||
return data
|
||||
@@ -3046,7 +3049,10 @@ async def api_precedent_delete(precedent_id: str):
|
||||
async def api_precedent_search(q: str, practice_area: str = "", limit: int = 10):
|
||||
"""Cross-case library typeahead. Returns one row per distinct citation."""
|
||||
result = await precedents_tools.precedent_search_library(q, practice_area, limit)
|
||||
return json.loads(result)
|
||||
parsed = json.loads(result) # GAP-48: typeahead expects an array
|
||||
if isinstance(parsed, dict) and parsed.get("status") == "error":
|
||||
raise HTTPException(400, parsed.get("message") or "")
|
||||
return parsed.get("data") or []
|
||||
|
||||
|
||||
# ── Exports API — drafts, versions, download, upload, mark-final ──
|
||||
@@ -3464,9 +3470,10 @@ async def api_start_workflow(case_number: str):
|
||||
"""
|
||||
# 1. Verify case exists and status is appropriate
|
||||
case_raw = await cases_tools.case_get(case_number)
|
||||
case_data = json.loads(case_raw)
|
||||
if "error" in case_data:
|
||||
case_env = json.loads(case_raw) # GAP-48
|
||||
if isinstance(case_env, dict) and case_env.get("status") == "error":
|
||||
raise HTTPException(404, f"תיק {case_number} לא נמצא")
|
||||
case_data = envelope_unwrap(case_env)
|
||||
|
||||
status = case_data.get("status", "")
|
||||
allowed = {"new", "documents_ready"}
|
||||
|
||||
Reference in New Issue
Block a user