173 lines
5.5 KiB
Python
173 lines
5.5 KiB
Python
from typing import Optional, Literal
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func, and_, extract
|
|
from datetime import datetime, timedelta
|
|
from decimal import Decimal
|
|
|
|
from app.database import get_db
|
|
from app.models import (
|
|
User, Employee, SecondaryAgent, ProductCategory,
|
|
PerformanceRecord, CalculationResult
|
|
)
|
|
from app.routers.auth import get_current_user
|
|
|
|
router = APIRouter(prefix="/dashboard", tags=["数据看板"])
|
|
|
|
|
|
@router.get("/summary", response_model=dict)
|
|
def get_dashboard_summary(
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""获取仪表盘汇总数据"""
|
|
# 本月业绩总额
|
|
now = datetime.now()
|
|
start_of_month = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
|
|
monthly_performance = db.query(
|
|
func.coalesce(func.sum(PerformanceRecord.amount), Decimal("0"))
|
|
).filter(
|
|
PerformanceRecord.record_date >= start_of_month.date()
|
|
).scalar()
|
|
|
|
# 员工收益总额(本月)
|
|
monthly_income = db.query(
|
|
func.coalesce(func.sum(CalculationResult.total_income), Decimal("0"))
|
|
).filter(
|
|
CalculationResult.calc_year == now.year,
|
|
CalculationResult.calc_month == now.month
|
|
).scalar()
|
|
|
|
# 员工总数
|
|
employee_count = db.query(Employee).join(User).filter(User.status == 1).count()
|
|
|
|
# 二级代理总数
|
|
agent_count = db.query(SecondaryAgent).join(User).filter(User.status == 1).count()
|
|
|
|
# 产品分类数
|
|
category_count = db.query(ProductCategory).filter(ProductCategory.status == 1).count()
|
|
|
|
return {
|
|
"code": 200,
|
|
"message": "success",
|
|
"data": {
|
|
"total_performance": str(monthly_performance),
|
|
"total_income": str(monthly_income),
|
|
"employee_count": employee_count,
|
|
"agent_count": agent_count,
|
|
"category_count": category_count
|
|
}
|
|
}
|
|
|
|
|
|
@router.get("/chart", response_model=dict)
|
|
def get_dashboard_chart(
|
|
type: Literal["performance", "category"] = Query(..., description="图表类型"),
|
|
months: int = Query(6, ge=1, le=12, description="显示月数"),
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""获取仪表盘图表数据"""
|
|
|
|
if type == "performance":
|
|
# 业绩趋势数据
|
|
end_date = datetime.now()
|
|
data = []
|
|
|
|
for i in range(months - 1, -1, -1):
|
|
month_date = end_date - timedelta(days=i * 30)
|
|
start_of_month = month_date.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
if month_date.month == 12:
|
|
end_of_month = month_date.replace(year=month_date.year + 1, month=1, day=1)
|
|
else:
|
|
end_of_month = month_date.replace(month=month_date.month + 1, day=1)
|
|
|
|
amount = db.query(
|
|
func.coalesce(func.sum(PerformanceRecord.amount), Decimal("0"))
|
|
).filter(
|
|
PerformanceRecord.record_date >= start_of_month.date(),
|
|
PerformanceRecord.record_date < end_of_month.date()
|
|
).scalar()
|
|
|
|
data.append({
|
|
"month": month_date.strftime("%Y-%m"),
|
|
"amount": float(amount)
|
|
})
|
|
|
|
return {
|
|
"code": 200,
|
|
"message": "success",
|
|
"data": data
|
|
}
|
|
|
|
elif type == "category":
|
|
# 产品分类占比数据
|
|
results = db.query(
|
|
ProductCategory.name,
|
|
func.coalesce(func.sum(PerformanceRecord.amount), Decimal("0")).label("amount")
|
|
).outerjoin(
|
|
PerformanceRecord, ProductCategory.id == PerformanceRecord.category_id
|
|
).filter(
|
|
ProductCategory.status == 1
|
|
).group_by(ProductCategory.id).all()
|
|
|
|
data = [
|
|
{"name": name, "amount": float(amount)}
|
|
for name, amount in results if amount > 0
|
|
]
|
|
|
|
return {
|
|
"code": 200,
|
|
"message": "success",
|
|
"data": data
|
|
}
|
|
|
|
return {
|
|
"code": 400,
|
|
"message": "不支持的图表类型",
|
|
"data": []
|
|
}
|
|
|
|
|
|
@router.get("/recent-performance", response_model=dict)
|
|
def get_recent_performance(
|
|
limit: int = Query(5, ge=1, le=20),
|
|
db: Session = Depends(get_db),
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""获取最近业绩记录"""
|
|
records = db.query(PerformanceRecord).order_by(
|
|
PerformanceRecord.record_date.desc()
|
|
).limit(limit).all()
|
|
|
|
data = []
|
|
for record in records:
|
|
employee_name = None
|
|
if record.employee_id:
|
|
emp = db.query(Employee).filter(Employee.id == record.employee_id).first()
|
|
if emp and emp.user:
|
|
employee_name = emp.user.name
|
|
|
|
category_name = None
|
|
if record.category_id:
|
|
cat = db.query(ProductCategory).filter(ProductCategory.id == record.category_id).first()
|
|
if cat:
|
|
category_name = cat.name
|
|
|
|
data.append({
|
|
"id": record.id,
|
|
"record_date": record.record_date.isoformat() if record.record_date else None,
|
|
"employee_name": employee_name,
|
|
"category_name": category_name,
|
|
"amount": str(record.amount),
|
|
"customer_name": record.customer_name,
|
|
"order_no": record.order_no
|
|
})
|
|
|
|
return {
|
|
"code": 200,
|
|
"message": "success",
|
|
"data": data
|
|
}
|