diff --git a/orders/migrations/0010_fakegraborder.py b/orders/migrations/0010_fakegraborder.py new file mode 100644 index 0000000..bfd7692 --- /dev/null +++ b/orders/migrations/0010_fakegraborder.py @@ -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')], + }, + ), + ] diff --git a/orders/models.py b/orders/models.py index 7c20838..19c880b 100644 --- a/orders/models.py +++ b/orders/models.py @@ -1037,6 +1037,59 @@ class ChatSession(QModel): 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']), + ] + + # =========================================================================== # 兼容别名(渐进迁移,全部迁移完成后可删除) # =========================================================================== diff --git a/orders/services/fake_order_pool.py b/orders/services/fake_order_pool.py new file mode 100644 index 0000000..ba15063 --- /dev/null +++ b/orders/services/fake_order_pool.py @@ -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, + }, + }) diff --git a/orders/views.py b/orders/views.py index 902c07b..4b85441 100644 --- a/orders/views.py +++ b/orders/views.py @@ -3050,6 +3050,13 @@ class DashouDingdanHuoquView(APIView): def post(self, request): 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. 获取请求参数 data = request.data leixing_id = pick_leixing_id(data)