fix: 修复统计页面无数据问题 - base_filter判断逻辑修正
This commit is contained in:
parent
4ae29eb4bf
commit
58c2291e83
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue