feat: 假单种子脚本、商家名称字段、返回随机顺序与时间
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
0
orders/management/__init__.py
Normal file
0
orders/management/__init__.py
Normal file
0
orders/management/commands/__init__.py
Normal file
0
orders/management/commands/__init__.py
Normal file
154
orders/management/commands/seed_fake_grab_orders.py
Normal file
154
orders/management/commands/seed_fake_grab_orders.py
Normal file
@@ -0,0 +1,154 @@
|
||||
"""写入抢单大厅假单种子数据。用法: python manage.py seed_fake_grab_orders --club-id xq --leixing-id 1"""
|
||||
import random
|
||||
import time
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
|
||||
from orders.models import FakeGrabOrder
|
||||
|
||||
DEFAULT_AVATAR = 'a_long/morentouxiang.jpg'
|
||||
|
||||
COMMON_TAIL = (
|
||||
'下单凑七套,不卡保底,不要私藏变卖,私藏变卖老板必退款,'
|
||||
'陪护也不能私藏,不能藏一丁点装备和变卖,不然必退款和罚款。'
|
||||
)
|
||||
|
||||
# 7 个模板(各生成 2 条 = 14 条)
|
||||
TEMPLATE_ROWS = [
|
||||
{
|
||||
'title': '2100W',
|
||||
'description': f'打手选图保底2100W,{COMMON_TAIL}',
|
||||
'amount': '35.00',
|
||||
},
|
||||
{
|
||||
'title': '4光子鸡',
|
||||
'description': (
|
||||
'单据4个光子鸡,不出,一直打,下单凑七套,装备和收益都归老板,'
|
||||
'不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,'
|
||||
'不能藏一丁点装备和变卖,不然必退款和罚款。'
|
||||
),
|
||||
'amount': '30.00',
|
||||
},
|
||||
{
|
||||
'title': '3金光',
|
||||
'description': (
|
||||
'单局出3个金光,下单凑七套,装备和收益都归老板,'
|
||||
'不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,'
|
||||
'不能藏一丁点装备和变卖,不然必退款和罚款。'
|
||||
),
|
||||
'amount': '20.00',
|
||||
},
|
||||
{
|
||||
'title': '1500W',
|
||||
'description': f'打手选图保底1500W,{COMMON_TAIL}',
|
||||
'amount': '25.00',
|
||||
},
|
||||
{
|
||||
'title': '300W',
|
||||
'description': f'保底,300w以上,{COMMON_TAIL}',
|
||||
'amount': '6.00',
|
||||
},
|
||||
{
|
||||
'title': '4金条',
|
||||
'description': (
|
||||
'单据4根,金条不出,一直打,下单凑七套,装备和收益都归老板,'
|
||||
'不卡保底,不要私藏变卖,私藏变卖老板必退款,陪护也不能私藏,'
|
||||
'不能藏一丁点装备和变卖,不然必退款和罚款。'
|
||||
),
|
||||
'amount': '18.00',
|
||||
},
|
||||
{
|
||||
'title': '1000W',
|
||||
'description': f'打手选图保底1000W,{COMMON_TAIL}',
|
||||
'amount': '15.00',
|
||||
},
|
||||
]
|
||||
|
||||
MERCHANT_NAMES = [
|
||||
'官方直营店',
|
||||
'接单秒结',
|
||||
'没实力的别接',
|
||||
'骂老板4千家',
|
||||
]
|
||||
|
||||
# 14 条:平台 5 + 商家 9;优质商家 6(仅商家单)
|
||||
# 索引 0-13 对应 7 模板各 2 条
|
||||
PLATFORM_INDEXES = {0, 1, 2, 3, 4}
|
||||
PREMIUM_MERCHANT_INDEXES = {5, 6, 7, 8, 9, 10}
|
||||
REMARK_INDEXES = {2, 5, 8, 11}
|
||||
REMARK_TEXT = '打的好奖励鸡腿'
|
||||
|
||||
POOL_USER_IDS = ['3829104', '5829104', '1928374', '6649201', '7731045', '8812345']
|
||||
|
||||
|
||||
def _gen_order_id(used):
|
||||
while True:
|
||||
oid = f'JD{int(time.time() * 1000)}{random.randint(1000, 9999)}'
|
||||
if oid not in used:
|
||||
used.add(oid)
|
||||
return oid
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = '写入抢单大厅假单(7 模板 ×2 = 14 条,可重复执行会先清理同俱乐部+类型旧 JD 假单)'
|
||||
|
||||
def add_arguments(self, parser):
|
||||
parser.add_argument('--club-id', default='xq', help='俱乐部 ID,默认 xq')
|
||||
parser.add_argument('--leixing-id', type=int, default=1, help='商品类型 ID(与抢单大厅 Tab 一致)')
|
||||
parser.add_argument('--no-clear', action='store_true', help='不清理旧 JD 假单,直接追加(可能 ID 冲突)')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
club_id = (options['club_id'] or 'xq').strip()
|
||||
leixing_id = int(options['leixing_id'])
|
||||
now = timezone.now()
|
||||
|
||||
if not options['no_clear']:
|
||||
deleted, _ = FakeGrabOrder.query.filter(
|
||||
ClubID=club_id,
|
||||
ProductTypeID=leixing_id,
|
||||
OrderID__startswith='JD',
|
||||
).delete()
|
||||
self.stdout.write(f'已清理旧假单 {deleted} 条(club={club_id}, leixing={leixing_id})')
|
||||
|
||||
used_ids = set()
|
||||
expanded = []
|
||||
for tpl in TEMPLATE_ROWS:
|
||||
expanded.append(tpl)
|
||||
expanded.append(tpl)
|
||||
|
||||
created = 0
|
||||
for idx, tpl in enumerate(expanded):
|
||||
is_platform = idx in PLATFORM_INDEXES
|
||||
is_premium = idx in PREMIUM_MERCHANT_INDEXES and not is_platform
|
||||
remark = REMARK_TEXT if idx in REMARK_INDEXES else ''
|
||||
|
||||
merchant_name = ''
|
||||
if not is_platform:
|
||||
merchant_name = MERCHANT_NAMES[idx % len(MERCHANT_NAMES)]
|
||||
|
||||
dispatcher_id = random.choice(POOL_USER_IDS)
|
||||
|
||||
FakeGrabOrder.query.create(
|
||||
OrderID=_gen_order_id(used_ids),
|
||||
Amount=tpl['amount'],
|
||||
ProductTypeID=leixing_id,
|
||||
Description=tpl['description'],
|
||||
Remark=remark,
|
||||
DispatcherUserID=dispatcher_id,
|
||||
DispatcherAvatar=DEFAULT_AVATAR,
|
||||
MerchantNickname=merchant_name,
|
||||
IsPremiumMerchant=is_premium,
|
||||
Platform=1 if is_platform else 2,
|
||||
ClubID=club_id,
|
||||
SortOrder=100 - idx,
|
||||
CreateTime=now,
|
||||
UpdateTime=now,
|
||||
)
|
||||
created += 1
|
||||
|
||||
self.stdout.write(self.style.SUCCESS(
|
||||
f'假单种子完成:新增 {created} 条 | club={club_id} leixing_id={leixing_id} '
|
||||
f'(平台单 {len(PLATFORM_INDEXES)} 商家单 {created - len(PLATFORM_INDEXES)} '
|
||||
f'优质商家 {len(PREMIUM_MERCHANT_INDEXES)})'
|
||||
))
|
||||
22
orders/migrations/0011_fakegraborder_merchantnickname.py
Normal file
22
orders/migrations/0011_fakegraborder_merchantnickname.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('orders', '0010_fakegraborder'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='fakegraborder',
|
||||
name='MerchantNickname',
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_column='shangjia_nicheng',
|
||||
max_length=50,
|
||||
null=True,
|
||||
verbose_name='商家名称(假单展示)',
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1067,6 +1067,10 @@ class FakeGrabOrder(QModel):
|
||||
max_length=500, null=True, blank=True,
|
||||
db_column='paidan_touxiang', verbose_name='派单者头像(展示用默认头像)',
|
||||
)
|
||||
MerchantNickname = models.CharField(
|
||||
max_length=50, null=True, blank=True,
|
||||
db_column='shangjia_nicheng', verbose_name='商家名称(假单展示)',
|
||||
)
|
||||
IsPremiumMerchant = models.BooleanField(
|
||||
default=False,
|
||||
db_column='is_youzhi_shangjia', verbose_name='是否优质商家',
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
"""抢单大厅假单:无资格/封禁打手仅展示假数据。"""
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils import timezone
|
||||
from rest_framework.response import Response
|
||||
|
||||
from backend.utils import fmt_datetime, pick_leixing_id
|
||||
@@ -36,14 +39,22 @@ def dashou_should_use_fake_pool(user):
|
||||
return True
|
||||
|
||||
|
||||
def _format_fake_row(row):
|
||||
def _random_display_time_str():
|
||||
"""返回给前端的创建时间:当前请求时刻 2~5 分钟前的随机时间。"""
|
||||
seconds_ago = random.randint(120, 300)
|
||||
dt = timezone.now() - timedelta(seconds=seconds_ago)
|
||||
return fmt_datetime(dt)
|
||||
|
||||
|
||||
def _format_fake_row(row, display_time=None):
|
||||
"""字段与 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)
|
||||
ct = display_time or _random_display_time_str()
|
||||
zid = (row.DispatcherUserID or '').strip()
|
||||
sj_name = (getattr(row, 'MerchantNickname', None) or '').strip()
|
||||
|
||||
return {
|
||||
'dingdan_id': oid,
|
||||
@@ -59,7 +70,7 @@ def _format_fake_row(row):
|
||||
'beizhu': row.Remark or '',
|
||||
'creat_time': ct,
|
||||
'create_time': ct,
|
||||
'sjnicheng': '',
|
||||
'sjnicheng': sj_name if platform == 2 else '',
|
||||
'sj_avatar': avatar if platform == 2 else '',
|
||||
'zhiding_uid': zid,
|
||||
'zhiding_avatar': avatar,
|
||||
@@ -85,12 +96,14 @@ def build_fake_order_pool_response(request):
|
||||
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])
|
||||
rows = list(qs)
|
||||
random.shuffle(rows)
|
||||
|
||||
formatted_list = [_format_fake_row(r) for r in rows]
|
||||
total = len(rows)
|
||||
offset = (page - 1) * page_size
|
||||
page_rows = rows[offset:offset + page_size]
|
||||
|
||||
formatted_list = [_format_fake_row(r) for r in page_rows]
|
||||
has_more = (page * page_size) < total
|
||||
|
||||
return Response({
|
||||
|
||||
Reference in New Issue
Block a user