You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

301 lines
12 KiB

import arrow
from io import BytesIO
from PIL import Image
from uuid import uuid4
from os.path import splitext
from datetime import timedelta
from paymentwall import Pingback
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.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.db.models import F, Func
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.timezone import now
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.user.models import AuthorRequest, EmailSubscription, SubscriptionCategory
from .forms import AuthorRequesForm, UserEditForm, WithdrawalForm
User = get_user_model()
@login_required
def resend_email_verify(request):
token = verification_email_token.make_token(request.user)
url = request.scheme + '://' + request.get_host() + str(reverse_lazy('lilcity:verification-email', args=[token, request.user.id]))
send_email('Вы успешно прошли регистрацию', request.user.email, "notification/email/verification_email.html", url=url)
messages.info(request, 'Письмо подтверждения отправлено.')
return redirect('user-edit-profile')
@method_decorator(login_required, name='dispatch')
class ProfileView(TemplateView):
model = User
template_name = 'user/profile.html'
def get(self, request, *args, **kwargs):
self.object = self.request.user
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, object):
context = super().get_context_data()
context['user'] = self.request.user
context['is_author'] = self.request.user.role == User.AUTHOR_ROLE
context['published'] = Course.objects.filter(
author=self.object,
)
context['paid'] = Course.objects.filter(
payments__in=CoursePayment.objects.filter(
user=self.object,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
),
).distinct()
school_payment = SchoolPayment.objects.filter(
user=self.object,
date_start__lte=now(),
date_end__gt=now(),
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
)
school_schedules_purchased = school_payment.annotate(
joined_weekdays=Func(F('weekdays'), function='unnest',)
).values_list('joined_weekdays', flat=True).distinct()
context['school_schedules_purchased'] = school_schedules_purchased
context['school_payment'] = school_payment
context['is_purchased'] = school_payment.exists()
context['profile'] = True
if school_payment.exists() and school_payment.last().date_end:
context['subscription_ends'] = school_payment.last().date_end
context['school_schedules'] = SchoolSchedule.objects.filter(
weekday__in=school_schedules_purchased if school_payment.exists() else [],
).all()
context['all_school_schedules'] = SchoolSchedule.objects.all()
school_payment_future = SchoolPayment.objects.filter(
user=self.object,
date_start__gte=now(),
date_end__gte=now()
)
context['is_purchased_future'] = school_payment_future.exists()
context['school_purchased_future'] = school_payment_future.last()
return context
class UserView(DetailView):
model = User
template_name = 'user/author_profile.html'
def get_context_data(self, object):
context = super().get_context_data()
context['published'] = Course.objects.filter(
author=self.object,
)
return context
class SubscribeView(View):
def post(self, request, pk=None, **kwargs):
refferer = request.META.get('HTTP_REFERER')
if request.user.is_authenticated:
messages.info(request, 'Вы уже подписаны на рассылки.')
return redirect(refferer)
email = request.POST.get('email', None)
if email:
if EmailSubscription.objects.filter(email=email).exists():
messages.error(request, 'Вы уже подписаны!')
return redirect(refferer)
email_subscription = EmailSubscription.objects.create(
email=email,
)
email_subscription.categories.set(
SubscriptionCategory.objects.filter(auto_add=True)
)
messages.info(request, 'Вы подписаны на новости.')
return redirect('subscribe-success')
else:
messages.error(request, 'Введите адрес электронной почты.')
return redirect(refferer)
@method_decorator(login_required, name='dispatch')
class NotificationEditView(TemplateView):
template_name = 'user/notification-settings.html'
def get(self, request, pk=None):
return super().get(request)
def post(self, request, pk=None):
categories = request.POST.getlist('category', [])
request.user.email_subscription.categories.set(
SubscriptionCategory.objects.filter(id__in=categories)
)
return redirect('user-edit-notifications', request.user.id)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['subscription_categories'] = SubscriptionCategory.objects.all()
return context
@method_decorator(login_required, name='dispatch')
class PaymentHistoryView(FormView):
template_name = 'user/payment-history.html'
form_class = WithdrawalForm
def get(self, request, pk=None):
return super().get(request)
def post(self, request, pk=None):
form = self.get_form()
if not settings.DEBUG and AuthorBalance.objects.filter(created_at__gte=now() - timedelta(days=30)).exists():
messages.error(request, 'Запрос на вывод средств можно сделать только один раз в 30 дней.')
return self.form_invalid(form)
if form.is_valid():
if request.user.balance < form.cleaned_data['amount']:
form.errors['amount'] = 'Сумма для вывода не может быть меньше средств на счету'
return self.form_invalid(form)
AuthorBalance.objects.create(
author=request.user,
type=AuthorBalance.OUT,
amount=form.cleaned_data['amount'],
status=AuthorBalance.PENDING,
card=form.cleaned_data['card'],
)
return self.form_valid(form)
else:
return self.form_invalid(form)
def get_success_url(self):
success_url = reverse_lazy('user-edit-payments', args=[self.request.user.id])
return success_url
@method_decorator(login_required, name='dispatch')
class ProfileEditView(UpdateView):
model = User
template_name = 'user/profile-settings.html'
form_class = UserEditForm
def get_object(self, queryset=None):
return self.request.user
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
# it's magic *-*-*-*-*
if 'photo' in request.FILES:
photo_fp = request.FILES.pop('photo')[0]
fname = photo_fp.name
photo = Image.open(photo_fp)
lowest_side = min(photo.size)
horizontal_padding = (lowest_side - photo.size[0]) / 2
vertical_padding = (lowest_side - photo.size[1]) / 2
photo = photo.crop(
(
-horizontal_padding,
-vertical_padding,
photo.size[0] + horizontal_padding,
photo.size[1] + vertical_padding
)
)
if photo.size[0] > 512:
photo = photo.resize((512, 512,))
buffer = BytesIO()
ext = splitext(fname)[1][1:].upper()
if ext == 'JPG':
ext = 'JPEG'
photo.save(buffer, ext)
fname = str(uuid4()) + '.' + ext.lower()
self.object.photo.save(fname, buffer)
buffer.close()
if not request.POST._mutable:
request.POST._mutable = True
old_password = request.POST.pop('old_password')[0]
new_password1 = request.POST.pop('new_password1')[0]
new_password2 = request.POST.pop('new_password2')[0]
if old_password:
if request.user.check_password(old_password) and new_password1 == new_password2:
request.user.set_password(new_password1)
request.user.save()
login(request, request.user)
else:
messages.error(request, 'Неверный пароль.')
messages.info(request, 'Данные сохранены.')
return super().post(request, *args, **kwargs)
def get_success_url(self):
return reverse('user-edit-profile')
class AuthorRequestView(FormView):
template_name = 'user/become-author.html'
form_class = AuthorRequesForm
success_url = reverse_lazy('author-request-success')
def post(self, request, pk=None):
form = self.get_form()
if form.is_valid():
if request.user.is_authenticated:
email = request.user.email
if request.user.role in [User.AUTHOR_ROLE, User.ADMIN_ROLE]:
messages.info(request, 'Вы уже являетесь автором')
return self.form_invalid(form)
else:
email = form.cleaned_data['email']
if AuthorRequest.objects.filter(email=email).exists():
messages.error(request, 'Вы уже отправили заявку на преподавателя')
return self.form_invalid(form)
AuthorRequest.objects.create(
first_name=form.cleaned_data['first_name'],
last_name=form.cleaned_data['last_name'],
email=email,
about=form.cleaned_data['about'],
facebook=form.cleaned_data['facebook'],
)
return self.form_valid(form)
else:
return self.form_invalid(form)
def get_context_data(self, **kwargs):
if self.request.user.is_authenticated:
self.initial = {
'first_name': self.request.user.first_name,
'last_name': self.request.user.last_name,
'email': self.request.user.email,
'about': self.request.user.about,
'facebook': self.request.user.facebook,
}
return super().get_context_data(**kwargs)