fix: 俱乐部ID统一解析;会员支付/分红/展示按club隔离
This commit is contained in:
@@ -3290,8 +3290,8 @@ class CheckPhoneAuthView(APIView):
|
||||
return False
|
||||
if dashou.yajin and dashou.yajin > 0:
|
||||
return True
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
club_id = resolve_club_id_from_request(self.request)
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
club_id = resolve_effective_club_id(self.request, user)
|
||||
if Huiyuangoumai.query.filter(yonghu_id=user.UserUID, club_id=club_id).exists():
|
||||
return True
|
||||
if (dashou.jiedanzongliang or 0) > 0 or (dashou.chengjiaozongliang or 0) > 0:
|
||||
|
||||
@@ -82,9 +82,29 @@ def filter_queryset_by_club(qs, request, club_field='club_id'):
|
||||
return qs.filter(**{club_field: club_id})
|
||||
|
||||
|
||||
def club_id_for_write(request):
|
||||
def resolve_effective_club_id(request, user=None):
|
||||
"""
|
||||
小程序/API 实际生效俱乐部(展示价、支付价、分红须一致)。
|
||||
优先级:Header X-Club-Id > 用户归属 ClubID > 默认 xq。
|
||||
勿用 middleware 注入的 request.club_id(无 Header 时恒为 xq)。
|
||||
"""
|
||||
header = request.META.get(f'HTTP_{CLUB_HEADER.upper().replace("-", "_")}', '')
|
||||
if not header and hasattr(request, 'headers'):
|
||||
header = request.headers.get(CLUB_HEADER, '')
|
||||
header = (header or '').strip()
|
||||
if header:
|
||||
return header
|
||||
if user is not None:
|
||||
from jituan.services.club_user import get_user_club_id
|
||||
user_club = get_user_club_id(user)
|
||||
if user_club:
|
||||
return user_club
|
||||
return CLUB_ID_DEFAULT
|
||||
|
||||
|
||||
def club_id_for_write(request, user=None):
|
||||
"""写入业务流水时使用的 club_id(集团汇总视图写入仍须指定目标 club)。"""
|
||||
return resolve_club_id_from_request(request)
|
||||
return resolve_effective_club_id(request, user)
|
||||
|
||||
|
||||
def orders_for_request(request):
|
||||
|
||||
@@ -12,7 +12,7 @@ def resolve_club_id_for_write(request=None, user=None, club_id=None):
|
||||
if club_id:
|
||||
return club_id
|
||||
if request is not None:
|
||||
return club_id_for_write(request)
|
||||
return club_id_for_write(request, user)
|
||||
if user is not None:
|
||||
return get_user_club_id(user)
|
||||
return CLUB_ID_DEFAULT
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
"""轮播 / 公告 / 弹窗按俱乐部读取与写入。"""
|
||||
from jituan.constants import CLUB_ID_DEFAULT, DATA_SCOPE_ALL
|
||||
from jituan.services.club_context import filter_queryset_by_club, resolve_club_id_from_request, resolve_club_scope
|
||||
from jituan.services.club_context import (
|
||||
filter_queryset_by_club,
|
||||
resolve_club_id_from_request,
|
||||
resolve_club_scope,
|
||||
resolve_effective_club_id,
|
||||
)
|
||||
from rest_framework.response import Response
|
||||
|
||||
# 定稿 B 方案 page_key
|
||||
@@ -46,16 +51,23 @@ def forbid_popup_page_out_of_scope(request, page):
|
||||
return None
|
||||
|
||||
|
||||
def _display_club_id(request):
|
||||
user = getattr(request, 'user', None)
|
||||
if user is not None and getattr(user, 'is_authenticated', False):
|
||||
return resolve_effective_club_id(request, user)
|
||||
return resolve_effective_club_id(request, None)
|
||||
|
||||
|
||||
def get_gonggao_content(request, notice_type=1):
|
||||
from config.models import Gonggao
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = _display_club_id(request)
|
||||
obj = Gonggao.query.filter(club_id=club_id, NoticeType=notice_type).first()
|
||||
return obj.Content if obj and obj.Content else ''
|
||||
|
||||
|
||||
def get_lunbo_urls(request, page_key=None, image_type=1):
|
||||
from config.models import Lunbo
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = _display_club_id(request)
|
||||
pk = normalize_page_key(page_key, image_type=image_type)
|
||||
qs = Lunbo.query.filter(club_id=club_id, ImageType=image_type, page_key=pk)
|
||||
return [row.ImageURL for row in qs.order_by('id') if row.ImageURL]
|
||||
@@ -67,13 +79,11 @@ def list_response_meta(request):
|
||||
|
||||
|
||||
def get_tupianpeizhi_url(request, image_type):
|
||||
"""按俱乐部读图片配置(无则 xq 回退,避免 xzj 未配时全空)。"""
|
||||
"""按俱乐部读图片配置(各俱乐部独立,不回退 xq,避免串台)。"""
|
||||
from config.models import Tupianpeizhi
|
||||
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = _display_club_id(request)
|
||||
row = Tupianpeizhi.query.filter(club_id=club_id, ImageType=image_type).first()
|
||||
if not row and club_id != CLUB_ID_DEFAULT:
|
||||
row = Tupianpeizhi.query.filter(club_id=CLUB_ID_DEFAULT, ImageType=image_type).first()
|
||||
return (row.ImageURL or '').strip() if row else ''
|
||||
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ from jituan.services.club_config import (
|
||||
get_huiyuan_price,
|
||||
get_huiyuan_fenchong,
|
||||
)
|
||||
from jituan.services.club_context import resolve_club_id_from_request
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
from jituan.services.club_write import resolve_club_id_for_write
|
||||
from jituan.services.club_user import get_payment_openid
|
||||
from jituan.services.club_penalty import resolve_gsfenhong_club_id
|
||||
@@ -269,7 +269,7 @@ class DashouHuiyuanList(APIView):
|
||||
# 3. 仅返回本俱乐部可售会员(club_huiyuan_price 已配置且启用)
|
||||
from jituan.services.member_recharge import club_huiyuan_sellable
|
||||
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
huiyuan_queryset = Huiyuan.query.all().only(
|
||||
'huiyuan_id', 'jieshao', 'jtjieshao', 'jiage',
|
||||
).order_by('jiage')
|
||||
@@ -290,7 +290,8 @@ class DashouHuiyuanList(APIView):
|
||||
return Response({
|
||||
'code': 200,
|
||||
'message': '获取会员列表成功',
|
||||
'data': huiyuan_list # 对应前端接收的列表
|
||||
'data': huiyuan_list,
|
||||
'club_id': club_id,
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
except Exception as e:
|
||||
@@ -1411,7 +1412,7 @@ class HuiyuanGoumai(APIView):
|
||||
'message': '会员信息不存在'
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
from jituan.services.member_recharge import club_huiyuan_sellable
|
||||
sellable, club_price = club_huiyuan_sellable(club_id, huiyuanid)
|
||||
if not sellable:
|
||||
@@ -1444,7 +1445,8 @@ class HuiyuanGoumai(APIView):
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"创建会员充值订单: 用户{request.user.UserUID}, 订单{dingdanid}, 会员{huiyuanid}, 金额{jine}元")
|
||||
f"创建会员充值订单: 用户{request.user.UserUID}, 订单{dingdanid}, "
|
||||
f"会员{huiyuanid}, 俱乐部{club_id}, 金额{jine}元")
|
||||
|
||||
# 7. 生成微信支付参数
|
||||
try:
|
||||
@@ -1471,8 +1473,10 @@ class HuiyuanGoumai(APIView):
|
||||
return Response({
|
||||
'code': 200,
|
||||
'message': '支付参数生成成功',
|
||||
'payParams': pay_params, # 对应前端payParams
|
||||
'dingdanid': dingdanid # 对应前端dingdanid
|
||||
'payParams': pay_params,
|
||||
'dingdanid': dingdanid,
|
||||
'club_id': club_id,
|
||||
'jine': jine,
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
except Exception as e:
|
||||
@@ -5738,7 +5742,7 @@ class CzhqdyView(APIView):
|
||||
# 会员
|
||||
try:
|
||||
huiyuan = Huiyuan.query.get(huiyuan_id=huiyuan_id)
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
target_price = get_huiyuan_price(club_id, huiyuan_id, huiyuan)
|
||||
except Huiyuan.DoesNotExist:
|
||||
return Response({'code': 404, 'msg': '会员不存在'}, status=status.HTTP_404_NOT_FOUND)
|
||||
@@ -5758,7 +5762,7 @@ class CzhqdyView(APIView):
|
||||
|
||||
# 获取所有费率(打手佣金、管事分红、组长分红、打手押金)
|
||||
rates = {}
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
for key in ['5', '6', '8', '11']:
|
||||
rates[key] = get_commission_rate(club_id, key)
|
||||
|
||||
@@ -5873,7 +5877,7 @@ class DsqrgmdhView(APIView):
|
||||
return Response({'code': 400, 'msg': 'yajin_jine 必须为正数'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
target_price = None
|
||||
club_id = resolve_club_id_from_request(request)
|
||||
club_id = resolve_effective_club_id(request, request.user)
|
||||
if leixing == 1:
|
||||
try:
|
||||
huiyuan = Huiyuan.query.get(huiyuan_id=huiyuan_id)
|
||||
@@ -5894,12 +5898,12 @@ class DsqrgmdhView(APIView):
|
||||
return Response({'code': 404, 'msg': '罚单不存在或不属于当前用户'}, status=status.HTTP_404_NOT_FOUND)
|
||||
|
||||
identity = IDENTITY_CONFIG.get(shenfen_id)
|
||||
from jituan.services.club_config import get_commission_rate
|
||||
try:
|
||||
rate_obj = CommissionRate.query.get(Platform=identity['rate_key'])
|
||||
rate = rate_obj.Rate
|
||||
rate = get_commission_rate(club_id, identity['rate_key'])
|
||||
if rate >= 1:
|
||||
return Response({'code': 400, 'msg': f"{identity['name']}费率异常"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except CommissionRate.DoesNotExist:
|
||||
except Exception:
|
||||
return Response({'code': 400, 'msg': f"{identity['name']}费率未配置"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
logger.info(f"目标价格={target_price}, 费率={rate}")
|
||||
@@ -5968,7 +5972,20 @@ class DsqrgmdhView(APIView):
|
||||
response_data = {}
|
||||
|
||||
if leixing == 1:
|
||||
huiyuan_record, is_first_buy = self._process_member_purchase(yonghuid, huiyuan_id, huiyuan)
|
||||
huiyuan_record, is_first_buy = self._process_member_purchase(
|
||||
yonghuid, huiyuan_id, huiyuan, club_id=club_id,
|
||||
)
|
||||
try:
|
||||
from jituan.services.member_recharge import (
|
||||
resolve_member_purchase_cishu,
|
||||
_apply_member_fenhong,
|
||||
)
|
||||
purchase_cishu = resolve_member_purchase_cishu(
|
||||
yonghuid, huiyuan_id, dingdan_id, club_id,
|
||||
)
|
||||
_apply_member_fenhong(czjilu, huiyuan, purchase_cishu)
|
||||
except Exception as exc:
|
||||
logger.error('余额购会员分红失败 dingdan=%s: %s', dingdan_id, exc, exc_info=True)
|
||||
response_data['huiyuan'] = {
|
||||
'huiyuanid': huiyuan_id,
|
||||
'huiyuanming': huiyuan.jieshao,
|
||||
@@ -6034,7 +6051,7 @@ class DsqrgmdhView(APIView):
|
||||
logger.error(f"接口顶层异常: {str(e)}", exc_info=True)
|
||||
return Response({'code': 500, 'msg': f'系统错误: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
def _process_member_purchase(self, yonghuid, huiyuan_id, huiyuan_obj):
|
||||
def _process_member_purchase(self, yonghuid, huiyuan_id, huiyuan_obj, club_id=None):
|
||||
is_first_buy_any = False
|
||||
try:
|
||||
record = Huiyuangoumai.query.filter(
|
||||
@@ -6050,13 +6067,14 @@ class DsqrgmdhView(APIView):
|
||||
other_count = Huiyuangoumai.query.filter(yonghu_id=yonghuid).exclude(huiyuan_id=huiyuan_id).count()
|
||||
if other_count == 0:
|
||||
is_first_buy_any = True
|
||||
resolved_club = club_id or get_user_club_id(User.query.filter(UserUID=yonghuid).first())
|
||||
record = Huiyuangoumai.query.create(
|
||||
yonghu_id=yonghuid,
|
||||
huiyuan_id=huiyuan_id,
|
||||
jieshao=huiyuan_obj.jieshao,
|
||||
huiyuan_zhuangtai=1,
|
||||
daoqi_time=timezone.now() + timedelta(days=30),
|
||||
club_id=get_user_club_id(User.query.filter(UserUID=yonghuid).first()),
|
||||
club_id=resolved_club,
|
||||
)
|
||||
return record, is_first_buy_any
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user