страница с ценами

remotes/origin/feature/packages-page-1-08-19
gzbender 7 years ago
parent c615bd1533
commit c232ea5cb3
  1. 3
      api/v1/views.py
  2. 18
      apps/notification/templates/notification/email/buy_email.html
  3. 36
      apps/payment/migrations/0038_auto_20190809_0133.py
  4. 25
      apps/payment/migrations/0038_auto_20190814_1506.py
  5. 96
      apps/payment/models.py
  6. 5
      apps/payment/templates/payment/payment_success.html
  7. 124
      apps/payment/views.py
  8. 2
      apps/school/views.py
  9. 1
      project/templates/lilcity/index.html
  10. 30
      project/templates/lilcity/packages.html
  11. 6
      project/urls.py
  12. 21
      project/views.py
  13. 6
      web/src/sass/_common.sass

@ -652,14 +652,13 @@ class PaymentViewSet(viewsets.ModelViewSet):
def calc_amount(self, request, pk=None):
user = request.query_params.get('user')
course = request.query_params.get('course')
weekdays = request.query_params.getlist('weekdays[]')
date_start = request.query_params.get('date_start')
is_camp = bool(request.query_params.get('is_camp'))
user = user and User.objects.get(pk=user)
course = course and Course.objects.get(pk=course)
date_start = date_start and datetime.strptime(date_start, '%Y-%m-%d')
return Response(Payment.calc_amount(user=user, course=course, date_start=date_start, weekdays=weekdays,
return Response(Payment.calc_amount(user=user, course=course, date_start=date_start,
is_camp=is_camp))

@ -3,12 +3,20 @@
{% block content %}
{% if product_type == 'course' %}
<p>Курс ждет вас по ссылке <a href="https://{% setting 'MAIN_HOST' %}{{ url }}">
<p>Добрый день! Спасибо за покупку знаний в «Lil School»!</p>
<p>Где искать уроки?</p>
<p>После оплаты курс появится в вашем личном кабинете на платформе.</p>
<p><a href="https://{% setting 'MAIN_HOST' %}{{ url }}">
https://{% setting 'MAIN_HOST' %}{{ url }}</a></p>
<p>Все ваши покупки будут храниться там в рамках срока доступа к курсу.</p>
{% endif %}
{% if product_type == 'school' %}
<p>Школа ждет вас по ссылке <a href="https://{% setting 'MAIN_HOST' %}{% url 'school:school' %}">
<p>Добрый день! Спасибо за покупку знаний в «Lil School»!</p>
<p>Где искать уроки?</p>
<p>После оплаты уроки появятся в вашем личном кабинете на платформе.</p>
<p><a href="https://{% setting 'MAIN_HOST' %}{% url 'school:school' %}">
https://{% setting 'MAIN_HOST' %}{% url 'school:school' %}</a></p>
<p>В онлайн-школе урок хранится неделю. Ровно до следующего урока.</p>
{% endif %}
{% if product_type == 'drawing_camp' %}
{% if date_start.month == 7 and date_start.day == 1 and date_end.day == 31 %}
@ -73,12 +81,6 @@
{% endif %}
{% endif %}
{% if product_type == 'package' %}
<p>Вы приобрели подписку с {{ date_start|date:'j-m-y' }} по {{ date_end|date:'j-m-y'}}</p>
{% else %}
<p>Так же вы можете найти ссылку в личном кабинете в разделе «Мои покупки».</p>
{% endif %}
<p>Занимайтесь с удовольствием!</p>
<p>Команда «Lil School».</p>

@ -1,36 +0,0 @@
# Generated by Django 2.0.7 on 2019-08-09 01:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('content', '0030_auto_20190809_0133'),
('payment', '0037_add_paid_one_more_bonuses'),
]
operations = [
migrations.CreateModel(
name='PackagePayment',
fields=[
('payment_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='payment.Payment')),
('date_start', models.DateField(blank=True, null=True, verbose_name='Дата начала подписки')),
('date_end', models.DateField(blank=True, null=True, verbose_name='Дата окончания подписки')),
('camp_payment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='payment.DrawingCampPayment')),
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='content.Package')),
('school_payment', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='payment.SchoolPayment')),
],
options={
'abstract': False,
'base_manager_name': 'objects',
},
bases=('payment.payment',),
),
migrations.AlterField(
model_name='payment',
name='bonus',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='purchase_payments', to='payment.UserBonus'),
),
]

