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]:
|
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)
|
period_type = RIQI_TO_PERIOD.get(riqi) or OPEN_RIQI_PERIOD_MAP.get(riqi)
|
||||||
sort_field = None
|
sort_field = None
|
||||||
if period_type:
|
if period_type:
|
||||||
scheme = RankRewardScheme.query.filter(
|
scheme = RankRewardScheme.objects.filter(
|
||||||
club_id=club_id, shenfen=shenfen, period_type=period_type,
|
club_id=club_id, shenfen=shenfen, period_type=period_type,
|
||||||
).first()
|
).first()
|
||||||
if scheme and scheme.enabled:
|
if scheme:
|
||||||
reg = SORT_FIELD_REGISTRY.get(shenfen) or {}
|
reg = SORT_FIELD_REGISTRY.get(shenfen) or {}
|
||||||
if scheme.sort_field in reg:
|
if scheme.sort_field in reg:
|
||||||
sort_field = scheme.sort_field
|
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:
|
def load_user_club_map(yonghuids: list) -> dict:
|
||||||
if not yonghuids:
|
if not yonghuids:
|
||||||
return {}
|
return {}
|
||||||
@@ -327,7 +458,7 @@ def tier_amount_for_rank(tiers, mingci: int) -> Optional[Decimal]:
|
|||||||
|
|
||||||
def build_tier_rewards_preview(scheme) -> dict:
|
def build_tier_rewards_preview(scheme) -> dict:
|
||||||
"""按方案档位生成各名次预计奖金(进行中周期展示用)。"""
|
"""按方案档位生成各名次预计奖金(进行中周期展示用)。"""
|
||||||
if not scheme or not scheme.enabled:
|
if not scheme:
|
||||||
return {}
|
return {}
|
||||||
tiers = list(RankRewardTier.query.filter(scheme_id=scheme.id).order_by('rank_from'))
|
tiers = list(RankRewardTier.query.filter(scheme_id=scheme.id).order_by('rank_from'))
|
||||||
if not tiers:
|
if not tiers:
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from rank.reward_services import (
|
|||||||
SORT_FIELD_LABELS,
|
SORT_FIELD_LABELS,
|
||||||
build_reward_payload,
|
build_reward_payload,
|
||||||
claim_reward,
|
claim_reward,
|
||||||
|
enrich_rank_stats,
|
||||||
list_my_pending_claims,
|
list_my_pending_claims,
|
||||||
query_club_rank_rows,
|
query_club_rank_rows,
|
||||||
query_group_rank_rows,
|
query_group_rank_rows,
|
||||||
@@ -53,9 +54,10 @@ def _load_display_maps(yonghuids, shenfen):
|
|||||||
return nick_map, avatar_map
|
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]
|
yonghuids = [r['yonghuid'] for r in rows]
|
||||||
nick_map, avatar_map = _load_display_maps(yonghuids, shenfen)
|
nick_map, avatar_map = _load_display_maps(yonghuids, shenfen)
|
||||||
|
stats_map = enrich_rank_stats(shenfen, yonghuids, riqi, club_id or '')
|
||||||
club_map = {}
|
club_map = {}
|
||||||
try:
|
try:
|
||||||
from rank.reward_services import load_user_club_map
|
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_label': sort_label,
|
||||||
'metric_is_int': is_int,
|
'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']
|
item[sort_field] = item['metric_value']
|
||||||
result.append(item)
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
@@ -180,16 +185,21 @@ class PhbJlPhbView(APIView):
|
|||||||
|
|
||||||
if fanwei == 'club':
|
if fanwei == 'club':
|
||||||
rows = query_club_rank_rows(club_id, shenfen, sort_field, riqi)
|
rows = query_club_rank_rows(club_id, shenfen, sort_field, riqi)
|
||||||
|
enrich_club = club_id
|
||||||
else:
|
else:
|
||||||
rows = query_group_rank_rows(shenfen, sort_field, riqi)
|
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)
|
reward = build_reward_payload(club_id, shenfen, riqi, request.user.UserUID)
|
||||||
|
|
||||||
# 仅俱乐部榜展示各行奖金(集团总榜名次与俱乐部分奖名次不同,不可混用)
|
# 仅俱乐部榜展示各行奖金(集团总榜名次与俱乐部分奖名次不同,不可混用)
|
||||||
rank_rewards = reward.get('rank_rewards') or {}
|
rank_rewards = reward.get('rank_rewards') or {}
|
||||||
tier_rewards = reward.get('tier_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:
|
for item in result_list:
|
||||||
mc = item['mingci']
|
mc = item['mingci']
|
||||||
settled = rank_rewards.get(mc)
|
settled = rank_rewards.get(mc)
|
||||||
|
|||||||
Reference in New Issue
Block a user