"""排行榜展示名与星之界扩展统计字段。""" from __future__ import annotations from django.db.models import Sum from backend.models import ManagerDailyStats from users.business_models import User from users.models import UserBoss, UserDashou, UserGuanshi, UserShangjia def is_openid_like(value: str) -> bool: if not value or not isinstance(value, str): return False s = value.strip() # 微信 openid 常见形态 return s.startswith('o') and len(s) >= 20 def resolve_rank_nickname(shenfen: str, user: User, profile_nick: str = '') -> str: """展示名:优先业务昵称,禁止把 openid 当昵称。""" nick = (profile_nick or '').strip() if nick and not is_openid_like(nick): return nick phone = (user.Phone or '').strip() if phone: return phone uname = (user.UserName or '').strip() if uname and not is_openid_like(uname): return uname defaults = { 'dashou': '打手', 'guanshi': '管事', 'zuzhang': '组长', 'shangjia': '商家', } return defaults.get(shenfen, '用户') def load_rank_nicknames(shenfen: str, yonghuids: list) -> dict: if not yonghuids: return {} users = {u.UserUID: u for u in User.objects.filter(UserUID__in=yonghuids)} nick_map = {} if shenfen == 'dashou': for p in UserDashou.objects.filter(user__UserUID__in=yonghuids).select_related('user'): u = p.user nick_map[u.UserUID] = resolve_rank_nickname('dashou', u, p.nicheng) elif shenfen == 'shangjia': for p in UserShangjia.objects.filter(user__UserUID__in=yonghuids).select_related('user'): u = p.user nick_map[u.UserUID] = resolve_rank_nickname('shangjia', u, p.nicheng) elif shenfen in ('guanshi', 'zuzhang'): boss_map = {} for b in UserBoss.objects.filter(user__UserUID__in=yonghuids).select_related('user'): boss_map[b.user.UserUID] = b.nickname for uid in yonghuids: u = users.get(uid) if not u: nick_map[uid] = '用户' continue nick_map[uid] = resolve_rank_nickname(shenfen, u, boss_map.get(uid, '')) else: for uid in yonghuids: u = users.get(uid) nick_map[uid] = resolve_rank_nickname(shenfen, u) if u else '用户' for uid in yonghuids: nick_map.setdefault(uid, '用户') return nick_map def apply_guanshi_wuxiao_fields(stats: dict) -> dict: invited = int(stats.get('yaoqing_dashou_shu') or 0) valid = int(stats.get('chongzhi_dashou_shu') or 0) stats['wuxiao_yaoqing_dashou_shu'] = max(0, invited - valid) return stats def count_youxiao_guanshi_for_zuzhang(zuzhang_uid, start_date=None, end_date=None) -> int: """组长旗下有充值打手记录的管事人数。""" guanshi_uids = list( UserGuanshi.objects.filter(yaoqingren=zuzhang_uid) .values_list('user__UserUID', flat=True) ) if not guanshi_uids: return 0 qs = ManagerDailyStats.objects.filter(ManagerID__in=guanshi_uids) if start_date and end_date: qs = qs.filter(Date__gte=start_date, Date__lte=end_date) qs = ( qs.values('ManagerID') .annotate(total_rc=Sum('RechargedPlayerCount')) .filter(total_rc__gt=0) ) return qs.count() def apply_zuzhang_wuxiao_fields(stats: dict, zuzhang_uid, start_date=None, end_date=None) -> dict: invited = int(stats.get('yaoqing_guanshi_shu') or 0) youxiao = count_youxiao_guanshi_for_zuzhang(zuzhang_uid, start_date, end_date) stats['youxiao_guanshi_shu'] = youxiao stats['wuxiao_yaoqing_guanshi_shu'] = max(0, invited - youxiao) return stats def enrich_extra_rank_fields(shenfen: str, stats_map: dict, riqi: str = '') -> dict: """为管事/组长补充无效/有效邀请等展示字段。""" from rank.reward_services import _resolve_date_range_for_display start_date, end_date = None, None if riqi and riqi != '总榜': dr = _resolve_date_range_for_display(riqi) if dr: start_date, end_date = dr for uid, stats in stats_map.items(): if not stats: stats_map[uid] = stats = {} if shenfen == 'guanshi': apply_guanshi_wuxiao_fields(stats) elif shenfen == 'zuzhang': apply_zuzhang_wuxiao_fields(stats, uid, start_date, end_date) return stats_map