diff --git a/api/v1/serializers/config.py b/api/v1/serializers/config.py index 46cb40b2..e494f861 100644 --- a/api/v1/serializers/config.py +++ b/api/v1/serializers/config.py @@ -20,8 +20,8 @@ class ConfigSerializer(serializers.ModelSerializer): MAIN_PAGE_TOP_IMAGE = serializers.SerializerMethodField() # SCHOOL_LOGO_IMAGE = serializers.ImageField(required=False, allow_null=True) # MAIN_PAGE_TOP_IMAGE = serializers.ImageField(required=False, allow_null=True) - REFERRER_CASHBACK = serializers.IntegerField() - REFERRAL_DISCOUNT = serializers.IntegerField() + REFERRER_BONUS = serializers.IntegerField() + REFERRAL_BONUS = serializers.IntegerField() class Meta: model = Config @@ -39,8 +39,8 @@ class ConfigSerializer(serializers.ModelSerializer): 'INSTAGRAM_PROFILE_URL', 'SCHOOL_LOGO_IMAGE', 'MAIN_PAGE_TOP_IMAGE', - 'REFERRER_CASHBACK', - 'REFERRAL_DISCOUNT', + 'REFERRER_BONUS', + 'REFERRAL_BONUS', ) def get_SCHOOL_LOGO_IMAGE(self, config): diff --git a/api/v1/views.py b/api/v1/views.py index ca551de4..7620244b 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -476,7 +476,7 @@ class PaymentViewSet(ExtendedModelViewSet): return queryset.filter(status__isnull=False).order_by('-created_at') - @action(methods=['get'], detail=False, url_path='calc-amount') + @action(methods=['get'], detail=False, url_path='calc-amount', authentication_classes=[], permission_classes=[]) def calc_amount(self, request, pk=None): user = request.query_params.get('user') course = request.query_params.get('course') diff --git a/apps/auth/views.py b/apps/auth/views.py index f83a9269..c9ae8dfc 100644 --- a/apps/auth/views.py +++ b/apps/auth/views.py @@ -56,8 +56,8 @@ class LearnerRegistrationView(FormView): user.save() referrer = self.request.session.get('referrer') if referrer: - Referral.objects.create(referral=user, referrer_id=referrer, discount=config.REFERRAL_DISCOUNT, - referrer_cashback=config.REFERRER_CASHBACK) + Referral.objects.create(referral=user, referrer_id=referrer, bonus=config.REFERRAL_BONUS, + referrer_bonus=config.REFERRER_BONUS) # TODO: email admins? мб реферера уже нет, старая ссылка self.request.session['referrer'] = None login(self.request, user) @@ -198,8 +198,8 @@ class FacebookLoginOrRegistration(View): referrer = self.request.session.get('referrer') if referrer: config = Config.load() - Referral.objects.create(referral=user, referrer_id=referrer, discount=config.REFERRAL_DISCOUNT, - referrer_cashback=config.REFERRER_CASHBACK) + Referral.objects.create(referral=user, referrer_id=referrer, bonus=config.REFERRAL_BONUS, + referrer_bonus=config.REFERRER_BONUS) # TODO: email admins? мб реферера уже нет, старая ссылка self.request.session['referrer'] = None diff --git a/apps/config/models.py b/apps/config/models.py index 7e7e833a..498dd00f 100644 --- a/apps/config/models.py +++ b/apps/config/models.py @@ -47,7 +47,7 @@ class Config(models.Model): 'SERVICE_DISCOUNT': '', 'SCHOOL_LOGO_IMAGE': '', 'MAIN_PAGE_TOP_IMAGE': '', - 'REFERRER_CASHBACK': '', - 'REFERRAL_DISCOUNT': '', + 'REFERRER_BONUS': '', + 'REFERRAL_BONUS': '', } return obj diff --git a/apps/payment/migrations/0020_userbonus.py b/apps/payment/migrations/0020_userbonus.py deleted file mode 100644 index 4b029f87..00000000 --- a/apps/payment/migrations/0020_userbonus.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.0.6 on 2018-08-20 06:51 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0025_auto_20180820_0651'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('payment', '0019_payment_roistat_visit'), - ] - - operations = [ - migrations.CreateModel( - name='UserBonus', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('amount', models.DecimalField(decimal_places=2, default=0, editable=False, max_digits=8)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('payment', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, to='payment.Payment')), - ('referral', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='user.Referral')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bonuses', to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/apps/payment/models.py b/apps/payment/models.py index 016646a7..81acf8e7 100644 --- a/apps/payment/models.py +++ b/apps/payment/models.py @@ -110,17 +110,17 @@ class Payment(PolymorphicModel): ordering = ('created_at',) @classmethod - def calc_amount(cls, course_payment=None, school_payment=None, user=None, course=None, weekdays=None, + def calc_amount(cls, payment=None, user=None, course=None, weekdays=None, add_days=False, date_start=None, date_end=None): - if course_payment: - course = course_payment.course - user = course_payment.user - if school_payment: - user = school_payment.user - weekdays = school_payment.weekdays - add_days = school_payment.add_days - date_start = school_payment.date_start - date_end = school_payment.date_end + if isinstance(payment, CoursePayment): + course = payment.course + user = payment.user + if isinstance(payment, SchoolPayment): + user = payment.user + weekdays = payment.weekdays + add_days = payment.add_days + date_start = payment.date_start + date_end = payment.date_end referral_bonus = 0 referrer_bonus = 0 if hasattr(user, 'referral') and not user.referral.payment: @@ -184,30 +184,25 @@ class Payment(PolymorphicModel): Pingback.PINGBACK_TYPE_RISK_REVIEWED_DECLINED, ] - -class CoursePayment(Payment): - course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='Курс', related_name='payments') - - class Meta: - verbose_name = 'Платеж за курс' - verbose_name_plural = 'Платежи за курсы' - def save(self, *args, **kwargs): - amount_data = Payment.calc_amount(course_payment=self) + amount_data = Payment.calc_amount(payment=self) self.amount = amount_data.get('amount') super().save(*args, **kwargs) - author_balance = getattr(self, 'authorbalance', None) - if not author_balance: - AuthorBalance.objects.create( - author=self.course.author, - amount=self.amount, - payment=self, - ) - else: - author_balance.amount = self.amount - author_balance.save() + if isinstance(self, CoursePayment): + author_balance = getattr(self, 'authorbalance', None) + if not author_balance: + AuthorBalance.objects.create( + author=self.course.author, + amount=self.amount, + payment=self, + ) + else: + author_balance.amount = self.amount + author_balance.save() # Если юзер реферал и нет платежа, где применялась скидка - if hasattr(self.user, 'referral') and not self.user.referral.payment: + if hasattr(self.user, 'referral') and not self.user.referral.payment\ + and self.status in [Pingback.PINGBACK_TYPE_REGULAR, Pingback.PINGBACK_TYPE_GOODWILL, + Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,]: # Платеж - как сигнал, что скидка применилась self.user.referral.payment = self self.user.referral.save() @@ -215,6 +210,14 @@ class CoursePayment(Payment): self.user.referral.send_bonuses(amount_data.get('referral_bonus'), amount_data.get('referrer_bonus')) +class CoursePayment(Payment): + course = models.ForeignKey(Course, on_delete=models.CASCADE, verbose_name='Курс', related_name='payments') + + class Meta: + verbose_name = 'Платеж за курс' + verbose_name_plural = 'Платежи за курсы' + + class SchoolPayment(Payment): weekdays = ArrayField(models.IntegerField(), size=7, verbose_name='Дни недели') add_days = models.BooleanField('Докупленные дни', default=False) @@ -232,18 +235,6 @@ class SchoolPayment(Payment): ]) return days - def save(self, *args, **kwargs): - amount_data = Payment.calc_amount(school_payment=self) - self.amount = amount_data.get('amount') - super().save(*args, **kwargs) - # Если юзер реферал и нет платежа, где применялась скидка - if not self.add_days and hasattr(self.user, 'referral') and not self.user.referral.payment: - # Платеж - как сигнал, что скидка применилась - self.user.referral.payment = self - self.user.referral.save() - # Отправляем кэшбэк - self.user.referral.send_bonuses(amount_data.get('referral_bonus'), amount_data.get('referrer_bonus')) - @property def date_end_humanize(self): return arrow.get(self.date_end, settings.TIME_ZONE).humanize(locale='ru') @@ -252,7 +243,7 @@ class SchoolPayment(Payment): class UserBonus(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='bonuses') amount = models.DecimalField(max_digits=8, decimal_places=2, default=0, editable=False) - payment = models.OneToOneField(Payment, on_delete=models.SET_NULL, null=True) + payment = models.ForeignKey(Payment, on_delete=models.SET_NULL, null=True) referral = models.ForeignKey('user.Referral', on_delete=models.SET_NULL, null=True) created_at = models.DateTimeField(auto_now_add=True) diff --git a/apps/user/migrations/0023_referral.py b/apps/user/migrations/0023_referral.py deleted file mode 100644 index 2edf4621..00000000 --- a/apps/user/migrations/0023_referral.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 2.0.6 on 2018-07-29 05:24 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0022_user_instagram_hashtag'), - ] - - operations = [ - migrations.CreateModel( - name='Referral', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('discount', models.IntegerField()), - ('referrer_cashback', models.IntegerField()), - ('referral', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ('referrer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='referrals', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'Реферал', - 'verbose_name_plural': 'Рефералы', - }, - ), - ] diff --git a/apps/user/migrations/0024_referral_payment.py b/apps/user/migrations/0024_referral_payment.py deleted file mode 100644 index f68f7632..00000000 --- a/apps/user/migrations/0024_referral_payment.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.0.6 on 2018-07-30 18:24 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('payment', '0019_payment_roistat_visit'), - ('user', '0023_referral'), - ] - - operations = [ - migrations.AddField( - model_name='referral', - name='payment', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='payment.Payment'), - ), - ] diff --git a/apps/user/migrations/0025_auto_20180820_0651.py b/apps/user/migrations/0025_auto_20180820_0651.py deleted file mode 100644 index ad53086e..00000000 --- a/apps/user/migrations/0025_auto_20180820_0651.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.0.6 on 2018-08-20 06:51 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('user', '0024_referral_payment'), - ] - - operations = [ - migrations.AlterField( - model_name='referral', - name='referral', - field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='referral', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/user/models.py b/apps/user/models.py index c2fcf3cd..887167ad 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -1,4 +1,6 @@ from json import dumps + +from django.utils.functional import cached_property from rest_framework.authtoken.models import Token from phonenumber_field.modelfields import PhoneNumberField @@ -89,7 +91,7 @@ class User(AbstractUser): user_data = dumps(user_data, ensure_ascii=False) return user_data - @property + @cached_property def balance(self): aggregate = self.balances.filter( type=0, @@ -103,9 +105,9 @@ class User(AbstractUser): commission = aggregate.get('commission__sum') or 0 return amount - commission - @property + @cached_property def bonus(self): - return self.balances.aggregate(models.Sum('amount')).get('amount__sum') or 0 + return int(self.bonuses.aggregate(models.Sum('amount')).get('amount__sum')) or 0 @receiver(post_save, sender=User) diff --git a/apps/user/templates/user/bonus-history.html b/apps/user/templates/user/bonus-history.html index 72be8b05..43e45fbd 100644 --- a/apps/user/templates/user/bonus-history.html +++ b/apps/user/templates/user/bonus-history.html @@ -40,12 +40,12 @@ {% if payment.balance %}