deliveryman-api/app/api/endpoints/withdraw.py
2025-01-24 23:01:31 +08:00

214 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.WITHDRAW,
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
})