Draft detail and Back button
This commit is contained in:
132
backend/app/api/documents_draft_open.py
Normal file
132
backend/app/api/documents_draft_open.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""
|
||||
Documents draft-open endpoint
|
||||
|
||||
This file provides a single, isolated endpoint to fetch the documents list
|
||||
and minimal claim metadata for a given claim_id. It is implemented as a
|
||||
separate router to avoid touching existing document/claim routes.
|
||||
"""
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from fastapi.responses import RedirectResponse
|
||||
from ..config import settings
|
||||
import logging
|
||||
import json
|
||||
from typing import Any, Dict
|
||||
from ..services.database import db
|
||||
|
||||
router = APIRouter(prefix="/api/v1/documents-draft", tags=["DocumentsDraft"])
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@router.get("/open/{claim_id}")
|
||||
async def open_documents_draft(claim_id: str):
|
||||
"""
|
||||
Return minimal draft info focused on documents for the given claim_id.
|
||||
|
||||
Response:
|
||||
{
|
||||
"success": True,
|
||||
"claim_id": "...",
|
||||
"session_token": "...",
|
||||
"status_code": "...",
|
||||
"documents_required": [...],
|
||||
"documents_meta": [...],
|
||||
"documents_count": 3,
|
||||
"created_at": "...",
|
||||
"updated_at": "..."
|
||||
}
|
||||
"""
|
||||
try:
|
||||
query = """
|
||||
SELECT
|
||||
id,
|
||||
payload->>'claim_id' AS claim_id,
|
||||
session_token,
|
||||
status_code,
|
||||
payload->'documents_required' AS documents_required,
|
||||
payload->'documents_meta' AS documents_meta,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM clpr_claims
|
||||
WHERE (payload->>'claim_id' = $1 OR id::text = $1)
|
||||
ORDER BY updated_at DESC
|
||||
LIMIT 1
|
||||
"""
|
||||
|
||||
row = await db.fetch_one(query, claim_id)
|
||||
if not row:
|
||||
raise HTTPException(status_code=404, detail=f"Draft not found: {claim_id}")
|
||||
|
||||
# Normalize JSONB fields which may be strings
|
||||
def parse_json_field(val: Any):
|
||||
if val is None:
|
||||
return []
|
||||
if isinstance(val, str):
|
||||
try:
|
||||
return json.loads(val)
|
||||
except Exception:
|
||||
return []
|
||||
return val if isinstance(val, list) else []
|
||||
|
||||
documents_required = parse_json_field(row.get("documents_required"))
|
||||
documents_meta = parse_json_field(row.get("documents_meta"))
|
||||
|
||||
result = {
|
||||
"success": True,
|
||||
"claim_id": row.get("claim_id") or str(row.get("id")),
|
||||
"session_token": row.get("session_token"),
|
||||
"status_code": row.get("status_code"),
|
||||
"documents_required": documents_required,
|
||||
"documents_meta": documents_meta,
|
||||
"documents_count": len(documents_required),
|
||||
"created_at": row.get("created_at").isoformat() if row.get("created_at") else None,
|
||||
"updated_at": row.get("updated_at").isoformat() if row.get("updated_at") else None,
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.exception("Failed to open documents draft")
|
||||
raise HTTPException(status_code=500, detail=f"Error opening documents draft: {str(e)}")
|
||||
|
||||
|
||||
|
||||
@router.get("/open/launch/{claim_id}")
|
||||
async def launch_documents_draft(
|
||||
claim_id: str,
|
||||
target: str = Query("miniapp", description="Where to open: 'miniapp' or 'max'"),
|
||||
bot_name: str | None = Query(None, description="MAX bot name (required if target=max)"),
|
||||
):
|
||||
"""
|
||||
Convenience launcher:
|
||||
- target=miniapp (default) -> redirects to our miniapp URL with claim_id
|
||||
https://miniapp.clientright.ru/hello?claim_id=...
|
||||
- target=max -> redirects to MAX deep link:
|
||||
https://max.ru/{bot_name}?startapp={claim_id}
|
||||
This endpoint only redirects; it does not change persisted data.
|
||||
"""
|
||||
try:
|
||||
# ensure claim exists
|
||||
query = "SELECT 1 FROM clpr_claims WHERE (payload->>'claim_id' = $1 OR id::text = $1) LIMIT 1"
|
||||
row = await db.fetch_one(query, claim_id)
|
||||
if not row:
|
||||
raise HTTPException(status_code=404, detail=f"Draft not found: {claim_id}")
|
||||
|
||||
if target == "max":
|
||||
bot = bot_name or getattr(settings, "MAX_BOT_NAME", None)
|
||||
if not bot:
|
||||
raise HTTPException(status_code=400, detail="bot_name is required when target=max")
|
||||
# claim_id is UUID with allowed chars (hex + hyphens) - OK for startapp
|
||||
url = f"https://max.ru/{bot}?startapp={claim_id}"
|
||||
return RedirectResponse(url)
|
||||
else:
|
||||
# default: open miniapp directly (hosted at /hello)
|
||||
url = f"https://miniapp.clientright.ru/hello?claim_id={claim_id}"
|
||||
return RedirectResponse(url)
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.exception("Failed to launch documents draft")
|
||||
raise HTTPException(status_code=500, detail=f"Error launching documents draft: {str(e)}")
|
||||
|
||||
Reference in New Issue
Block a user