Add interactive case creation wizard + document upload with auto-rename
New SPA UI with 4 views: - Case list (#/) with status cards and document counts - New case wizard (#/new) with 4-step form: details, parties, schedule, review+create - Case view (#/case/:id) with grouped documents and drag-drop upload with tagging - Legacy upload (#/upload) for backwards compatibility Auto-creation pipeline in wizard step 4: 1. Creates case in legal-ai DB with local git repo 2. Creates Gitea repo in 'cases' org and pushes initial commit 3. Creates Paperclip project via direct DB insert Document upload with smart rename: - scan_001.pdf -> כתב-ערר-קובר-1130-25.pdf - Based on doc_type + party_name + case_number New files: - web/gitea_client.py: Gitea REST API client - web/paperclip_client.py: Paperclip embedded DB client Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
77
web/paperclip_client.py
Normal file
77
web/paperclip_client.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""Paperclip project creation via direct DB access (embedded PostgreSQL)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
import asyncpg
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
PAPERCLIP_DB_URL = "postgresql://paperclip:paperclip@127.0.0.1:54329/paperclip"
|
||||
|
||||
# Company IDs from Paperclip DB
|
||||
COMPANIES = {
|
||||
"licensing": "42a7acd0-30c5-4cbd-ac97-7424f65df294", # CMP — רישוי ובניה
|
||||
"betterment": "8639e837-4c9d-47fa-a76b-95788d651896", # CMPA — היטלי השבחה
|
||||
}
|
||||
|
||||
APPEAL_TYPE_TO_COMPANY = {
|
||||
"רישוי": "licensing",
|
||||
"licensing": "licensing",
|
||||
"היטל השבחה": "betterment",
|
||||
"betterment_levy": "betterment",
|
||||
"פיצויים": "betterment",
|
||||
"compensation": "betterment",
|
||||
}
|
||||
|
||||
|
||||
def _get_company_id(appeal_type: str) -> str:
|
||||
key = APPEAL_TYPE_TO_COMPANY.get(appeal_type, "licensing")
|
||||
return COMPANIES[key]
|
||||
|
||||
|
||||
async def create_project(
|
||||
case_number: str,
|
||||
title: str,
|
||||
description: str = "",
|
||||
appeal_type: str = "רישוי",
|
||||
color: str = "#6366f1",
|
||||
) -> dict:
|
||||
"""Create a project in the Paperclip embedded DB."""
|
||||
company_id = _get_company_id(appeal_type)
|
||||
project_id = str(uuid.uuid4())
|
||||
|
||||
conn = await asyncpg.connect(PAPERCLIP_DB_URL)
|
||||
try:
|
||||
await conn.execute(
|
||||
"""INSERT INTO projects (id, company_id, name, description, status, color)
|
||||
VALUES ($1, $2::uuid, $3, $4, 'backlog', $5)
|
||||
ON CONFLICT DO NOTHING""",
|
||||
project_id, company_id, f"ערר {case_number} — {title}"[:200], description[:500] if description else "", color,
|
||||
)
|
||||
return {
|
||||
"id": project_id,
|
||||
"company_id": company_id,
|
||||
"name": f"ערר {case_number} — {title}",
|
||||
"url": f"https://pc.nautilus.marcusgroup.org/{'CMP' if 'licensing' in appeal_type or appeal_type == 'רישוי' else 'CMPA'}/projects/{project_id}/issues",
|
||||
}
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
|
||||
async def get_project_url(case_number: str) -> str | None:
|
||||
"""Find existing Paperclip project for a case number."""
|
||||
conn = await asyncpg.connect(PAPERCLIP_DB_URL)
|
||||
try:
|
||||
row = await conn.fetchrow(
|
||||
"SELECT id, company_id FROM projects WHERE name LIKE $1",
|
||||
f"%{case_number}%",
|
||||
)
|
||||
if row:
|
||||
prefix = "CMP" if row["company_id"] == uuid.UUID(COMPANIES["licensing"]) else "CMPA"
|
||||
return f"https://pc.nautilus.marcusgroup.org/{prefix}/projects/{row['id']}/issues"
|
||||
return None
|
||||
finally:
|
||||
await conn.close()
|
||||
Reference in New Issue
Block a user