@ -0,0 +1,25 @@
# Generated by Django 2.0.7 on 2019-08-14 15:06
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('content', '0030_auto_20190809_0133'),
('payment', '0037_add_paid_one_more_bonuses'),
]
operations = [
migrations.AddField(
model_name='schoolpayment',
name='package',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='content.Package'),
),
migrations.AlterField(
model_name='payment',
name='bonus',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='purchase_payments', to='payment.UserBonus'),
),
]

@ -128,7 +128,7 @@ class Payment(PolymorphicModel):
ordering = ('created_at',)
@classmethod
def ajust_date_bounds(cls, date_start=None, date_end=None, is_camp=False):
def adjust_date_bounds(cls, date_start=None, date_end=None, is_camp=False):
school_start = date(now().year, 9, 1)
school_end = date(now().year, 5, 31)
camp_start = date(now().year, 6, 1)
@ -158,7 +158,7 @@ class Payment(PolymorphicModel):
date_start = date_start or now().date()
if isinstance(date_start, datetime):
date_start = date_start.date()
date_start = cls.ajust_date_bounds(date_start=date_start, is_camp=is_camp)
date_start = cls.adjust_date_bounds(date_start=date_start, is_camp=is_camp)
if is_camp and date_start.month == 6 and date_start.day > 16:
date_start = date_start.replace(month=7, day=1)
date_end = arrow.get(date_start + timedelta(days=days), settings.TIME_ZONE).shift(months=months).date() - timedelta(1)
@ -166,11 +166,11 @@ class Payment(PolymorphicModel):
if is_camp or (date_start.month == 2 and date_start.day >= 28) or (date_start.day == 31 and date_end.day <= 30) \
or (date_start.month == 1 and date_start.day >= 29 and date_end.day == 28):
date_end = date_start.replace(day=1, month=date_start.month + 1) - timedelta(1)
date_end = cls.ajust_date_bounds(date_end=date_end, is_camp=is_camp)
date_end = cls.adjust_date_bounds(date_end=date_end, is_camp=is_camp)
return [date_start, date_end]
@classmethod
def calc_amount(cls, payment=None, user=None, course=None, date_start=None, weekdays=None, is_camp=False):
def calc_amount(cls, package=None, payment=None, user=None, course=None, date_start=None, weekdays=None, is_camp=False):
price = 0
discount = 0
referral_bonus = 0
@ -180,14 +180,14 @@ class Payment(PolymorphicModel):
user = payment.user
if isinstance(payment, SchoolPayment):
user = payment.user
weekdays = payment.weekdays
date_start = payment.date_start
package=payment.package
if isinstance(payment, DrawingCampPayment):
user = payment.user
date_start = payment.date_start
if issubclass(cls, DrawingCampPayment):
is_camp = True
date_start, date_end = Payment.get_date_range(date_start, months=1, is_camp=is_camp)
date_start, date_end = Payment.get_date_range(date_start, months=package.duration if package else 1, is_camp=is_camp)
if hasattr(user, 'referral') and not user.referral.payment:
referral_bonus = user.referral.bonus
referrer_bonus = user.referral.referrer_bonus
@ -215,40 +215,22 @@ class Payment(PolymorphicModel):
date_end__gte=date_start,
status__in=Payment.PW_PAID_STATUSES,
)
school_schedules_purchased = school_payments.annotate(
joined_weekdays=Func(F('weekdays'), function='unnest', )
).values_list('joined_weekdays', flat=True).distinct()
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
school_schedules = SchoolSchedule.objects.filter(
weekday__in=weekdays,
is_camp=False,
)
if add_days:
date_end = prev_school_payment.date_end
weekdays_count = weekdays_in_date_range(date_start, prev_school_payment.date_end)
all_weekdays_count = weekdays_in_date_range(prev_school_payment.date_start, prev_school_payment.date_end)
for ss in school_schedules:
price += ss.month_price // all_weekdays_count.get(ss.weekday, 0) * weekdays_count.get(
ss.weekday, 0)
if prev_school_payment:
date_start, date_end = Payment.get_date_range(prev_school_payment.date_end + timedelta(1),
months=package.duration, is_camp=False)
school_schedules = SchoolSchedule.objects.filter(is_camp=False).exclude(title='')
weekdays = list(school_schedules.values_list('weekday', flat=True))
# FIXME после мая 2019 убрать?
# Если хотят купить школу в мае, то оплатить ее можно только до 31 мая, потом школа закроется
if date_start.month == 5:
weekdays_count = weekdays_in_date_range(date_start, date_end)
weekdays_count = sum(weekdays_count[wd] for wd in weekdays)
all_weekdays_count = weekdays_in_date_range(date_start.replace(day=1), date_end)
all_weekdays_count = sum(all_weekdays_count[wd] for wd in weekdays)
price = package.price // all_weekdays_count * weekdays_count
else:
# FIXME после мая 2019 убрать?
# Если хотят купить школу в мае, то оплатить ее можно только до 31 мая, потом школа закроется
if date_start.month == 5:
weekdays_count = weekdays_in_date_range(date_start, date_end)
all_weekdays_count = weekdays_in_date_range(date_start.replace(day=1), date_end)
for ss in school_schedules:
price += ss.month_price // all_weekdays_count.get(ss.weekday, 0) * weekdays_count.get(
ss.weekday, 0)
else:
price = school_schedules.aggregate(
models.Sum('month_price'),
).get('month_price__sum', 0)
if not (payment and payment.id) and price >= config.SERVICE_DISCOUNT_MIN_AMOUNT:
discount = config.SERVICE_DISCOUNT
price = package.price
amount = price - discount
referral_bonus = round(amount * referral_bonus / 100)
referrer_bonus = round(amount * referrer_bonus / 100)
@ -299,35 +281,6 @@ class Payment(PolymorphicModel):
self.weekdays = amount_data.get('weekdays')
super().save(*args, **kwargs)
if self.is_paid():
if isinstance(self, PackagePayment):
year_start = date(now().year, 1, 1)
year_end = date(now().year, 12, 31)
school_start = date(now().year, 9, 1)
school_end = date(now().year, 5, 31)
camp_start = date(now().year, 6, 1)
camp_end = date(now().year, 8, 31)
# TODO
if dates_overlap(self.date_start, self.date_end, camp_start, camp_end):
cp_amount_date = DrawingCampPayment.calc_amount()
DrawingCampPayment.objects.create(
user=self.user,
roistat_visit=self.roistat_visit,
date_start=self.date_start,
date_end=self.date_end,
amount=0,
status=self.status,
)
if dates_overlap(self.date_start, self.date_end, school_start, year_end)\
or dates_overlap(self.date_start, self.date_end, year_start, school_end):
SchoolPayment.objects.create(
user=self.user,
weekdays=[1, 2, 3, 4, 5, 6, 7],
roistat_visit=self.roistat_visit,
date_start=self.date_start,
date_end=self.date_end,
amount=0,
status=self.status,
)
if isinstance(self, CoursePayment):
if not getattr(self, 'authorbalance', None):
AuthorBalance.objects.create(
@ -368,6 +321,7 @@ class CoursePayment(Payment):
class SchoolPayment(Payment):
weekdays = ArrayField(models.IntegerField(), size=7, verbose_name='Дни недели')
add_days = models.BooleanField('Докупленные дни', default=False)
package = models.ForeignKey(Package, null=True, blank=True, on_delete=models.SET_NULL)
date_start = models.DateField('Дата начала подписки', null=True, blank=True)
date_end = models.DateField('Дата окончания подписки', null=True, blank=True)
@ -415,14 +369,6 @@ class GiftCertificatePayment(Payment):
verbose_name_plural = 'Платежи за подарочные сертификаты'
class PackagePayment(Payment):
date_start = models.DateField('Дата начала подписки', null=True, blank=True)
date_end = models.DateField('Дата окончания подписки', null=True, blank=True)
package = models.ForeignKey(Package, on_delete=models.CASCADE)
school_payment = models.ForeignKey(SchoolPayment, on_delete=models.SET_NULL, null=True, blank=True)
camp_payment = models.ForeignKey(DrawingCampPayment, on_delete=models.SET_NULL, null=True, blank=True)
class UserBonus(models.Model):
ACTION_FILL_PROFILE = 'fill_profile'
ACTION_PAID_ONE_MORE = 'paid_one_more'

@ -1,9 +1,10 @@
{% extends "templates/lilcity/index.html" %} {% load static %} {% block content %}
{% extends "templates/lilcity/index.html" %} {% load static %}{% load plural %}
{% block content %}
<div class="section">
<div class="section__center center center_xs">
<div class="done">
{% if school %}
<div class="done__title title">Вы успешно приобрели доступ к урокам онлайн-школы!</div>
<div class="done__title title">Вы успешно приобрели доступ на {{ duration|rupluralize:"месяц,месяца,месяцев" }}!</div>
<div class="done__foot">
<a class="done__btn btn btn_md btn_stroke" href="{% url 'school:school' %}">ПЕРЕЙТИ К ШКОЛЕ</a>
</div>

@ -26,7 +26,7 @@ from apps.payment.tasks import transaction_to_mixpanel, product_payment_to_mixpa
from apps.notification.utils import send_email
from .models import AuthorBalance, CoursePayment, SchoolPayment, Payment, UserBonus, GiftCertificate, \
GiftCertificatePayment, UserGiftCertificate, DrawingCampPayment, PackagePayment
GiftCertificatePayment, UserGiftCertificate, DrawingCampPayment
logger = logging.getLogger('django')
@ -49,7 +49,12 @@ class SchoolBuySuccessView(TemplateView):
template_name = 'payment/payment_success.html'
def get(self, request, pk=None, is_camp=False, *args, **kwargs):
return self.render_to_response(context={'camp': True} if is_camp else {'school': True})
context = {
'duration': request.GET.get('duration'),
'camp': is_camp,
'school': not is_camp
}
return self.render_to_response(context=context)
@method_decorator(login_required, name='dispatch')
@ -117,56 +122,23 @@ class SchoolBuyView(TemplateView):
template_name = 'payment/paymentwall_widget.html'
def get(self, request, *args, **kwargs):
raise Http404() # FIXME
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')
duration = request.GET.get('duration')
package = get_object_or_404(Package, duration=duration)
date_start = date_start and datetime.datetime.strptime(date_start, '%Y-%m-%d').date() or now().date()
date_start, date_end = Payment.get_date_range(date_start, months=1)
if not weekdays:
messages.error(request, 'Выберите несколько дней недели.')
return redirect('school:school')
try:
weekdays = [int(weekday) for weekday in weekdays]
except ValueError:
messages.error(request, 'Ошибка выбора дней недели.')
return redirect('school:school')
prev_school_payment = SchoolPayment.objects.filter(
amount_data = SchoolPayment.calc_amount(package=package, user=request.user, date_start=date_start)
school_payment = SchoolPayment.objects.create(
user=request.user,
date_start__lte=date_start,
date_end__gte=date_start,
add_days=False,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
).last()
add_days = bool(prev_school_payment)
if add_days:
school_payment = SchoolPayment.objects.create(
user=request.user,
weekdays=weekdays,
date_start=date_start,
date_end=prev_school_payment.date_end,
add_days=True,
roistat_visit=roistat_visit,
)
# Если произойдет ошибка и оплату бонусами повторят еще раз на те же дни, то вернет ошибку
if school_payment.amount <= 0:
messages.error(request, 'Выбранные дни отсутствуют в оставшемся периоде подписки')
return redirect(reverse_lazy('school:school'))
else:
school_payment = SchoolPayment.objects.create(
user=request.user,
weekdays=weekdays,
roistat_visit=roistat_visit,
date_start=date_start,
date_end=date_end,
)
weekdays=amount_data.get('weekdays'),
roistat_visit=roistat_visit,
date_start=amount_data.get('date_start'),
date_end=amount_data.get('date_end'),
package=package,
)
if use_bonuses and request.user.bonus:
if request.user.bonus >= school_payment.amount:
bonus = UserBonus.objects.create(amount= -school_payment.amount, user=request.user, payment=school_payment)
@ -184,7 +156,7 @@ class SchoolBuyView(TemplateView):
f'school_{school_payment.id}',
school_payment.amount,
'RUB',
'Школа',
'Подписка',
)
widget = Widget(
str(request.user.id),
@ -196,7 +168,7 @@ class SchoolBuyView(TemplateView):
'evaluation': 1,
'demo': 1,
'test_mode': 1,
'success_url': host + str(reverse_lazy('payment-success')),
'success_url': host + str(reverse_lazy('payment-success')) + '?duration=%s' % duration,
'failure_url': host + str(reverse_lazy('payment-error')),
}
)
@ -297,8 +269,6 @@ class PaymentwallCallbackView(View):
product_payment_class = DrawingCampPayment
elif product_type_name == 'gift_certificate':
product_payment_class = GiftCertificatePayment
elif product_type_name == 'package':
product_payment_class = PackagePayment
else:
return HttpResponse(status=403)
@ -365,16 +335,6 @@ class PaymentwallCallbackView(View):
'created_at': payment.created_at,
'update_at': payment.update_at,
}
elif product_type_name == 'package':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'date_start': payment.date_start,
'date_end': payment.date_end,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
payment.save()
@ -405,9 +365,6 @@ class PaymentwallCallbackView(View):
elif product_type_name != 'drawing_camp':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name, date_start=payment.date_start, date_end=payment.date_end)
elif product_type_name != 'package':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name, date_start=payment.date_start, date_end=payment.date_end)
author_balance = getattr(payment, 'author_balance', None)
if author_balance and author_balance.type == AuthorBalance.IN:
@ -503,46 +460,3 @@ class GiftCertificateGetView(TemplateView):
context = self.get_context_data(**kwargs)
return self.render_to_response(context)
@method_decorator(login_required, name='dispatch')
class PackagePaymentBuyView(TemplateView):
model = PackagePayment
template_name = 'payment/paymentwall_widget.html'
def get(self, request, pk, *args, **kwargs):
package = get_object_or_404(Package, pk=pk)
roistat_visit = request.COOKIES.get('roistat_visit', None)
pp = PackagePayment.objects.create(
user=request.user,
package=package,
roistat_visit=roistat_visit, )
context = self.get_context_data(**kwargs)
product = Product(
f'package_{pp.id}',
pp.amount,
'RUB',
'Пакет',
)
host = urlsplit(self.request.META.get('HTTP_REFERER'))
host = str(host[0]) + '://' + str(host[1])
widget = Widget(
str(request.user.id),
'p1_1',
[product],
extra_params={
'lang': 'ru',
'evaluation': 1,
'demo': 1,
'test_mode': 1,
'success_url': host + str(
reverse_lazy('package-payment-success', args=[pp.id])),
'failure_url': host + str(reverse_lazy('payment-error')),
}
)
context['widget'] = widget.get_html_code()
return self.render_to_response(context)
@method_decorator(login_required, name='dispatch')
class PackagePaymentBuySuccessView(TemplateView):
template_name = 'payment/package_payment_success.html'

