import logging import string import random from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.sites.models import Site from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse_lazy from django.utils.translation import ugettext_lazy as _ # Create your models here. from registration.signals import user_activated from core.models import AbstractStatusModel, STATUS_ACTIVE, STATUS_CHOICES from referral.mixins import StatsFormatterMixin from referral.utils import get_cookie logger = logging.getLogger(__name__) # --------------------------------- Referral status list ----------------------------# REFERRAL_DEFAULT_CHOICE = STATUS_ACTIVE # @TODO: translate into english and use translation class Referral(AbstractStatusModel): CODE_LENGTH = 8 referral_owner = models.OneToOneField(get_user_model(), verbose_name=_('пользователь'), on_delete=models.CASCADE, primary_key=True ) code = models.CharField(_('код'), max_length=255) status = models.SmallIntegerField(_('статус'), default=REFERRAL_DEFAULT_CHOICE, choices=STATUS_CHOICES) @classmethod def create(cls, user, code): referral = cls(referral_owner=user, code=code) return referral @staticmethod def generate_code(): def _generate_code(): return ''.join([random.choice(string.ascii_uppercase + string.digits) for n in range(Referral.CODE_LENGTH)]) code = _generate_code() while Referral.active.filter(code=code).exists(): code = _generate_code() return code @property def url(self): path = reverse_lazy('index:index') site_url = settings.DEFAULT_SITE_URL return "{}{}".format(site_url, path) def __str__(self): return self.code class Meta: verbose_name = _('Реферал') verbose_name_plural = _('Рефералы') class ReferralStats(StatsFormatterMixin, AbstractStatusModel): referral = models.OneToOneField(Referral, verbose_name=_('Реферал'), on_delete=models.CASCADE, primary_key=True) visits = models.IntegerField(_('Посищения'), default=0) registrations = models.IntegerField(_('Регистрации'), default=0) class Meta: verbose_name = _('Реферальная статистика') verbose_name_plural = _('Реферальная статистика') class PartnerStats(StatsFormatterMixin, AbstractStatusModel): user = models.OneToOneField(get_user_model(), verbose_name=_('username'), on_delete=models.CASCADE, primary_key=True) total_visits = models.BigIntegerField(_('Всего посещений'), default=0) total_regs = models.BigIntegerField(_('Всего регистраций'), default=0) class Meta: verbose_name = _('Партнеская статистика') verbose_name_plural = _('Партнерская статистика') @receiver(post_save, sender=get_user_model()) def create_user_referral(sender, instance, created, **kwargs): if created and Referral.objects.filter(user=instance).first() is None: Referral.create(user=instance, code=Referral.generate_code()).save() @receiver(post_save, sender=Referral) def init_referral_stuff(sender, instance, created, *args, **kwargs): if created: if PartnerStats.objects.filter(user=instance.referral_owner).count() == 0: PartnerStats.objects.create(user=instance.referral_owner).save() if ReferralStats.active.filter(referral=instance).count() == 0: ReferralStats.active.create(referral=instance).save() @receiver(user_activated) def update_ref_stats(sender, user, request, **kwargs): referral_code = get_cookie(request.COOKIES, 'referral') if referral_code: referral = Referral.objects.filter(code__exact=referral_code).first() if referral: referral.referralstats.registrations += 1 referral.referralstats.save() referral.user.partnerstats.total_regs += 1 referral.user.partnerstats.save() user.referral_code = referral user.referral_user = referral.referral_owner user.save() else: logger.warning("Missing referral code in database: " + referral_code)