urmi-ai/backend/app/routes_dlt.py
2026-10-02 11:22:40 +05:30

130 lines
5.1 KiB
Python

from datetime import datetime, timezone
from pathlib import Path
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from .auth import current_user
from .config import settings
from .database import get_db
from .dlt_constants import DLT_DOCUMENT_TYPES, DLT_UPLOAD_DOCUMENT_TYPES, PE_TM_CHAIN_BINDING_ID
from .dlt_service import ensure_dlt_application, serialize_dlt
from .kyc_constants import ALLOWED_UPLOAD_EXTENSIONS
from .kyc_service import upload_root
from .models import UserAccount
router = APIRouter(prefix="/api/v1/dlt", tags=["dlt"])
@router.get("/me")
def get_my_dlt(db: Session = Depends(get_db), user: UserAccount = Depends(current_user)) -> dict:
application = ensure_dlt_application(db, user)
return serialize_dlt(application)
@router.get("/loa")
def download_loa(_: UserAccount = Depends(current_user)) -> FileResponse:
template = Path(settings.dlt_loa_template_path)
if not template.is_file():
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="LOA template not found")
return FileResponse(
template,
media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
filename="Updated LOA.docx",
)
@router.post("/chain-binding/confirm")
def confirm_chain_binding(
db: Session = Depends(get_db),
user: UserAccount = Depends(current_user),
) -> dict:
application = ensure_dlt_application(db, user)
if application.status == "approved":
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Approved DLT cannot be edited")
document = next(doc for doc in application.documents if doc.document_type == "pe_tm_chain_binding")
if document.status == "approved":
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Chain binding already approved")
document.original_filename = f"Chain binding {PE_TM_CHAIN_BINDING_ID}"
document.stored_path = None
document.status = "pending"
document.review_note = None
document.uploaded_at = datetime.now(timezone.utc)
document.reviewed_at = None
if application.status in {"not_started", "in_progress", "rejected"}:
application.status = "in_progress"
db.commit()
db.refresh(application)
return serialize_dlt(application)
@router.post("/documents/{document_type}")
async def upload_document(
document_type: str,
file: UploadFile = File(...),
db: Session = Depends(get_db),
user: UserAccount = Depends(current_user),
) -> dict:
if document_type not in DLT_DOCUMENT_TYPES:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid document type")
if document_type not in DLT_UPLOAD_DOCUMENT_TYPES:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="This item uses chain binding confirmation instead of file upload",
)
application = ensure_dlt_application(db, user)
if application.status == "approved":
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Approved DLT cannot be edited")
filename = file.filename or ""
extension = Path(filename).suffix.lower()
if extension not in ALLOWED_UPLOAD_EXTENSIONS:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Allowed file types: PDF, PNG, JPG, DOC, DOCX",
)
content = await file.read()
if not content:
raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="File is empty")
if len(content) > settings.max_upload_bytes:
raise HTTPException(status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="File exceeds 10 MB limit")
document = next(doc for doc in application.documents if doc.document_type == document_type)
root = upload_root(settings.upload_dir)
stored_name = f"{application.id}_{document_type}{extension}"
stored_path = root / stored_name
stored_path.write_bytes(content)
document.original_filename = filename
document.stored_path = str(stored_path)
document.status = "pending"
document.review_note = None
document.uploaded_at = datetime.now(timezone.utc)
document.reviewed_at = None
if application.status in {"not_started", "in_progress", "rejected"}:
application.status = "in_progress"
db.commit()
db.refresh(application)
return serialize_dlt(application)
@router.post("/submit")
def submit_dlt(db: Session = Depends(get_db), user: UserAccount = Depends(current_user)) -> dict:
application = ensure_dlt_application(db, user)
if application.status == "approved":
return serialize_dlt(application)
missing = [doc.document_type for doc in application.documents if doc.status == "missing"]
if missing:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
detail="Complete all required DLT items before submitting",
)
application.status = "submitted"
application.submitted_at = datetime.now(timezone.utc)
db.commit()
db.refresh(application)
return serialize_dlt(application)