@ -70,7 +70,7 @@ class DrawingCampLessonsView(ListView):
def get_queryset(self):
date_start = (now() - timedelta(days=7)).date()
date_start, date_end = DrawingCampPayment.ajust_date_bounds(date_start, date_start + timedelta(days=23), is_camp=True)
date_start, date_end = DrawingCampPayment.adjust_date_bounds(date_start, date_start + timedelta(days=23), is_camp=True)
date_range = Q(
date__range=[date_start, date_end]
)

@ -20,7 +20,6 @@
</div>
{% include "templates/blocks/footer.html" %}
{% include "templates/blocks/popup_auth.html" %}
{% include "templates/blocks/popup_school_buy.html" %}
{% if is_gift_certificate_url %}
{% include "templates/blocks/popup_gift_certificate.html" %}
{% endif %}

@ -1,13 +1,14 @@
{% extends "templates/lilcity/index.html" %}
{% load static %}
{% load ruplural from plural %}
{% load plural %}
{% block content %}
<div class="section">
<div class="section__center center">
<div class="packages">
{% for package in packages %}
<div class="package">
<div class="package"
{% if forloop.counter == 4 %}style="box-shadow: 0 10px 30px 0 rgba(241, 175, 50, 0.32);"{% endif %}>
<div class="package__title subtitle">
{% if package.duration == 12 %}
<b>1</b>&nbsp;год
@ -27,15 +28,31 @@
<div>{{ package.options_html|safe }}</div>
</div>
<div>
<a href="#" class="package__btn btn {% if forloop.counter == 2 %}btn_light{% endif %}"
<a class="package__btn btn {% if forloop.counter == 2 %}btn_light{% endif %}
{% if school_months_left < package.duration %}btn_disabled{% endif %}"
{% if forloop.counter == 1 %}
style="background-image: linear-gradient(104deg, #f8f8f8, #fff2f2)"
{% endif %}
{% if forloop.counter == 4 %}
style="background-image: linear-gradient(to bottom, #ffe790, #f9d055 45%, #f9c155); padding: 12px 9px;"
{% endif %}
{% if school_months_left >= package.duration %}
{% if user.is_authenticated %}
href="{% url 'school-checkout' %}?duration={{ package.duration }}"
{% else %}
href="#" data-popup=".js-popup-auth"
{% endif %}
{% else %}href="#"{% endif %}
>{% if forloop.counter == 4 %}Вступить в Lil-Клуб{% else %}Купить{% endif %}</a>
</div>
{% if next_buy_date %}
<div style="font-size: 12px; margin-top: 10px; height: 15px;">
{% if school_months_left >= package.duration %}
на {{ package.duration|rupluralize:"месяц,месяца,месяцев" }} с {{ next_buy_date|date:'j b' }}
{% endif %}
</div>
{% endif %}
</div>
{% endfor %}
<div class="mobile-show">&nbsp;</div>
@ -52,9 +69,12 @@
Приглашайте друзей и знакомых на платформу и получайте 30% от суммы их первой покупки.<br>
Просто отправьте специальную ссылку, по которой ваши друзья могут присоединиться к нам.
</p>
<p><a href="#">Узнать больше о том, как зарабатывать вместе с Lil School</a></p>
{% if user.is_authenticated %}
<p><a href="{% url 'user-bonuses' %}">Узнать больше о том, как зарабатывать вместе с Lil School</a></p>
{% endif %}
<p style="text-align: center; margin: 35px 0;">
<a href="#" class="btn btn_white btn_shadow">Получить бесплатный урок 🎁</a>
<a href="#" class="btn btn_white btn_shadow js-video-modal"
data-video-url="{{ config.MAIN_PAGE_VIDEO_URL|safe }}" data-trial-lesson="1">Получить бесплатный урок 🎁</a>
</p>
<p></p>
</div>

