Files
Django/rank/reward_views.py
XingQue 1e3d65e0e4 fix: 排行榜昵称与管事/组长统计字段对齐
管事/组长不再展示 openid,改读业务昵称;俱乐部榜补充无效/有效邀请与收益字段;管事按有效人数、组长按收益总额排序。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-07 21:49:36 +08:00

230 lines
8.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""排行榜奖励 — 小程序 API不修改 phbhqsj"""
import logging
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from jituan.models import Club
from jituan.services.club_user import get_user_club_id
from rank.reward_services import (
BALANCE_FIELD_MAP,
OPEN_RIQI,
SORT_FIELD_LABELS,
build_reward_payload,
claim_reward,
enrich_rank_stats,
list_my_pending_claims,
query_club_rank_rows,
query_group_rank_rows,
resolve_sort_field_for_display,
sort_field_options_for_shenfen,
)
from users.business_models import User
from users.models import UserDashou, UserShangjia
from rank.display_utils import load_rank_nicknames
logger = logging.getLogger(__name__)
SHENFEN_OPTIONS = frozenset({'dashou', 'guanshi', 'zuzhang', 'shangjia'})
RIQI_OPTIONS = frozenset({'今日', '本周', '本月', '总榜', '昨日', '上周', '上月'})
def _resolve_club_id(request, data_club_id=''):
from jituan.services.club_context import resolve_club_id_from_request
cid = (data_club_id or '').strip()
if not cid:
cid = resolve_club_id_from_request(request) or ''
if not cid:
cid = get_user_club_id(request.user) or getattr(request.user, 'ClubID', None) or ''
return cid or 'xq'
def _load_display_maps(yonghuids, shenfen):
users = User.objects.filter(UserUID__in=yonghuids)
nick_map = load_rank_nicknames(shenfen, yonghuids)
avatar_map = {u.UserUID: u.Avatar or '' for u in users}
return nick_map, avatar_map
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
club_map = load_user_club_map(yonghuids)
except Exception:
pass
club_names = {}
if club_map:
cids = set(club_map.values()) - {''}
for c in Club.query.filter(club_id__in=cids):
club_names[c.club_id] = c.name
result = []
for idx, row in enumerate(rows):
uid = row['yonghuid']
cid = club_map.get(uid, '')
metric = row['metric']
is_int = row.get('is_int', False)
item = {
'mingci': idx + 1,
'yonghuid': uid,
'nicheng': nick_map.get(uid, '用户'),
'touxiang': avatar_map.get(uid, '') or '',
'club_id': cid,
'club_name': club_names.get(cid, cid),
'sort_field': sort_field,
'metric_value': int(metric) if is_int else float(metric),
'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
class PhbJlXxView(APIView):
"""POST /yonghu/phbjlxx 奖励规则 + 我的待领/已领(按俱乐部分奖)"""
permission_classes = [IsAuthenticated]
def post(self, request):
shenfen = (request.data.get('shenfen') or 'dashou').strip()
riqi = (request.data.get('riqi') or '上周').strip()
club_id = _resolve_club_id(request, request.data.get('club_id'))
if shenfen not in SHENFEN_OPTIONS:
return Response({'code': 400, 'msg': '身份参数错误', 'data': None})
if riqi not in RIQI_OPTIONS:
return Response({'code': 400, 'msg': '周期参数错误', 'data': None})
uid = request.user.UserUID
payload = build_reward_payload(club_id, shenfen, riqi, uid)
payload['balance_hint'] = BALANCE_FIELD_MAP.get(shenfen, '')
return Response({'code': 200, 'msg': 'success', 'data': payload})
class PhbJlWdView(APIView):
"""POST /yonghu/phbjlwd 我的全部待领取"""
permission_classes = [IsAuthenticated]
def post(self, request):
club_id = _resolve_club_id(request, request.data.get('club_id'))
items = list_my_pending_claims(request.user.UserUID, club_id)
return Response({'code': 200, 'msg': 'success', 'data': {'list': items, 'total': len(items)}})
class PhbJlLqView(APIView):
"""POST /yonghu/phbjllq 领取奖励"""
permission_classes = [IsAuthenticated]
def post(self, request):
claim_id = request.data.get('claim_id')
if not claim_id:
return Response({'code': 400, 'msg': '缺少 claim_id', 'data': None})
try:
claim_id = int(claim_id)
except (TypeError, ValueError):
return Response({'code': 400, 'msg': 'claim_id 无效', 'data': None})
shenfen = (request.data.get('shenfen') or '').strip()
result = claim_reward(claim_id, request.user, request_shenfen=shenfen)
if not result.get('ok'):
return Response({'code': 400, 'msg': result.get('msg', '领取失败'), 'data': None})
return Response({
'code': 200,
'msg': result.get('msg', '领取成功'),
'data': {
'amount': result.get('amount'),
'shenfen': result.get('shenfen'),
'duplicate': result.get('duplicate', False),
},
})
class PhbJlPhbView(APIView):
"""
POST /yonghu/phbjlphb
俱乐部榜 / 集团榜(展示用);分奖仍只按 club 方案。
fanwei: jituan | club
"""
permission_classes = [IsAuthenticated]
def post(self, request):
shenfen = (request.data.get('shenfen') or 'dashou').strip()
riqi = (request.data.get('riqi') or '今日').strip()
fanwei = (request.data.get('fanwei') or 'jituan').strip()
club_id = _resolve_club_id(request, request.data.get('club_id'))
sort_field = (request.data.get('sort_field') or '').strip()
if shenfen not in SHENFEN_OPTIONS:
return Response({'code': 400, 'msg': '身份参数错误', 'data': {'list': []}})
if riqi not in RIQI_OPTIONS:
return Response({'code': 400, 'msg': '周期参数错误', 'data': {'list': []}})
from rank.reward_services import SORT_FIELD_REGISTRY
scheme_sort, sort_label = resolve_sort_field_for_display(club_id, shenfen, riqi)
if not sort_field:
sort_field = scheme_sort
elif sort_field not in (SORT_FIELD_REGISTRY.get(shenfen) or {}):
return Response({'code': 400, 'msg': '排序指标无效', 'data': {'list': []}})
else:
sort_label = SORT_FIELD_LABELS.get(sort_field, sort_field)
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, 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 {}
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)
preview = tier_rewards.get(mc, 0)
item['reward_amount'] = settled if settled else preview
item['reward_is_preview'] = not settled and preview > 0
return Response({
'code': 200,
'msg': '获取成功',
'data': {
'list': result_list,
'fanwei': fanwei,
'club_id': club_id,
'sort_field': sort_field,
'sort_label': sort_label,
'reward': reward,
},
})
class PhbJlClubListView(APIView):
"""POST /yonghu/phbjljlb 有奖励方案的俱乐部列表(展示筛选用)"""
permission_classes = [IsAuthenticated]
def post(self, request):
from rank.reward_models import RankRewardScheme
cids = RankRewardScheme.query.filter(enabled=True).values_list('club_id', flat=True).distinct()
clubs = []
for c in Club.query.filter(club_id__in=list(cids)).order_by('sort_order', 'club_id'):
clubs.append({'club_id': c.club_id, 'name': c.name})
my_club = _resolve_club_id(request)
return Response({'code': 200, 'msg': 'success', 'data': {'clubs': clubs, 'my_club_id': my_club}})