diff --git a/apps/payment/migrations/0020_userbonus.py b/apps/payment/migrations/0020_userbonus.py
new file mode 100644
index 00000000..eaf9f835
--- /dev/null
+++ b/apps/payment/migrations/0020_userbonus.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.0.6 on 2018-09-03 22:57
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('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')),
+ ],
+ ),
+ ]
diff --git a/apps/payment/migrations/0021_auto_20180903_2257.py b/apps/payment/migrations/0021_auto_20180903_2257.py
new file mode 100644
index 00000000..381eebd8
--- /dev/null
+++ b/apps/payment/migrations/0021_auto_20180903_2257.py
@@ -0,0 +1,27 @@
+# Generated by Django 2.0.6 on 2018-09-03 22:57
+
+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', '0020_userbonus'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userbonus',
+ name='referral',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='user.Referral'),
+ ),
+ migrations.AddField(
+ model_name='userbonus',
+ name='user',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bonuses', to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/apps/payment/migrations/0022_auto_20180904_0106.py b/apps/payment/migrations/0022_auto_20180904_0106.py
new file mode 100644
index 00000000..d0b3dc03
--- /dev/null
+++ b/apps/payment/migrations/0022_auto_20180904_0106.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.0.6 on 2018-09-04 01:06
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('payment', '0021_auto_20180903_2257'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='userbonus',
+ name='payment',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='payment.Payment'),
+ ),
+ ]
diff --git a/apps/payment/migrations/0023_payment_bonus.py b/apps/payment/migrations/0023_payment_bonus.py
new file mode 100644
index 00000000..3cc2a771
--- /dev/null
+++ b/apps/payment/migrations/0023_payment_bonus.py
@@ -0,0 +1,19 @@
+# Generated by Django 2.0.6 on 2018-09-05 23:37
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('payment', '0022_auto_20180904_0106'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='payment',
+ name='bonus',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='purchase_payments', to='payment.UserBonus'),
+ ),
+ ]
diff --git a/apps/payment/models.py b/apps/payment/models.py
index e2d7cb13..b59269c9 100644
--- a/apps/payment/models.py
+++ b/apps/payment/models.py
@@ -1,3 +1,4 @@
+from decimal import Decimal
import arrow
from django.db.models import Func, F
@@ -102,6 +103,7 @@ class Payment(PolymorphicModel):
roistat_visit = models.PositiveIntegerField('Номер визита Roistat', null=True, editable=False)
created_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
+ bonus = models.ForeignKey('payment.UserBonus', null=True, on_delete=models.SET_NULL, related_name='purchase_payments')
objects = PaymentManger()
@@ -120,18 +122,23 @@ class Payment(PolymorphicModel):
return result.datetime
@classmethod
- def calc_amount(cls, course_payment=None, school_payment=None, user=None, course=None, date_start=None, weekdays=None):
+ def calc_amount(cls, payment=None, user=None, course=None, date_start=None, weekdays=None):
date_start = date_start or now().date()
date_end = Payment.add_months(date_start, 1)
- if course_payment:
- course = course_payment.course
- user = course_payment.user
- if school_payment:
- user = school_payment.user
- weekdays = school_payment.weekdays
- date_start = school_payment.date_start
- discount = 0
+ if isinstance(payment, CoursePayment):
+ course = payment.course
+ user = payment.user
+ if isinstance(payment, SchoolPayment):
+ user = payment.user
+ weekdays = payment.weekdays
+ date_start = payment.date_start
price = 0
+ referral_bonus = 0
+ referrer_bonus = 0
+ if hasattr(user, 'referral') and not user.referral.payment:
+ referral_bonus = user.referral.bonus
+ referrer_bonus = user.referral.referrer_bonus
+ discount = 0
if course:
price = course.price
else:
@@ -140,7 +147,6 @@ class Payment(PolymorphicModel):
user=user,
date_start__lte=date_start,
date_end__gte=date_start,
- add_days=False,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
@@ -150,8 +156,8 @@ class Payment(PolymorphicModel):
school_schedules_purchased = school_payments.annotate(
joined_weekdays=Func(F('weekdays'), function='unnest', )
).values_list('joined_weekdays', flat=True).distinct()
- weekdays = set(map(int, weekdays)) - set(school_schedules_purchased)
- prev_school_payment = school_payments.last()
+ weekdays = list(set(map(int, weekdays)) - set(school_schedules_purchased))
+ prev_school_payment = school_payments.filter(add_days=False).last()
add_days = bool(prev_school_payment)
else:
add_days = False
@@ -169,15 +175,20 @@ class Payment(PolymorphicModel):
price = school_schedules.aggregate(
models.Sum('month_price'),
).get('month_price__sum', 0)
- if not (school_payment and school_payment.id) and price >= config.SERVICE_DISCOUNT_MIN_AMOUNT:
+ if not (payment and payment.id) and price >= config.SERVICE_DISCOUNT_MIN_AMOUNT:
discount = config.SERVICE_DISCOUNT
amount = price - discount
+ referral_bonus = round(amount * referral_bonus / 100)
+ referrer_bonus = round(amount * referrer_bonus / 100)
return {
'price': price,
'amount': amount,
+ 'referral_bonus': referral_bonus,
+ 'referrer_bonus': referrer_bonus,
'discount': discount,
'date_start': date_start,
'date_end': date_end,
+ 'weekdays': weekdays,
}
def calc_commission(self):
@@ -199,6 +210,36 @@ class Payment(PolymorphicModel):
Pingback.PINGBACK_TYPE_RISK_REVIEWED_DECLINED,
]
+ def save(self, *args, **kwargs):
+ paid = self.status in [Pingback.PINGBACK_TYPE_REGULAR, Pingback.PINGBACK_TYPE_GOODWILL,
+ Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,]
+ amount_data = Payment.calc_amount(payment=self)
+ print('amount_data', amount_data)
+ if self.status is None and not self.bonus:
+ print(123)
+ self.amount = amount_data.get('amount')
+ if isinstance(self, SchoolPayment):
+ self.weekdays = amount_data.get('weekdays')
+ super().save(*args, **kwargs)
+ if isinstance(self, CoursePayment) and paid:
+ 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 and paid:
+ # Платеж - как сигнал, что скидка применилась
+ self.user.referral.payment = self
+ self.user.referral.save()
+ # Отправляем кэшбэк
+ 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')
@@ -207,22 +248,6 @@ class CoursePayment(Payment):
verbose_name = 'Платеж за курс'
verbose_name_plural = 'Платежи за курсы'
- def save(self, *args, **kwargs):
- if self.status is None:
- amount_data = Payment.calc_amount(course_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()
-
class SchoolPayment(Payment):
weekdays = ArrayField(models.IntegerField(), size=7, verbose_name='Дни недели')
@@ -241,12 +266,17 @@ class SchoolPayment(Payment):
])
return days
- def save(self, *args, **kwargs):
- if self.status is None:
- amount_data = Payment.calc_amount(school_payment=self)
- self.amount = amount_data.get('amount')
- super().save(*args, **kwargs)
-
@property
def date_end_humanize(self):
return arrow.get(self.date_end, settings.TIME_ZONE).humanize(locale='ru')
+
+
+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.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)
+
+ class Meta:
+ ordering = ('created_at',)
diff --git a/apps/payment/views.py b/apps/payment/views.py
index ad5a76ef..5663df39 100644
--- a/apps/payment/views.py
+++ b/apps/payment/views.py
@@ -27,7 +27,7 @@ from apps.course.models import Course
from apps.school.models import SchoolSchedule
from apps.payment.tasks import transaction_to_mixpanel, product_payment_to_mixpanel, transaction_to_roistat
-from .models import AuthorBalance, CoursePayment, SchoolPayment, Payment
+from .models import AuthorBalance, CoursePayment, SchoolPayment, Payment, UserBonus
logger = logging.getLogger('django')
@@ -100,17 +100,18 @@ class SchoolBuyView(TemplateView):
host = urlsplit(self.request.META.get('HTTP_REFERER'))
host = str(host[0]) + '://' + str(host[1])
weekdays = set(request.GET.getlist('weekdays', []))
+ use_bonuses = request.GET.get('use_bonuses')
roistat_visit = request.COOKIES.get('roistat_visit', None)
date_start = request.GET.get('date_start')
date_start = date_start and datetime.datetime.strptime(date_start, '%Y-%m-%d') or now().date()
if not weekdays:
messages.error(request, 'Выберите несколько дней недели.')
- return redirect('school:summer-school')
+ return redirect('school:school')
try:
weekdays = [int(weekday) for weekday in weekdays]
except ValueError:
messages.error(request, 'Ошибка выбора дней недели.')
- return redirect('school:summer-school')
+ return redirect('school:school')
prev_school_payment = SchoolPayment.objects.filter(
user=request.user,
date_start__lte=date_start,
@@ -132,6 +133,7 @@ class SchoolBuyView(TemplateView):
add_days=True,
roistat_visit=roistat_visit,
)
+ # Если произойдет ошибка и оплату бонусами повторят еще раз на те же дни, то вернет ошибку
if school_payment.amount <= 0:
messages.error(request, 'Выбранные дни отсутствуют в оставшемся периоде подписки')
return redirect(reverse_lazy('school:school'))
@@ -143,6 +145,19 @@ class SchoolBuyView(TemplateView):
date_start=date_start,
date_end=Payment.add_months(date_start),
)
+ if use_bonuses:
+ if request.user.bonus >= school_payment.amount:
+ bonus = UserBonus.objects.create(amount= -school_payment.amount, user=request.user, payment=school_payment)
+ school_payment.amount = 0
+ school_payment.status = Pingback.PINGBACK_TYPE_REGULAR
+ else:
+ bonus = UserBonus.objects.create(amount= -request.user.bonus, user=request.user,
+ payment=school_payment)
+ school_payment.amount -= request.user.bonus
+ school_payment.bonus = bonus
+ school_payment.save()
+ if school_payment.status == Pingback.PINGBACK_TYPE_REGULAR:
+ return redirect(reverse_lazy('payment-success'))
product = Product(
f'school_{school_payment.id}',
school_payment.amount,
@@ -213,6 +228,7 @@ class PaymentwallCallbackView(View):
product_type_name,
)
+
if product_type_name == 'course':
properties = {
'payment_id': payment.id,
diff --git a/apps/school/views.py b/apps/school/views.py
index bac97f5a..bdb3a848 100644
--- a/apps/school/views.py
+++ b/apps/school/views.py
@@ -63,30 +63,23 @@ class LiveLessonsDetailView(DetailView):
template_name = 'school/livelesson_detail.html'
def get(self, request, pk=None):
- response = super().get(request, pk=pk)
- # ??? где проверка?
- #try:
- # school_payment = SchoolPayment.objects.get(
- # user=request.user,
- # add_days=False,
- # date_start__lte=now(),
- # date_end__gte=now(),
- # status__in=[
- # Pingback.PINGBACK_TYPE_REGULAR,
- # Pingback.PINGBACK_TYPE_GOODWILL,
- # Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
- # ],
- # )
- #except SchoolPayment.DoesNotExist:
- # school_payment = None
- #if request.user.role not in [User.ADMIN_ROLE, User.TEACHER_ROLE] and not (
- # request.user.role == User.USER_ROLE and
- # school_payment and
- # school_payment.is_deliverable()
- #):
- # raise Http404
-
- return response
+ self.object = self.get_object()
+ is_purchased = SchoolPayment.objects.filter(
+ user=request.user,
+ date_start__lte=now(),
+ date_end__gte=now(),
+ status__in=[
+ Pingback.PINGBACK_TYPE_REGULAR,
+ Pingback.PINGBACK_TYPE_GOODWILL,
+ Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
+ ],
+ weekdays__contains=[self.object.date.weekday() + 1],
+ ).exists()
+ if not is_purchased and request.user.role not in [User.ADMIN_ROLE, User.TEACHER_ROLE]:
+ raise Http404
+
+ context = self.get_context_data(object=self.object)
+ return self.render_to_response(context)
@method_decorator([login_required, is_admin_or_teacher], name='dispatch')
diff --git a/apps/user/forms.py b/apps/user/forms.py
index a38debe6..4a0ccf0e 100644
--- a/apps/user/forms.py
+++ b/apps/user/forms.py
@@ -36,6 +36,7 @@ class UserEditForm(forms.ModelForm):
'first_name',
'last_name',
'email',
+ 'slug',
'phone',
'city',
'country',
diff --git a/apps/user/migrations/0024_referral.py b/apps/user/migrations/0024_referral.py
new file mode 100644
index 00000000..f16eeed5
--- /dev/null
+++ b/apps/user/migrations/0024_referral.py
@@ -0,0 +1,31 @@
+# Generated by Django 2.0.6 on 2018-09-03 22:57
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('payment', '0020_userbonus'),
+ ('user', '0023_user_trial_lesson'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Referral',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('bonus', models.IntegerField()),
+ ('referrer_bonus', models.IntegerField()),
+ ('payment', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='payment.Payment')),
+ ('referral', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='referral', 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_user_slug.py b/apps/user/migrations/0024_user_slug.py
new file mode 100644
index 00000000..3ebe7d0a
--- /dev/null
+++ b/apps/user/migrations/0024_user_slug.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.0.6 on 2018-09-26 13:05
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('user', '0023_user_trial_lesson'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='user',
+ name='slug',
+ field=models.SlugField(allow_unicode=True, blank=True, max_length=100, null=True, unique=True),
+ ),
+ ]
diff --git a/apps/user/migrations/0025_merge_20180927_2353.py b/apps/user/migrations/0025_merge_20180927_2353.py
new file mode 100644
index 00000000..d5ab9d4a
--- /dev/null
+++ b/apps/user/migrations/0025_merge_20180927_2353.py
@@ -0,0 +1,14 @@
+# Generated by Django 2.0.6 on 2018-09-27 23:53
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('user', '0024_referral'),
+ ('user', '0024_user_slug'),
+ ]
+
+ operations = [
+ ]
diff --git a/apps/user/models.py b/apps/user/models.py
index 47008960..84d9a329 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
@@ -9,10 +11,10 @@ from django.contrib.auth.models import AbstractUser, UserManager as BaseUserMana
from django.contrib.postgres import fields as pgfields
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
+from django.urls import reverse
from api.v1 import serializers
from apps.notification.utils import send_email
-
from apps.user.tasks import user_to_mixpanel
@@ -76,6 +78,10 @@ class User(AbstractUser):
photo = models.ImageField('Фото', null=True, blank=True, upload_to='users')
show_in_mainpage = models.BooleanField('Показывать на главной странице', default=False)
trial_lesson = models.URLField(default='', null=True, blank=True)
+ slug = models.SlugField(
+ allow_unicode=True, null=True, blank=True,
+ max_length=100, unique=True, db_index=True,
+ )
objects = UserManager()
@@ -85,12 +91,16 @@ class User(AbstractUser):
class Meta(AbstractUser.Meta):
ordering = ('-date_joined',)
+ @property
+ def url(self):
+ return reverse('user', args=[self.slug or self.id])
+
def serialized(self):
user_data = serializers.user.UserSerializer(instance=self).data
user_data = dumps(user_data, ensure_ascii=False)
return user_data
- @property
+ @cached_property
def balance(self):
income = self.balances.filter(
type=0,
@@ -108,6 +118,10 @@ class User(AbstractUser):
return income_amount - income_commission - payout_amount
+ @cached_property
+ def bonus(self):
+ return int(self.bonuses.aggregate(models.Sum('amount')).get('amount__sum') or 0)
+
@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
@@ -261,3 +275,20 @@ class EmailSubscription(models.Model):
email = models.EmailField(_('email address'), unique=True)
categories = models.ManyToManyField(SubscriptionCategory)
mailchimp_status = models.PositiveSmallIntegerField(choices=MAILCHIMP_STATUS_CHOICES, default=ERROR)
+
+
+class Referral(models.Model):
+ referral = models.OneToOneField(User, on_delete=models.CASCADE, related_name='referral')
+ referrer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='referrals')
+ bonus = models.IntegerField()
+ referrer_bonus = models.IntegerField()
+ payment = models.OneToOneField('payment.Payment', null=True, blank=True, on_delete=models.CASCADE)
+
+ class Meta:
+ verbose_name = 'Реферал'
+ verbose_name_plural = 'Рефералы'
+
+ def send_bonuses(self, referral_bonus, referrer_bonus):
+ from apps.payment.models import UserBonus
+ UserBonus.objects.create(user=self.referral, amount=referral_bonus, payment=self.payment, referral=self)
+ UserBonus.objects.create(user=self.referrer, amount=referrer_bonus, payment=self.payment, referral=self)
diff --git a/apps/user/templates/blocks/profile-menu.html b/apps/user/templates/blocks/profile-menu.html
new file mode 100644
index 00000000..5bb21b94
--- /dev/null
+++ b/apps/user/templates/blocks/profile-menu.html
@@ -0,0 +1,14 @@
+
diff --git a/apps/user/templates/user/bonus-history.html b/apps/user/templates/user/bonus-history.html
new file mode 100644
index 00000000..d4f32bcb
--- /dev/null
+++ b/apps/user/templates/user/bonus-history.html
@@ -0,0 +1,71 @@
+{% extends "templates/lilcity/index.html" %}
+{% load static %}
+{% load rupluralize from plural %}
+
+{% block content %}
+{% include "../blocks/profile-menu.html" with active="bonuses" %}
+
+
+
+
Бонусы
+
У вас {{ request.user.bonus|rupluralize:"бонус,бонуса,бонусов" }}
+
+ Вы можете пригласить своих друзей в наш сервис, за это
+ {% if config.REFERRER_BONUS == config.REFERRAL_BONUS %}
+ вы и они получите по {{ config.REFERRER_BONUS }}%
+ {% else %}
+ вы получите {{ config.REFERRER_BONUS }}%, а они {{ config.REFERRAL_BONUS }}%
+ {% endif %}
+ от суммы их первой покупки на бонусный счет. Приглашайте друзей, накапливайте бонусные баллы, тратьте бонусы
+ на приобретения доступа к школе и курсам. Оплата услуг возможна только, если вы накопили баллов на стоимость услуги.
+
+ Просто отправьте им эту ссылку, по которой они смогут зарегистрироваться:
+
+
+
+
+
+
+
+
История бонусов
+
+
+
+
Продукт
+
Сумма покупки
+
Реферал
+
Сумма бонусов
+
+ {% for bonus in bonuses %}
+
+ {% with payment=bonus.payment %}
+ {% if payment.course %}
+
Курс. {{ payment.course.title }}
+ {% else %}
+
+ {% if request.user_agent.is_mobile %}
+ Школа. {% if payment.date_start and payment.date_end %}{{ payment.date_start|date:"j b" }} - {{ payment.date_end|date:"j b" }}{% endif %}
+ {% else %}
+ Школа. {% if payment.date_start and payment.date_end %}{{ payment.date_start }} - {{ payment.date_end }}{% endif %}
+ {% endif %}
+
+ {% endif %}
+
{{payment.amount }}
+
+ {% if bonus.referral %}{{ bonus.referral.referral.get_full_name }}{% endif %}
+
+
{{ bonus.amount|floatformat }}
+ {% endwith %}
+
+ {% empty %}
+ Нет истории бонусов
+ {% endfor %}
+
+
+
+
+{% endblock content %}
diff --git a/apps/user/templates/user/notification-settings.html b/apps/user/templates/user/notification-settings.html
index 40c679e5..b73bb35d 100644
--- a/apps/user/templates/user/notification-settings.html
+++ b/apps/user/templates/user/notification-settings.html
@@ -1,13 +1,5 @@
{% extends "templates/lilcity/index.html" %} {% load static %} {% block content %}
-
+{% include "../blocks/profile-menu.html" with active="notifications" %}
{% if not user.is_email_proved %}
diff --git a/apps/user/templates/user/payment-history.html b/apps/user/templates/user/payment-history.html
index dff8619c..b30eee13 100644
--- a/apps/user/templates/user/payment-history.html
+++ b/apps/user/templates/user/payment-history.html
@@ -1,13 +1,5 @@
{% extends "templates/lilcity/index.html" %} {% load static %} {% block content %}
-
+{% include "../blocks/profile-menu.html" with active="payments" %}
{% if not user.is_email_proved %}
@@ -73,42 +65,42 @@
История платежей
-
+
{% if request.user.payments.all.exists %}
{% for payment in request.user.payments.all %}
{% if payment.course %}
-
Курс. {{payment.course.title}}
+
Курс. {{payment.course.title}}
{% else %}
-
+
Школа. {% if payment.date_start and payment.date_end %}{{ payment.date_start }} - {{ payment.date_end }}{% endif %}
{% endif %}
{% if payment.balance %}
-
{{payment.balance.amount}}
+
{{payment.balance.amount}}
{% else %}
-
{{payment.amount}}
+
{{payment.amount}}
{% endif %}
{% if payment.balance.type == 1 %}
-
+
{% if payment.balance.status == 0 %}
- Ожидается подтверждение выплаты
+ Ожидается подтверждение выплаты
{% elif payment.balance.status == 1 %}
- Выплачено
+ Выплачено
{% else %}
- Выплата отменена
+ Выплата отменена
Причина: "{{ payment.balance.cause }}
{% endif %}
{% else %}
-
+
{% if payment.is_deliverable %}
- Оплачено
+ Оплачено
{% elif payment.is_under_review %}
- Ожидается подтверждение оплаты
+ Ожидается подтверждение оплаты
{% else %}
- Ошибка оплаты
+ Ошибка оплаты
{% endif %}
{% endif %}
diff --git a/apps/user/templates/user/profile-settings.html b/apps/user/templates/user/profile-settings.html
index 90470b96..436cb374 100644
--- a/apps/user/templates/user/profile-settings.html
+++ b/apps/user/templates/user/profile-settings.html
@@ -1,13 +1,9 @@
-{% extends "templates/lilcity/index.html" %} {% load static %} {% load thumbnail %} {% block content %}
-
+{% extends "templates/lilcity/index.html" %}
+{% load static %}
+{% load settings %}
+{% load thumbnail %}
+{% block content %}
+{% include "../blocks/profile-menu.html" with active="profile" %}
{% if not user.is_email_proved %}
@@ -44,7 +40,7 @@
{% empty %}
{% endthumbnail %}
-
+
@@ -55,7 +51,7 @@
-
{% endblock content %}
diff --git a/apps/user/views.py b/apps/user/views.py
index 103ff126..6f54861d 100644
--- a/apps/user/views.py
+++ b/apps/user/views.py
@@ -4,18 +4,16 @@ from uuid import uuid4
from os.path import splitext
from datetime import timedelta
from paymentwall import Pingback
+import short_url
from django.conf import settings
from django.contrib.auth import login
-from django.core.exceptions import ValidationError
-from django.shortcuts import render, reverse, redirect
+from django.shortcuts import reverse, redirect
from django.views import View
from django.views.generic import DetailView, UpdateView, TemplateView, FormView
from django.contrib import messages
from django.contrib.auth import get_user_model
-from django.contrib.auth.decorators import login_required, permission_required
-from django.contrib.auth.hashers import check_password, make_password
-from django.http import Http404
+from django.contrib.auth.decorators import login_required
from django.db.models import F, Func, Sum, Min, Max
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
@@ -99,6 +97,7 @@ class ProfileView(TemplateView):
class UserView(DetailView):
model = User
template_name = 'user/author_profile.html'
+ query_pk_and_slug = True
def get_context_data(self, object):
context = super().get_context_data()
@@ -146,7 +145,7 @@ class NotificationEditView(TemplateView):
request.user.email_subscription.categories.set(
SubscriptionCategory.objects.filter(id__in=categories)
)
- return redirect('user-edit-notifications', request.user.id)
+ return redirect('user-edit-notifications')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@@ -183,7 +182,7 @@ class PaymentHistoryView(FormView):
return self.form_invalid(form)
def get_success_url(self):
- success_url = reverse_lazy('user-edit-payments', args=[self.request.user.id])
+ success_url = reverse_lazy('user-edit-payments')
return success_url
@@ -292,3 +291,17 @@ class AuthorRequestView(FormView):
'facebook': self.request.user.facebook,
}
return super().get_context_data(**kwargs)
+
+
+@method_decorator(login_required, name='dispatch')
+class BonusHistoryView(TemplateView):
+ model = User
+ template_name = 'user/bonus-history.html'
+
+ def get(self, request, *args, **kwargs):
+ context = self.get_context_data(**kwargs)
+ context['bonuses'] = request.user.bonuses.all()
+ context['referrer_url'] = '%s%s?referrer=%s' % (
+ settings.MAIN_HOST, reverse('index'), short_url.encode_url(request.user.id)
+ )
+ return self.render_to_response(context)
diff --git a/project/context_processors.py b/project/context_processors.py
index ebb36f25..6e954da7 100644
--- a/project/context_processors.py
+++ b/project/context_processors.py
@@ -1,11 +1,14 @@
from django.db.models import Func, F
from django.utils.timezone import now
from paymentwall.pingback import Pingback
-
+from django.contrib.auth import get_user_model
+from django.conf import settings
from apps.config.models import Config
from apps.content.models import Baner
from apps.payment.models import SchoolPayment
+User = get_user_model()
+
def config(request):
return {"config": Config.load()}
@@ -39,3 +42,17 @@ def school_purchased(request):
'is_school_purchased': False,
'school_schedules_purchased': [],
}
+
+
+def referrer(request):
+ referrer = request.session.get('referrer')
+ if referrer:
+ try:
+ referrer = User.objects.get(pk=referrer)
+ except:
+ referrer = None
+ return {'referrer': referrer}
+
+
+def settings(request):
+ return {'settings': settings}
diff --git a/project/settings.py b/project/settings.py
index 51545f31..8cdb2ed2 100644
--- a/project/settings.py
+++ b/project/settings.py
@@ -31,6 +31,7 @@ SECRET_KEY = os.getenv('SECRET_KEY', 'jelm*91lj(_-o20+6^a+bgv!4s6e_efry^#+f#=1ak
DEBUG = os.getenv('DEBUG', False)
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '*').split(',')
+MAIN_HOST = os.getenv('MAIN_HOST', 'lil.school')
# Application definition
@@ -95,6 +96,8 @@ TEMPLATES = [
'project.context_processors.config',
'project.context_processors.baner',
'project.context_processors.school_purchased',
+ 'project.context_processors.referrer',
+ 'project.context_processors.settings',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
diff --git a/project/templates/blocks/lil_store_js.html b/project/templates/blocks/lil_store_js.html
index 4fbb805d..29aacb22 100644
--- a/project/templates/blocks/lil_store_js.html
+++ b/project/templates/blocks/lil_store_js.html
@@ -20,7 +20,13 @@
},
components: {},
urls: {
- courses: "{% url 'courses' %}"
+ courses: "{% url 'courses' %}",
+ userProfileEdit: "{% url 'user-edit-profile' %}",
+ },
+ flags: {
+ referrer: '{{ referrer.id|default:'' }}',
+ referrerName: '{% if referrer %}{{ referrer.get_full_name }}{% endif %}',
+ isReferralUrl: {{ is_referral_url|yesno:"true,false" }},
},
};
diff --git a/project/templates/blocks/popup_auth.html b/project/templates/blocks/popup_auth.html
index 092cee9b..5fbca404 100644
--- a/project/templates/blocks/popup_auth.html
+++ b/project/templates/blocks/popup_auth.html
@@ -10,13 +10,13 @@