175 lines
7.2 KiB
Python
175 lines
7.2 KiB
Python
"""
|
||
Сигналы для реферальной системы.
|
||
"""
|
||
from django.db.models.signals import post_save
|
||
from django.dispatch import receiver
|
||
from django.conf import settings
|
||
from decimal import Decimal
|
||
|
||
from .models import (
|
||
UserReferralProfile,
|
||
BonusAccount,
|
||
ReferralLevel,
|
||
ReferralSettings,
|
||
ReferralEarning,
|
||
generate_referral_code
|
||
)
|
||
|
||
|
||
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
|
||
def create_referral_profile(sender, instance, created, **kwargs):
|
||
"""Создать реферальный профиль и бонусный счет при создании пользователя."""
|
||
if created:
|
||
# Генерируем уникальный код
|
||
code = generate_referral_code()
|
||
while UserReferralProfile.objects.filter(referral_code=code).exists():
|
||
code = generate_referral_code()
|
||
|
||
# Создаем профиль
|
||
profile = UserReferralProfile.objects.create(
|
||
user=instance,
|
||
referral_code=code
|
||
)
|
||
|
||
# Устанавливаем начальный уровень
|
||
level1 = ReferralLevel.objects.filter(level=1).first()
|
||
if level1:
|
||
profile.current_level = level1
|
||
profile.save(update_fields=['current_level'])
|
||
|
||
# Создаем бонусный счет
|
||
BonusAccount.objects.create(user=instance)
|
||
|
||
|
||
@receiver(post_save, sender='subscriptions.Payment')
|
||
def process_referral_earnings(sender, instance, created, **kwargs):
|
||
"""Обработать начисление бонусов с рефералов после успешного платежа."""
|
||
# Проверяем что платеж успешен
|
||
if instance.status != 'succeeded':
|
||
return
|
||
|
||
# Проверяем что это не повторная обработка
|
||
if ReferralEarning.objects.filter(payment=instance).exists():
|
||
return
|
||
|
||
# Получаем пользователя
|
||
user = instance.user
|
||
|
||
try:
|
||
profile = user.referral_profile
|
||
except UserReferralProfile.DoesNotExist:
|
||
return
|
||
|
||
# Если нет реферера - выходим
|
||
if not profile.referred_by:
|
||
return
|
||
|
||
settings_obj = ReferralSettings.get_settings()
|
||
payment_amount = instance.amount
|
||
|
||
# Уровень 1: начисляем прямому рефереру
|
||
try:
|
||
referrer_profile = profile.referred_by.referral_profile
|
||
referrer_bonus_account = profile.referred_by.bonus_account
|
||
|
||
# Рассчитываем комиссию
|
||
commission_amount = payment_amount * (settings_obj.level1_commission / 100)
|
||
|
||
# Начисляем бонусы
|
||
referrer_bonus_account.add_bonus(
|
||
commission_amount,
|
||
reason=f'Комиссия с реферала {user.email}'
|
||
)
|
||
|
||
# Создаем запись о заработке
|
||
ReferralEarning.objects.create(
|
||
referrer=profile.referred_by,
|
||
referral=user,
|
||
payment=instance,
|
||
level=1,
|
||
payment_amount=payment_amount,
|
||
commission_percent=settings_obj.level1_commission,
|
||
earned_amount=commission_amount
|
||
)
|
||
|
||
# Обновляем статистику
|
||
referrer_profile.total_earned += commission_amount
|
||
referrer_profile.save(update_fields=['total_earned'])
|
||
|
||
except (UserReferralProfile.DoesNotExist, BonusAccount.DoesNotExist):
|
||
pass
|
||
|
||
# Уровень 2: начисляем рефереру реферера
|
||
if profile.referred_by:
|
||
try:
|
||
level1_referrer_profile = profile.referred_by.referral_profile
|
||
|
||
if level1_referrer_profile.referred_by:
|
||
level2_referrer = level1_referrer_profile.referred_by
|
||
level2_referrer_profile = level2_referrer.referral_profile
|
||
level2_bonus_account = level2_referrer.bonus_account
|
||
|
||
# Рассчитываем комиссию
|
||
commission_amount = payment_amount * (settings_obj.level2_commission / 100)
|
||
|
||
# Начисляем бонусы
|
||
level2_bonus_account.add_bonus(
|
||
commission_amount,
|
||
reason=f'Комиссия с реферала 2 уровня {user.email}'
|
||
)
|
||
|
||
# Создаем запись о заработке
|
||
ReferralEarning.objects.create(
|
||
referrer=level2_referrer,
|
||
referral=user,
|
||
payment=instance,
|
||
level=2,
|
||
payment_amount=payment_amount,
|
||
commission_percent=settings_obj.level2_commission,
|
||
earned_amount=commission_amount
|
||
)
|
||
|
||
# Обновляем статистику
|
||
level2_referrer_profile.total_earned += commission_amount
|
||
level2_referrer_profile.save(update_fields=['total_earned'])
|
||
|
||
except (UserReferralProfile.DoesNotExist, BonusAccount.DoesNotExist):
|
||
pass
|
||
|
||
|
||
@receiver(post_save, sender=UserReferralProfile)
|
||
def update_referrer_stats(sender, instance, created, **kwargs):
|
||
"""Обновить статистику реферера при добавлении нового реферала."""
|
||
if created and instance.referred_by:
|
||
try:
|
||
referrer_profile = instance.referred_by.referral_profile
|
||
settings_obj = ReferralSettings.get_settings()
|
||
|
||
# Увеличиваем счетчик прямых рефералов
|
||
referrer_profile.direct_referrals_count += 1
|
||
referrer_profile.save(update_fields=['direct_referrals_count'])
|
||
|
||
# Начисляем очки за прямого реферала
|
||
referrer_profile.add_points(
|
||
settings_obj.points_direct_referral,
|
||
reason=f'Регистрация реферала {instance.user.email}'
|
||
)
|
||
|
||
# Если у реферера есть свой реферер - начисляем ему очки за непрямого реферала
|
||
if referrer_profile.referred_by:
|
||
try:
|
||
level2_referrer_profile = referrer_profile.referred_by.referral_profile
|
||
level2_referrer_profile.indirect_referrals_count += 1
|
||
level2_referrer_profile.save(update_fields=['indirect_referrals_count'])
|
||
|
||
level2_referrer_profile.add_points(
|
||
settings_obj.points_indirect_referral,
|
||
reason=f'Регистрация непрямого реферала {instance.user.email}'
|
||
)
|
||
except UserReferralProfile.DoesNotExist:
|
||
pass
|
||
|
||
except UserReferralProfile.DoesNotExist:
|
||
pass
|
||
|