From 7f7859c2a4f2b898ce15aa8aec56d8b6e742c692 Mon Sep 17 00:00:00 2001 From: XingQue Date: Wed, 1 Jul 2026 19:32:29 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=8E=92=E8=A1=8C=E6=A6=9C=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E5=AE=8C=E6=95=B4=E7=BB=9F=E8=AE=A1=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=B9=B6=E8=B7=9F=E9=9A=8F=E5=90=8E=E5=8F=B0=E6=8E=92=E5=BA=8F?= =?UTF-8?q?=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rank/reward_services.py | 139 ++++++++++++++++++++++++++++++++++++++-- rank/reward_views.py | 16 ++++- 2 files changed, 148 insertions(+), 7 deletions(-) diff --git a/rank/reward_services.py b/rank/reward_services.py index 3095563..56f79e1 100644 --- a/rank/reward_services.py +++ b/rank/reward_services.py @@ -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: diff --git a/rank/reward_views.py b/rank/reward_views.py index d6fc884..3fbdd57 100644 --- a/rank/reward_views.py +++ b/rank/reward_views.py @@ -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)