@ -35,8 +35,7 @@ from apps.payment.views import (
CourseBuySuccessView, CourseBuyView,
PaymentwallCallbackView, SchoolBuySuccessView,
SchoolBuyView, GiftCertificatesView, GiftCertificateBuyView,
GiftCertificateBuySuccessView, GiftCertificateGetView, DrawingCampBuyView, PackagePaymentBuySuccessView,
PackagePaymentBuyView)
GiftCertificateBuySuccessView, GiftCertificateGetView, DrawingCampBuyView)
from .views import AboutView, IndexView, SchoolSchedulesView, LinksView, PackagesView
@ -105,9 +104,6 @@ urlpatterns = [
path('faq', FAQView.as_view(), name='faq'),
path('links', LinksView.as_view(), name='links'),
path('packages', PackagesView.as_view(), name='packages'),
path('package/<int:pk>/checkout', PackagePaymentBuyView.as_view(), name='package-checkout'),
path('payments/package/success', PackagePaymentBuySuccessView.as_view(),
name='package-payment-success'),
]

@ -1,4 +1,4 @@
from datetime import datetime, timedelta
from datetime import datetime, timedelta, date
from random import shuffle
import short_url
@ -151,4 +151,23 @@ class PackagesView(TemplateView):
context = super().get_context_data()
context['packages'] = Package.objects.all()[:4]
context['banners'] = Banner.get_for_page(Banner.PAGE_PACKAGES)[:1]
last_school_payment = None
school_end = date(now().year, 5, 31)
today = now().date()
if self.request.user.is_authenticated:
last_school_payment = SchoolPayment.objects.filter(
user=self.request.user,
date_end__gte=today,
status__in=Payment.PW_PAID_STATUSES,
).last()
context['last_school_payment'] = last_school_payment
if last_school_payment:
context['next_buy_date'] = last_school_payment.date_end + timedelta(1)
context['school_months_left'] = (school_end.month - last_school_payment.date_end.month
if last_school_payment.date_end.month < school_end.month
else (school_end.month + 12) - last_school_payment.date_end.month) + 1
else:
context['school_months_left'] = (school_end.month - today.month
if today.month < school_end.month
else (school_end.month + 12) - today.month) + 1
return context

@ -218,6 +218,12 @@ button
color: $cl
&_pink-blue
background-image: linear-gradient(100deg, #8febff, #ffa2cb)
&_disabled
opacity: 0.5
cursor: default
&:hover,
&:active
color: $cl
&_shadow
border-radius: 10px
box-shadow: 0 10px 20px 0 rgba(0, 0, 0, 0.05), 0 9px 24px 0 rgba(33, 74, 211, 0.1)

Loading…
Cancel
Save