feat(case-ui): חלוקת רשימת-המסמכים בטאב-הסקירה ל-4 קבוצות
חלוקה פנימית (לנוחות בלבד, לא משנה doc_type) של רשימת מסמכי-התיק:
1. עיקריים (appeal/response/appraisal) · 2. נלווים · 3. פרוטוקול ועדת הערר ·
4. לאחר הדיון. הסיווג נגזר בצד-הלקוח מ-doc_type + שני דגלי-metadata.
שני פקדים חדשים בעורך-התיוג:
- מתג "התקבל אחרי הדיון" → metadata.is_post_hearing (כבר נצרך ע"י בלוק-ח);
גובר על הסיווג-לפי-סוג ומעביר לקבוצה 4.
- בורר "פרוטוקול של: ועדת הערר / ועדה מקומית-מחוזית" → metadata.protocol_scope
(נראה רק כשהסוג protocol); ברירת-מחדל appeal→קבוצה 3, lower→קבוצה 2.
Backend: PATCH /documents/{id} + MCP document_update מקבלים is_post_hearing
ו-protocol_scope, נשמרים ב-metadata JSONB (אותו מסלול כמו appraiser_side).
עיצוב אושר ב-Claude Design (X17): 18k-case-documents-grouped.html.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -433,17 +433,24 @@ ALLOWED_DOC_TYPES = {
|
||||
# Allowed appraiser_side values; '' (empty) clears the tag.
|
||||
ALLOWED_APPRAISER_SIDES = {"committee", "appellant", "deciding", ""}
|
||||
|
||||
# Allowed protocol_scope values (protocol docs only); mirrors web/app.py.
|
||||
# appeal = ועדת הערר (default when absent) · lower = ועדה מקומית/מחוזית.
|
||||
ALLOWED_PROTOCOL_SCOPES = {"appeal", "lower"}
|
||||
|
||||
|
||||
async def document_update(
|
||||
case_number: str,
|
||||
doc_id: str,
|
||||
doc_type: str = "",
|
||||
appraiser_side: str = "",
|
||||
is_post_hearing: bool | None = None,
|
||||
protocol_scope: str = "",
|
||||
) -> str:
|
||||
"""עדכון תיוג מסמך — doc_type ו/או appraiser_side. ריק = אין שינוי.
|
||||
"""עדכון תיוג מסמך — doc_type / appraiser_side / is_post_hearing / protocol_scope.
|
||||
|
||||
הולידציה זהה ל-PATCH endpoint ב-web/app.py. appraiser_side נשמר ב-
|
||||
documents.metadata JSONB (מתפרסם משם ע"י extract_appraiser_facts).
|
||||
הולידציה זהה ל-PATCH endpoint ב-web/app.py. הדגלים נשמרים ב-
|
||||
documents.metadata JSONB (appraiser_side מתפרסם משם ע"י extract_appraiser_facts;
|
||||
is_post_hearing נצרך ע"י כותב בלוק-ח; protocol_scope מסווג פרוטוקול בטאב-הסקירה).
|
||||
|
||||
Args:
|
||||
case_number: מספר תיק הערר (לאישור שייכות)
|
||||
@@ -452,6 +459,9 @@ async def document_update(
|
||||
permit/appraisal/exhibit/objection/reference). ריק = אין שינוי.
|
||||
appraiser_side: ערך חדש (committee/appellant/deciding). ריק = אין שינוי;
|
||||
העבר במפורש מחרוזת ריקה לא-default אם רוצים לנקות.
|
||||
is_post_hearing: True = התקבל אחרי הדיון · False = מנקה את הדגל · None = אין שינוי.
|
||||
protocol_scope: היקף פרוטוקול (appeal=ועדת הערר / lower=ועדה מקומית-מחוזית).
|
||||
ריק = אין שינוי. רלוונטי רק כשהסוג protocol.
|
||||
"""
|
||||
case = await db.get_case_by_number(case_number)
|
||||
if not case:
|
||||
@@ -477,17 +487,37 @@ async def document_update(
|
||||
data={"allowed": sorted(ALLOWED_DOC_TYPES)})
|
||||
updates["doc_type"] = doc_type
|
||||
|
||||
# appraiser_side is optional. The MCP tool can't distinguish "skip" from
|
||||
# "set to empty string", so we use the convention: only update if non-empty.
|
||||
# To clear, the operator must edit metadata directly (rare).
|
||||
# appraiser_side / protocol_scope are optional. The MCP tool can't
|
||||
# distinguish "skip" from "set to empty string", so we use the convention:
|
||||
# only update if non-empty. To clear, edit metadata directly (rare).
|
||||
# is_post_hearing is a tri-state bool: None skips, True/False set/clear.
|
||||
metadata = doc.get("metadata") or {}
|
||||
if isinstance(metadata, str):
|
||||
metadata = json.loads(metadata)
|
||||
metadata_dirty = False
|
||||
|
||||
if appraiser_side:
|
||||
if appraiser_side not in ALLOWED_APPRAISER_SIDES:
|
||||
return err(f"appraiser_side לא תקין: {appraiser_side}",
|
||||
data={"allowed": sorted(s for s in ALLOWED_APPRAISER_SIDES if s)})
|
||||
metadata = doc.get("metadata") or {}
|
||||
if isinstance(metadata, str):
|
||||
metadata = json.loads(metadata)
|
||||
metadata["appraiser_side"] = appraiser_side
|
||||
metadata_dirty = True
|
||||
|
||||
if is_post_hearing is not None:
|
||||
if is_post_hearing:
|
||||
metadata["is_post_hearing"] = True
|
||||
else:
|
||||
metadata.pop("is_post_hearing", None)
|
||||
metadata_dirty = True
|
||||
|
||||
if protocol_scope:
|
||||
if protocol_scope not in ALLOWED_PROTOCOL_SCOPES:
|
||||
return err(f"protocol_scope לא תקין: {protocol_scope}",
|
||||
data={"allowed": sorted(ALLOWED_PROTOCOL_SCOPES)})
|
||||
metadata["protocol_scope"] = protocol_scope
|
||||
metadata_dirty = True
|
||||
|
||||
if metadata_dirty:
|
||||
updates["metadata"] = metadata
|
||||
|
||||
if not updates:
|
||||
|
||||
Reference in New Issue
Block a user