fix: 修复统计页面无数据问题 - base_filter判断逻辑修正

This commit is contained in:
甲辰生产 2026-04-17 14:19:07 +08:00
parent 4ae29eb4bf
commit 58c2291e83
1 changed files with 209 additions and 66 deletions

View File

@ -5,7 +5,7 @@ import re
from typing import Optional, List
from fastapi import APIRouter, Depends, HTTPException, status, Query, UploadFile, File
from sqlalchemy import func, text
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, joinedload
from app.core.database import get_db
from app.core.auth import get_current_user
from app.core.logging_config import logger
@ -195,6 +195,9 @@ def get_collections(
# 总数(应用筛选条件后的数量)
total = query.count()
# 使用joinedload预加载图片避免N+1查询问题
query = query.options(joinedload(Collection.images))
# 分页
data = query.order_by(Collection.f99_92_created_at.desc()) \
.offset((page - 1) * limit) \
@ -246,13 +249,8 @@ def get_collections(
'images': []
}
# 加载图片数据
from app.models.models import CollectionImage
images = db.query(CollectionImage).filter(
CollectionImage.collection_id == collection_item.f99_90_id
).all()
for img in images:
# 直接使用预加载的图片数据,无需再查询
for img in collection_item.images:
item_dict['images'].append({
'id': img.id,
'filename': img.filename,
@ -279,69 +277,215 @@ def get_stats(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""获取藏品统计"""
# 获取所有藏品
if current_user is None or current_user.role != "admin":
all_collections = db.query(Collection).filter(
Collection.f99_91_user_id == current_user.f99_90_id
).all()
"""获取藏品统计 - 使用SQL聚合查询优化性能"""
# 非管理员或未登录用户只能查看自己的藏品
if current_user is None:
return {
"totalCount": 0,
"byCategory": [],
"byStatus": [],
"byGrading": [],
"byPackaging": [],
"byRarity": [],
"byVersion": [],
"byGradingCompany": [],
"byGradingScore": [],
"bySpecialMark": [],
"byNumberCategory": [],
"byProfitLoss": [],
"totalCost": 0,
"totalTarget": 0,
"expectedProfit": 0,
"totalRevenue": 0,
"totalProfit": 0
}
# 构建基础查询条件
is_admin = current_user.role == "admin"
if not is_admin:
base_filter = Collection.f99_91_user_id == current_user.f99_90_id
else:
all_collections = db.query(Collection).all()
base_filter = None
# 总数
total_count = len(all_collections)
# 总数 - 使用SQL COUNT
total_count = db.query(func.count(Collection.f99_90_id)).filter(
base_filter if base_filter is not None else True
).scalar()
if base_filter is not None:
total_count = db.query(func.count(Collection.f99_90_id)).filter(base_filter).scalar()
else:
total_count = db.query(func.count(Collection.f99_90_id)).scalar()
# 按分类统计
from collections import Counter
by_category = Counter(c.f01_03_category for c in all_collections).items()
# 按分类统计 - 使用SQL GROUP BY
if base_filter is not None:
by_category = db.query(
Collection.f01_03_category,
func.count(Collection.f99_90_id)
).filter(base_filter).group_by(Collection.f01_03_category).all()
# 按状态统计
by_status = Counter(c.f01_04_status for c in all_collections).items()
by_status = db.query(
Collection.f01_04_status,
func.count(Collection.f99_90_id)
).filter(base_filter).group_by(Collection.f01_04_status).all()
# 按是否评级统计
by_graded = Counter(c.f03_20_is_graded for c in all_collections).items()
by_graded = db.query(
Collection.f03_20_is_graded,
func.count(Collection.f99_90_id)
).filter(base_filter).group_by(Collection.f03_20_is_graded).all()
# 新增8 个分布统计
by_packaging = Counter(c.f02_12_packaging for c in all_collections if c.f02_12_packaging).items()
by_rarity = Counter(c.f02_13_rarity for c in all_collections if c.f02_13_rarity).items()
by_version = Counter(c.f02_11_version for c in all_collections if c.f02_11_version).items()
by_grading_company = Counter(c.f03_21_grading_company for c in all_collections if c.f03_20_is_graded and c.f03_21_grading_company).items()
by_grading_score = Counter(c.f03_22_grading_score for c in all_collections if c.f03_20_is_graded and c.f03_22_grading_score).items()
by_special_mark = Counter(c.f04_30_special_mark for c in all_collections if c.f04_30_special_mark).items()
by_number_category = Counter(c.f02_14_number_category for c in all_collections if c.f02_14_number_category).items()
by_packaging = db.query(
Collection.f02_12_packaging,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f02_12_packaging.isnot(None)).group_by(Collection.f02_12_packaging).all()
# 总成本: SUM(cost_price + repair_fee + grading_fee) for ALL collections
total_cost = sum(
(c.f05_40_cost_price or 0) + (c.f05_43_repair_fee or 0) + (c.f05_44_grading_fee or 0)
for c in all_collections
)
by_rarity = db.query(
Collection.f02_13_rarity,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f02_13_rarity.isnot(None)).group_by(Collection.f02_13_rarity).all()
# 预期利润: SUM(target_price - cost_price) for collections with target_price > 0
expected_profit = sum(
(c.f05_41_target_price or 0) - (c.f05_40_cost_price or 0)
for c in all_collections
if c.f05_41_target_price and c.f05_41_target_price > 0
)
by_version = db.query(
Collection.f02_11_version,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f02_11_version.isnot(None)).group_by(Collection.f02_11_version).all()
# 已售商品:状态为 sold 且出售价 > 0
sold_collections = [
c for c in all_collections
if c.f01_04_status == 'sold' and c.f05_42_goal_price and c.f05_42_goal_price > 0
]
by_grading_company = db.query(
Collection.f03_21_grading_company,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f03_20_is_graded == True, Collection.f03_21_grading_company.isnot(None)).group_by(Collection.f03_21_grading_company).all()
# 总收入SUM(出售价) for 已售商品(售价>0
total_revenue = sum(
c.f05_42_goal_price or 0
for c in sold_collections
)
by_grading_score = db.query(
Collection.f03_22_grading_score,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f03_20_is_graded == True, Collection.f03_22_grading_score.isnot(None)).group_by(Collection.f03_22_grading_score).all()
# 总利润已实现利润SUM(出售价 - 成本价 - 修复费 - 评级费) for 已售商品
# 单藏品总成本 = 成本价 + 修复费 + 评级费
by_special_mark = db.query(
Collection.f04_30_special_mark,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f04_30_special_mark.isnot(None)).group_by(Collection.f04_30_special_mark).all()
by_number_category = db.query(
Collection.f02_14_number_category,
func.count(Collection.f99_90_id)
).filter(base_filter, Collection.f02_14_number_category.isnot(None)).group_by(Collection.f02_14_number_category).all()
# 成本相关统计 - 使用SQL SUM
cost_result = db.query(
func.coalesce(func.sum(Collection.f05_40_cost_price), 0) +
func.coalesce(func.sum(Collection.f05_43_repair_fee), 0) +
func.coalesce(func.sum(Collection.f05_44_grading_fee), 0)
).filter(base_filter).first()
total_cost = cost_result[0] if cost_result else 0
# 预期利润
expected_profit_result = db.query(
func.coalesce(func.sum(Collection.f05_41_target_price - Collection.f05_40_cost_price), 0)
).filter(base_filter, Collection.f05_41_target_price.isnot(None), Collection.f05_41_target_price > 0).first()
expected_profit = expected_profit_result[0] if expected_profit_result else 0
# 已售藏品统计
sold_collections = db.query(Collection).filter(
base_filter,
Collection.f01_04_status == 'sold',
Collection.f05_42_goal_price.isnot(None),
Collection.f05_42_goal_price > 0
).all()
else:
# 管理员查看所有数据
by_category = db.query(
Collection.f01_03_category,
func.count(Collection.f99_90_id)
).group_by(Collection.f01_03_category).all()
by_status = db.query(
Collection.f01_04_status,
func.count(Collection.f99_90_id)
).group_by(Collection.f01_04_status).all()
by_graded = db.query(
Collection.f03_20_is_graded,
func.count(Collection.f99_90_id)
).group_by(Collection.f03_20_is_graded).all()
by_packaging = db.query(
Collection.f02_12_packaging,
func.count(Collection.f99_90_id)
).filter(Collection.f02_12_packaging.isnot(None)).group_by(Collection.f02_12_packaging).all()
by_rarity = db.query(
Collection.f02_13_rarity,
func.count(Collection.f99_90_id)
).filter(Collection.f02_13_rarity.isnot(None)).group_by(Collection.f02_13_rarity).all()
by_version = db.query(
Collection.f02_11_version,
func.count(Collection.f99_90_id)
).filter(Collection.f02_11_version.isnot(None)).group_by(Collection.f02_11_version).all()
by_grading_company = db.query(
Collection.f03_21_grading_company,
func.count(Collection.f99_90_id)
).filter(Collection.f03_20_is_graded == True, Collection.f03_21_grading_company.isnot(None)).group_by(Collection.f03_21_grading_company).all()
by_grading_score = db.query(
Collection.f03_22_grading_score,
func.count(Collection.f99_90_id)
).filter(Collection.f03_20_is_graded == True, Collection.f03_22_grading_score.isnot(None)).group_by(Collection.f03_22_grading_score).all()
by_special_mark = db.query(
Collection.f04_30_special_mark,
func.count(Collection.f99_90_id)
).filter(Collection.f04_30_special_mark.isnot(None)).group_by(Collection.f04_30_special_mark).all()
by_number_category = db.query(
Collection.f02_14_number_category,
func.count(Collection.f99_90_id)
).filter(Collection.f02_14_number_category.isnot(None)).group_by(Collection.f02_14_number_category).all()
# 总成本
cost_result = db.query(
func.coalesce(func.sum(Collection.f05_40_cost_price), 0) +
func.coalesce(func.sum(Collection.f05_43_repair_fee), 0) +
func.coalesce(func.sum(Collection.f05_44_grading_fee), 0)
).first()
total_cost = cost_result[0] if cost_result else 0
# 预期利润
expected_profit_result = db.query(
func.coalesce(func.sum(Collection.f05_41_target_price - Collection.f05_40_cost_price), 0)
).filter(Collection.f05_41_target_price.isnot(None), Collection.f05_41_target_price > 0).first()
expected_profit = expected_profit_result[0] if expected_profit_result else 0
# 已售藏品
sold_collections = db.query(Collection).filter(
Collection.f01_04_status == 'sold',
Collection.f05_42_goal_price.isnot(None),
Collection.f05_42_goal_price > 0
).all()
# 总收入和总利润(已售藏品)
total_revenue = sum(c.f05_42_goal_price or 0 for c in sold_collections)
total_profit = sum(
(c.f05_42_goal_price or 0) - (c.f05_40_cost_price or 0) - (c.f05_43_repair_fee or 0) - (c.f05_44_grading_fee or 0)
for c in sold_collections
)
# 盈亏统计
profit_count = sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price > c.f05_40_cost_price)
loss_count = sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price <= c.f05_40_cost_price)
# 目标价格总和
total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).filter(
base_filter if base_filter is not None else True
).first()
if base_filter is not None:
total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).filter(base_filter).first()
else:
total_target_result = db.query(func.coalesce(func.sum(Collection.f05_41_target_price), 0)).first()
total_target = total_target_result[0] if total_target_result else 0
return {
"totalCount": total_count,
"byCategory": [{"category": c, "count": n} for c, n in by_category],
@ -354,13 +498,12 @@ def get_stats(
"byGradingScore": [{"score": s, "count": n} for s, n in by_grading_score],
"bySpecialMark": [{"mark": m, "count": n} for m, n in by_special_mark],
"byNumberCategory": [{"numberCategory": n, "count": c} for n, c in by_number_category],
# 盈亏统计(只统计已售且有价格的藏品)
"byProfitLoss": [
{"type": "profit", "label": "盈利", "count": sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price > c.f05_40_cost_price)},
{"type": "loss", "label": "亏损", "count": sum(1 for c in sold_collections if c.f05_42_goal_price and c.f05_40_cost_price and c.f05_42_goal_price <= c.f05_40_cost_price)}
{"type": "profit", "label": "盈利", "count": profit_count},
{"type": "loss", "label": "亏损", "count": loss_count}
],
"totalCost": total_cost,
"totalTarget": sum(c.f05_41_target_price or 0 for c in all_collections),
"totalTarget": total_target,
"expectedProfit": expected_profit,
"totalRevenue": total_revenue,
"totalProfit": total_profit