Files
Django/orders/views/boss_orders.py
XingQue 6cb3dff949 fix: 老板订单详情查询打手表现字段错误导致接单后整页500
dingdanxiangqing2 误用 OrderID 过滤 DashouBiaoxian(应为 dingdan_id),有人接单即服务器内部错误,打手信息无法返回。同步修正结算写入 fanche_cishu 与评分整数累加。不影响其它俱乐部业务分支。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 04:06:05 +08:00

832 lines
34 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""orders.views.boss_orders - auto-generated by split script."""
# ==================== 标准库 ====================
import hmac
import os
import json
import time
import random
import string
import traceback
import threading
import requests
import hashlib
import xml.etree.ElementTree as ET
import xmltodict
import logging
from decimal import Decimal
from django.conf import settings
from django.db import models, transaction
from gvsdsdk.fluent import db, func, FQ
from django.db.models import F, Q, OuterRef, Subquery
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from django.utils import timezone
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions, status
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.parsers import JSONParser
from rest_framework.throttling import AnonRateThrottle
from rest_framework_simplejwt.authentication import JWTAuthentication
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.sts.v20180813 import sts_client, models
from utils.weixin_broadcast import WeixinBroadcastSender
from utils.money import yuan_to_fen
from utils.chat_utils import (
_send_group_message, _subscribe_users_to_group, establish_order_chat,
prepare_order_group_chat, resolve_pair_group_id,
parse_pair_from_group_id, resolve_pair_from_order, check_pair_chat_permission,
query_pair_orders, order_to_chat_dict,
)
from utils.fadan_utils import check_fadan_qiangdan_eligible
from orders.utils import (
calc_shangjia_order_fencheng,
update_daily_payout,
settle_shangjia_order_guanshi_fenhong
)
from shop.utils import calculate_pingtai_and_dianpu_shouyi, validate_shangpin_and_dianpu, update_dianpu_daily_stat
from products.utils import update_shangpin_daily_stat
from backend.utils import update_shangjia_daily, update_dashou_daily_by_action, pick_leixing_id, datetime_aliases, fmt_datetime
from rank.services import record_dashou_biaoxian
from rank.utils import check_dashou_biaoqian_required
from orders.notice_tasks import dingdan_guangbo
from ..models import (
Order, MerchantOrderExt, PlatformOrderExt, PlayerDeliveryImage,
PenaltyRecord, PenaltyEvidenceImage, Penalty, PenaltyAppealImage, PenaltyBonus, PenaltyBonusRate,
CommissionRate, PlayerRating, RefundRecord,
)
from jituan.services.club_config import get_commission_rate, get_commission_rate_object
from jituan.services.club_context import resolve_club_id_from_request
from jituan.services.club_user import get_payment_openid
from jituan.services.club_penalty import resolve_penalty_club_id, resolve_penalty_record_club_id
from users.fadan_fenhong_utils import lock_penalty_bonus
from users.fadan_fenhong_utils import lock_penalty_bonus
from products.models import Shangpin, ShangpinLeixing, Huiyuangoumai
from users.models import UserDashou, UserShangjia, UserBoss
from users.business_models import User
from rank.models import DashouBiaoxian, Chenghao, DingdanBiaoqian, YonghuChenghao
from config.models import (
ShangjiaLianjie
)
logger = logging.getLogger(__name__)
class DingdanHuoquView(APIView):
"""订单获取接口"""
permission_classes = [IsAuthenticated]
def post(self, request):
# 获取当前登录用户
try:
current_user = request.user
yonghuid = current_user.UserUID
except Exception as e:
return Response({
'code': 1,
'msg': '用户认证失败',
'data': None
})
# 获取前端参数
try:
data = request.data
zhuangtai_list = data.get('zhuangtai_list', [])
page = int(data.get('page', 1))
page_size = int(data.get('page_size', 10))
except Exception as e:
return Response({
'code': 2,
'msg': '参数格式错误',
'data': None
})
# 参数验证
if not isinstance(zhuangtai_list, list) or len(zhuangtai_list) == 0:
return Response({
'code': 3,
'msg': '状态列表不能为空',
'data': None
})
if page < 1:
page = 1
if page_size <= 0:
page_size = 10
try:
# 查询扩展表获取用户的所有订单ID
pingtai_orders = PlatformOrderExt.query.filter(BossID=yonghuid)
pingtai_order_ids = list(pingtai_orders.values_list('Order__OrderID', flat=True))
if not pingtai_order_ids:
return Response({
'code': 0,
'msg': '成功',
'data': {
'list': [],
'has_more': False,
'total': 0
}
})
# 查询主表
status_query = Q()
if zhuangtai_list != [1, 2, 3, 4, 5, 6, 7, 8]:
status_query = Q(Status__in=zhuangtai_list)
query = Q(OrderID__in=pingtai_order_ids) & status_query
orders = Order.query.filter(query).order_by('-CreateTime')
#total_orders = orders.count()
# 手动分页逻辑
start_index = (page - 1) * page_size
end_index = start_index + page_size
# 获取当前页的数据
current_page_orders = orders[start_index:end_index]
# 构建返回数据
order_list = []
for order in current_page_orders:
order_data = {
'dingdanId': order.OrderID,
'zhuangtai': order.Status,
'jine': float(order.Amount) if order.Amount else 0.0,
'tupian': order.ImageURL or '',
'jieshao': order.Description or '',
'beizhu': order.Remark or '',
'nicheng': order.Nickname or '',
'chuangjianshijian': fmt_datetime(order.CreateTime),
'create_time': fmt_datetime(order.CreateTime),
}
order_list.append(order_data)
# 判断是否还有更多数据
current_page_count = len(current_page_orders)
has_more = current_page_count == page_size
return Response({
'code': 0,
'msg': '成功',
'data': {
'list': order_list,
'has_more': has_more,
#'total': total_orders
}
})
except Exception as e:
return Response({
'code': 4,
'msg': '服务器内部错误',
'data': None
})
class DingdanXiangqingView(APIView):
"""订单详情接口"""
permission_classes = [IsAuthenticated]
def post(self, request):
# 获取当前登录用户
try:
current_user = request.user
yonghuid = current_user.UserUID
except Exception as e:
return Response({
'code': 1,
'msg': '用户认证失败',
'data': None
})
# 获取前端参数
try:
data = request.data
dingdan_id = data.get('dingdanId', '')
except Exception as e:
return Response({
'code': 2,
'msg': '参数格式错误',
'data': None
})
# 参数验证
if not dingdan_id:
return Response({
'code': 3,
'msg': '订单ID不能为空',
'data': None
})
try:
# 1. 验证订单是否属于当前用户
# 查询平台订单扩展表检查laoban_id是否等于当前用户
pingtai_kuozhan = PlatformOrderExt.query.filter(
BossID=yonghuid,
Order__OrderID=dingdan_id
).first()
if not pingtai_kuozhan:
# 如果不是平台订单,检查商家订单
shangjia_kuozhan = MerchantOrderExt.query.filter(
MerchantID=yonghuid,
Order__OrderID=dingdan_id
).first()
if not shangjia_kuozhan:
return Response({
'code': 4,
'msg': '订单不存在或无权限查看',
'data': None
})
# 2. 查询订单主表
dingdan = Order.query.filter(OrderID=dingdan_id).first()
if not dingdan:
return Response({
'code': 5,
'msg': '订单不存在',
'data': None
})
# 3. 获取订单信息
zhuangtai = dingdan.Status or 0
zhiding_id = dingdan.AssignedID or ''
jiedan_dashou_id = dingdan.PlayerID or ''
dashou_liuyan = dingdan.PlayerRemark or ''
# 4. 查询打手交付图片
dashoutupian_records = PlayerDeliveryImage.query.filter(
OrderID=dingdan_id
).order_by('CreateTime')[:9] # 最多取9条
dashoujiaofu_list = []
for record in dashoutupian_records:
if record.ImageURL:
dashoujiaofu_list.append(record.ImageURL)
# 5. 构建返回数据(字段名与前端对应)
response_data = {
'zhuangtai': zhuangtai, # 订单状态
'zhiding': zhiding_id, # 指定打手ID
'jiedan_dashou_id': jiedan_dashou_id, # 服务打手ID
'dashouliuyan': dashou_liuyan, # 打手留言
'dashoujiaofu': dashoujiaofu_list # 打手交付图片列表
}
# 6. 返回成功响应
return Response({
'code': 0,
'msg': '成功',
'data': response_data
})
except Exception as e:
print(f"订单详情查询失败: {str(e)}")
return Response({
'code': 6,
'msg': '服务器内部错误',
'data': None
})
class JiedanView(APIView):
"""结单接口"""
permission_classes = [IsAuthenticated]
def post(self, request):
# 获取当前登录用户
try:
current_user = request.user
yonghuid = current_user.UserUID
except Exception as e:
return Response({
'code': 1,
'msg': '用户认证失败',
'data': None
})
# 获取前端参数
try:
data = request.data
dingdan_id = data.get('dingdanId', '')
pingfen = int(data.get('pingfen', 0)) # 评分默认0
liuyan = data.get('liuyan', '') # 留言,默认空
except Exception as e:
return Response({
'code': 2,
'msg': '参数格式错误',
'data': None
})
# 参数验证
if not dingdan_id:
return Response({
'code': 3,
'msg': '订单ID不能为空',
'data': None
})
# 验证评分范围
if pingfen < 0 or pingfen > 5:
return Response({
'code': 4,
'msg': '评分必须在0-5分之间',
'data': None
})
# 使用事务确保数据一致性
try:
with transaction.atomic():
# 1. 验证订单是否存在且属于当前用户
pingtai_kuozhan = PlatformOrderExt.query.filter(
BossID=yonghuid,
Order__OrderID=dingdan_id
).select_related('Order').first()
if not pingtai_kuozhan:
return Response({
'code': 5,
'msg': '订单不存在或无权限操作',
'data': None
})
dingdan = pingtai_kuozhan.Order
# 2. 验证订单状态(必须是结算中 - 状态8
if dingdan.Status != 8:
return Response({
'code': 6,
'msg': '订单不在结算状态,无法结单',
'data': None
})
# 3. 获取订单相关数据
dashou_fencheng = dingdan.PlayerCommission or Decimal('0.00') # 打手分成
jiedan_dashou_id = dingdan.PlayerID or '' # 接单打手ID
shangpin_id = dingdan.ProductID # 商品ID
# 4. 更新平台扩展表的老板评价(如果有留言)
if liuyan:
pingtai_kuozhan.BossReview = liuyan
pingtai_kuozhan.save()
# 5. 如果有评分,更新评分表
if pingfen > 0 and jiedan_dashou_id:
# 使用filter查询更健壮
pingfen_records = PlayerRating.query.filter(PlayerID=jiedan_dashou_id)
if pingfen_records.exists():
# 已有记录,更新
pingfen_record = pingfen_records.first()
pingfen_record.TotalScore += Decimal(str(pingfen))
pingfen_record.RatingCount += 1
pingfen_record.save()
else:
# 新记录,创建
PlayerRating.query.create(
PlayerID=jiedan_dashou_id,
TotalScore=Decimal(str(pingfen)),
RatingCount=1
)
# 6. 更新商品真实销量如果有商品ID
if shangpin_id:
shangpin_records = Shangpin.query.filter(id=shangpin_id)
if shangpin_records.exists():
shangpin = shangpin_records.first()
# 检查字段是否存在
if hasattr(shangpin, 'zhenshi_xiaoliang'):
shangpin.zhenshi_xiaoliang = (shangpin.zhenshi_xiaoliang or 0) + 1
shangpin.save()
# 7. 更新打手扩展表如果有打手ID和分成
if jiedan_dashou_id and dashou_fencheng > 0:
# 查询打手用户
dashou_user = User.query.filter(UserUID=jiedan_dashou_id).select_related('DashouProfile').first()
if dashou_user:
# 查询打手扩展表
try:
dashou_kuozhan = dashou_user.DashouProfile
except UserDashou.DoesNotExist:
dashou_kuozhan = None
if dashou_kuozhan:
# 更新四个金额字段
dashou_kuozhan.zonge = (dashou_kuozhan.zonge or Decimal('0.00')) + dashou_fencheng
dashou_kuozhan.yue = (dashou_kuozhan.yue or Decimal('0.00')) + dashou_fencheng
dashou_kuozhan.jinrishouyi = (dashou_kuozhan.jinrishouyi or Decimal(
'0.00')) + dashou_fencheng
dashou_kuozhan.jinyueshouyi = (dashou_kuozhan.jinyueshouyi or Decimal(
'0.00')) + dashou_fencheng
# 成交总量加1
dashou_kuozhan.chengjiaozongliang = (dashou_kuozhan.chengjiaozongliang or 0) + 1
# 状态改为数字1
dashou_kuozhan.zhuangtai = 1
dashou_kuozhan.save()
# 8. 更新订单状态为已完成状态3
dingdan.Status = 3
dingdan.save()
# 🔥 新增:调用打手每日统计(成交)
try:
update_dashou_daily_by_action(
yonghuid=jiedan_dashou_id,
amount=dashou_fencheng,
action=2 # 2 表示成交(结算)
)
logger.info(f"打手 {jiedan_dashou_id} 每日统计更新成功")
except Exception as e:
logger.error(f"打手每日统计更新失败: {e}")
# 不影响主流程
# ========== 新增:商品和店铺每日统计 ==========
try:
# 商品每日统计只要有商品ID就执行
if dingdan.ProductID:
# 从扩展表获取已计算好的收益值(下单时已存储)
pingtai_shouyi = Decimal('0.00')
dianpu_shouyi = Decimal('0.00')
if hasattr(dingdan, 'pingtai_kuozhan'):
pingtai_shouyi = dingdan.pingtai_kuozhan.PlatformIncome or Decimal('0.00')
dianpu_shouyi = dingdan.pingtai_kuozhan.ShopIncome or Decimal('0.00')
update_shangpin_daily_stat(
ProductID=dingdan.ProductID,
caozuo_leixing=2, # 2 = 结单
dingdan_jiage=dingdan.Amount,
PlatformIncome=pingtai_shouyi,
dianpu_zongshouyi=dianpu_shouyi
)
logger.info(f"商品统计更新完成商品ID: {dingdan.ProductID}")
# 店铺每日统计仅当存在店铺ID时执行
# ========== 修改为 ==========
# 店铺每日统计(包含上级分红)
dianpu_id = None
shangji_id = None
shangji_fen = Decimal('0.00')
if hasattr(dingdan, 'pingtai_kuozhan'):
dianpu_id = dingdan.pingtai_kuozhan.ShopID
shangji_id = dingdan.pingtai_kuozhan.ParentShopID
shangji_fen = dingdan.pingtai_kuozhan.ParentBonus or Decimal('0.00')
if dianpu_id:
dianpu_shouyi = dingdan.pingtai_kuozhan.ShopIncome or Decimal('0.00')
update_dianpu_daily_stat(
ShopID=dianpu_id,
caozuo_leixing=2, # 结算
dingdan_jiage=dingdan.Amount,
ShopIncome=dianpu_shouyi,
shangji_ShopID=shangji_id, # 新增上级店铺ID
ParentBonus=shangji_fen # 新增:该单给上级的分红
)
logger.info(f"店铺统计更新完成店铺ID: {dianpu_id}, 上级ID: {shangji_id}, 上级分红: {shangji_fen}")
'''dianpu_id = None
if hasattr(dingdan, 'pingtai_kuozhan'):
dianpu_id = dingdan.pingtai_kuozhan.ShopID
if dianpu_id:
dianpu_shouyi = dingdan.pingtai_kuozhan.ShopIncome or Decimal('0.00')
update_dianpu_daily_stat(
ShopID=dianpu_id,
caozuo_leixing=2, # 2 = 结单
dingdan_jiage=dingdan.Amount,
ShopIncome=dianpu_shouyi
)
logger.info(f"店铺统计更新完成店铺ID: {dianpu_id}")'''
except Exception as e:
logger.error(f"商品/店铺统计更新失败: {e}")
logger.error(traceback.format_exc())
# 统计失败不影响主流程
# =============================================
# 9. 返回成功响应
return Response({
'code': 0,
'msg': '结单成功',
'data': None
})
except Exception as e:
# 事务会自动回滚
return Response({
'code': 7,
'msg': '结单失败,服务器内部错误',
'data': None
})
class DingdanXiangqingView2(APIView):
"""订单详情接口(老板端)- 返回完整评价信息"""
permission_classes = [IsAuthenticated]
def post(self, request):
try:
yonghuid = request.user.UserUID
except Exception:
return Response({'code': 1, 'msg': '用户认证失败', 'data': None})
dingdan_id = request.data.get('dingdanId', '')
if not dingdan_id:
return Response({'code': 2, 'msg': '订单ID不能为空', 'data': None})
try:
# 权限验证
pingtai_ext = PlatformOrderExt.query.filter(
BossID=yonghuid,
Order__OrderID=dingdan_id
).select_related('Order').first()
if not pingtai_ext:
return Response({'code': 3, 'msg': '订单不存在或无权限查看', 'data': None})
order = pingtai_ext.Order
zhuangtai = order.Status or 0
jiedan_dashou_id = order.PlayerID or ''
dashou_liuyan = order.PlayerRemark or ''
UpdateTime = order.UpdateTime.strftime('%Y-%m-%d %H:%M:%S') if order.UpdateTime else ''
# 交付图片
dashoujiaofu_list = list(
PlayerDeliveryImage.query.filter(OrderID=dingdan_id)
.order_by('CreateTime')[:9]
.values_list('ImageURL', flat=True)
)
# 打手信息
dashou_nicheng = ''
dashou_touxiang = ''
jiedan_time = ''
tijiao_time = ''
if jiedan_dashou_id:
dashou_user = User.query.filter(UserUID=jiedan_dashou_id).select_related('DashouProfile').first()
if dashou_user:
dashou_touxiang = dashou_user.Avatar or ''
try:
dashou_nicheng = dashou_user.DashouProfile.nicheng or ''
except Exception:
# 无打手扩展档案时仍返回打手 UID / 头像
pass
# DashouBiaoxian 外键字段是 dingdan列 dingdan_id勿用 OrderID会 FieldError → 整单详情 500
try:
biaoxian = DashouBiaoxian.query.filter(
dingdan_id=dingdan_id,
dashou_id=jiedan_dashou_id
).first()
if biaoxian:
if biaoxian.jiedan_time:
jiedan_time = biaoxian.jiedan_time.strftime('%Y-%m-%d %H:%M:%S')
if biaoxian.tijiao_time:
tijiao_time = biaoxian.tijiao_time.strftime('%Y-%m-%d %H:%M:%S')
except Exception as e:
logger.warning(f"读取打手表现失败 dingdan={dingdan_id}: {e}")
# 老板自己的评价(如果已经结算过,可能已有评价)
laoban_pingjia = pingtai_ext.BossReview or ''
shangxian_sudu = None
fuwu_taidu = None
fanche_cishu = None
if jiedan_dashou_id and zhuangtai in [3, 4, 5, 6]: # 已完成或退款相关状态才可能有评价
try:
biaoxian = DashouBiaoxian.query.filter(
dingdan_id=dingdan_id,
dashou_id=jiedan_dashou_id
).first()
if biaoxian:
shangxian_sudu = biaoxian.shangxian_sudu
fuwu_taidu = biaoxian.fuwu_taidu
fanche_cishu = biaoxian.fanche_cishu
except Exception as e:
logger.warning(f"读取结算评价失败 dingdan={dingdan_id}: {e}")
data = {
'zhuangtai': zhuangtai,
'dashou': jiedan_dashou_id,
'dashou_nicheng': dashou_nicheng,
'dashou_touxiang': dashou_touxiang,
'dashouliuyan': dashou_liuyan,
'dashoujiaofu': dashoujiaofu_list,
'UpdateTime': UpdateTime,
'jiedan_time': jiedan_time,
'tijiao_time': tijiao_time,
'laoban_pingjia': laoban_pingjia,
'shangxian_sudu': shangxian_sudu, # 1-5 或 null
'fuwu_taidu': fuwu_taidu, # 1-5 或 null
'fanche_cishu': fanche_cishu # int 或 null
}
return Response({'code': 0, 'msg': '成功', 'data': data})
except Exception as e:
logger.error(f"订单详情查询异常: {e}", exc_info=True)
return Response({'code': 4, 'msg': '服务器内部错误', 'data': None})
class JiedanView2(APIView):
"""结单接口(老板端)- 接收全新评价字段并写入表现表"""
permission_classes = [IsAuthenticated]
def post(self, request):
# 1. 用户认证
try:
current_user = request.user
yonghuid = current_user.UserUID
except Exception:
return Response({'code': 1, 'msg': '用户认证失败', 'data': None})
# 2. 获取参数(字段名与前端完全一致)
try:
data = request.data
dingdan_id = data.get('dingdanId', '')
fanche_cishu = data.get('fanche_cishu') # 前端传的字符串或数字,后端转为整数
shangxian_sudu = data.get('shangxian_sudu')
fuwu_taidu = data.get('fuwu_taidu')
liuyan = data.get('liuyan', '')
except Exception:
return Response({'code': 2, 'msg': '参数格式错误', 'data': None})
# 参数校验
if not dingdan_id:
return Response({'code': 3, 'msg': '订单ID不能为空', 'data': None})
# 转换并校验必填评价字段
try:
fanche_cishu = int(fanche_cishu) if fanche_cishu is not None else None
shangxian_sudu = int(shangxian_sudu) if shangxian_sudu is not None else None
fuwu_taidu = int(fuwu_taidu) if fuwu_taidu is not None else None
except (ValueError, TypeError):
return Response({'code': 4, 'msg': '评价参数必须为整数', 'data': None})
if fanche_cishu is None:
return Response({'code': 5, 'msg': '翻车次数不能为空', 'data': None})
if not (1 <= shangxian_sudu <= 5 and 1 <= fuwu_taidu <= 5):
return Response({'code': 6, 'msg': '评价分数必须在1-5之间', 'data': None})
# 使用事务保证数据一致性
try:
with transaction.atomic():
# 3. 权限验证:订单属于当前老板
pingtai_ext = PlatformOrderExt.query.filter(
BossID=yonghuid,
Order__OrderID=dingdan_id
).select_related('Order').first()
if not pingtai_ext:
return Response({'code': 7, 'msg': '订单不存在或无权限操作', 'data': None})
order = pingtai_ext.Order
# 4. 状态校验必须是结算中状态8
if order.Status != 8:
return Response({'code': 8, 'msg': '订单不在结算状态', 'data': None})
# 5. 提取订单关键数据
dashou_fencheng = order.PlayerCommission or Decimal('0.00')
jiedan_dashou_id = order.PlayerID or ''
shangpin_id = order.ProductID
# 6. 保存老板评价(兼容旧逻辑)
if liuyan:
pingtai_ext.BossReview = liuyan
pingtai_ext.save()
# 7. 更新评分表(用服务态度分作为综合评分,保留原有统计)
if jiedan_dashou_id and fuwu_taidu:
pingfen_records = PlayerRating.query.filter(PlayerID=jiedan_dashou_id)
if pingfen_records.exists():
pf = pingfen_records.first()
pf.TotalScore = int(pf.TotalScore or 0) + int(fuwu_taidu)
pf.RatingCount = int(pf.RatingCount or 0) + 1
pf.save()
else:
PlayerRating.query.create(
PlayerID=jiedan_dashou_id,
TotalScore=int(fuwu_taidu),
RatingCount=1
)
# 8. 更新商品真实销量
if shangpin_id:
shangpin_qs = Shangpin.query.filter(id=shangpin_id)
if shangpin_qs.exists():
sp = shangpin_qs.first()
if hasattr(sp, 'zhenshi_xiaoliang'):
sp.zhenshi_xiaoliang = (sp.zhenshi_xiaoliang or 0) + 1
sp.save()
# 9. 更新打手收益与状态
if jiedan_dashou_id and dashou_fencheng > 0:
dashou_user = User.query.filter(UserUID=jiedan_dashou_id).select_related('DashouProfile').first()
if dashou_user:
try:
dashou_ext = dashou_user.DashouProfile
dashou_ext.zonge = (dashou_ext.zonge or Decimal('0.00')) + dashou_fencheng
dashou_ext.yue = (dashou_ext.yue or Decimal('0.00')) + dashou_fencheng
dashou_ext.jinrishouyi = (dashou_ext.jinrishouyi or Decimal('0.00')) + dashou_fencheng
dashou_ext.jinyueshouyi = (dashou_ext.jinyueshouyi or Decimal('0.00')) + dashou_fencheng
dashou_ext.chengjiaozongliang = (dashou_ext.chengjiaozongliang or 0) + 1
dashou_ext.zhuangtai = 1
dashou_ext.save()
except UserDashou.DoesNotExist:
pass
# 10. 更新订单状态为已完成
order.Status = 3
order.save()
# 11. 打手每日统计(成交)
try:
update_dashou_daily_by_action(
UserID=jiedan_dashou_id,
amount=dashou_fencheng,
action=2 # 2=结算/成交
)
except Exception as e:
logger.error(f"打手每日统计失败: {e}")
# 12. 商品/店铺每日统计
try:
if shangpin_id:
# 从扩展表取已计算收益
pingtai_shouyi = Decimal('0.00')
dianpu_shouyi = Decimal('0.00')
if hasattr(order, 'pingtai_kuozhan'):
pingtai_shouyi = order.pingtai_kuozhan.PlatformIncome or Decimal('0.00')
dianpu_shouyi = order.pingtai_kuozhan.ShopIncome or Decimal('0.00')
update_shangpin_daily_stat(
ProductID=shangpin_id,
caozuo_leixing=2,
dingdan_jiage=order.Amount,
PlatformIncome=pingtai_shouyi,
dianpu_zongshouyi=dianpu_shouyi
)
# 店铺统计(含上级分红)
if hasattr(order, 'pingtai_kuozhan'):
dianpu_id = order.pingtai_kuozhan.ShopID
shangji_id = order.pingtai_kuozhan.ParentShopID
shangji_fen = order.pingtai_kuozhan.ParentBonus or Decimal('0.00')
if dianpu_id:
update_dianpu_daily_stat(
ShopID=dianpu_id,
caozuo_leixing=2,
dingdan_jiage=order.Amount,
ShopIncome=dianpu_shouyi,
shangji_ShopID=shangji_id,
ParentBonus=shangji_fen
)
except Exception as e:
logger.error(f"商品/店铺统计失败: {e}")
# 14. 写入打手表现表(结算评价);字段名须与 record_dashou_biaoxian 一致
if jiedan_dashou_id:
record_dashou_biaoxian(
dingdan_id=dingdan_id,
dashou_id=jiedan_dashou_id,
xingwei=3, # 3=结算
fanche_cishu=fanche_cishu,
shangxian_sudu=shangxian_sudu,
fuwu_taidu=fuwu_taidu
)
# 15. 返回成功
return Response({'code': 0, 'msg': '结单成功', 'data': None})
except Exception as e:
logger.error(f"结单事务异常: {e}", exc_info=True)
return Response({'code': 9, 'msg': '服务器内部错误,结单失败', 'data': None})