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, WUXIAO_TOTAL_RANK_SORT_FIELDS
|
||
|
||
if riqi == '总榜' and shenfen in WUXIAO_TOTAL_RANK_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}})
|