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