201 lines
5.6 KiB
Python

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