feat(proceeding-type): explicit ערר/בל"מ field for cases + corpus
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m40s
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 1m40s
Same case_number can exist as both a regular appeal (ערר) and an extension-of-time request (בל"מ), and we were inferring the difference from appeal_subtype prefixes — fragile, and case-number lookups weren't disambiguated. Now stored as a first-class field on both case_law (corpus) and cases (live cases), with partial unique indexes on (case_number, proceeding_type). - SCHEMA_V15: column + CHECK constraints + backfill from appeal_subtype LIKE 'extension_request_%' + partial unique indexes replace the old global UNIQUE(case_number). - derive_proceeding_type() centralizes the inference rule (extension_request_* → בל"מ; subject regex fallback; default ערר). - Metadata extractor prompt asks Claude to populate the new field explicitly; apply_to_record writes it for internal_committee rows. - internal_decision_upload, case_create, case_update accept an optional proceeding_type; FastAPI request models expose it. - Wizard + edit dialog get a sided Select; case header renders the resolved label (ערר / בל"מ). - Uploaded the 2 staged בל"מ decisions on betterment levy: 8126/24 (סופר נוח, 13 chunks), 8047/23 (הרנון, 48 chunks). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -130,6 +130,7 @@ async def case_create(
|
||||
expected_outcome: str = "",
|
||||
practice_area: str = "",
|
||||
appeal_subtype: str = "",
|
||||
proceeding_type: str = "",
|
||||
) -> str:
|
||||
"""יצירת תיק ערר חדש.
|
||||
|
||||
@@ -150,6 +151,7 @@ async def case_create(
|
||||
אוטומטית ממספר התיק (1xxx→רישוי, 8xxx→השבחה, 9xxx→197)
|
||||
appeal_subtype: סוג ערר (building_permit / betterment_levy / compensation_197).
|
||||
ריק = יוסק אוטומטית ממספר התיק
|
||||
proceeding_type: 'ערר' / 'בל"מ'. ריק = יוסק מ-appeal_subtype/subject.
|
||||
"""
|
||||
from datetime import date as date_type
|
||||
|
||||
@@ -173,6 +175,11 @@ async def case_create(
|
||||
appeal_subtype = derived_subtype
|
||||
pa.validate(practice_area, appeal_subtype)
|
||||
|
||||
# proceeding_type: explicit override > derived from subtype/subject > 'ערר'
|
||||
resolved_proc = proceeding_type.strip() or pa.derive_proceeding_type(
|
||||
appeal_subtype=appeal_subtype, subject=subject,
|
||||
)
|
||||
|
||||
case = await db.create_case(
|
||||
case_number=case_number,
|
||||
title=title,
|
||||
@@ -187,6 +194,7 @@ async def case_create(
|
||||
expected_outcome=expected_outcome,
|
||||
practice_area=practice_area,
|
||||
appeal_subtype=appeal_subtype,
|
||||
proceeding_type=resolved_proc,
|
||||
)
|
||||
|
||||
# If the user overrode the case-number convention (e.g. case 8500 marked
|
||||
@@ -290,6 +298,7 @@ async def case_update(
|
||||
respondents: list[str] | None = None,
|
||||
property_address: str = "",
|
||||
permit_number: str = "",
|
||||
proceeding_type: str = "",
|
||||
) -> str:
|
||||
"""עדכון פרטי תיק.
|
||||
|
||||
@@ -307,6 +316,7 @@ async def case_update(
|
||||
respondents: רשימת משיבים חדשה
|
||||
property_address: כתובת נכס חדשה
|
||||
permit_number: מספר תכנית/בקשה חדש
|
||||
proceeding_type: 'ערר' / 'בל"מ' — ריק = ללא שינוי
|
||||
"""
|
||||
from datetime import date as date_type
|
||||
|
||||
@@ -359,6 +369,12 @@ async def case_update(
|
||||
fields["property_address"] = property_address
|
||||
if permit_number:
|
||||
fields["permit_number"] = permit_number
|
||||
if proceeding_type:
|
||||
if proceeding_type not in {"ערר", 'בל"מ'}:
|
||||
raise ValueError(
|
||||
f"proceeding_type לא תקין: {proceeding_type!r}. ערכים תקפים: ערר / בל\"מ"
|
||||
)
|
||||
fields["proceeding_type"] = proceeding_type
|
||||
|
||||
updated = await db.update_case(UUID(case["id"]), **fields)
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ from legal_mcp.services import internal_decisions as int_svc
|
||||
# Valid Hebrew district names (matches _COURT_TO_DISTRICT in service)
|
||||
VALID_DISTRICTS = {"ירושלים", "מרכז", "תל אביב", "תל-אביב", "צפון", "דרום", "חיפה", "ארצי"}
|
||||
|
||||
# proceeding_type — ערר vs בל"מ. The service can derive it from
|
||||
# appeal_subtype/subject if left empty, so this stays optional at the API.
|
||||
VALID_PROCEEDING_TYPES = {"ערר", 'בל"מ'}
|
||||
|
||||
|
||||
def _ok(payload) -> str:
|
||||
return json.dumps(payload, ensure_ascii=False, indent=2, default=str)
|
||||
@@ -43,6 +47,7 @@ async def internal_decision_upload(
|
||||
subject_tags: list[str] | None = None,
|
||||
summary: str = "",
|
||||
is_binding: bool = False,
|
||||
proceeding_type: str = "",
|
||||
) -> str:
|
||||
"""העלאת החלטה של ועדת ערר (internal_committee) לקורפוס הסמכותי.
|
||||
|
||||
@@ -62,6 +67,7 @@ async def internal_decision_upload(
|
||||
appeal_subtype: building_permit / וכו'.
|
||||
subject_tags: תגיות נושא.
|
||||
is_binding: בד"כ False (ועדת ערר לא מחייבת ועדה אחרת — שכנוע אופקי).
|
||||
proceeding_type: 'ערר' או 'בל"מ'. אם ריק — נגזר מ-appeal_subtype/case_name.
|
||||
|
||||
Returns: JSON עם case_law_id, מספר chunks, halachot_pending.
|
||||
"""
|
||||
@@ -83,6 +89,11 @@ async def internal_decision_upload(
|
||||
f"district לא תקין: {district!r}. ערכים תקפים: "
|
||||
+ ", ".join(sorted(VALID_DISTRICTS))
|
||||
)
|
||||
if proceeding_type.strip() and proceeding_type.strip() not in VALID_PROCEEDING_TYPES:
|
||||
return _err(
|
||||
f"proceeding_type לא תקין: {proceeding_type!r}. ערכים תקפים: "
|
||||
+ ", ".join(sorted(VALID_PROCEEDING_TYPES))
|
||||
)
|
||||
|
||||
try:
|
||||
result = await int_svc.ingest_internal_decision(
|
||||
@@ -98,6 +109,7 @@ async def internal_decision_upload(
|
||||
summary=summary,
|
||||
is_binding=is_binding,
|
||||
file_path=file_path,
|
||||
proceeding_type=proceeding_type,
|
||||
)
|
||||
except Exception as e:
|
||||
return _err(str(e))
|
||||
|
||||
Reference in New Issue
Block a user