import json from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db, get_admin_user from app.models.user import User from app.models.recharge_package import RechargePackage from app.schemas.recharge_package import ( RechargePackageCreate, RechargePackageUpdate, RechargePackageOut, ) from app.services.operation_log import log_operation from app.utils.id_gen import generate_id router = APIRouter(prefix="/admin/recharge-packages", tags=["admin-recharge-packages"]) def _to_out(pkg: RechargePackage) -> dict: return { "id": pkg.id, "name": pkg.name, "credits": round(pkg.credits, 2), "price": round(pkg.price, 2), "bonus_credits": round(pkg.bonus_credits, 2), "total_credits": round(pkg.credits + pkg.bonus_credits, 2), "description": pkg.description, "package_type": pkg.package_type, "is_gift": pkg.is_gift, "is_active": pkg.is_active, "sort_order": pkg.sort_order, } @router.get("", response_model=list[RechargePackageOut]) async def admin_list_packages( admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RechargePackage).order_by(RechargePackage.sort_order) ) return [_to_out(p) for p in result.scalars().all()] @router.post("", response_model=RechargePackageOut) async def create_package( data: RechargePackageCreate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): pkg = RechargePackage(id=generate_id(), **data.model_dump()) db.add(pkg) await db.flush() await log_operation( db, admin.id, admin.username, f"创建充值套餐 {pkg.name}", "POST", "/admin/recharge-packages", detail=json.dumps( { "id": pkg.id, "name": pkg.name, "price": round(pkg.price, 2), "credits": round(pkg.credits, 2), "bonus_credits": round(pkg.bonus_credits, 2), }, ensure_ascii=False, ), ) await db.commit() return _to_out(pkg) @router.put("/{pkg_id}", response_model=RechargePackageOut) async def update_package( pkg_id: str, data: RechargePackageUpdate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RechargePackage).where(RechargePackage.id == pkg_id).limit(1) ) pkg = result.scalar_one_or_none() if not pkg: raise HTTPException(status_code=404, detail="套餐不存在") before = _to_out(pkg) for k, v in data.model_dump(exclude_unset=True).items(): setattr(pkg, k, v) await db.flush() after = _to_out(pkg) await log_operation( db, admin.id, admin.username, f"更新充值套餐 {pkg.name}", "PUT", f"/admin/recharge-packages/{pkg_id}", detail=json.dumps( { "id": pkg_id, "before": before, "after": after, }, ensure_ascii=False, ), ) await db.commit() return _to_out(pkg) @router.delete("/{pkg_id}") async def delete_package( pkg_id: str, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RechargePackage).where(RechargePackage.id == pkg_id).limit(1) ) pkg = result.scalar_one_or_none() if not pkg: raise HTTPException(status_code=404, detail="套餐不存在") pkg_name = pkg.name await db.delete(pkg) await db.flush() await log_operation( db, admin.id, admin.username, f"删除充值套餐 {pkg_name}", "DELETE", f"/admin/recharge-packages/{pkg_id}", detail=json.dumps( { "id": pkg_id, "name": pkg_name, }, ensure_ascii=False, ), ) await db.commit() return {"ok": True}