diff --git a/orders/migrations/0014_order_assigned_response.py b/orders/migrations/0014_order_assigned_response.py new file mode 100644 index 0000000..14e7350 --- /dev/null +++ b/orders/migrations/0014_order_assigned_response.py @@ -0,0 +1,39 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('orders', '0013_fakegrabordershufflestate_ordersequence'), + ] + + operations = [ + migrations.AddField( + model_name='order', + name='AssignedResponse', + field=models.PositiveSmallIntegerField( + blank=True, null=True, + db_column='zhiding_hf', + verbose_name='指定打手响应 1想接 2不想接 3等会接', + ), + ), + migrations.AddField( + model_name='order', + name='AssignedResponseAt', + field=models.DateTimeField( + blank=True, null=True, + db_column='zhiding_hf_sj', + verbose_name='指定响应时间', + ), + ), + migrations.AddField( + model_name='order', + name='AssignedLaterNote', + field=models.CharField( + blank=True, default='', + max_length=100, + db_column='zhiding_dhj_sm', + verbose_name='等会接说明', + ), + ), + ] diff --git a/orders/models.py b/orders/models.py index 18ada1d..a722474 100644 --- a/orders/models.py +++ b/orders/models.py @@ -81,6 +81,18 @@ class Order(QModel): max_length=32, null=True, blank=True, db_column='zhiding_id', verbose_name='指定ID', ) + AssignedResponse = models.PositiveSmallIntegerField( + null=True, blank=True, + db_column='zhiding_hf', verbose_name='指定打手响应 1想接 2不想接 3等会接', + ) + AssignedResponseAt = models.DateTimeField( + null=True, blank=True, + db_column='zhiding_hf_sj', verbose_name='指定响应时间', + ) + AssignedLaterNote = models.CharField( + max_length=100, blank=True, default='', + db_column='zhiding_dhj_sm', verbose_name='等会接说明', + ) ProductID = models.IntegerField( null=True, blank=True, db_column='shangpin_id', verbose_name='商品ID', diff --git a/orders/urls.py b/orders/urls.py index 4d2e543..eaa38ba 100644 --- a/orders/urls.py +++ b/orders/urls.py @@ -10,7 +10,8 @@ from .views import CreateOrderView, WechatPayNotifyView, \ AdGengHuanDaShou,ShangjiaCOSZhengshuView, DashouHuoquLeixingView,AdJuJueJieSuan, AdZhuanYiDaTing, AdQuXiaoZhiDing,DashouXiugaiView,DaiLiQunLiaoXiaoXiView,\ ShangjiaLianjieLiuYanZhuanFaView, DingdanXiangqingView2, JiedanView2, ZxsjghdsView, \ ShangjiaFakuanApplyView, ShangjiaFakuaiXiugaiView, ShangjiaShujuTongjiView, LianTongDuiHuaZhunBeiView, \ - LianTongPeiDuiDingDanLieBiaoView, LianTongDingDanZhuangTaiView, LianTongDingDanZhuangTaiPiLiangView + LianTongPeiDuiDingDanLieBiaoView, LianTongDingDanZhuangTaiView, LianTongDingDanZhuangTaiPiLiangView, \ + ZhiDingChaxunView, ZhiDingHuiFuView urlpatterns = [ @@ -36,6 +37,8 @@ urlpatterns = [ # 获取订单列表 path('ddhq', DashouDingdanHuoquView.as_view(), name='打手抢单页获取订单'), + path('zdcx', ZhiDingChaxunView.as_view(), name='查询被指定订单'), + path('zdhf', ZhiDingHuiFuView.as_view(), name='指定订单打手响应'), path('qiangdan', QiangdanView.as_view(), name='打手抢单'), path('dsscpz', DashouCOSZhengshuView.as_view(), name='打手上传图片OSS参数获取接口'), # 打手提交订单完成接口 diff --git a/orders/views.py b/orders/views.py index 1e107f6..5e81611 100644 --- a/orders/views.py +++ b/orders/views.py @@ -82,6 +82,9 @@ from config.models import ( logger = logging.getLogger(__name__) +ZHIDING_HF_TEXT = {1: '想接', 2: '不想接', 3: '等会接'} + + class PaymentFailView(APIView): """ 前端支付失败接口 - 处理用户主动取消或支付失败 @@ -3104,7 +3107,8 @@ class DashouDingdanHuoquView(APIView): MerchantNickname=Subquery(shangjia_sub) ).values( 'OrderID', 'Status', 'Platform', 'PlayerCommission', - 'AssignedID', 'ProductTypeID', 'ImageURL', 'GrabRequirement', + 'AssignedID', 'AssignedResponse', 'AssignedResponseAt', 'AssignedLaterNote', + 'ProductTypeID', 'ImageURL', 'GrabRequirement', 'MembershipID', 'CommissionReq', 'Description', 'Remark', 'CreateTime', 'MerchantNickname' ) @@ -3279,6 +3283,10 @@ class DashouDingdanHuoquView(APIView): 'zhiding_uid': order['AssignedID'] or '', 'zhiding_avatar': info.get('avatar', ''), 'zhiding_nicheng': info.get('nicheng', ''), + 'zhiding_hf': order.get('AssignedResponse'), + 'zhiding_hf_text': ZHIDING_HF_TEXT.get(order.get('AssignedResponse'), ''), + 'zhiding_dhj_sm': order.get('AssignedLaterNote') or '', + 'zhiding_hf_sj': fmt_datetime(order['AssignedResponseAt']) if order.get('AssignedResponseAt') else '', # 三层标签 'xuqiu_biaoqian': xuqiu_tags_map.get(oid, []), 'dashou_biaoqian': dashou_tags_map.get(oid, []), @@ -6317,6 +6325,133 @@ class AdQuXiaoZhiDing(APIView): ) + + +class ZhiDingChaxunView(APIView): + """ + 查询当前打手被指定的待接订单 + POST /dingdan/zdcx + """ + permission_classes = [IsAuthenticated] + + def post(self, request): + try: + dashou_uid = str(request.user.UserUID) + try: + dashou_profile = request.user.DashouProfile + if dashou_profile.zhanghaozhuangtai != 1: + return Response({'code': 403, 'msg': '账号状态异常'}, status=403) + except Exception: + return Response({'code': 403, 'msg': '您不是打手'}, status=403) + + orders = Order.query.filter( + Status=7, + AssignedID=dashou_uid, + ).filter( + Q(PlayerID__isnull=True) | Q(PlayerID='') + ).order_by('-CreateTime')[:20] + + result = [] + for o in orders: + hf = getattr(o, 'AssignedResponse', None) + result.append({ + 'dingdan_id': o.OrderID, + 'zhuangtai': o.Status, + 'pingtai': o.Platform, + 'dashou_fencheng': float(o.PlayerCommission or 0), + 'leixing_id': o.ProductTypeID or 0, + 'tupian': o.ImageURL or '', + 'jieshao': o.Description or '', + 'beizhu': o.Remark or '', + 'creat_time': fmt_datetime(o.CreateTime), + 'create_time': fmt_datetime(o.CreateTime), + 'zhiding_uid': o.AssignedID or '', + 'zhiding_hf': hf, + 'zhiding_hf_text': ZHIDING_HF_TEXT.get(hf, ''), + 'zhiding_dhj_sm': getattr(o, 'AssignedLaterNote', '') or '', + 'zhiding_hf_sj': fmt_datetime(o.AssignedResponseAt) if getattr(o, 'AssignedResponseAt', None) else '', + 'yaoqiuleixing': o.GrabRequirement or 0, + 'huiyuan_id': o.MembershipID or '', + 'yajin': float(o.CommissionReq or 0), + }) + + return Response({ + 'code': 200, + 'msg': '获取成功', + 'data': {'list': result, 'count': len(result)}, + }) + except Exception as e: + logger.error(f"指定订单查询失败: {e}", exc_info=True) + return Response({'code': 500, 'msg': '服务器内部错误'}, status=500) + + +class ZhiDingHuiFuView(APIView): + """ + 指定单打手响应:想接 / 不想接 / 等会接 + POST /dingdan/zdhf + 参数: dingdan_id, huifu (1|2|3), deng_hui_note (等会接说明,可选) + """ + permission_classes = [IsAuthenticated] + + def post(self, request): + try: + data = request.data + dingdan_id = str(data.get('dingdan_id') or data.get('OrderID') or '').strip() + huifu = int(data.get('huifu') or 0) + deng_hui_note = str(data.get('deng_hui_note') or '').strip()[:100] + + if not dingdan_id: + return Response({'code': 400, 'msg': '订单ID不能为空'}, status=400) + if huifu not in (1, 2, 3): + return Response({'code': 400, 'msg': '无效的响应类型'}, status=400) + if huifu == 3 and not deng_hui_note: + return Response({'code': 400, 'msg': '请填写预计接待时间'}, status=400) + + dashou_uid = str(request.user.UserUID) + + with transaction.atomic(): + try: + order = Order.query.select_for_update().get(OrderID=dingdan_id) + except Order.DoesNotExist: + return Response({'code': 404, 'msg': '订单不存在'}, status=404) + + if order.Status != 7: + return Response({'code': 400, 'msg': '订单已不是指定中状态'}, status=400) + if str(order.AssignedID or '') != dashou_uid: + return Response({'code': 403, 'msg': '您不是该订单的指定打手'}, status=403) + if order.PlayerID: + return Response({'code': 400, 'msg': '订单已被接单'}, status=400) + + now = timezone.now() + order.AssignedResponse = huifu + order.AssignedResponseAt = now + + if huifu == 2: + order.Status = 1 + order.AssignedID = None + order.AssignedLaterNote = '' + elif huifu == 3: + order.AssignedLaterNote = deng_hui_note + else: + order.AssignedLaterNote = '' + + order.save() + + msg_map = {1: '已标记想接,请点击接待完成接单', 2: '已婉拒,订单已退回大厅', 3: '已记录,请按时接待'} + return Response({ + 'code': 200, + 'msg': msg_map.get(huifu, '操作成功'), + 'data': { + 'dingdan_id': dingdan_id, + 'huifu': huifu, + 'huifu_text': ZHIDING_HF_TEXT.get(huifu, ''), + }, + }) + except Exception as e: + logger.error(f"指定订单响应失败: {e}", exc_info=True) + return Response({'code': 500, 'msg': '服务器内部错误'}, status=500) + + class DashouXiugaiView(APIView): """ 打手修改订单交付内容接口