233 lines
8.9 KiB
Python
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}})
|