更新代码管事分红问题
This commit is contained in:
@@ -336,9 +336,23 @@ def update_daily_payout(amount):
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import IntegrityError
|
||||
|
||||
from dingdan.models import Lilubiao
|
||||
|
||||
|
||||
def _normalize_lilu_rate(raw):
|
||||
"""Lilubiao 存小数比例;若后台误填 15 表示 15%,自动除以 100"""
|
||||
if raw is None:
|
||||
return Decimal('0')
|
||||
rate = Decimal(str(raw))
|
||||
if rate <= 0:
|
||||
return Decimal('0')
|
||||
if rate > 1:
|
||||
rate = (rate / Decimal('100')).quantize(Decimal('0.0001'))
|
||||
return rate
|
||||
|
||||
|
||||
def calc_shangjia_order_fencheng(jine):
|
||||
"""
|
||||
商家发单时计算打手/管事分成。
|
||||
@@ -350,22 +364,20 @@ def calc_shangjia_order_fencheng(jine):
|
||||
jine = Decimal(str(jine))
|
||||
try:
|
||||
lilu_obj = Lilubiao.objects.get(fadanpingtai='3')
|
||||
rate_dashou = Decimal(str(lilu_obj.lilu)) if lilu_obj.lilu and lilu_obj.lilu > 0 else Decimal('1')
|
||||
rate_dashou = _normalize_lilu_rate(lilu_obj.lilu) if lilu_obj.lilu else Decimal('1')
|
||||
if rate_dashou <= 0:
|
||||
rate_dashou = Decimal('1')
|
||||
except Lilubiao.DoesNotExist:
|
||||
rate_dashou = Decimal('1')
|
||||
|
||||
lilu_guanshi_dashou_obj = Lilubiao.objects.filter(fadanpingtai='13').first()
|
||||
rate_guanshi_dashou = (
|
||||
Decimal(str(lilu_guanshi_dashou_obj.lilu))
|
||||
if lilu_guanshi_dashou_obj and lilu_guanshi_dashou_obj.lilu is not None
|
||||
else Decimal('0')
|
||||
rate_guanshi_dashou = _normalize_lilu_rate(
|
||||
lilu_guanshi_dashou_obj.lilu if lilu_guanshi_dashou_obj else None
|
||||
)
|
||||
|
||||
lilu_guanshi_shangjia_obj = Lilubiao.objects.filter(fadanpingtai='15').first()
|
||||
rate_guanshi_shangjia = (
|
||||
Decimal(str(lilu_guanshi_shangjia_obj.lilu))
|
||||
if lilu_guanshi_shangjia_obj and lilu_guanshi_shangjia_obj.lilu is not None
|
||||
else Decimal('0')
|
||||
rate_guanshi_shangjia = _normalize_lilu_rate(
|
||||
lilu_guanshi_shangjia_obj.lilu if lilu_guanshi_shangjia_obj else None
|
||||
)
|
||||
|
||||
dashou_fencheng = min(
|
||||
@@ -401,6 +413,17 @@ def _pay_guanshi_order_fenhong(order, guanshi_id, amount, related_user_id, niche
|
||||
logger.info(f"管事分红已处理: 订单{order.dingdan_id}, 类型{fenhong_leixing}")
|
||||
return False
|
||||
|
||||
# 旧表结构 dingdan_id 全局唯一时,第二笔分红会插入失败
|
||||
legacy_conflict = Gsfenhong.objects.filter(dingdan_id=order.dingdan_id).exclude(
|
||||
fenhong_leixing=fenhong_leixing
|
||||
).exists()
|
||||
if legacy_conflict:
|
||||
logger.error(
|
||||
f"管事分红写入失败: 订单{order.dingdan_id} 已有其他类型分红记录,"
|
||||
f"请执行 python manage.py migrate shangpin 0010 更新 gsfenhong 表唯一约束"
|
||||
)
|
||||
return False
|
||||
|
||||
try:
|
||||
with transaction.atomic():
|
||||
guanshi = UserGuanshi.objects.select_for_update().get(user__yonghuid=guanshi_id)
|
||||
@@ -425,6 +448,14 @@ def _pay_guanshi_order_fenhong(order, guanshi_id, amount, related_user_id, niche
|
||||
except UserGuanshi.DoesNotExist:
|
||||
logger.warning(f"管事分红跳过: 管事{guanshi_id}不存在")
|
||||
return False
|
||||
except IntegrityError as e:
|
||||
logger.error(
|
||||
f"管事分红写入失败(数据库约束): 订单{order.dingdan_id}, 类型{fenhong_leixing}, "
|
||||
f"关联用户{related_user_id}, 错误={e}. "
|
||||
f"请确认已执行 migrate shangpin 0010 与 migrate dingdan 0017",
|
||||
exc_info=True,
|
||||
)
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(f"管事分红失败: {e}", exc_info=True)
|
||||
return False
|
||||
@@ -441,6 +472,11 @@ def _pay_guanshi_order_fenhong(order, guanshi_id, amount, related_user_id, niche
|
||||
return True
|
||||
|
||||
|
||||
def _resolve_dashou_inviter_guanshi(dashou_profile):
|
||||
guanshi_id = (dashou_profile.yaoqingren or '').strip()
|
||||
return guanshi_id or None
|
||||
|
||||
|
||||
def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
"""
|
||||
商家订单结单时结算管事分红(幂等,失败不抛异常阻断主流程)。
|
||||
@@ -448,14 +484,34 @@ def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
- 管事商家派单分红:派单商家打手身份的邀请管事(guanshi_shangjia_fencheng)
|
||||
同一管事可同时获得两笔分红。
|
||||
"""
|
||||
from dingdan.models import DingdanShangjia
|
||||
from dingdan.models import Dingdan, DingdanShangjia
|
||||
from yonghu.models import UserDashou
|
||||
|
||||
if getattr(order, 'fadan_pingtai', None) != 2:
|
||||
return
|
||||
|
||||
# 1. 接单打手邀请管事分红
|
||||
# 重新读订单,确保拿到发单时写入的分红金额
|
||||
try:
|
||||
order = Dingdan.objects.get(dingdan_id=order.dingdan_id)
|
||||
except Dingdan.DoesNotExist:
|
||||
logger.warning(f"管事分红跳过: 订单{order.dingdan_id}不存在")
|
||||
return
|
||||
|
||||
guanshi_fencheng = order.guanshi_fencheng or Decimal('0')
|
||||
guanshi_shangjia_fencheng = order.guanshi_shangjia_fencheng or Decimal('0')
|
||||
logger.info(
|
||||
f"商家订单管事分红结算: 订单{order.dingdan_id}, 打手{dashou_id}, "
|
||||
f"打手接单分红={guanshi_fencheng}, 商家派单分红={guanshi_shangjia_fencheng}"
|
||||
)
|
||||
|
||||
if guanshi_fencheng <= 0 and guanshi_shangjia_fencheng <= 0:
|
||||
logger.info(
|
||||
f"管事分红跳过: 订单{order.dingdan_id} 两项分红均为0 "
|
||||
f"(请检查 Lilubiao 13/15 费率及打手分成是否占满订单金额)"
|
||||
)
|
||||
return
|
||||
|
||||
# 1. 接单打手邀请管事分红
|
||||
if guanshi_fencheng > 0 and dashou_id:
|
||||
try:
|
||||
dashou = UserDashou.objects.select_related('user').get(user__yonghuid=dashou_id)
|
||||
@@ -463,11 +519,12 @@ def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
logger.info(f"管事打手分红跳过: 打手{dashou_id}不存在")
|
||||
dashou = None
|
||||
|
||||
if dashou and dashou.yaoqingren:
|
||||
guanshi_id = _resolve_dashou_inviter_guanshi(dashou) if dashou else None
|
||||
if dashou and guanshi_id:
|
||||
user_main = dashou.user
|
||||
_pay_guanshi_order_fenhong(
|
||||
order=order,
|
||||
guanshi_id=dashou.yaoqingren,
|
||||
guanshi_id=guanshi_id,
|
||||
amount=guanshi_fencheng,
|
||||
related_user_id=dashou_id,
|
||||
nicheng=dashou.nicheng,
|
||||
@@ -476,13 +533,14 @@ def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
shuoming='商家订单打手分红',
|
||||
)
|
||||
else:
|
||||
logger.info(f"管事打手分红跳过: 打手{dashou_id}无邀请管事")
|
||||
logger.info(f"管事打手分红跳过: 打手{dashou_id}无邀请管事(yaoqingren为空)")
|
||||
|
||||
# 2. 派单商家邀请管事分红
|
||||
guanshi_shangjia_fencheng = order.guanshi_shangjia_fencheng or Decimal('0')
|
||||
if guanshi_shangjia_fencheng > 0:
|
||||
try:
|
||||
shangjia_ext = DingdanShangjia.objects.select_related('dingdan').get(dingdan__dingdan_id=order.dingdan_id)
|
||||
shangjia_ext = DingdanShangjia.objects.select_related('dingdan').get(
|
||||
dingdan__dingdan_id=order.dingdan_id
|
||||
)
|
||||
shangjia_id = shangjia_ext.shangjia_id
|
||||
except DingdanShangjia.DoesNotExist:
|
||||
logger.info(f"管事商家分红跳过: 订单{order.dingdan_id}无商家扩展")
|
||||
@@ -495,11 +553,12 @@ def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
logger.info(f"管事商家分红跳过: 商家{shangjia_id}无打手扩展")
|
||||
merchant_dashou = None
|
||||
|
||||
if merchant_dashou and merchant_dashou.yaoqingren:
|
||||
guanshi_id = _resolve_dashou_inviter_guanshi(merchant_dashou) if merchant_dashou else None
|
||||
if merchant_dashou and guanshi_id:
|
||||
user_main = merchant_dashou.user
|
||||
_pay_guanshi_order_fenhong(
|
||||
order=order,
|
||||
guanshi_id=merchant_dashou.yaoqingren,
|
||||
guanshi_id=guanshi_id,
|
||||
amount=guanshi_shangjia_fencheng,
|
||||
related_user_id=shangjia_id,
|
||||
nicheng=shangjia_ext.sjnicheng or merchant_dashou.nicheng,
|
||||
@@ -508,4 +567,6 @@ def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
|
||||
shuoming='商家派单管事分红',
|
||||
)
|
||||
else:
|
||||
logger.info(f"管事商家分红跳过: 商家{shangjia_id}打手身份无邀请管事")
|
||||
logger.info(
|
||||
f"管事商家分红跳过: 商家{shangjia_id}打手身份无邀请管事(yaoqingren为空)"
|
||||
)
|
||||
@@ -3159,6 +3159,8 @@ class ShangjiaJiesuanView(APIView):
|
||||
'data': None
|
||||
}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
settle_ctx = None
|
||||
success_response = None
|
||||
try:
|
||||
with transaction.atomic():
|
||||
# 4. 查询订单并加锁(修复并发问题)
|
||||
@@ -3311,13 +3313,8 @@ class ShangjiaJiesuanView(APIView):
|
||||
action=2 # 2 = 结算
|
||||
)
|
||||
|
||||
# 商家订单管事分红(仅 fadan_pingtai=2)
|
||||
if order.fadan_pingtai == 2:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_shangjia_order_guanshi_fenhong(order, jiedan_dashou_id)
|
||||
|
||||
# 返回成功
|
||||
return Response({
|
||||
settle_ctx = (dingdan_id, jiedan_dashou_id)
|
||||
success_response = Response({
|
||||
'code': 0,
|
||||
'msg': '结单成功',
|
||||
'data': {
|
||||
@@ -3331,6 +3328,14 @@ class ShangjiaJiesuanView(APIView):
|
||||
}
|
||||
}, status=status.HTTP_200_OK)
|
||||
|
||||
if settle_ctx:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_order = Dingdan.objects.get(dingdan_id=settle_ctx[0])
|
||||
settle_shangjia_order_guanshi_fenhong(settle_order, settle_ctx[1])
|
||||
|
||||
if success_response is not None:
|
||||
return success_response
|
||||
|
||||
except Dingdan.DoesNotExist:
|
||||
return Response({
|
||||
'code': 5,
|
||||
@@ -6359,9 +6364,10 @@ class AdQiangZhiJieDan(APIView):
|
||||
# 商家扩展表不存在,跳过商家更新
|
||||
logger.warning(f"强制结单:商家{shangjia_id}扩展信息不存在,跳过商家更新")
|
||||
|
||||
if fadan_pingtai == 2 and jiedan_dashou_id:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_shangjia_order_guanshi_fenhong(dingdan_obj, jiedan_dashou_id)
|
||||
if fadan_pingtai == 2 and jiedan_dashou_id:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_order = Dingdan.objects.get(dingdan_id=dingdan_id)
|
||||
settle_shangjia_order_guanshi_fenhong(settle_order, jiedan_dashou_id)
|
||||
|
||||
# 11. 返回成功响应
|
||||
return Response({
|
||||
|
||||
@@ -359,6 +359,8 @@ class GetCrossOrderDetailView(APIView):
|
||||
'partner_club_id': dingdan_obj.partner_club_id or '',
|
||||
'jine': float(dingdan_obj.jine) if dingdan_obj.jine else 0.00,
|
||||
'dashou_fencheng': float(dingdan_obj.dashou_fencheng) if dingdan_obj.dashou_fencheng else 0.00,
|
||||
'guanshi_fencheng': float(dingdan_obj.guanshi_fencheng) if dingdan_obj.guanshi_fencheng else 0.00,
|
||||
'guanshi_shangjia_fencheng': float(dingdan_obj.guanshi_shangjia_fencheng) if dingdan_obj.guanshi_shangjia_fencheng else 0.00,
|
||||
'jiedan_dashou_id': dingdan_obj.jiedan_dashou_id or '',
|
||||
'dashou_liuyan': dingdan_obj.dashou_liuyan or '',
|
||||
'zhiding_id': dingdan_obj.zhiding_id or '',
|
||||
@@ -6833,6 +6835,8 @@ class UpdateWithdrawSettingsView(APIView):
|
||||
val = order_rates.get(str(role), order_rates.get(role))
|
||||
if val is not None:
|
||||
rate = Decimal(str(val))
|
||||
if rate > 1:
|
||||
rate = (rate / Decimal('100')).quantize(Decimal('0.0001'))
|
||||
code = order_rate_code_map[role]
|
||||
obj, created = Lilubiao.objects.select_for_update().get_or_create(
|
||||
fadanpingtai=code,
|
||||
|
||||
@@ -8722,6 +8722,7 @@ class KefuGetOrderDetailView(APIView):
|
||||
'shangjia_kuozhan'
|
||||
).only(
|
||||
'dingdan_id', 'zhuangtai', 'fadan_pingtai', 'jine', 'dashou_fencheng',
|
||||
'guanshi_fencheng', 'guanshi_shangjia_fencheng',
|
||||
'jiedan_dashou_id', 'dashou_liuyan', 'zhiding_id', 'shangpin_id',
|
||||
'leixing_id', 'tupian', 'jieshao', 'beizhu', 'tkly', 'nicheng',
|
||||
'clkf', 'create_time', 'update_time'
|
||||
@@ -8741,6 +8742,8 @@ class KefuGetOrderDetailView(APIView):
|
||||
'fadanpingtai': dingdan_obj.fadan_pingtai or 0,
|
||||
'jiage': float(dingdan_obj.jine) if dingdan_obj.jine else 0.00,
|
||||
'dashou_fencheng': float(dingdan_obj.dashou_fencheng) if dingdan_obj.dashou_fencheng else 0.00,
|
||||
'guanshi_fencheng': float(dingdan_obj.guanshi_fencheng) if dingdan_obj.guanshi_fencheng else 0.00,
|
||||
'guanshi_shangjia_fencheng': float(dingdan_obj.guanshi_shangjia_fencheng) if dingdan_obj.guanshi_shangjia_fencheng else 0.00,
|
||||
'jiedan_dashou_id': dingdan_obj.jiedan_dashou_id or '',
|
||||
'dashou_liuyan': dingdan_obj.dashou_liuyan or '',
|
||||
'zhiding_id': dingdan_obj.zhiding_id or '',
|
||||
@@ -10236,6 +10239,7 @@ class KefuForceCompleteView(APIView):
|
||||
return Response({'code': 401, 'msg': '客服状态异常'})
|
||||
|
||||
# 2. 订单处理(事务内)
|
||||
guanshi_settle_ctx = None
|
||||
try:
|
||||
with transaction.atomic():
|
||||
order = Dingdan.objects.select_for_update().get(dingdan_id=dingdan_id)
|
||||
@@ -10351,10 +10355,8 @@ class KefuForceCompleteView(APIView):
|
||||
logger.error(f"打手每日统计更新失败: {e}")
|
||||
# 不影响主流程
|
||||
|
||||
# 商家订单管事分红
|
||||
if order.fadan_pingtai == 2:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_shangjia_order_guanshi_fenhong(order, dashou_id)
|
||||
guanshi_settle_ctx = (dingdan_id, dashou_id)
|
||||
|
||||
# 8. 更新客服统计
|
||||
kefu.jinrichuli = F('jinrichuli') + 1
|
||||
@@ -10362,6 +10364,11 @@ class KefuForceCompleteView(APIView):
|
||||
kefu.zongchuli = F('zongchuli') + 1
|
||||
kefu.save(update_fields=['jinrichuli', 'jinyuechuli', 'zongchuli'])
|
||||
|
||||
if guanshi_settle_ctx:
|
||||
from dingdan.utils import settle_shangjia_order_guanshi_fenhong
|
||||
settle_order = Dingdan.objects.get(dingdan_id=guanshi_settle_ctx[0])
|
||||
settle_shangjia_order_guanshi_fenhong(settle_order, guanshi_settle_ctx[1])
|
||||
|
||||
return Response({'code': 0, 'msg': '强制结单成功'})
|
||||
|
||||
except Dingdan.DoesNotExist:
|
||||
|
||||
Reference in New Issue
Block a user