feat: 抢单大厅假单池,仅改造 ddhq 接口
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
34
orders/migrations/0010_fakegraborder.py
Normal file
34
orders/migrations/0010_fakegraborder.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('orders', '0009_penalty_bonus_lock_fields'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='FakeGrabOrder',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('OrderID', models.CharField(db_column='dingdan_id', db_index=True, max_length=32, unique=True, verbose_name='订单ID')),
|
||||||
|
('Amount', models.DecimalField(db_column='jine', decimal_places=2, max_digits=10, verbose_name='订单价格(展示为打手分红)')),
|
||||||
|
('ProductTypeID', models.IntegerField(db_column='leixing_id', verbose_name='订单类型ID')),
|
||||||
|
('Description', models.TextField(blank=True, db_column='jieshao', null=True, verbose_name='订单介绍')),
|
||||||
|
('Remark', models.TextField(blank=True, db_column='beizhu', null=True, verbose_name='订单备注')),
|
||||||
|
('DispatcherUserID', models.CharField(blank=True, db_column='paidan_yonghuid', max_length=32, null=True, verbose_name='派单者用户ID')),
|
||||||
|
('DispatcherAvatar', models.CharField(blank=True, db_column='paidan_touxiang', max_length=500, null=True, verbose_name='派单者头像(展示用默认头像)')),
|
||||||
|
('IsPremiumMerchant', models.BooleanField(db_column='is_youzhi_shangjia', default=False, verbose_name='是否优质商家')),
|
||||||
|
('Platform', models.IntegerField(db_column='fadan_pingtai', default=1, verbose_name='发单平台:1平台2商家')),
|
||||||
|
('ClubID', models.CharField(db_column='club_id', db_index=True, default='xq', max_length=16, verbose_name='所属俱乐部')),
|
||||||
|
('SortOrder', models.IntegerField(default=0, verbose_name='排序(大在前)')),
|
||||||
|
('CreateTime', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
|
||||||
|
('UpdateTime', models.DateTimeField(auto_now=True, verbose_name='更新时间')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'db_table': 'fake_grab_order',
|
||||||
|
'indexes': [models.Index(fields=['ClubID', 'ProductTypeID'], name='fake_grab_o_club_id_6a8f2a_idx')],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1037,6 +1037,59 @@ class ChatSession(QModel):
|
|||||||
return f'{self.User1ID} <-> {self.User2ID} ({self.Status})'
|
return f'{self.User1ID} <-> {self.User2ID} ({self.Status})'
|
||||||
|
|
||||||
|
|
||||||
|
class FakeGrabOrder(QModel):
|
||||||
|
"""抢单大厅假单(仅展示,不可抢单结算)。"""
|
||||||
|
|
||||||
|
OrderID = models.CharField(
|
||||||
|
max_length=32, unique=True, db_index=True,
|
||||||
|
db_column='dingdan_id', verbose_name='订单ID',
|
||||||
|
)
|
||||||
|
Amount = models.DecimalField(
|
||||||
|
max_digits=10, decimal_places=2,
|
||||||
|
db_column='jine', verbose_name='订单价格(展示为打手分红)',
|
||||||
|
)
|
||||||
|
ProductTypeID = models.IntegerField(
|
||||||
|
db_column='leixing_id', verbose_name='订单类型ID',
|
||||||
|
)
|
||||||
|
Description = models.TextField(
|
||||||
|
null=True, blank=True,
|
||||||
|
db_column='jieshao', verbose_name='订单介绍',
|
||||||
|
)
|
||||||
|
Remark = models.TextField(
|
||||||
|
null=True, blank=True,
|
||||||
|
db_column='beizhu', verbose_name='订单备注',
|
||||||
|
)
|
||||||
|
DispatcherUserID = models.CharField(
|
||||||
|
max_length=32, null=True, blank=True,
|
||||||
|
db_column='paidan_yonghuid', verbose_name='派单者用户ID',
|
||||||
|
)
|
||||||
|
DispatcherAvatar = models.CharField(
|
||||||
|
max_length=500, null=True, blank=True,
|
||||||
|
db_column='paidan_touxiang', verbose_name='派单者头像(展示用默认头像)',
|
||||||
|
)
|
||||||
|
IsPremiumMerchant = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
db_column='is_youzhi_shangjia', verbose_name='是否优质商家',
|
||||||
|
)
|
||||||
|
Platform = models.IntegerField(
|
||||||
|
default=1,
|
||||||
|
db_column='fadan_pingtai', verbose_name='发单平台:1平台2商家',
|
||||||
|
)
|
||||||
|
ClubID = models.CharField(
|
||||||
|
max_length=16, default='xq', db_index=True,
|
||||||
|
db_column='club_id', verbose_name='所属俱乐部',
|
||||||
|
)
|
||||||
|
SortOrder = models.IntegerField(default=0, verbose_name='排序(大在前)')
|
||||||
|
CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
|
||||||
|
UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = 'fake_grab_order'
|
||||||
|
indexes = [
|
||||||
|
models.Index(fields=['ClubID', 'ProductTypeID']),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# 兼容别名(渐进迁移,全部迁移完成后可删除)
|
# 兼容别名(渐进迁移,全部迁移完成后可删除)
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
|
|||||||
107
orders/services/fake_order_pool.py
Normal file
107
orders/services/fake_order_pool.py
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
"""抢单大厅假单:无资格/封禁打手仅展示假数据。"""
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
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 orders.models import FakeGrabOrder
|
||||||
|
|
||||||
|
DEFAULT_DISPATCHER_AVATAR = 'a_long/morentouxiang.jpg'
|
||||||
|
|
||||||
|
|
||||||
|
def dashou_should_use_fake_pool(user):
|
||||||
|
"""
|
||||||
|
打手是否只能看假单:
|
||||||
|
- 账号封禁(zhanghaozhuangtai != 1)
|
||||||
|
- 或未开通有效会员 且 押金不大于 5
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
dashou = user.DashouProfile
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if dashou.zhanghaozhuangtai != 1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
yajin = Decimal(str(dashou.yajin or 0))
|
||||||
|
if yajin > Decimal('5'):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if user_has_active_member(user.UserUID):
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _format_fake_row(row):
|
||||||
|
"""字段与 DashouDingdanHuoquView 真实单列表保持一致。"""
|
||||||
|
avatar = DEFAULT_DISPATCHER_AVATAR
|
||||||
|
platform = int(row.Platform or 1)
|
||||||
|
oid = row.OrderID
|
||||||
|
price = float(row.Amount or 0)
|
||||||
|
ct = fmt_datetime(row.CreateTime)
|
||||||
|
zid = (row.DispatcherUserID or '').strip()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'dingdan_id': oid,
|
||||||
|
'zhuangtai': 1,
|
||||||
|
'pingtai': platform,
|
||||||
|
'dashou_fencheng': price,
|
||||||
|
'leixing_id': row.ProductTypeID or 0,
|
||||||
|
'tupian': avatar,
|
||||||
|
'yaoqiuleixing': 0,
|
||||||
|
'huiyuan_id': '',
|
||||||
|
'yajin': 0.0,
|
||||||
|
'jieshao': row.Description or '',
|
||||||
|
'beizhu': row.Remark or '',
|
||||||
|
'creat_time': ct,
|
||||||
|
'create_time': ct,
|
||||||
|
'sjnicheng': '',
|
||||||
|
'sj_avatar': avatar if platform == 2 else '',
|
||||||
|
'zhiding_uid': zid,
|
||||||
|
'zhiding_avatar': avatar,
|
||||||
|
'zhiding_nicheng': '',
|
||||||
|
'xuqiu_biaoqian': [],
|
||||||
|
'dashou_biaoqian': [],
|
||||||
|
'shangjia_biaoqian': [],
|
||||||
|
'shangjia_identity_biaoqian': [],
|
||||||
|
'zhiding_identity_biaoqian': [],
|
||||||
|
'shangjia_youzhi': bool(row.IsPremiumMerchant) if platform == 2 else False,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_fake_order_pool_response(request):
|
||||||
|
data = request.data
|
||||||
|
leixing_id = pick_leixing_id(data)
|
||||||
|
page = max(1, int(data.get('page', 1)))
|
||||||
|
page_size = max(1, min(int(data.get('page_size', 10)), 50))
|
||||||
|
|
||||||
|
club_id = resolve_effective_club_id(request, getattr(request, 'user', None))
|
||||||
|
|
||||||
|
qs = FakeGrabOrder.query.filter(ClubID=club_id)
|
||||||
|
if leixing_id is not None:
|
||||||
|
qs = qs.filter(ProductTypeID=leixing_id)
|
||||||
|
|
||||||
|
qs = qs.order_by('-SortOrder', '-CreateTime')
|
||||||
|
total = qs.count()
|
||||||
|
offset = (page - 1) * page_size
|
||||||
|
rows = list(qs[offset:offset + page_size])
|
||||||
|
|
||||||
|
formatted_list = [_format_fake_row(r) for r in rows]
|
||||||
|
has_more = (page * page_size) < total
|
||||||
|
|
||||||
|
return Response({
|
||||||
|
'code': 200,
|
||||||
|
'msg': '获取成功',
|
||||||
|
'data': {
|
||||||
|
'list': formatted_list,
|
||||||
|
'has_more': has_more,
|
||||||
|
'total': total,
|
||||||
|
'current_page': page,
|
||||||
|
'page_size': page_size,
|
||||||
|
'total_pages': (total + page_size - 1) // page_size if page_size else 0,
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -3050,6 +3050,13 @@ class DashouDingdanHuoquView(APIView):
|
|||||||
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
try:
|
try:
|
||||||
|
from orders.services.fake_order_pool import (
|
||||||
|
dashou_should_use_fake_pool,
|
||||||
|
build_fake_order_pool_response,
|
||||||
|
)
|
||||||
|
if dashou_should_use_fake_pool(request.user):
|
||||||
|
return build_fake_order_pool_response(request)
|
||||||
|
|
||||||
# 1. 获取请求参数
|
# 1. 获取请求参数
|
||||||
data = request.data
|
data = request.data
|
||||||
leixing_id = pick_leixing_id(data)
|
leixing_id = pick_leixing_id(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user