增加支付管理页面的搜索和逻辑

This commit is contained in:
2026-06-11 14:06:02 +08:00
parent bb087cc8a6
commit e975ccc6d2
6 changed files with 343 additions and 193 deletions
+63 -8
View File
@@ -442,10 +442,14 @@ async def batch_update_payment_configs(
@router.get("/payment-stats")
async def get_payment_stats(
payment_method: str | None = Query(None),
status: str | None = Query(None),
start_date: str | None = Query(None),
end_date: str | None = Query(None),
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
"""Return payment statistics for admin dashboard."""
"""Return payment statistics for admin dashboard with filters."""
from sqlalchemy import func
# Ensure by_status has all expected statuses with defaults
@@ -455,13 +459,39 @@ async def get_payment_stats(
"cancelled": {"count": 0, "amount": 0.0},
}
# Parse dates and build base query filters
now_cst = datetime.now(CST)
today_start = now_cst.replace(hour=0, minute=0, second=0, microsecond=0)
today_end = today_start + timedelta(days=1)
# Default to today if no date range provided
query_start = today_start
query_end = today_end
if start_date:
query_start = datetime.fromisoformat(start_date).replace(tzinfo=CST)
if end_date:
query_end = (datetime.fromisoformat(end_date) + timedelta(days=1)).replace(tzinfo=CST)
# Build filter list for status breakdown
breakdown_filters = []
if payment_method:
breakdown_filters.append(PaymentOrder.payment_method == payment_method)
if status:
breakdown_filters.append(PaymentOrder.status == status)
# Always apply date range to breakdown
breakdown_filters.append(PaymentOrder.created_at >= query_start)
breakdown_filters.append(PaymentOrder.created_at < query_end)
# Status breakdown
status_result = await db.execute(
select(
PaymentOrder.status,
func.count().label("count"),
func.coalesce(func.sum(PaymentOrder.amount), 0).label("amount"),
).group_by(PaymentOrder.status)
)
.where(*breakdown_filters)
.group_by(PaymentOrder.status)
)
for row in status_result.all():
if row.status in by_status:
@@ -474,11 +504,7 @@ async def get_payment_stats(
by_status["cancelled"]["count"] += row.count
by_status["cancelled"]["amount"] += round(float(row.amount), 2)
# Today's stats (CST time zone)
now_cst = datetime.now(CST)
today_start = now_cst.replace(hour=0, minute=0, second=0, microsecond=0)
today_end = today_start + timedelta(days=1)
# Today's stats (CST time zone) - independent of filter
today_result = await db.execute(
select(
func.count().label("paid_count"),
@@ -491,9 +517,34 @@ async def get_payment_stats(
)
today_row = today_result.one()
# Recent 50 orders
# Monthly cumulative stats
month_start = now_cst.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
month_end = (month_start + timedelta(days=32)).replace(day=1, hour=0, minute=0, second=0, microsecond=0)
month_result = await db.execute(
select(
func.count().label("paid_count"),
func.coalesce(func.sum(PaymentOrder.amount), 0).label("paid_amount"),
).where(
PaymentOrder.status == "paid",
PaymentOrder.paid_at >= month_start,
PaymentOrder.paid_at < month_end,
)
)
month_row = month_result.one()
# Recent orders with filters
recent_filters = []
if payment_method:
recent_filters.append(PaymentOrder.payment_method == payment_method)
if status:
recent_filters.append(PaymentOrder.status == status)
recent_filters.append(PaymentOrder.created_at >= query_start)
recent_filters.append(PaymentOrder.created_at < query_end)
recent_result = await db.execute(
select(PaymentOrder)
.where(*recent_filters)
.order_by(PaymentOrder.created_at.desc())
.limit(50)
)
@@ -505,6 +556,10 @@ async def get_payment_stats(
"paid_count": today_row.paid_count,
"paid_amount": round(float(today_row.paid_amount), 2),
},
"month": {
"paid_count": month_row.paid_count,
"paid_amount": round(float(month_row.paid_amount), 2),
},
"recent": [
{
"id": o.id,