Files
Django/orders/utils.py

221 lines
7.3 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.
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):
"""
原子更新当日收入统计金额累加笔数加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 = 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}")