207 lines
6.0 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.models.transaction import TransactionType
from app.models.wallet import WalletType
from app.services.file_upload import save_deposit_proof
from app.core.email import send_deposit_confirmation
from app.core.config import settings
router = APIRouter()
@router.post("/request", response_model=schemas.Deposit)
async def create_deposit_request(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_verified_user),
amount: float = Form(...),
transaction_hash: str = Form(...),
proof_image: UploadFile = File(...),
) -> Any:
"""
Create a new deposit request.
"""
# Validate minimum deposit amount
if amount < settings.MIN_DEPOSIT_AMOUNT:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Minimum deposit amount is {settings.MIN_DEPOSIT_AMOUNT} USDT",
)
# Save proof image
proof_image_path = save_deposit_proof(current_user.id, proof_image)
# Create deposit request
deposit_in = schemas.DepositCreate(
user_id=current_user.id,
amount=amount,
transaction_hash=transaction_hash,
)
deposit = crud.deposit.create(db, obj_in=deposit_in)
# Update deposit with proof image path
crud.deposit.update(db, db_obj=deposit, obj_in={"proof_image_path": proof_image_path})
return deposit
@router.get("/", response_model=List[schemas.Deposit])
def read_deposits(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_verified_user),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve user's deposit requests.
"""
deposits = crud.deposit.get_by_user(db, user_id=current_user.id, skip=skip, limit=limit)
return deposits
@router.get("/{deposit_id}", response_model=schemas.Deposit)
def read_deposit(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_active_verified_user),
deposit_id: int,
) -> Any:
"""
Get a specific deposit by ID.
"""
deposit = crud.deposit.get(db, id=deposit_id)
if not deposit:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Deposit not found",
)
if deposit.user_id != current_user.id and current_user.role != "admin":
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Access denied",
)
return deposit
# Admin endpoints
@router.get("/admin/pending", response_model=List[schemas.Deposit])
def read_pending_deposits(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve all pending deposit requests (admin only).
"""
deposits = crud.deposit.get_all_pending(db, skip=skip, limit=limit)
return deposits
@router.put("/admin/{deposit_id}/approve", response_model=schemas.Deposit)
def approve_deposit_request(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
deposit_id: int,
deposit_data: schemas.DepositApprove,
) -> Any:
"""
Approve a deposit request (admin only).
"""
deposit = crud.deposit.get(db, id=deposit_id)
if not deposit:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Deposit not found",
)
if deposit.status != "pending":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Deposit is already {deposit.status}",
)
# Get user's spot wallet
spot_wallet = crud.wallet.get_by_user_and_type(
db, user_id=deposit.user_id, wallet_type=WalletType.SPOT
)
if not spot_wallet:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="User's spot wallet not found",
)
# Update wallet balance
crud.wallet.update_balance(db, wallet_id=spot_wallet.id, amount=deposit.amount, add=True)
# Approve deposit
updated_deposit = crud.deposit.approve(
db, db_obj=deposit, admin_notes=deposit_data.admin_notes
)
# Create transaction record
transaction = crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=deposit.user_id,
wallet_id=spot_wallet.id,
amount=deposit.amount,
transaction_type=TransactionType.DEPOSIT,
description=f"Deposit - {deposit.transaction_hash}",
deposit_id=deposit.id,
),
)
# Send confirmation email to user
user = crud.user.get(db, id=deposit.user_id)
if user:
send_deposit_confirmation(
email_to=user.email,
amount=deposit.amount,
transaction_id=str(transaction.id),
)
return updated_deposit
@router.put("/admin/{deposit_id}/reject", response_model=schemas.Deposit)
def reject_deposit_request(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
deposit_id: int,
deposit_data: schemas.DepositReject,
) -> Any:
"""
Reject a deposit request (admin only).
"""
deposit = crud.deposit.get(db, id=deposit_id)
if not deposit:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Deposit not found",
)
if deposit.status != "pending":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Deposit is already {deposit.status}",
)
# Reject deposit
updated_deposit = crud.deposit.reject(
db, db_obj=deposit, admin_notes=deposit_data.admin_notes
)
return updated_deposit