feat: v0.9 样板数据完整性验证/解析加固/报表统计
- 双源确认样板库完整性: search接口与画图编辑器for_ht目录均为254条, 0遗漏 - 全量体检: 6套样板含7个畸形段(缺ps/pe)导致解析报错 前后端重放/算料统一加固过滤, 254样板0异常/1046窗格 - 报表统计模块(/chart): 近N天订单数金额按日柱图+8项总量+状态分布 - 样板库官方/我的样板双Tab(is_default过滤) - 使用指南接入帮助文章接口(种子8篇), seed分类树幂等修复 - 全接口回归18/18通过
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"""报表统计路由(对齐原站 /chart 报表)。"""
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from fastapi import APIRouter
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from huamenchuang.core.deps import CurrentUser, DbSession
|
||||
from huamenchuang.core.response import ok
|
||||
from huamenchuang.models.business import AfterSale, MeasureOrder, Quotation
|
||||
from huamenchuang.models.contract import Contract, Customer
|
||||
from huamenchuang.models.order import Order
|
||||
|
||||
router = APIRouter(prefix="/reports", tags=["报表"])
|
||||
|
||||
|
||||
@router.get("/summary")
|
||||
async def summary(user: CurrentUser, db: DbSession, days: int = 14):
|
||||
"""经营汇总:近 N 天订单数/金额按日 + 各实体总数。"""
|
||||
since = datetime.utcnow() - timedelta(days=days)
|
||||
cid = user.company_id
|
||||
|
||||
# 按日订单数与金额
|
||||
day_rows = (await db.execute(
|
||||
select(func.date(Order.created_at), func.count(), func.sum(Order.money))
|
||||
.where(Order.company_id == cid, Order.created_at >= since)
|
||||
.group_by(func.date(Order.created_at))
|
||||
)).all()
|
||||
by_day = [{"date": str(d), "count": c, "money": float(m or 0)} for d, c, m in day_rows]
|
||||
|
||||
async def count(model, extra=None):
|
||||
conds = [model.company_id == cid]
|
||||
if extra is not None:
|
||||
conds.append(extra)
|
||||
return (await db.execute(select(func.count()).select_from(model).where(*conds))).scalar_one()
|
||||
|
||||
totals = {
|
||||
"orders": await count(Order),
|
||||
"intentions": await count(Order, Order.status == 0),
|
||||
"finished": await count(Order, Order.status == 3),
|
||||
"quotations": await count(Quotation),
|
||||
"customers": await count(Customer),
|
||||
"contracts": await count(Contract),
|
||||
"measures": await count(MeasureOrder),
|
||||
"after_sales": await count(AfterSale, AfterSale.status != 2),
|
||||
}
|
||||
|
||||
# 订单状态分布
|
||||
status_rows = (await db.execute(
|
||||
select(Order.status, func.count()).where(Order.company_id == cid).group_by(Order.status)
|
||||
)).all()
|
||||
status_dist = [{"status": s, "count": c} for s, c in status_rows]
|
||||
|
||||
return ok(data={"by_day": by_day, "totals": totals, "status_dist": status_dist, "days": days})
|
||||
Reference in New Issue
Block a user