286 lines
8.8 KiB
Python

from typing import Any, List, Dict
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy import func
from app import crud, models, schemas
from app.api import deps
from app.services.bot_simulation import get_bot_simulation_stats
router = APIRouter()
@router.get("/users", response_model=List[schemas.User])
def read_users(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve all users (admin only).
"""
users = db.query(models.User).offset(skip).limit(limit).all()
return users
@router.get("/users/{user_id}", response_model=schemas.User)
def read_user(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
user_id: int,
) -> Any:
"""
Get a specific user by ID (admin only).
"""
user = crud.user.get(db, id=user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
return user
@router.put("/users/{user_id}/activate", response_model=schemas.User)
def activate_user(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
user_id: int,
) -> Any:
"""
Activate a user (admin only).
"""
user = crud.user.get(db, id=user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
if user.is_active:
return user
updated_user = crud.user.update(db, db_obj=user, obj_in={"is_active": True})
return updated_user
@router.put("/users/{user_id}/deactivate", response_model=schemas.User)
def deactivate_user(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
user_id: int,
) -> Any:
"""
Deactivate a user (admin only).
"""
if user_id == current_user.id:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="You cannot deactivate your own account",
)
user = crud.user.get(db, id=user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
if not user.is_active:
return user
updated_user = crud.user.update(db, db_obj=user, obj_in={"is_active": False})
return updated_user
@router.get("/wallets/{user_id}", response_model=List[schemas.Wallet])
def read_user_wallets(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
user_id: int,
) -> Any:
"""
Get a specific user's wallets (admin only).
"""
user = crud.user.get(db, id=user_id)
if not user:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found",
)
wallets = crud.wallet.get_by_user(db, user_id=user_id)
return wallets
@router.put("/wallets/{wallet_id}/adjust", response_model=schemas.Wallet)
def adjust_wallet_balance(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
wallet_id: int,
amount: float,
description: str,
) -> Any:
"""
Adjust a wallet's balance (admin only).
"""
wallet = crud.wallet.get(db, id=wallet_id)
if not wallet:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Wallet not found",
)
# Check if adjustment would make balance negative
if wallet.balance + amount < 0:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Adjustment would result in negative balance",
)
# Update wallet balance
updated_wallet = crud.wallet.update_balance(
db, wallet_id=wallet_id, amount=abs(amount), add=(amount > 0)
)
# Create transaction record
crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=wallet.user_id,
wallet_id=wallet.id,
amount=amount,
transaction_type=models.TransactionType.ADMIN_ADJUSTMENT,
description=f"Admin adjustment: {description}",
),
)
return updated_wallet
@router.get("/transactions", response_model=List[schemas.Transaction])
def read_all_transactions(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve all transactions (admin only).
"""
transactions = crud.transaction.get_all(db, skip=skip, limit=limit)
return transactions
@router.get("/statistics", response_model=Dict)
def get_statistics(
*,
db: Session = Depends(deps.get_db),
current_user: models.User = Depends(deps.get_current_admin),
) -> Any:
"""
Get platform statistics (admin only).
"""
# User statistics
total_users = db.query(func.count(models.User.id)).scalar()
active_users = db.query(func.count(models.User.id)).filter(models.User.is_active).scalar()
verified_users = db.query(func.count(models.User.id)).filter(models.User.is_verified).scalar()
kyc_verified_users = db.query(func.count(models.User.id)).filter(models.User.is_kyc_verified).scalar()
# Wallet statistics
total_spot_balance = db.query(func.sum(models.Wallet.balance)).filter(
models.Wallet.wallet_type == models.WalletType.SPOT
).scalar() or 0
total_trading_balance = db.query(func.sum(models.Wallet.balance)).filter(
models.Wallet.wallet_type == models.WalletType.TRADING
).scalar() or 0
# Deposit statistics
total_deposits = db.query(func.count(models.Deposit.id)).scalar()
pending_deposits = db.query(func.count(models.Deposit.id)).filter(
models.Deposit.status == models.DepositStatus.PENDING
).scalar()
approved_deposits = db.query(func.count(models.Deposit.id)).filter(
models.Deposit.status == models.DepositStatus.APPROVED
).scalar()
total_deposit_amount = db.query(func.sum(models.Deposit.amount)).filter(
models.Deposit.status == models.DepositStatus.APPROVED
).scalar() or 0
# Withdrawal statistics
total_withdrawals = db.query(func.count(models.Withdrawal.id)).scalar()
pending_withdrawals = db.query(func.count(models.Withdrawal.id)).filter(
models.Withdrawal.status == models.WithdrawalStatus.PENDING
).scalar()
approved_withdrawals = db.query(func.count(models.Withdrawal.id)).filter(
models.Withdrawal.status == models.WithdrawalStatus.APPROVED
).scalar()
total_withdrawal_amount = db.query(func.sum(models.Withdrawal.amount)).filter(
models.Withdrawal.status == models.WithdrawalStatus.APPROVED
).scalar() or 0
# Bot statistics
total_bots = db.query(func.count(models.Bot.id)).scalar()
active_bots = db.query(func.count(models.Bot.id)).filter(models.Bot.is_active).scalar()
bot_stats = get_bot_simulation_stats(db)
# KYC statistics
total_kyc = db.query(func.count(models.KYC.id)).scalar()
pending_kyc = db.query(func.count(models.KYC.id)).filter(
models.KYC.status == models.KYCStatus.PENDING
).scalar()
approved_kyc = db.query(func.count(models.KYC.id)).filter(
models.KYC.status == models.KYCStatus.APPROVED
).scalar()
rejected_kyc = db.query(func.count(models.KYC.id)).filter(
models.KYC.status == models.KYCStatus.REJECTED
).scalar()
return {
"users": {
"total": total_users,
"active": active_users,
"verified": verified_users,
"kyc_verified": kyc_verified_users,
},
"wallets": {
"total_spot_balance": total_spot_balance,
"total_trading_balance": total_trading_balance,
"total_platform_balance": total_spot_balance + total_trading_balance,
},
"deposits": {
"total": total_deposits,
"pending": pending_deposits,
"approved": approved_deposits,
"total_amount": total_deposit_amount,
},
"withdrawals": {
"total": total_withdrawals,
"pending": pending_withdrawals,
"approved": approved_withdrawals,
"total_amount": total_withdrawal_amount,
},
"bots": {
"total": total_bots,
"active": active_bots,
**bot_stats,
},
"kyc": {
"total": total_kyc,
"pending": pending_kyc,
"approved": approved_kyc,
"rejected": rejected_kyc,
},
}