Files
Django/rank/reward_views.py
T

233 lines
8.9 KiB
Python

"""排行榜奖励 — 小程序 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, TOTAL_RANK_INVITE_SORT_FIELDS
if riqi == '总榜' and shenfen in TOTAL_RANK_INVITE_SORT_FIELDS:
sort_field, sort_label = resolve_sort_field_for_display(club_id, shenfen, riqi)
else:
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}})