deliveryman-api/app/api/endpoints/statistics.py
2025-03-11 08:59:27 +08:00

176 lines
5.9 KiB
Python
Raw Permalink 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, HTTPException, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime, date, timedelta
from app.models.database import get_db
from app.models.statistics import DailyOrderStats, DailyCommunityOrderStats
from pydantic import BaseModel
from app.api.deps import get_current_user
from enum import Enum
router = APIRouter()
class DailyOrderStatsResponse(BaseModel):
stats_date: date
total_order_count: int
total_original_amount: float
total_final_amount: float
total_communities: int
class Config:
from_attributes = True
class DailyCommunityOrderStatsResponse(BaseModel):
stats_date: date
community_id: int
community_name: str
order_count: int
total_original_amount: float
total_final_amount: float
class Config:
from_attributes = True
class OrderFilter(str, Enum):
ALL = "all" # 所有小区
WITH_ORDERS = "with_orders" # 有订单的小区
WITHOUT_ORDERS = "without_orders" # 没有订单的小区
@router.get("/daily-stats", response_model=List[DailyOrderStatsResponse])
async def get_daily_order_stats(
start_date: Optional[date] = None,
end_date: Optional[date] = None,
limit: int = Query(30, ge=1, le=100),
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""
获取每日订单统计数据
- **start_date**: 开始日期(可选)
- **end_date**: 结束日期(可选)
- **limit**: 返回记录数量限制默认30条
"""
query = db.query(DailyOrderStats)
if start_date:
query = query.filter(DailyOrderStats.stats_date >= start_date)
if end_date:
query = query.filter(DailyOrderStats.stats_date <= end_date)
# 按日期降序排序,最新的在前面
query = query.order_by(DailyOrderStats.stats_date.desc()).limit(limit)
return query.all()
@router.get("/daily-stats/{stats_date}", response_model=DailyOrderStatsResponse)
async def get_daily_order_stats_by_date(
stats_date: date,
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""
获取指定日期的订单统计数据
- **stats_date**: 统计日期
"""
stats = db.query(DailyOrderStats).filter(
DailyOrderStats.stats_date == stats_date
).first()
if not stats:
raise HTTPException(status_code=404, detail=f"未找到{stats_date}的统计数据")
return stats
@router.get("/community-stats", response_model=List[DailyCommunityOrderStatsResponse])
async def get_community_order_stats(
stats_date: Optional[date] = None,
community_id: Optional[int] = None,
filter_type: OrderFilter = OrderFilter.ALL,
limit: int = Query(50, ge=1, le=500),
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""
获取小区订单统计数据
- **stats_date**: 统计日期(可选)
- **community_id**: 小区ID可选
- **filter_type**: 过滤类型all: 所有小区, with_orders: 有订单的小区, without_orders: 没有订单的小区)
- **limit**: 返回记录数量限制默认50条
"""
query = db.query(DailyCommunityOrderStats)
if stats_date:
query = query.filter(DailyCommunityOrderStats.stats_date == stats_date)
if community_id:
query = query.filter(DailyCommunityOrderStats.community_id == community_id)
# 根据过滤类型筛选
if filter_type == OrderFilter.WITH_ORDERS:
query = query.filter(DailyCommunityOrderStats.order_count > 0)
elif filter_type == OrderFilter.WITHOUT_ORDERS:
query = query.filter(DailyCommunityOrderStats.order_count == 0)
# 如果没有指定日期,则按日期降序排序
if not stats_date:
query = query.order_by(DailyCommunityOrderStats.stats_date.desc())
# 按订单数量降序排序
if filter_type != OrderFilter.WITHOUT_ORDERS:
query = query.order_by(DailyCommunityOrderStats.order_count.desc())
else:
# 对于无订单的小区,按小区名称排序
query = query.order_by(DailyCommunityOrderStats.community_name)
query = query.limit(limit)
return query.all()
@router.get("/community-stats/{community_id}/trend", response_model=List[DailyCommunityOrderStatsResponse])
async def get_community_order_stats_trend(
community_id: int,
days: int = Query(7, ge=1, le=30),
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""
获取指定小区的订单统计趋势数据
- **community_id**: 小区ID
- **days**: 天数默认7天
"""
end_date = datetime.now().date()
start_date = end_date - timedelta(days=days)
stats = db.query(DailyCommunityOrderStats).filter(
DailyCommunityOrderStats.community_id == community_id,
DailyCommunityOrderStats.stats_date >= start_date,
DailyCommunityOrderStats.stats_date <= end_date
).order_by(DailyCommunityOrderStats.stats_date.asc()).all()
return stats
@router.get("/community-stats/date/{stats_date}/summary", response_model=List[DailyCommunityOrderStatsResponse])
async def get_community_stats_summary_by_date(
stats_date: date,
top_n: int = Query(10, ge=1, le=100),
db: Session = Depends(get_db),
current_user = Depends(get_current_user)
):
"""
获取指定日期的小区订单统计摘要前N名
- **stats_date**: 统计日期
- **top_n**: 返回前N名小区默认10
"""
stats = db.query(DailyCommunityOrderStats).filter(
DailyCommunityOrderStats.stats_date == stats_date,
DailyCommunityOrderStats.order_count > 0
).order_by(DailyCommunityOrderStats.order_count.desc()).limit(top_n).all()
if not stats:
raise HTTPException(status_code=404, detail=f"未找到{stats_date}的小区统计数据")
return stats