feat: 假单按俱乐部开关,并按商品类型会员资格展示
This commit is contained in:
@@ -371,7 +371,8 @@ CELERY_TASK_QUEUES = {
|
||||
# 订单超时自动结算(Celery process_expired_order / check_order_expire_task)总开关:False=彻底关闭
|
||||
ORDER_AUTO_SETTLEMENT_ENABLED = False
|
||||
# 打手抢单大厅假单展示:False=仅返回真实订单(后台假单管理仍可用;改 True 可恢复假单池)
|
||||
FAKE_GRAB_ORDER_POOL_ENABLED = False
|
||||
# 假单功能总闸(紧急关闭用)。实际是否对打手生效由各俱乐部 config_json.fake_grab_order_enabled 控制。
|
||||
FAKE_GRAB_ORDER_POOL_ENABLED = True
|
||||
ORDER_EXPIRE_SECONDS = 48 * 60 * 60 # 48小时 = 172800秒(开关关闭时不生效)
|
||||
DAILY_TASK_HOUR = 0
|
||||
DAILY_TASK_MINUTE = 30
|
||||
|
||||
@@ -113,6 +113,7 @@ def build_fake_order_list_payload(request, leixing_id=None, page=1, page_size=20
|
||||
'scope': resolve_club_scope(request),
|
||||
'scope_error': CLUB_READ_SCOPE_MSG,
|
||||
'leixing_options': build_leixing_options(),
|
||||
'fake_grab_enabled': False,
|
||||
**list_response_meta(request),
|
||||
}
|
||||
|
||||
@@ -129,6 +130,8 @@ def build_fake_order_list_payload(request, leixing_id=None, page=1, page_size=20
|
||||
rows = list(qs[offset:offset + page_size])
|
||||
names = _leixing_name_map()
|
||||
|
||||
from jituan.services.fake_grab_switch import is_club_fake_grab_enabled
|
||||
|
||||
return {
|
||||
'list': [_row_to_dict(r, names) for r in rows],
|
||||
'total': total,
|
||||
@@ -137,10 +140,35 @@ def build_fake_order_list_payload(request, leixing_id=None, page=1, page_size=20
|
||||
'club_id': club_id,
|
||||
'scope': resolve_club_scope(request),
|
||||
'leixing_options': build_leixing_options(),
|
||||
'fake_grab_enabled': is_club_fake_grab_enabled(club_id),
|
||||
**list_response_meta(request),
|
||||
}
|
||||
|
||||
|
||||
def set_fake_grab_enabled(request, enabled):
|
||||
"""开启/关闭本俱乐部打手侧假单功能。"""
|
||||
if club_write_blocked(request):
|
||||
return None, CLUB_WRITE_SCOPE_MSG
|
||||
|
||||
from jituan.models import Club
|
||||
from jituan.services.fake_grab_switch import (
|
||||
is_club_fake_grab_enabled,
|
||||
set_club_fake_grab_enabled,
|
||||
)
|
||||
|
||||
club_id = club_id_for_write(request)
|
||||
club = Club.query.filter(club_id=club_id).first()
|
||||
if not club:
|
||||
return None, '俱乐部不存在'
|
||||
|
||||
set_club_fake_grab_enabled(club, bool(enabled))
|
||||
club.save(update_fields=['config_json'])
|
||||
return {
|
||||
'club_id': club_id,
|
||||
'fake_grab_enabled': is_club_fake_grab_enabled(club_id),
|
||||
}, None
|
||||
|
||||
|
||||
def _parse_decimal(value, field_name='金额'):
|
||||
try:
|
||||
val = Decimal(str(value))
|
||||
|
||||
36
jituan/services/fake_grab_switch.py
Normal file
36
jituan/services/fake_grab_switch.py
Normal file
@@ -0,0 +1,36 @@
|
||||
"""俱乐部级假单功能开关(config_json.fake_grab_order_enabled)。"""
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_KEY = 'fake_grab_order_enabled'
|
||||
|
||||
|
||||
def is_club_fake_grab_enabled(club_id: str) -> bool:
|
||||
"""某俱乐部是否对打手侧开启假单池。默认关闭。"""
|
||||
cid = (club_id or '').strip()
|
||||
if not cid:
|
||||
return False
|
||||
try:
|
||||
from django.conf import settings
|
||||
if not getattr(settings, 'FAKE_GRAB_ORDER_POOL_ENABLED', True):
|
||||
return False
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
from jituan.models import Club
|
||||
club = Club.query.filter(club_id=cid).first()
|
||||
if not club:
|
||||
return False
|
||||
cfg = club.config_json or {}
|
||||
return bool(cfg.get(CONFIG_KEY))
|
||||
except Exception:
|
||||
logger.exception('read fake_grab_order_enabled failed club=%s', cid)
|
||||
return False
|
||||
|
||||
|
||||
def set_club_fake_grab_enabled(club, enabled: bool) -> None:
|
||||
"""写入 club.config_json,调用方负责 save。"""
|
||||
cfg = dict(getattr(club, 'config_json', None) or {})
|
||||
cfg[CONFIG_KEY] = bool(enabled)
|
||||
club.config_json = cfg
|
||||
@@ -59,6 +59,7 @@ class FakeGrabOrderManageView(APIView):
|
||||
from jituan.services.fake_grab_order_admin import (
|
||||
create_fake_order,
|
||||
delete_fake_order,
|
||||
set_fake_grab_enabled,
|
||||
update_fake_order,
|
||||
)
|
||||
|
||||
@@ -82,6 +83,26 @@ class FakeGrabOrderManageView(APIView):
|
||||
return Response({'code': 400, 'msg': err_msg})
|
||||
return Response({'code': 0, 'msg': '已删除', 'data': data})
|
||||
|
||||
if action in ('set_enabled', 'enable', 'disable'):
|
||||
if action == 'enable':
|
||||
enabled = True
|
||||
elif action == 'disable':
|
||||
enabled = False
|
||||
else:
|
||||
raw = request.data.get('enabled', request.data.get('fake_grab_enabled'))
|
||||
if isinstance(raw, str):
|
||||
enabled = raw.strip().lower() in ('1', 'true', 'yes', 'on')
|
||||
else:
|
||||
enabled = bool(raw)
|
||||
data, err_msg = set_fake_grab_enabled(request, enabled)
|
||||
if err_msg:
|
||||
return Response({'code': 400, 'msg': err_msg})
|
||||
return Response({
|
||||
'code': 0,
|
||||
'msg': '假单功能已开启' if data.get('fake_grab_enabled') else '假单功能已关闭',
|
||||
'data': data,
|
||||
})
|
||||
|
||||
return Response({'code': 400, 'msg': '无效的 action'})
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"""抢单大厅假单:无资格/封禁打手仅展示假数据。"""
|
||||
"""抢单大厅假单:按俱乐部开关 + 按商品类型会员资格展示假数据。"""
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import transaction
|
||||
@@ -11,19 +10,41 @@ from rest_framework.response import Response
|
||||
|
||||
from backend.utils import fmt_datetime, pick_leixing_id
|
||||
from jituan.services.club_context import resolve_effective_club_id
|
||||
from jituan.services.dashou_exam import user_has_active_member
|
||||
from jituan.services.fake_grab_switch import is_club_fake_grab_enabled
|
||||
from jituan.services.huiyuan_bundle import normalize_huiyuan_id, user_has_huiyuan_access
|
||||
from orders.models import FakeGrabOrder, FakeGrabOrderShuffleState
|
||||
|
||||
DEFAULT_DISPATCHER_AVATAR = 'beijing/morentouxiang.jpg'
|
||||
SHUFFLE_STATE_PK = 1
|
||||
|
||||
|
||||
def dashou_should_use_fake_pool(user):
|
||||
def _leixing_required_huiyuan_id(leixing_id):
|
||||
"""商品类型绑定的会员 ID;无绑定则视为不要求会员。"""
|
||||
if leixing_id is None:
|
||||
return ''
|
||||
try:
|
||||
from products.models import ShangpinLeixing
|
||||
row = ShangpinLeixing.query.filter(id=int(leixing_id)).values('huiyuan_id').first()
|
||||
if not row:
|
||||
return ''
|
||||
return normalize_huiyuan_id(row.get('huiyuan_id'))
|
||||
except Exception:
|
||||
return ''
|
||||
|
||||
|
||||
def dashou_should_use_fake_pool(user, club_id=None, leixing_id=None):
|
||||
"""
|
||||
打手是否只能看假单:
|
||||
- 账号封禁(zhanghaozhuangtai != 1)
|
||||
- 或未开通有效会员 且 押金不大于 5
|
||||
当前 Tab(商品类型)是否只展示假单:
|
||||
- 俱乐部未开启假单功能 → 否(看真实单)
|
||||
- 账号封禁 → 是
|
||||
- 该类型要求的会员:已充(含总会员覆盖子类型)→ 否
|
||||
- 未充对应会员 → 是
|
||||
不同类型互不影响;假单在独立表,抢不了。
|
||||
"""
|
||||
cid = (club_id or '').strip()
|
||||
if not cid or not is_club_fake_grab_enabled(cid):
|
||||
return False
|
||||
|
||||
try:
|
||||
dashou = user.DashouProfile
|
||||
except ObjectDoesNotExist:
|
||||
@@ -32,11 +53,16 @@ def dashou_should_use_fake_pool(user):
|
||||
if dashou.zhanghaozhuangtai != 1:
|
||||
return True
|
||||
|
||||
yajin = Decimal(str(dashou.yajin or 0))
|
||||
if yajin > Decimal('5'):
|
||||
if leixing_id is None:
|
||||
# 未指定类型时不整池切假单,走真实单列表
|
||||
return False
|
||||
|
||||
if user_has_active_member(user.UserUID):
|
||||
required = _leixing_required_huiyuan_id(leixing_id)
|
||||
if not required:
|
||||
# 类型未绑会员 → 不推假单
|
||||
return False
|
||||
|
||||
if user_has_huiyuan_access(user.UserUID, required, club_id=cid):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@@ -97,14 +97,10 @@ class DashouDingdanHuoquView(APIView):
|
||||
|
||||
def post(self, request):
|
||||
try:
|
||||
from django.conf import settings
|
||||
from orders.services.fake_order_pool import (
|
||||
dashou_should_use_fake_pool,
|
||||
build_fake_order_pool_response,
|
||||
)
|
||||
if getattr(settings, 'FAKE_GRAB_ORDER_POOL_ENABLED', False):
|
||||
if dashou_should_use_fake_pool(request.user):
|
||||
return build_fake_order_pool_response(request)
|
||||
|
||||
# 1. 获取请求参数
|
||||
data = request.data
|
||||
@@ -119,6 +115,11 @@ class DashouDingdanHuoquView(APIView):
|
||||
resolve_grab_pool_member_display,
|
||||
)
|
||||
club_id = resolve_effective_club_id(request, getattr(request, 'user', None))
|
||||
|
||||
# 假单:按俱乐部开关 + 当前商品类型是否具备对应会员(含总会员覆盖)
|
||||
if dashou_should_use_fake_pool(request.user, club_id=club_id, leixing_id=leixing_id):
|
||||
return build_fake_order_pool_response(request)
|
||||
|
||||
yonghuid = request.user.UserUID
|
||||
_has_member, user_clumber = refresh_grab_pool_membership_state(
|
||||
yonghuid, club_id=club_id,
|
||||
|
||||
Reference in New Issue
Block a user