feat: 俱乐部组队开关与提现会员/积分门槛分店配置

This commit is contained in:
XingQue committed 2026-08-04 12:47:17 +08:00
1 parent 527e83eeb2
commit 080c55bf2a
7 files changed
+257 -35

No files matched your search

+55
View File
@@ -0,0 +1,55 @@
"""俱乐部:是否允许打手组队(config_json)。
默认关闭:未配置或显式关闭时,打手不可开启/加入组队。
"""
import logging
logger = logging.getLogger(__name__)
CONFIG_KEY = 'dashou_team_recruit_enabled'
def _club(club_id: str):
cid = (club_id or '').strip()
if not cid:
return None
from jituan.models import Club
club = Club.query.filter(club_id=cid).first()
if not club and cid != cid.lower():
club = Club.query.filter(club_id=cid.lower()).first()
return club
def _as_bool(raw, default=False) -> bool:
if raw is None:
return default
if isinstance(raw, str):
return raw.strip().lower() in ('1', 'true', 'yes', 'on')
return bool(raw)
def is_dashou_team_recruit_enabled(club_id: str) -> bool:
"""开启=允许本俱乐部打手组队;关闭(默认)=不可开队/入队。"""
club = _club(club_id)
if not club:
return False
try:
cfg = club.config_json or {}
if CONFIG_KEY not in cfg:
return False
return _as_bool(cfg.get(CONFIG_KEY), False)
except Exception:
logger.exception('read dashou_team_recruit_enabled failed club=%s', club_id)
return False
def set_dashou_team_recruit_enabled(club, enabled: bool) -> None:
cfg = dict(getattr(club, 'config_json', None) or {})
cfg[CONFIG_KEY] = bool(enabled)
club.config_json = cfg
def ensure_dashou_team_recruit_enabled(club_id: str) -> None:
"""未开启则抛 ValueError,供组队服务统一拦截。"""
if not is_dashou_team_recruit_enabled(club_id):
raise ValueError('本俱乐部未开放组队功能')
@@ -0,0 +1,75 @@
"""俱乐部:打手提现/收款是否校验正式会员与积分(config_json)。
默认开启(与现网硬门槛一致):
- 须持有有效正式/赠送会员(体验会员不可提佣金)
- 积分须 ≥ 10
关闭后:对应校验整段跳过,不再看会员/积分。
仅影响打手佣金提现(leixing=1)与押金提取(leixing=5)的申请与自动收款校验。
"""
import logging
logger = logging.getLogger(__name__)
REQUIRE_HUIYUAN_KEY = 'withdraw_require_formal_huiyuan'
REQUIRE_JIFEN_KEY = 'withdraw_require_jifen'
JIFEN_MIN = 10
def _club(club_id: str):
cid = (club_id or '').strip()
if not cid:
return None
from jituan.models import Club
club = Club.query.filter(club_id=cid).first()
if not club and cid != cid.lower():
club = Club.query.filter(club_id=cid.lower()).first()
return club
def _as_bool(raw, default: bool) -> bool:
if raw is None:
return default
if isinstance(raw, str):
s = raw.strip().lower()
if s in ('1', 'true', 'yes', 'on'):
return True
if s in ('0', 'false', 'no', 'off'):
return False
return default
return bool(raw)
def _read_bool_default_true(club_id: str, key: str) -> bool:
"""缺省/读失败均按 True,避免误关导致免校验放钱。"""
club = _club(club_id)
if not club:
return True
try:
cfg = club.config_json or {}
if key not in cfg:
return True
return _as_bool(cfg.get(key), True)
except Exception:
logger.exception('read %s failed club=%s', key, club_id)
return True
def is_withdraw_require_formal_huiyuan(club_id: str) -> bool:
return _read_bool_default_true(club_id, REQUIRE_HUIYUAN_KEY)
def is_withdraw_require_jifen(club_id: str) -> bool:
return _read_bool_default_true(club_id, REQUIRE_JIFEN_KEY)
def set_withdraw_require_formal_huiyuan(club, enabled: bool) -> None:
cfg = dict(getattr(club, 'config_json', None) or {})
cfg[REQUIRE_HUIYUAN_KEY] = bool(enabled)
club.config_json = cfg
def set_withdraw_require_jifen(club, enabled: bool) -> None:
cfg = dict(getattr(club, 'config_json', None) or {})
cfg[REQUIRE_JIFEN_KEY] = bool(enabled)
club.config_json = cfg
+38
View File
@@ -638,6 +638,11 @@ class ClubManageView(APIView):
is_dashou_chat_allow_without_member,
)
from jituan.services.yajin_jifen_switch import is_yajin_purchase_fill_jifen
from jituan.services.team_recruit_switch import is_dashou_team_recruit_enabled
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
)
cfg_json = club.config_json or {}
base = {
@@ -659,6 +664,9 @@ class ClubManageView(APIView):
'dashou_chat_allow_without_member': is_dashou_chat_allow_without_member(club.club_id),
'dashou_chat_yajin_threshold': float(get_dashou_chat_yajin_threshold(club.club_id)),
'yajin_purchase_fill_jifen': is_yajin_purchase_fill_jifen(club.club_id),
'dashou_team_recruit_enabled': is_dashou_team_recruit_enabled(club.club_id),
'withdraw_require_formal_huiyuan': is_withdraw_require_formal_huiyuan(club.club_id),
'withdraw_require_jifen': is_withdraw_require_jifen(club.club_id),
}
if full:
mch_key = self._effective_mch_key(club)
@@ -769,6 +777,36 @@ class ClubManageView(APIView):
set_yajin_purchase_fill_jifen(club, enabled)
if 'config_json' not in update_fields:
update_fields.append('config_json')
if 'dashou_team_recruit_enabled' in request.data:
from jituan.services.team_recruit_switch import set_dashou_team_recruit_enabled
raw = request.data.get('dashou_team_recruit_enabled')
if isinstance(raw, str):
enabled = raw.strip().lower() in ('1', 'true', 'yes', 'on')
else:
enabled = bool(raw)
set_dashou_team_recruit_enabled(club, enabled)
if 'config_json' not in update_fields:
update_fields.append('config_json')
if 'withdraw_require_formal_huiyuan' in request.data:
from jituan.services.withdraw_eligibility_switch import set_withdraw_require_formal_huiyuan
raw = request.data.get('withdraw_require_formal_huiyuan')
if isinstance(raw, str):
enabled = raw.strip().lower() in ('1', 'true', 'yes', 'on')
else:
enabled = bool(raw)
set_withdraw_require_formal_huiyuan(club, enabled)
if 'config_json' not in update_fields:
update_fields.append('config_json')
if 'withdraw_require_jifen' in request.data:
from jituan.services.withdraw_eligibility_switch import set_withdraw_require_jifen
raw = request.data.get('withdraw_require_jifen')
if isinstance(raw, str):
enabled = raw.strip().lower() in ('1', 'true', 'yes', 'on')
else:
enabled = bool(raw)
set_withdraw_require_jifen(club, enabled)
if 'config_json' not in update_fields:
update_fields.append('config_json')
if update_fields:
club.save(update_fields=update_fields)
return Response({
+4
View File
@@ -287,9 +287,11 @@ def open_recruit(
max_fine_rate=None,
):
from orders.models import TeamRecruit, TeamMember
from jituan.services.team_recruit_switch import ensure_dashou_team_recruit_enabled
oid = order.OrderID
club_id = (getattr(order, 'ClubID', None) or '').strip() or 'xq'
ensure_dashou_team_recruit_enabled(club_id)
if int(order.Status or 0) != 2:
raise ValueError('仅进行中订单可开启组队')
if (order.PlayerID or '') != leader_uid:
@@ -474,6 +476,7 @@ def join_recruit(*, recruit_id: int, user_uid: str, game_id: str, request=None,
from orders.models import TeamRecruit, TeamMember, Order
from users.models import UserDashou
from utils.fadan_utils import check_fadan_qiangdan_eligible
from jituan.services.team_recruit_switch import ensure_dashou_team_recruit_enabled
game_id = (game_id or '').strip()
if not game_id:
@@ -485,6 +488,7 @@ def join_recruit(*, recruit_id: int, user_uid: str, game_id: str, request=None,
# 组队强制本俱乐部:不认跨店互通抢单
if require_club_id and (rec.club_id or '') != require_club_id:
raise ValueError('仅本俱乐部可加入组队')
ensure_dashou_team_recruit_enabled(rec.club_id or require_club_id or '')
if rec.status != TeamRecruit.STATUS_RECRUITING:
raise ValueError('招募已结束')
if int(rec.joined_count or 0) >= int(rec.need_count or 0):
+14
View File
@@ -166,6 +166,19 @@ class ZuduiDatingView(APIView):
club, err = _require_club(request)
if err:
return err
from jituan.services.team_recruit_switch import is_dashou_team_recruit_enabled
if not is_dashou_team_recruit_enabled(club):
return Response({
'code': 0,
'msg': '本俱乐部未开放组队功能',
'data': {
'list': [],
'total': 0,
'page': 1,
'page_size': 10,
'team_recruit_enabled': False,
},
})
page = max(1, int(request.data.get('page') or 1))
page_size = min(50, max(1, int(request.data.get('page_size') or 10)))
leixing = request.data.get('leixing_id')
@@ -222,6 +235,7 @@ class ZuduiDatingView(APIView):
'page': page,
'page_size': page_size,
'has_more': start + len(rows) < total,
'team_recruit_enabled': True,
**badge,
},
})
+54 -26
View File
@@ -356,14 +356,21 @@ def validate_withdraw_eligibility(user_main, leixing, jine):
return False, '您不是打手身份,无法提现佣金', {}
if dashou.zhanghaozhuangtai != 1:
return False, '打手账号已被封禁,无法提现', {}
if dashou.jifen < 10:
return False, '积分不足10分,请补充积分后提现', {}
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg, {}
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(yonghuid)
if not trial_ok:
return False, trial_msg, {}
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
JIFEN_MIN,
)
club_id = club_id_for_tixian_yonghuid(yonghuid)
if is_withdraw_require_jifen(club_id) and dashou.jifen < JIFEN_MIN:
return False, f'积分不足{JIFEN_MIN}分,请补充积分后提现', {}
if is_withdraw_require_formal_huiyuan(club_id):
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg, {}
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(yonghuid)
if not trial_ok:
return False, trial_msg, {}
if _dashou_has_orders_blocking_withdraw_apply(yonghuid):
return False, '您还有未完成或未退款的订单,请先处理完毕再提现', {}
if _dashou_has_open_penalties(yonghuid):
@@ -412,11 +419,18 @@ def validate_withdraw_eligibility(user_main, leixing, jine):
return False, '您不是打手身份,无法提取押金', {}
if dashou.zhanghaozhuangtai != 1:
return False, '打手账号已禁用,无法提取押金', {}
if dashou.jifen < 10:
return False, '积分不足10分,请补充积分后提取押金', {}
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg, {}
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
JIFEN_MIN,
)
club_id = club_id_for_tixian_yonghuid(yonghuid)
if is_withdraw_require_jifen(club_id) and dashou.jifen < JIFEN_MIN:
return False, f'积分不足{JIFEN_MIN}分,请补充积分后提取押金', {}
if is_withdraw_require_formal_huiyuan(club_id):
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg, {}
if dashou.yajin < jine:
return False, f'押金余额不足,当前押金: {dashou.yajin}', {}
if _dashou_has_orders_blocking_withdraw_apply(yonghuid):
@@ -488,14 +502,21 @@ def validate_collect_eligibility(user_main, leixing):
return False, '打手账号已被封禁,无法收款'
if dashou.zhuangtai != 1:
return False, '您有订单进行中,请完成后再收款'
if dashou.jifen < 10:
return False, '积分不足10分,无法收款'
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(yonghuid)
if not trial_ok:
return False, trial_msg
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
JIFEN_MIN,
)
club_id = club_id_for_tixian_yonghuid(yonghuid)
if is_withdraw_require_jifen(club_id) and dashou.jifen < JIFEN_MIN:
return False, f'积分不足{JIFEN_MIN}分,无法收款'
if is_withdraw_require_formal_huiyuan(club_id):
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(yonghuid)
if not trial_ok:
return False, trial_msg
if _dashou_has_orders_blocking_withdraw_apply(yonghuid):
return False, '您还有进行中的订单,请完成后再收款'
if _dashou_has_open_penalties(yonghuid):
@@ -511,11 +532,18 @@ def validate_collect_eligibility(user_main, leixing):
return False, '打手账号已禁用,无法收款'
if dashou.zhuangtai != 1:
return False, '您有订单进行中,请完成后再收款'
if dashou.jifen < 10:
return False, '积分不足10分,无法收款'
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
JIFEN_MIN,
)
club_id = club_id_for_tixian_yonghuid(yonghuid)
if is_withdraw_require_jifen(club_id) and dashou.jifen < JIFEN_MIN:
return False, f'积分不足{JIFEN_MIN}分,无法收款'
if is_withdraw_require_formal_huiyuan(club_id):
huiyuan_ok, huiyuan_msg = check_dashou_has_formal_huiyuan_for_withdraw(yonghuid)
if not huiyuan_ok:
return False, huiyuan_msg
if _dashou_has_orders_blocking_withdraw_apply(yonghuid):
return False, '您还有进行中的订单,请完成后再收款'
if _dashou_has_open_penalties(yonghuid):
+17 -9
View File
@@ -515,7 +515,7 @@ class TixianShenqingView(APIView):
# ==================== 校验函数 ====================
def _check_dashou_commission_withdraw(self, user_main, jine):
"""打手佣金提现校验"""
"""打手佣金提现校验(遗留辅助;主路径用 validate_withdraw_eligibility)"""
try:
dashou = UserDashou.query.get(user=user_main)
except ObjectDoesNotExist:
@@ -525,18 +525,26 @@ class TixianShenqingView(APIView):
return {'code': 11, 'msg': '打手账号已被封禁,无法提现'}
if dashou.zhuangtai != 1:
return {'code': 12, 'msg': '您有订单进行中,请完成后提现'}
if dashou.jifen < 10:
return {'code': 15, 'msg': '积分不足10分,请补充积分后提现'}
from jituan.services.wechat_pay import club_id_for_tixian_yonghuid
from jituan.services.withdraw_eligibility_switch import (
is_withdraw_require_formal_huiyuan,
is_withdraw_require_jifen,
JIFEN_MIN,
)
club_id = club_id_for_tixian_yonghuid(user_main.UserUID)
if is_withdraw_require_jifen(club_id) and dashou.jifen < JIFEN_MIN:
return {'code': 15, 'msg': f'积分不足{JIFEN_MIN}分,请补充积分后提现'}
if dashou.yue < jine:
return {'code': 13, 'msg': f'余额不足,当前余额: {dashou.yue}'}
formal_ok, formal_msg = check_dashou_has_formal_huiyuan_for_withdraw(user_main.UserUID)
if not formal_ok:
return {'code': 14, 'msg': formal_msg}
if is_withdraw_require_formal_huiyuan(club_id):
formal_ok, formal_msg = check_dashou_has_formal_huiyuan_for_withdraw(user_main.UserUID)
if not formal_ok:
return {'code': 14, 'msg': formal_msg}
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(user_main.UserUID)
if not trial_ok:
return {'code': 16, 'msg': trial_msg}
trial_ok, trial_msg = check_dashou_trial_blocks_commission_withdraw(user_main.UserUID)
if not trial_ok:
return {'code': 16, 'msg': trial_msg}
return {'code': 0, 'msg': 'ok', 'data': {'nicheng': dashou.nicheng or ''}}