Уведомление об окончании доступа к курсу

remotes/origin/feature/course-access-expire-notification
gzbender 6 years ago
parent a8123347ad
commit 627a7bed98
  1. 566
      apps/payment/views.py

@ -14,7 +14,7 @@ from django.http import HttpResponse, Http404
from django.shortcuts import redirect, get_object_or_404
from django.views.generic import View, TemplateView
from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse_lazy
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.timezone import now
@ -35,146 +35,129 @@ class DisallowedPingbackHost(Exception):
pass
@method_decorator(login_required, name='dispatch')
class CourseBuySuccessView(TemplateView):
template_name = 'payment/course_payment_success.html'
def get(self, request, pk=None, *args, **kwargs):
course = get_object_or_404(Course, pk=pk)
return self.render_to_response(context={'course': course})
@method_decorator(login_required, name='dispatch')
class SchoolBuySuccessView(TemplateView):
template_name = 'payment/payment_success.html'
def get(self, request, pk=None, is_camp=False, *args, **kwargs):
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')
class CourseBuyView(TemplateView):
class BuyMixin(object):
template_name = 'payment/pay.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)
def get(self, request, *args, **kwargs):
roistat_visit = request.COOKIES.get('roistat_visit', None)
if request.user == course.author:
messages.error(request, 'Вы не можете приобрести свой курс.')
return redirect(reverse_lazy('course', args=[course.id]))
prev_payment = CoursePayment.objects.filter(user=request.user, course=course,
status__in=Payment.PW_PAID_STATUSES).order_by('-access_expire').first()
access_duration = course.access_duration or 90
access_expire = prev_payment.access_expire + timedelta(days=access_duration) if prev_payment \
else now().date() + timedelta(days=access_duration - 1)
course_payment = CoursePayment.objects.create(
user=request.user,
course=course,
access_expire=access_expire,
roistat_visit=roistat_visit,
)
if use_bonuses and request.user.bonus:
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_payment.amount,
'RUB',
f'Курс "{course.title}"',
)
widget = Widget(
str(request.user.id),
'p1_1',
[product],
extra_params={
'email': request.user.email,
'lang': 'ru',
'evaluation': 1,
'demo': 1,
'test_mode': 1,
'success_url': host + str(reverse_lazy('course_payment_success', args=[course.id])),
'failure_url': host + str(reverse_lazy('payment-error')),
}
)
attrs = {}
if request.user_agent.is_mobile:
attrs['width'] = '100%'
attrs['height'] = '600'
return self.render_to_response(context={'widget': widget.get_html_code(attrs)})
use_bonuses = request.GET.get('use_bonuses')
product_name = ''
context = self.get_context_data(**kwargs)
payment = None
@method_decorator(login_required, name='dispatch')
class SchoolBuyView(TemplateView):
template_name = 'payment/pay.html'
if self.product_type == 'gift_certificate':
gift_certificate = get_object_or_404(GiftCertificate, pk=kwargs.get('pk'))
def get(self, request, *args, **kwargs):
host = urlsplit(self.request.META.get('HTTP_REFERER'))
host = str(host[0]) + '://' + str(host[1])
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')
payment_id = request.GET.get('payment_id')
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()
prev_payment = SchoolPayment.objects.paid().filter(
payment = GiftCertificatePayment.objects.create(
user=request.user,
gift_certificate=gift_certificate,
roistat_visit=roistat_visit, )
success_url = reverse('gift-certificate-payment-success', args=[payment.id])
product_name = 'Подарочный сертификат'
if self.product_type == 'course':
course = Course.objects.get(id=kwargs.get('pk'))
if request.user == course.author:
messages.error(request, 'Вы не можете приобрести свой курс.')
return redirect(reverse('course', args=[course.id]))
prev_payment = CoursePayment.objects.filter(user=request.user, course=course,
status__in=Payment.PW_PAID_STATUSES).order_by(
'-access_expire').first()
access_duration = course.access_duration or 90
access_expire = prev_payment.access_expire + timedelta(days=access_duration) if prev_payment \
else now().date() + timedelta(days=access_duration - 1)
payment = CoursePayment.objects.create(
user=request.user,
course=course,
access_expire=access_expire,
roistat_visit=roistat_visit,
)
success_url = reverse('course_payment_success', args=[course.id])
product_name = f'Курс "{course.title}"'
context['course'] = course
if self.product_type == 'school':
date_start = request.GET.get('date_start')
duration = request.GET.get('duration')
payment_id = request.GET.get('payment_id')
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()
prev_payment = SchoolPayment.objects.paid().filter(
user=self.request.user,
date_end__gte=now().date(),).last()
if prev_payment and prev_payment.date_end > date_start:
date_start = prev_payment.date_end + timedelta(1)
if payment_id:
school_payment = get_object_or_404(SchoolPayment, id=payment_id)
else:
amount_data = SchoolPayment.calc_amount(package=package, user=request.user, date_start=date_start)
school_payment = SchoolPayment.objects.create(
date_end__gte=now().date(), ).last()
if prev_payment and prev_payment.date_end > date_start:
date_start = prev_payment.date_end + timedelta(1)
if payment_id:
payment = get_object_or_404(SchoolPayment, id=payment_id)
else:
amount_data = SchoolPayment.calc_amount(package=package, user=request.user, date_start=date_start)
payment = SchoolPayment.objects.create(
user=request.user,
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 payment_id and payment.bonus and not use_bonuses:
bonus = payment.bonus
payment.amount += payment.bonus
payment.bonus = None
bonus.delete()
success_url = '%s?duration=%s' % (reverse('payment-success'), duration)
product_name = 'Подписка'
context['school'] = True
if self.product_type == 'drawing_camp':
date_start = request.GET.get('date_start')
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, is_camp=True)
prev_payment = DrawingCampPayment.objects.filter(
user=request.user,
date_start__lte=date_start,
date_end__gte=date_start,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
).exists()
if prev_payment:
return HttpResponse(status=403)
payment = DrawingCampPayment.objects.create(
user=request.user,
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,
date_start=date_start,
date_end=date_end,
)
success_url = reverse('camp-payment-success')
product_name = 'Подписка'
context['camp'] = True
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)
school_payment.amount = 0
school_payment.status = Pingback.PINGBACK_TYPE_REGULAR
if request.user.bonus >= payment.amount:
bonus = UserBonus.objects.create(amount=-payment.amount, user=request.user, payment=payment)
payment.amount = 0
payment.status = Pingback.PINGBACK_TYPE_REGULAR
else:
school_payment.amount -= request.user.bonus
bonus = UserBonus.objects.create(amount= -request.user.bonus, user=request.user,
payment=school_payment)
school_payment.bonus = bonus
school_payment.save()
if school_payment.is_paid():
return redirect('%s?duration=%s' % (str(reverse_lazy('payment-success')), duration))
if payment_id and school_payment.bonus and not use_bonuses:
bonus = school_payment.bonus
school_payment.amount += school_payment.bonus
school_payment.bonus = None
bonus.delete()
bonus = UserBonus.objects.create(amount=-request.user.bonus, user=request.user,
payment=payment)
payment.amount -= request.user.bonus
payment.bonus = bonus
payment.save()
if payment.is_paid():
self.after_buy(payment)
return redirect(success_url)
product = Product(
f'school_{school_payment.id}',
school_payment.amount,
f'course_{payment.id}',
payment.amount,
'RUB',
'Подписка',
product_name,
)
widget = Widget(
str(request.user.id),
@ -186,8 +169,8 @@ class SchoolBuyView(TemplateView):
'evaluation': 1,
'demo': 1,
'test_mode': 1,
'success_url': host + str(reverse_lazy('payment-success')) + '?duration=%s' % duration,
'failure_url': host + str(reverse_lazy('payment-error')),
'success_url': request.build_absolute_uri(success_url),
'failure_url': request.build_absolute_uri(reverse('payment-error')),
}
)
if self.request.is_ajax():
@ -196,86 +179,143 @@ class SchoolBuyView(TemplateView):
if request.user_agent.is_mobile:
attrs['width'] = '100%'
attrs['height'] = '600'
return self.render_to_response(context={
'widget': widget.get_html_code(attrs),
'school': True,
'payment': school_payment,
})
context['widget'] = widget.get_html_code(attrs)
return self.render_to_response(context)
def after_buy(self, payment):
product_type_name = None
if isinstance(payment, CoursePayment):
product_type_name == 'course'
elif isinstance(payment, SchoolPayment):
product_type_name == 'school'
elif isinstance(payment, DrawingCampPayment):
product_type_name == 'drawing_camp'
elif isinstance(payment, GiftCertificatePayment):
product_type_name == 'gift_certificate'
if product_type_name == 'course':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'course': payment.course.id,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
elif product_type_name == 'school':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'weekdays': payment.weekdays,
'add_days': payment.add_days,
'date_start': payment.date_start,
'date_end': payment.date_end,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
elif product_type_name == 'drawing_camp':
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,
}
elif product_type_name == 'gift_certificate':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'gift_certificate': payment.gift_certificate.id,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
@method_decorator(login_required, name='dispatch')
class DrawingCampBuyView(TemplateView):
template_name = 'payment/pay.html'
product_payment_to_mixpanel.delay(
payment.user.id,
f'{product_type_name.title()} payment',
now().strftime('%Y-%m-%dT%H:%M:%S'),
properties,
)
def get(self, request, *args, **kwargs):
host = urlsplit(self.request.META.get('HTTP_REFERER'))
host = str(host[0]) + '://' + str(host[1])
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').date() or now().date()
date_start, date_end = Payment.get_date_range(date_start, months=1, is_camp=True)
prev_payment = DrawingCampPayment.objects.filter(
user=request.user,
date_start__lte=date_start,
date_end__gte=date_start,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
).exists()
if prev_payment:
return HttpResponse(status=403)
camp_payment = DrawingCampPayment.objects.create(
user=request.user,
roistat_visit=roistat_visit,
date_start=date_start,
date_end=date_end,
transaction_to_roistat.delay(
payment.user.id,
payment.id,
f'{product_type_name.title()} payment',
payment.amount,
datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
payment.status,
product_type_name,
payment.roistat_visit,
)
if use_bonuses and request.user.bonus:
if request.user.bonus >= camp_payment.amount:
bonus = UserBonus.objects.create(amount=-camp_payment.amount, user=request.user,
payment=camp_payment)
camp_payment.amount = 0
camp_payment.status = Pingback.PINGBACK_TYPE_REGULAR
if product_type_name == 'course':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name, url=payment.course.url,
username=payment.user.get_full_name(), course_title=payment.course.title,
access_duration=payment.access_duration)
elif product_type_name != 'school':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name)
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)
author_balance = getattr(payment, 'author_balance', None)
if author_balance and author_balance.type == AuthorBalance.IN:
if payment.is_deliverable():
payment.author_balance.status = AuthorBalance.ACCEPTED
elif payment.is_under_review():
payment.author_balance.status = AuthorBalance.PENDING
else:
bonus = UserBonus.objects.create(amount=-request.user.bonus, user=request.user,
payment=camp_payment)
camp_payment.amount -= request.user.bonus
camp_payment.bonus = bonus
camp_payment.save()
if camp_payment.is_paid():
return redirect(reverse_lazy('camp-payment-success'))
product = Product(
f'drawing_camp_{camp_payment.id}',
camp_payment.amount,
'RUB',
'Школа',
)
widget = Widget(
str(request.user.id),
'p1_1',
[product],
extra_params={
'email': request.user.email,
'lang': 'ru',
'evaluation': 1,
'demo': 1,
'test_mode': 1,
'success_url': host + str(reverse_lazy('camp-payment-success')),
'failure_url': host + str(reverse_lazy('payment-error')),
}
)
attrs = {}
if request.user_agent.is_mobile:
attrs['width'] = '100%'
attrs['height'] = '600'
return self.render_to_response(context={'widget': widget.get_html_code(attrs)})
payment.author_balance.status = AuthorBalance.DECLINED
payment.author_balance.save()
@method_decorator(login_required, name='dispatch')
class CourseBuySuccessView(TemplateView):
template_name = 'payment/course_payment_success.html'
def get(self, request, pk=None, *args, **kwargs):
course = get_object_or_404(Course, pk=pk)
return self.render_to_response(context={'course': course})
@method_decorator(login_required, name='dispatch')
class SchoolBuySuccessView(TemplateView):
template_name = 'payment/payment_success.html'
def get(self, request, pk=None, is_camp=False, *args, **kwargs):
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')
class CourseBuyView(BuyMixin, TemplateView):
template_name = 'payment/pay.html'
product_type = 'course'
@method_decorator(login_required, name='dispatch')
class SchoolBuyView(BuyMixin, TemplateView):
template_name = 'payment/pay.html'
product_type = 'school'
@method_decorator(login_required, name='dispatch')
class DrawingCampBuyView(BuyMixin, TemplateView):
template_name = 'payment/pay.html'
product_type = 'drawing_camp'
@method_decorator(csrf_exempt, name='dispatch')
class PaymentwallCallbackView(View):
class PaymentwallCallbackView(BuyMixin, View):
def get_request_ip(self):
x_forwarded_for = self.request.META.get('HTTP_X_FORWARDED_FOR')
@ -327,88 +367,8 @@ class PaymentwallCallbackView(View):
product_type_name,
)
if product_type_name == 'course':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'course': payment.course.id,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
elif product_type_name == 'school':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'weekdays': payment.weekdays,
'add_days': payment.add_days,
'date_start': payment.date_start,
'date_end': payment.date_end,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
elif product_type_name == 'drawing_camp':
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,
}
elif product_type_name == 'gift_certificate':
properties = {
'payment_id': payment.id,
'amount': payment.amount,
'status': payment.status,
'gift_certificate': payment.gift_certificate.id,
'created_at': payment.created_at,
'update_at': payment.update_at,
}
self.after_buy(payment)
payment.save()
product_payment_to_mixpanel.delay(
payment.user.id,
f'{product_type_name.title()} payment',
now().strftime('%Y-%m-%dT%H:%M:%S'),
properties,
)
transaction_to_roistat.delay(
payment.user.id,
payment.id,
f'{product_type_name.title()} payment',
payment.amount,
datetime.datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'),
pingback.get_type(),
product_type_name,
payment.roistat_visit,
)
if product_type_name == 'course':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name, url=payment.course.url,
username=payment.user.get_full_name(), course_title=payment.course.title,
access_duration=payment.access_duration)
elif product_type_name != 'school':
send_email.delay('Спасибо за покупку!', payment.user.email, 'notification/email/buy_email.html',
product_type=product_type_name)
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)
author_balance = getattr(payment, 'author_balance', None)
if author_balance and author_balance.type == AuthorBalance.IN:
if pingback.is_deliverable():
payment.author_balance.status = AuthorBalance.ACCEPTED
elif pingback.is_under_review():
payment.author_balance.status = AuthorBalance.PENDING
else:
payment.author_balance.status = AuthorBalance.DECLINED
payment.author_balance.save()
return HttpResponse('OK')
else:
raise DisallowedPingbackHost
@ -427,45 +387,9 @@ class GiftCertificatesView(TemplateView):
@method_decorator(login_required, name='dispatch')
class GiftCertificateBuyView(TemplateView):
class GiftCertificateBuyView(BuyMixin, TemplateView):
model = GiftCertificate
template_name = 'payment/pay.html'
def get(self, request, pk, *args, **kwargs):
gift_certificate = get_object_or_404(GiftCertificate, pk=pk)
roistat_visit = request.COOKIES.get('roistat_visit', None)
gift_certificate_payment = GiftCertificatePayment.objects.create(
user=request.user,
gift_certificate=gift_certificate,
roistat_visit=roistat_visit,)
context = self.get_context_data(**kwargs)
product = Product(
f'gift_certificate_{gift_certificate_payment.id}',
gift_certificate_payment.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('gift-certificate-payment-success', args=[gift_certificate_payment.id])),
'failure_url': host + str(reverse_lazy('payment-error')),
}
)
attrs = {}
if request.user_agent.is_mobile:
attrs['width'] = '100%'
attrs['height'] = '600'
context['widget'] = widget.get_html_code(attrs)
return self.render_to_response(context)
product_type = 'gift_certificate'
@method_decorator(login_required, name='dispatch')

Loading…
Cancel
Save