Files
Django/orders/utils.py
T

221 lines
7.4 KiB
Python

import logging
from datetime import date
from decimal import Decimal
from django.db import transaction
from django.db.models import F
from config.models import DailyIncomeStat, DailyPayoutStat
from orders.models import Order, PlatformOrderExt, MerchantOrderExt, CommissionRate
from jituan.services.club_config import get_commission_rate
from products.models import Gsfenhong
from jituan.services.club_penalty import resolve_gsfenhong_club_id
from users.models import UserDashou, UserGuanshi
from backend.utils import update_guanshi_daily_by_action
logger = logging.getLogger(__name__)
def get_order_user_id(order):
if order.Platform == 1:
try:
ext = PlatformOrderExt.objects.get(Order=order)
return ext.BossID
except PlatformOrderExt.DoesNotExist:
return None
elif order.Platform == 2:
try:
ext = MerchantOrderExt.objects.get(Order=order)
return ext.MerchantID
except MerchantOrderExt.DoesNotExist:
return None
return None
def update_daily_income(amount, club_id=None, stat_date=None):
"""
原子更新当日收入统计(金额累加,笔数加1)。
用于微信支付成功回调。
"""
from jituan.constants import CLUB_ID_DEFAULT
cid = club_id or CLUB_ID_DEFAULT
today = stat_date or date.today()
year, month, day = today.year, today.month, today.day
with transaction.atomic():
stat, created = DailyIncomeStat.objects.select_for_update().get_or_create(
date=today,
club_id=cid,
defaults={
'year': year,
'month': month,
'day': day,
'total_amount': amount,
'total_count': 1,
},
)
if not created:
stat.total_amount = F('total_amount') + amount
stat.total_count = F('total_count') + 1
stat.save(update_fields=['total_amount', 'total_count'])
logger.info(
f"每日收入更新[{cid}]: {today}, +{amount}元"
)
def subtract_daily_income(amount, club_id=None, stat_date=None):
"""扣减指定日期的收入统计(repair 反向操作用)。"""
from jituan.constants import CLUB_ID_DEFAULT
cid = club_id or CLUB_ID_DEFAULT
target = stat_date or date.today()
with transaction.atomic():
stat = DailyIncomeStat.objects.select_for_update().filter(
date=target, club_id=cid,
).first()
if not stat:
return
jine = Decimal(str(amount))
zero = Decimal('0.00')
new_amt = max(zero, Decimal(str(stat.total_amount or 0)) - jine)
new_cnt = max(0, int(stat.total_count or 0) - 1)
stat.total_amount = new_amt
stat.total_count = new_cnt
stat.save(update_fields=['total_amount', 'total_count'])
logger.info(f"每日收入扣减[{cid}]: {target}, -{amount}元")
def update_daily_payout(amount, club_id=None):
"""
原子更新当日出款统计(金额累加,笔数加1)。
用于提现成功、结算打款等场景。
"""
from jituan.constants import CLUB_ID_DEFAULT
cid = club_id or CLUB_ID_DEFAULT
today = date.today()
year, month, day = today.year, today.month, today.day
with transaction.atomic():
stat, created = DailyPayoutStat.objects.select_for_update().get_or_create(
date=today,
club_id=cid,
defaults={
'year': year,
'month': month,
'day': day,
'total_amount': amount,
'total_count': 1,
},
)
if not created:
stat.total_amount = F('total_amount') + amount
stat.total_count = F('total_count') + 1
stat.save(update_fields=['total_amount', 'total_count'])
logger.info(f"每日出款更新[{cid}]: {today}, +{amount}元")
def calc_shangjia_order_fencheng(jine, club_id=None):
"""
商家发单时计算打手/管事分成。
打手优先:打手+管事 > 订单金额时,管事分成为 0。
"""
from jituan.constants import CLUB_ID_DEFAULT
jine = Decimal(str(jine))
cid = club_id or CLUB_ID_DEFAULT
rate_dashou = get_commission_rate(cid, '3')
if not rate_dashou or rate_dashou <= 0:
rate_dashou = Decimal('1')
rate_guanshi = get_commission_rate(cid, '13')
dashou_fencheng = (jine * rate_dashou).quantize(Decimal('0.01'))
guanshi_raw = (jine * rate_guanshi).quantize(Decimal('0.01'))
if dashou_fencheng + guanshi_raw > jine:
guanshi_fencheng = Decimal('0.00')
else:
guanshi_fencheng = guanshi_raw
return dashou_fencheng, guanshi_fencheng
def settle_shangjia_order_guanshi_fenhong(order, dashou_id):
"""
商家订单结单时结算管事分红(幂等,失败不抛异常阻断主流程)。
"""
if getattr(order, 'Platform', None) != 2:
return
guanshi_fencheng = order.ManagerCommission or Decimal('0')
if guanshi_fencheng <= 0:
return
if Gsfenhong.objects.filter(dingdan_id=order.OrderID).exists():
logger.info(f"商家订单管事分红已处理: {order.OrderID}")
return
if not dashou_id:
return
try:
dashou = UserDashou.objects.select_related('user').get(user__UserUID=dashou_id)
except UserDashou.DoesNotExist:
logger.info(f"商家订单管事分红跳过: 打手{dashou_id}不存在")
return
guanshi_id = dashou.yaoqingren
if not guanshi_id:
logger.info(f"商家订单管事分红跳过: 打手{dashou_id}无邀请管事")
return
try:
with transaction.atomic():
guanshi = UserGuanshi.objects.select_for_update().get(user__UserUID=guanshi_id)
UserGuanshi.objects.filter(id=guanshi.id).update(
yue=F('yue') + guanshi_fencheng,
chongzhifenrun=F('chongzhifenrun') + guanshi_fencheng,
)
user_main = dashou.user
Gsfenhong.objects.create(
dingdan_id=order.OrderID,
guanshi=guanshi_id,
dashouid=dashou_id,
shuoming='商家订单分红',
fenhong=guanshi_fencheng,
avatar=user_main.Avatar if user_main else None,
nicheng=dashou.nicheng or '未知打手',
fenhong_leixing=3,
club_id=resolve_gsfenhong_club_id(dingdan_id=order.OrderID, dashouid=dashou_id, order=order),
)
logger.info(
f"商家订单管事分红成功: 订单{order.OrderID}, 管事{guanshi_id}, "
f"打手{dashou_id}, 金额{guanshi_fencheng}元"
)
except UserGuanshi.DoesNotExist:
logger.warning(f"商家订单管事分红跳过: 管事{guanshi_id}不存在")
return
except Exception as e:
logger.error(f"商家订单管事分红失败: {e}", exc_info=True)
return
try:
update_guanshi_daily_by_action(
yonghuid=guanshi_id,
action=3,
amount=guanshi_fencheng,
)
except Exception as e:
logger.error(f"商家订单管事日统计更新失败: {e}")