Files
Scoring-System/backend/shop/services.py
爽哒哒 f26d35da66
All checks were successful
Deploy to Server / deploy (push) Successful in 18s
创赢未来评分系统 - 初始化提交(移除大文件)
2026-03-18 22:41:23 +08:00

178 lines
7.2 KiB
Python

import logging
from django.db import models
from .models import Order, CommissionLog, Distributor
# To avoid circular imports, import other models inside function if needed
logger = logging.getLogger(__name__)
def handle_post_payment(order):
"""
处理订单支付成功后的业务逻辑
包括:
1. 更新活动报名状态
2. 发送活动报名短信
3. 计算分销佣金
4. 发送普通订单短信
"""
print(f"开始处理订单 {order.id} 支付后逻辑...")
# 1. Handle Activity Signup
if hasattr(order, 'activity') and order.activity:
try:
# Use apps.get_model to avoid circular dependency
from django.apps import apps
ActivitySignup = apps.get_model('community', 'ActivitySignup')
signup = ActivitySignup.objects.filter(order=order).first()
# Fallback: try to find by user and activity if not found by order
if not signup and order.wechat_user:
print(f"Warning: ActivitySignup not found by order {order.id}, trying by user/activity")
signup = ActivitySignup.objects.filter(
user=order.wechat_user,
activity=order.activity,
status='unpaid'
).first()
if signup:
print(f"Found signup {signup.id} by user/activity, linking order...")
signup.order = order
signup.save()
if signup:
# Determine status based on activity setting
# Use the model method if available, otherwise manual logic
if hasattr(signup, 'check_payment_status'):
signup.check_payment_status()
print(f"活动报名状态已更新(check_payment_status): {signup.id} -> {signup.status}")
else:
new_status = 'confirmed' if signup.activity.auto_confirm else 'pending'
signup.status = new_status
signup.save()
print(f"活动报名状态已更新: {signup.id} -> {new_status}")
# Send Activity SMS
try:
from .sms_utils import notify_user_activity_signup_success
notify_user_activity_signup_success(order, signup)
except Exception as sms_e:
print(f"发送活动报名短信失败: {str(sms_e)}")
else:
print(f"Error: No ActivitySignup found for paid order {order.id}")
except Exception as e:
print(f"更新活动报名状态失败: {str(e)}")
import traceback
traceback.print_exc()
# 2. 计算佣金 (旧版销售员系统 & 新版分销员系统)
try:
# 旧版销售员系统
salesperson = order.salesperson
if salesperson:
# 1. 计算直接佣金 (一级)
# 优先级: 产品独立分润比例 > 销售员个人分润比例
rate_1 = 0
if order.config:
rate_1 = order.config.commission_rate if order.config.commission_rate > 0 else salesperson.commission_rate
elif order.course:
# 课程暂时使用销售员默认比例
rate_1 = salesperson.commission_rate
amount_1 = order.total_price * rate_1
if amount_1 > 0:
CommissionLog.objects.create(
order=order,
salesperson=salesperson,
amount=amount_1,
level=1,
status='pending'
)
print(f"生成一级佣金(Salesperson): {salesperson.name} - {amount_1}")
# 2. 计算上级佣金 (二级)
parent = salesperson.parent
if parent:
rate_2 = parent.second_level_rate
amount_2 = order.total_price * rate_2
if amount_2 > 0:
CommissionLog.objects.create(
order=order,
salesperson=parent,
amount=amount_2,
level=2,
status='pending'
)
print(f"生成二级佣金(Salesperson): {parent.name} - {amount_2}")
# 新版分销员系统
distributor = order.distributor
if distributor:
# 1. 计算直接佣金 (一级)
# 优先级: 产品独立分润比例 > 分销员个人分润比例
rate_1 = 0
if order.config:
rate_1 = order.config.commission_rate if order.config.commission_rate > 0 else distributor.commission_rate
elif order.course:
# 课程暂时使用分销员默认比例
rate_1 = distributor.commission_rate
amount_1 = order.total_price * rate_1
if amount_1 > 0:
CommissionLog.objects.create(
order=order,
distributor=distributor,
amount=amount_1,
level=1,
status='settled' # 简化流程,直接结算到余额
)
# 更新余额
distributor.total_earnings += amount_1
distributor.withdrawable_balance += amount_1
distributor.save()
print(f"生成一级佣金(Distributor): {distributor.user.nickname} - {amount_1}")
# 2. 计算上级佣金 (二级)
parent = distributor.parent
if parent:
# 二级固定比例 2% (0.02)
rate_2 = 0.02
amount_2 = order.total_price * models.DecimalField(max_digits=5, decimal_places=4).to_python(rate_2)
if amount_2 > 0:
CommissionLog.objects.create(
order=order,
distributor=parent,
amount=amount_2,
level=2,
status='settled'
)
# 更新余额
parent.total_earnings += amount_2
parent.withdrawable_balance += amount_2
parent.save()
print(f"生成二级佣金(Distributor): {parent.user.nickname} - {amount_2}")
except Exception as e:
print(f"佣金计算失败: {str(e)}")
import traceback
traceback.print_exc()
# 3. 发送普通商品/课程购买的短信通知(排除活动报名,避免重复发送)
# 活动报名的短信已经在上面发送过了
if not (hasattr(order, 'activity') and order.activity):
try:
from .sms_utils import notify_admins_order_paid, notify_user_order_paid
notify_admins_order_paid(order)
notify_user_order_paid(order)
except Exception as e:
print(f"发送短信通知失败: {str(e)}")
else:
# 额外保险:如果是活动订单,手动标记不触发 signals 中的支付/发货通知
# 因为 signals 可能会在 save() 时触发
order._was_paid = False
order._was_shipped = False