from typing import Any, List from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form from sqlalchemy.orm import Session from app import crud, models, schemas from app.api import deps from app.services.file_upload import save_kyc_document from app.core.email import send_kyc_status_update router = APIRouter() @router.post("/upload", response_model=schemas.KYC) async def upload_kyc_documents( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_active_verified_user), full_name: str = Form(...), id_document_type: schemas.IDDocumentType = Form(...), id_document: UploadFile = File(...), selfie: UploadFile = File(...), additional_document: UploadFile = File(None), ) -> Any: """ Upload KYC documents. """ # Check if user already has KYC submission existing_kyc = crud.kyc.get_by_user(db, user_id=current_user.id) if existing_kyc: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"You already have a KYC submission with status: {existing_kyc.status}", ) # Save documents id_document_path = save_kyc_document(current_user.id, "id_document", id_document) selfie_path = save_kyc_document(current_user.id, "selfie", selfie) additional_document_path = None if additional_document: additional_document_path = save_kyc_document(current_user.id, "additional", additional_document) # Create KYC record kyc_in = schemas.KYCCreate( user_id=current_user.id, full_name=full_name, id_document_type=id_document_type, id_document_path=id_document_path, selfie_path=selfie_path, additional_document_path=additional_document_path, ) kyc = crud.kyc.create(db, obj_in=kyc_in) return kyc @router.get("/status", response_model=schemas.KYC) def get_kyc_status( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_active_verified_user), ) -> Any: """ Get user's KYC status. """ kyc = crud.kyc.get_by_user(db, user_id=current_user.id) if not kyc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="No KYC submission found", ) return kyc # Admin endpoints @router.get("/admin/pending", response_model=List[schemas.KYC]) def get_pending_kyc( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_admin), skip: int = 0, limit: int = 100, ) -> Any: """ Get all pending KYC submissions (admin only). """ kyc_submissions = crud.kyc.get_all_pending(db, skip=skip, limit=limit) return kyc_submissions @router.get("/admin/{kyc_id}", response_model=schemas.KYC) def get_kyc( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_admin), kyc_id: int, ) -> Any: """ Get a specific KYC submission by ID (admin only). """ kyc = crud.kyc.get(db, id=kyc_id) if not kyc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="KYC submission not found", ) return kyc @router.put("/admin/{kyc_id}/approve", response_model=schemas.KYC) def approve_kyc_submission( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_admin), kyc_id: int, ) -> Any: """ Approve a KYC submission (admin only). """ kyc = crud.kyc.get(db, id=kyc_id) if not kyc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="KYC submission not found", ) if kyc.status != "pending": raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"KYC submission is already {kyc.status}", ) # Get user user = crud.user.get(db, id=kyc.user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) # Update KYC status updated_kyc = crud.kyc.approve(db, db_obj=kyc) # Update user's KYC status crud.user.set_kyc_verified(db, user=user) # Send email notification send_kyc_status_update( email_to=user.email, status="approved", ) return updated_kyc @router.put("/admin/{kyc_id}/reject", response_model=schemas.KYC) def reject_kyc_submission( *, db: Session = Depends(deps.get_db), current_user: models.User = Depends(deps.get_current_admin), kyc_id: int, kyc_data: schemas.KYCReject, ) -> Any: """ Reject a KYC submission (admin only). """ kyc = crud.kyc.get(db, id=kyc_id) if not kyc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="KYC submission not found", ) if kyc.status != "pending": raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=f"KYC submission is already {kyc.status}", ) # Get user user = crud.user.get(db, id=kyc.user_id) if not user: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found", ) # Update KYC status updated_kyc = crud.kyc.reject(db, db_obj=kyc, rejection_reason=kyc_data.rejection_reason) # Send email notification send_kyc_status_update( email_to=user.email, status="rejected", reason=kyc_data.rejection_reason, ) return updated_kyc