uchill/backend/apps/referrals/signals.py

175 lines
7.2 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.

"""
Сигналы для реферальной системы.
"""
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