diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index 5b651689..20266fe1 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -34,7 +34,8 @@ {% if user.is_authenticated %} {% if not pending %} data-course-buy - href="{% url 'course-checkout' course.id %}" + data-popup=".js-popup-course-buy" + href="#" {% endif %} {% else %} data-popup=".js-popup-auth" diff --git a/apps/payment/models.py b/apps/payment/models.py index 90478c98..0d406323 100644 --- a/apps/payment/models.py +++ b/apps/payment/models.py @@ -134,9 +134,6 @@ class Payment(PolymorphicModel): discount = 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 if isinstance(payment, CoursePayment): course = payment.course user = payment.user @@ -144,6 +141,9 @@ class Payment(PolymorphicModel): user = payment.user weekdays = payment.weekdays date_start = payment.date_start + if hasattr(user, 'referral') and not user.referral.payment: + referral_bonus = user.referral.bonus + referrer_bonus = user.referral.referrer_bonus if payment and payment.is_paid(): price = payment.amount elif course: @@ -226,17 +226,15 @@ class Payment(PolymorphicModel): ] 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) if self.status is None and not self.bonus: 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: + if isinstance(self, CoursePayment) and self.is_paid(): author_balance = getattr(self, 'authorbalance', None) - if not author_balance : + if not author_balance: AuthorBalance.objects.create( author=self.course.author, amount=self.amount, @@ -246,7 +244,7 @@ class Payment(PolymorphicModel): author_balance.amount = self.amount author_balance.save() # Если юзер реферал и нет платежа, где применялась скидка - if hasattr(self.user, 'referral') and not self.user.referral.payment and paid: + if hasattr(self.user, 'referral') and not self.user.referral.payment and self.is_paid(): # Платеж - как сигнал, что скидка применилась self.user.referral.payment = self self.user.referral.save() diff --git a/apps/payment/views.py b/apps/payment/views.py index 5663df39..6be7734f 100644 --- a/apps/payment/views.py +++ b/apps/payment/views.py @@ -58,6 +58,7 @@ class CourseBuyView(TemplateView): template_name = 'payment/paymentwall_widget.html' def get(self, request, pk=None, *args, **kwargs): + use_bonuses = request.GET.get('use_bonuses') host = urlsplit(self.request.META.get('HTTP_REFERER')) host = str(host[0]) + '://' + str(host[1]) course = Course.objects.get(id=pk) @@ -70,9 +71,22 @@ class CourseBuyView(TemplateView): course=course, roistat_visit=roistat_visit, ) + if use_bonuses: + if request.user.bonus >= course_payment.amount: + bonus = UserBonus.objects.create(amount= -course_payment.amount, user=request.user, payment=course_payment) + course_payment.amount = 0 + course_payment.status = Pingback.PINGBACK_TYPE_REGULAR + else: + bonus = UserBonus.objects.create(amount= -request.user.bonus, user=request.user, + payment=course_payment) + course_payment.amount -= request.user.bonus + course_payment.bonus = bonus + course_payment.save() + if course_payment.is_paid(): + return redirect(reverse_lazy('course_payment_success', args=[course.id])) product = Product( f'course_{course_payment.id}', - course.price, + course_payment.amount, 'RUB', f'Курс "{course.title}"', ) @@ -156,7 +170,7 @@ class SchoolBuyView(TemplateView): school_payment.amount -= request.user.bonus school_payment.bonus = bonus school_payment.save() - if school_payment.status == Pingback.PINGBACK_TYPE_REGULAR: + if school_payment.is_paid(): return redirect(reverse_lazy('payment-success')) product = Product( f'school_{school_payment.id}', diff --git a/apps/school/templates/blocks/schedule.html b/apps/school/templates/blocks/schedule.html index ab97055f..15b129fb 100644 --- a/apps/school/templates/blocks/schedule.html +++ b/apps/school/templates/blocks/schedule.html @@ -5,7 +5,7 @@
Расписание
- {% for school_schedule in school_schedules %} + {% for school_schedule in school_schedules_sorted %} {% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson purchased=True %} {% endfor %}
diff --git a/apps/school/templates/summer/schedule_purchased.html b/apps/school/templates/summer/schedule_purchased.html index a2106299..3f722678 100644 --- a/apps/school/templates/summer/schedule_purchased.html +++ b/apps/school/templates/summer/schedule_purchased.html @@ -42,7 +42,7 @@ {% endif %} {% endfor %} {% else %} - {% for school_schedule in school_schedules %} + {% for school_schedule in school_schedules_sorted %} {% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson purchased=True %} {% endfor %} {% endif %} diff --git a/apps/school/views.py b/apps/school/views.py index bdb3a848..5729f04c 100644 --- a/apps/school/views.py +++ b/apps/school/views.py @@ -128,7 +128,7 @@ class SchoolView(TemplateView): school_schedules = SchoolSchedule.objects.all() try: - school_schedules = sorted(school_schedules, key=lambda ss: ss.current_live_lesson and ss.current_live_lesson.date) + school_schedules_sorted = sorted(school_schedules, key=lambda ss: ss.current_live_lesson and ss.current_live_lesson.date) except Exception: pass school_schedules_dict = {ss.weekday: ss for ss in school_schedules} @@ -190,6 +190,7 @@ class SchoolView(TemplateView): 'is_purchased': school_payment_exists, 'is_purchased_future': False, 'min_school_price': SchoolSchedule.objects.aggregate(Min('month_price'))['month_price__min'], + 'school_schedules_sorted': school_schedules_sorted, 'school_schedules': school_schedules, 'school_schedules_purchased': school_schedules_purchased, 'school_purchased_future': False, diff --git a/apps/user/models.py b/apps/user/models.py index 84d9a329..3f41a016 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -102,10 +102,11 @@ class User(AbstractUser): @cached_property def balance(self): + from apps.payment.models import Payment income = self.balances.filter( type=0, payment__isnull=False, - payment__status__isnull=False + payment__status__in=Payment.PW_PAID_STATUSES, ).aggregate( models.Sum('amount'), models.Sum('commission'), @@ -120,7 +121,11 @@ class User(AbstractUser): @cached_property def bonus(self): - return int(self.bonuses.aggregate(models.Sum('amount')).get('amount__sum') or 0) + from apps.payment.models import Payment + return int(self.bonuses.filter( + payment__isnull=False, + payment__status__in=Payment.PW_PAID_STATUSES, + ).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 d4f32bcb..cfddee9d 100644 --- a/apps/user/templates/user/bonus-history.html +++ b/apps/user/templates/user/bonus-history.html @@ -17,7 +17,7 @@ вы получите {{ config.REFERRER_BONUS }}%, а они {{ config.REFERRAL_BONUS }}% {% endif %} от суммы их первой покупки на бонусный счет. Приглашайте друзей, накапливайте бонусные баллы, тратьте бонусы - на приобретения доступа к школе и курсам. Оплата услуг возможна только, если вы накопили баллов на стоимость услуги. + на приобретения доступа к школе и курсам.
Просто отправьте им эту ссылку, по которой они смогут зарегистрироваться:
diff --git a/apps/user/views.py b/apps/user/views.py index 6f54861d..3b18c952 100644 --- a/apps/user/views.py +++ b/apps/user/views.py @@ -23,7 +23,7 @@ from apps.auth.tokens import verification_email_token from apps.course.models import Course from apps.notification.utils import send_email from apps.school.models import SchoolSchedule -from apps.payment.models import AuthorBalance, CoursePayment, SchoolPayment +from apps.payment.models import AuthorBalance, CoursePayment, SchoolPayment, Payment from apps.user.models import AuthorRequest, EmailSubscription, SubscriptionCategory from .forms import AuthorRequesForm, UserEditForm, WithdrawalForm @@ -300,7 +300,10 @@ class BonusHistoryView(TemplateView): def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) - context['bonuses'] = request.user.bonuses.all() + context['bonuses'] = request.user.bonuses.filter( + payment__isnull=False, + payment__status__in=Payment.PW_PAID_STATUSES, + ) context['referrer_url'] = '%s%s?referrer=%s' % ( settings.MAIN_HOST, reverse('index'), short_url.encode_url(request.user.id) ) diff --git a/project/templates/blocks/popup_course_buy.html b/project/templates/blocks/popup_course_buy.html new file mode 100644 index 00000000..1ce320ca --- /dev/null +++ b/project/templates/blocks/popup_course_buy.html @@ -0,0 +1,49 @@ +{% load static %} + + diff --git a/project/templates/blocks/popup_buy.html b/project/templates/blocks/popup_school_buy.html similarity index 98% rename from project/templates/blocks/popup_buy.html rename to project/templates/blocks/popup_school_buy.html index 093b19ac..7178b415 100644 --- a/project/templates/blocks/popup_buy.html +++ b/project/templates/blocks/popup_school_buy.html @@ -11,7 +11,7 @@
-
Выбор курса/дня
+
Выбор дня
diff --git a/project/templates/lilcity/index.html b/project/templates/lilcity/index.html index 7b8204a0..fbf876b3 100644 --- a/project/templates/lilcity/index.html +++ b/project/templates/lilcity/index.html @@ -146,7 +146,10 @@
{% include "templates/blocks/footer.html" %} {% include "templates/blocks/popup_auth.html" %} - {% include "templates/blocks/popup_buy.html" %} + {% include "templates/blocks/popup_school_buy.html" %} + {% if course %} + {% include "templates/blocks/popup_course_buy.html" %} + {% endif %} {% include "templates/blocks/popup_course_lock.html" %} {% include "templates/blocks/popup_subscribe.html" %}
diff --git a/project/urls.py b/project/urls.py index cf0a3c0c..38773131 100644 --- a/project/urls.py +++ b/project/urls.py @@ -39,6 +39,7 @@ from apps.payment.views import ( from .views import AboutView, IndexView, SchoolSchedulesView +# TODO trim slash in the end urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include(('apps.auth.urls', 'lilcity'))), diff --git a/web/src/js/modules/popup.js b/web/src/js/modules/popup.js index adfa7510..b7fe9789 100644 --- a/web/src/js/modules/popup.js +++ b/web/src/js/modules/popup.js @@ -87,10 +87,47 @@ $(document).ready(function () { }); } } + popup.on('change', '[data-day]', function(){ + updateCart(); + }); + + popup.on('change', '[data-bonuses]', function(){ + updateCart(); + }); updateCart(); } + if(data === '.js-popup-course-buy'){ + const updateCourseCart = () => { + var $orderPrice = popup.find('.order_price_text'); + var useBonuses = $bonusesCheckbox.prop('checked'); + var amount = useBonuses ? coursePrice - bonusesCount : coursePrice; + + $orderPrice.html(amount !== coursePrice ? `${coursePrice} ${amount}р.` : `${amount}р.`); + $buyBtn.attr('href', link + '?' + decodeURIComponent($.param({ + use_bonuses: useBonuses || '' + }))); + } + var $buyBtn = popup.find('.but_btn_popup'); + var link = $buyBtn.data('link'); + var coursePrice = +$buyBtn.data('price').replace(',', '.'); + var $bonuses = popup.find('.buy__bonuses'); + var $bonusesCount = popup.find('.buy__bonuses-count'); + var $bonusesCheckbox = popup.find('[data-bonuses]'); + var bonuses = +$bonusesCheckbox.data('bonuses'); + var bonusesCount = bonuses > coursePrice ? coursePrice : bonuses; + + $bonuses.hide(); + if(bonuses){ + $bonusesCount.text(rupluralize(bonusesCount, ['бонус', 'бонуса', 'бонусов'])); + $bonuses.show(); + } + + popup.on('change', '[data-bonuses]', updateCourseCart); + updateCourseCart(); + } + if( data === '.js-popup-auth') { let nextUrl = $this.data('auth-next-url'); if(nextUrl === 'href') { @@ -146,26 +183,18 @@ $(document).ready(function () { }); } - $(document).on('change', '[data-day]', function(){ - updateCart(); - }); - - $(document).on('change', '[data-bonuses]', function(){ - updateCart(); - }); - function updateCart(){ - var link = $('.but_btn_popup').data('link'); - var $order = $('.order'); - var $orderPrice = $('.order_price_text'); - var $orderDates = $('.order__dates'); + var link = popup.find('.but_btn_popup').data('link'); + var $order = popup.find('.order'); + var $orderPrice = popup.find('.order_price_text'); + var $orderDates = popup.find('.order__dates'); var dateStart = popup.data('date-start'); var days = ['', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье']; var weekdays = []; var daysText = []; - var $bonuses = $('.buy__bonuses'); - var $bonusesCheckbox = $('[data-bonuses]'); - var $bonusesCount = $('.buy__bonuses-count'); + var $bonuses = popup.find('.buy__bonuses'); + var $bonusesCheckbox = popup.find('[data-bonuses]'); + var $bonusesCount = popup.find('.buy__bonuses-count'); var useBonuses = $bonusesCheckbox.prop('checked'); var bonuses = +$bonusesCheckbox.data('bonuses'); $('[data-day]').each(function() { diff --git a/web/src/sass/_common.sass b/web/src/sass/_common.sass index afe6fd2c..a585dbb8 100755 --- a/web/src/sass/_common.sass +++ b/web/src/sass/_common.sass @@ -3055,6 +3055,8 @@ a.grey-link right: 0; padding: 0; top: 9px; + &__bonuses + margin-top: 10px .order padding: 2px