from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from app.models.withdraw import WithdrawDB, WithdrawCreate, WithdrawInfo, WithdrawStatus from app.models.user_bank_card import UserBankCardDB from app.models.user_account import UserAccountDB, AccountDetailDB, AccountDetailType from app.models.database import get_db from app.api.deps import get_current_user, get_admin_user from app.models.user import UserDB from app.core.response import success_response, error_response, ResponseModel from decimal import Decimal from typing import List, Optional, Dict from datetime import datetime router = APIRouter() @router.post("", response_model=ResponseModel) async def create_withdraw( withdraw: WithdrawCreate, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """申请提现""" # 验证银行卡 bank_card = db.query(UserBankCardDB).filter( UserBankCardDB.id == withdraw.bank_card_id, UserBankCardDB.user_id == current_user.userid ).first() if not bank_card: return error_response(code=404, message="银行卡不存在") # 验证余额 account = db.query(UserAccountDB).filter( UserAccountDB.user_id == current_user.userid ).first() if not account or account.balance < withdraw.amount: return error_response(code=400, message="余额不足") try: # 创建提现记录 withdraw_record = WithdrawDB( user_id=current_user.userid, bank_card_id=withdraw.bank_card_id, amount=withdraw.amount, status=WithdrawStatus.PENDING ) db.add(withdraw_record) # 更新账户余额 account.balance -= Decimal(str(withdraw.amount)) account.lock_balance += Decimal(str(withdraw.amount)) db.commit() db.refresh(withdraw_record) return success_response(data=WithdrawInfo.model_validate(withdraw_record)) except Exception as e: db.rollback() return error_response(code=500, message=f"申请提现失败: {str(e)}") @router.post("/{withdraw_id}/approve", response_model=ResponseModel) async def approve_withdraw( withdraw_id: int, db: Session = Depends(get_db), admin: UserDB = Depends(get_admin_user) ): """通过提现申请""" withdraw = db.query(WithdrawDB).filter( WithdrawDB.id == withdraw_id, WithdrawDB.status == WithdrawStatus.PENDING ).first() if not withdraw: return error_response(code=404, message="提现申请不存在或已处理") try: # 更新提现状态 withdraw.status = WithdrawStatus.APPROVED # 更新账户锁定余额 account = db.query(UserAccountDB).filter( UserAccountDB.user_id == withdraw.user_id ).first() account.lock_balance -= withdraw.amount # 添加账户明细记录 detail = AccountDetailDB( user_id=withdraw.user_id, type=AccountDetailType.EXPENSE, amount=withdraw.amount, balance=account.balance, description=f"提现到银行卡(尾号{withdraw.bank_card.card_number[-4:]})" ) db.add(detail) db.commit() return success_response(message="提现申请已通过") except Exception as e: db.rollback() return error_response(code=500, message=f"处理失败: {str(e)}") @router.post("/{withdraw_id}/reject", response_model=ResponseModel) async def reject_withdraw( withdraw_id: int, remark: str, db: Session = Depends(get_db), admin: UserDB = Depends(get_admin_user) ): """驳回提现申请""" withdraw = db.query(WithdrawDB).filter( WithdrawDB.id == withdraw_id, WithdrawDB.status == WithdrawStatus.PENDING ).first() if not withdraw: return error_response(code=404, message="提现申请不存在或已处理") try: # 更新提现状态 withdraw.status = WithdrawStatus.REJECTED withdraw.remark = remark # 返还锁定余额 account = db.query(UserAccountDB).filter( UserAccountDB.user_id == withdraw.user_id ).first() account.balance += withdraw.amount account.lock_balance -= withdraw.amount db.commit() return success_response(message="提现申请已驳回") except Exception as e: db.rollback() return error_response(code=500, message=f"处理失败: {str(e)}") @router.get("/user", response_model=ResponseModel) async def get_user_withdraws( status: Optional[WithdrawStatus] = None, db: Session = Depends(get_db), current_user: UserDB = Depends(get_current_user) ): """获取提现记录列表""" query = db.query(WithdrawDB).filter(WithdrawDB.user_id == current_user.userid) if status: query = query.filter(WithdrawDB.status == status) withdraws = query.order_by(WithdrawDB.create_time.desc()).all() return success_response(data=[WithdrawInfo.model_validate(w) for w in withdraws]) @router.get("", response_model=ResponseModel) async def get_all_withdraws( status: Optional[WithdrawStatus] = None, start_time: Optional[datetime] = None, end_time: Optional[datetime] = None, skip: int = 0, limit: int = 20, db: Session = Depends(get_db), admin: UserDB = Depends(get_admin_user) ): """ 管理员获取所有提现记录 Args: status: 提现状态筛选 start_time: 开始时间 end_time: 结束时间 skip: 跳过记录数 limit: 返回记录数 """ # 构建查询 query = db.query(WithdrawDB).join( UserBankCardDB, WithdrawDB.bank_card_id == UserBankCardDB.id ) # 应用筛选条件 if status: query = query.filter(WithdrawDB.status == status) if start_time: query = query.filter(WithdrawDB.create_time >= start_time) if end_time: query = query.filter(WithdrawDB.create_time <= end_time) # 计算总数 total = query.count() # 分页 withdraws = query.order_by(WithdrawDB.create_time.desc())\ .offset(skip)\ .limit(limit)\ .all() # 构建返回数据 withdraw_list = [] for w in withdraws: withdraw_info = WithdrawInfo.model_validate(w) # 添加额外信息 withdraw_info_dict = withdraw_info.model_dump() withdraw_info_dict.update({ "bank_card_number": w.bank_card.card_number, # 银行卡号 "bank_name": w.bank_card.bank_name, # 银行名称 "name": w.bank_card.name # 持卡人姓名 }) withdraw_list.append(withdraw_info_dict) return success_response(data={ "items": withdraw_list, "total": total })