Trigger appraiser-facts extraction from the UI
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 36s

Extraction is expensive (multi-minute LLM calls) and runs across every
appraisal in the case at once, so we don't kick it off silently on every
tag save. The chair tags the appraisals, then runs extraction once when
they're ready.

- New POST /api/cases/{n}/extract-appraiser-facts endpoint returns the
  extractor's summary as-is: status=completed with fact counts and
  conflicts, or status=sides_missing with the list of still-untagged
  appraisal docs.
- DocumentTypeEditor now has a two-phase popover. After a successful
  save on an appraisal doc, the body switches to a confirmation view
  with a "חלץ עובדות שמאיות עכשיו" button. The result (completed /
  sides_missing / no_appraisals / error) renders in the same popover
  so the chair sees exactly which appraisals still need tagging
  without closing and reopening anything.
- useExtractAppraiserFacts React-Query mutation invalidates the case
  detail on success so downstream views (conflict rendering in
  block-tet context) pick up the new facts.
This commit is contained in:
2026-04-19 09:42:49 +00:00
parent c536ed0e63
commit eac7784b87
3 changed files with 294 additions and 69 deletions

View File

@@ -3064,6 +3064,33 @@ async def api_patch_document(case_number: str, doc_id: str, req: DocumentPatchRe
return {"status": "completed", "document": fresh}
@app.post("/api/cases/{case_number}/extract-appraiser-facts")
async def api_extract_appraiser_facts(case_number: str):
"""Run structured extraction of plans + permits from every appraisal
document in the case, and detect conflicts between appraisers.
Blocks if any appraisal document is missing metadata.appraiser_side —
the chair must tag every appraisal (committee / appellant / deciding)
before extraction can identify the deciding appraiser's governing view.
Returns the extractor's summary dict as-is. Shape:
{"status": "completed"|"sides_missing"|"no_appraisals", ...}
"""
from legal_mcp.services import appraiser_facts_extractor
case = await db.get_case_by_number(case_number)
if not case:
raise HTTPException(404, f"תיק {case_number} לא נמצא")
try:
result = await appraiser_facts_extractor.extract_appraiser_facts(
UUID(case["id"])
)
except Exception as e:
raise HTTPException(500, f"חילוץ נכשל: {e}")
return result
@app.delete("/api/cases/{case_number}/documents/{doc_id}")
async def api_delete_document(case_number: str, doc_id: str):
"""Delete a single document from a case (including its chunks and file)."""