fix: 排行榜返回完整统计字段并跟随后台排序方案
This commit is contained in:
@@ -109,14 +109,14 @@ def sort_field_options_for_shenfen(shenfen: str) -> list:
|
||||
|
||||
|
||||
def resolve_sort_field_for_display(club_id: str, shenfen: str, riqi: str) -> tuple[str, str]:
|
||||
"""按后台奖励方案决定展示/排序字段(进行中与已结束周期均适用)。"""
|
||||
"""按后台奖励方案决定展示/排序字段(方案存在即生效,与是否启用奖励无关)。"""
|
||||
period_type = RIQI_TO_PERIOD.get(riqi) or OPEN_RIQI_PERIOD_MAP.get(riqi)
|
||||
sort_field = None
|
||||
if period_type:
|
||||
scheme = RankRewardScheme.query.filter(
|
||||
scheme = RankRewardScheme.objects.filter(
|
||||
club_id=club_id, shenfen=shenfen, period_type=period_type,
|
||||
).first()
|
||||
if scheme and scheme.enabled:
|
||||
if scheme:
|
||||
reg = SORT_FIELD_REGISTRY.get(shenfen) or {}
|
||||
if scheme.sort_field in reg:
|
||||
sort_field = scheme.sort_field
|
||||
@@ -299,6 +299,137 @@ def _query_group_rank_rows(shenfen: str, sort_field: str, riqi: str, limit: int
|
||||
]
|
||||
|
||||
|
||||
def _fmt_stat_value(val, is_int: bool):
|
||||
if val is None:
|
||||
return 0 if is_int else 0.0
|
||||
if is_int:
|
||||
return int(val)
|
||||
if isinstance(val, Decimal):
|
||||
return float(val.quantize(Decimal('0.01')))
|
||||
return float(val)
|
||||
|
||||
|
||||
def _enrich_today_profiles(shenfen: str, yonghuids: list) -> dict:
|
||||
"""今日日统计为空时,从 Profile 补全展示字段(与 phbhqsj 回退一致)。"""
|
||||
from users.models import UserDashou, UserGuanshi, UserShangjia, UserZuzhang
|
||||
from users.paihang_views import ROLE_CONFIG
|
||||
|
||||
cfg = ROLE_CONFIG[shenfen]
|
||||
response_field_map = cfg['response_field_map']
|
||||
int_fields = cfg['int_fields']
|
||||
id_field = cfg['id_field']
|
||||
|
||||
profile_cfg = {
|
||||
'dashou': (UserDashou, {
|
||||
'AcceptedOrderTotal': 'jinrijiedan',
|
||||
'CompletedOrderTotal': 'jinrijiedan',
|
||||
'AcceptedAmount': 'jinrishouyi',
|
||||
'CompletedAmount': 'jinrishouyi',
|
||||
}),
|
||||
'guanshi': (UserGuanshi, {
|
||||
'InvitedPlayerCount': None,
|
||||
'RechargedPlayerCount': 'jinrichongzhi',
|
||||
'TotalIncome': None,
|
||||
}),
|
||||
'zuzhang': (UserZuzhang, {
|
||||
'InvitedManagerCount': None,
|
||||
'CommissionAmount': 'jinri_fenyong',
|
||||
'TotalIncome': 'jinri_fenyong',
|
||||
}),
|
||||
'shangjia': (UserShangjia, {
|
||||
'AssignedOrderCount': 'jinridingdan',
|
||||
'AssignedAmount': 'jinriliushui',
|
||||
'SettledOrderCount': None,
|
||||
'SettledAmount': None,
|
||||
}),
|
||||
}
|
||||
model_cls, field_map = profile_cfg.get(shenfen, (None, {}))
|
||||
if not model_cls:
|
||||
return {}
|
||||
|
||||
out = {}
|
||||
qs = model_cls.objects.filter(user__UserUID__in=yonghuids).select_related('user')
|
||||
for p in qs:
|
||||
uid = p.user.UserUID
|
||||
row = {}
|
||||
for db_field, profile_field in field_map.items():
|
||||
key = response_field_map.get(db_field, db_field)
|
||||
if profile_field:
|
||||
val = getattr(p, profile_field, 0) or 0
|
||||
else:
|
||||
val = 0
|
||||
row[key] = _fmt_stat_value(val, db_field in int_fields)
|
||||
out[uid] = row
|
||||
return out
|
||||
|
||||
|
||||
def enrich_rank_stats(shenfen: str, yonghuids: list, riqi: str, club_id: str = '') -> dict:
|
||||
"""加载榜单行完整统计(排序指标 + 其它单量/金额),避免前端只看到一个数。"""
|
||||
if not yonghuids:
|
||||
return {}
|
||||
from users.paihang_views import ROLE_CONFIG
|
||||
|
||||
cfg = ROLE_CONFIG[shenfen]
|
||||
model = cfg['model']
|
||||
id_field = cfg['id_field']
|
||||
fields = cfg['fields']
|
||||
int_fields = cfg['int_fields']
|
||||
response_field_map = cfg['response_field_map']
|
||||
|
||||
base_filter = {f'{id_field}__in': yonghuids}
|
||||
if club_id and hasattr(model, 'club_id'):
|
||||
base_filter['club_id'] = club_id
|
||||
|
||||
result = {uid: {} for uid in yonghuids}
|
||||
|
||||
def _fill_from_row(uid, row_data):
|
||||
for f in fields:
|
||||
key = response_field_map.get(f, f)
|
||||
result[uid][key] = _fmt_stat_value(row_data.get(f), f in int_fields)
|
||||
|
||||
if riqi == '总榜':
|
||||
rows = (
|
||||
model.objects.filter(**base_filter)
|
||||
.values(id_field)
|
||||
.annotate(**{f: Sum(f) for f in fields})
|
||||
)
|
||||
for r in rows:
|
||||
uid = r[id_field]
|
||||
if uid in result:
|
||||
_fill_from_row(uid, r)
|
||||
return result
|
||||
|
||||
date_range = _resolve_date_range_for_display(riqi)
|
||||
if not date_range:
|
||||
return result
|
||||
start_date, end_date = date_range
|
||||
|
||||
if start_date == end_date:
|
||||
qs = model.objects.filter(Date=start_date, **base_filter)
|
||||
if qs.exists():
|
||||
for r in qs:
|
||||
uid = getattr(r, id_field)
|
||||
if uid not in result:
|
||||
continue
|
||||
row_data = {f: getattr(r, f) for f in fields}
|
||||
_fill_from_row(uid, row_data)
|
||||
return result
|
||||
if riqi == '今日':
|
||||
return _enrich_today_profiles(shenfen, yonghuids)
|
||||
return result
|
||||
|
||||
rows = (
|
||||
model.objects.filter(Date__gte=start_date, Date__lte=end_date, **base_filter)
|
||||
.values(id_field)
|
||||
.annotate(**{f: Sum(f) for f in fields})
|
||||
)
|
||||
for r in rows:
|
||||
uid = r[id_field]
|
||||
if uid in result:
|
||||
_fill_from_row(uid, r)
|
||||
return result
|
||||
|
||||
|
||||
def load_user_club_map(yonghuids: list) -> dict:
|
||||
if not yonghuids:
|
||||
return {}
|
||||
@@ -327,7 +458,7 @@ def tier_amount_for_rank(tiers, mingci: int) -> Optional[Decimal]:
|
||||
|
||||
def build_tier_rewards_preview(scheme) -> dict:
|
||||
"""按方案档位生成各名次预计奖金(进行中周期展示用)。"""
|
||||
if not scheme or not scheme.enabled:
|
||||
if not scheme:
|
||||
return {}
|
||||
tiers = list(RankRewardTier.query.filter(scheme_id=scheme.id).order_by('rank_from'))
|
||||
if not tiers:
|
||||
|
||||
@@ -13,6 +13,7 @@ from rank.reward_services import (
|
||||
SORT_FIELD_LABELS,
|
||||
build_reward_payload,
|
||||
claim_reward,
|
||||
enrich_rank_stats,
|
||||
list_my_pending_claims,
|
||||
query_club_rank_rows,
|
||||
query_group_rank_rows,
|
||||
@@ -53,9 +54,10 @@ def _load_display_maps(yonghuids, shenfen):
|
||||
return nick_map, avatar_map
|
||||
|
||||
|
||||
def _format_rank_list(rows, shenfen, sort_field, sort_label):
|
||||
def _format_rank_list(rows, shenfen, sort_field, sort_label, riqi='', club_id=''):
|
||||
yonghuids = [r['yonghuid'] for r in rows]
|
||||
nick_map, avatar_map = _load_display_maps(yonghuids, shenfen)
|
||||
stats_map = enrich_rank_stats(shenfen, yonghuids, riqi, club_id or '')
|
||||
club_map = {}
|
||||
try:
|
||||
from rank.reward_services import load_user_club_map
|
||||
@@ -86,6 +88,9 @@ def _format_rank_list(rows, shenfen, sort_field, sort_label):
|
||||
'metric_label': sort_label,
|
||||
'metric_is_int': is_int,
|
||||
}
|
||||
extra = stats_map.get(uid) or {}
|
||||
for k, v in extra.items():
|
||||
item[k] = v
|
||||
item[sort_field] = item['metric_value']
|
||||
result.append(item)
|
||||
return result
|
||||
@@ -180,16 +185,21 @@ class PhbJlPhbView(APIView):
|
||||
|
||||
if fanwei == 'club':
|
||||
rows = query_club_rank_rows(club_id, shenfen, sort_field, riqi)
|
||||
enrich_club = club_id
|
||||
else:
|
||||
rows = query_group_rank_rows(shenfen, sort_field, riqi)
|
||||
enrich_club = ''
|
||||
|
||||
result_list = _format_rank_list(rows, shenfen, sort_field, sort_label)
|
||||
result_list = _format_rank_list(
|
||||
rows, shenfen, sort_field, sort_label, riqi=riqi, club_id=enrich_club,
|
||||
)
|
||||
reward = build_reward_payload(club_id, shenfen, riqi, request.user.UserUID)
|
||||
|
||||
# 仅俱乐部榜展示各行奖金(集团总榜名次与俱乐部分奖名次不同,不可混用)
|
||||
rank_rewards = reward.get('rank_rewards') or {}
|
||||
tier_rewards = reward.get('tier_rewards') or {}
|
||||
if fanwei == 'club' and reward.get('scheme_enabled'):
|
||||
tiers = reward.get('tiers') or []
|
||||
if fanwei == 'club' and (reward.get('scheme_enabled') or tiers):
|
||||
for item in result_list:
|
||||
mc = item['mingci']
|
||||
settled = rank_rewards.get(mc)
|
||||
|
||||
Reference in New Issue
Block a user