diff --git a/apps/course/views.py b/apps/course/views.py index 90957d68..d4598354 100644 --- a/apps/course/views.py +++ b/apps/course/views.py @@ -167,9 +167,8 @@ class CourseEditView(TemplateView): self.object = Course.objects.create( author=request.user, ) - #TODO - #if (request.user != self.object.author and request.user.role < User.AUTHOR_ROLE) or request.user.role != User.ADMIN_ROLE: - # raise Http404 + if not request.user.has_access(self.object): + raise Http404 return super().get(request) def get_context_data(self): @@ -190,25 +189,15 @@ class CourseView(DetailView): response = super().get(request, *args, **kwargs) context = self.get_context_data() if (not request.user.is_authenticated and self.object.status != Course.PUBLISHED) or\ - (request.user.is_authenticated and request.user.role < User.AUTHOR_ROLE and self.object.author != request.user and self.only_lessons and not context['paid']): + (request.user.is_authenticated and request.user.has_access(self.object)): raise Http404 return response - # ((self.object.status != Course.PUBLISHED and request.user.role != User.ADMIN_ROLE) or - # (self.object.status != Course.PUBLISHED and request.user.role != User.AUTHOR_ROLE and self.object.author != request.user)): - def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.request.user.is_authenticated: context['next'] = self.request.GET.get('next', None) - context['paid'] = self.object.payments.filter( - user=self.request.user, - status__in=[ - Pingback.PINGBACK_TYPE_REGULAR, - Pingback.PINGBACK_TYPE_GOODWILL, - Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, - ], - ).exists() + context['paid'] = self.request.user.has_access(self.object) context['pending'] = self.object.payments.filter( user=self.request.user, status=Pingback.PINGBACK_TYPE_RISK_UNDER_REVIEW, @@ -290,9 +279,7 @@ class LessonView(DetailView): def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) - if (self.object.course.status != Course.PUBLISHED and not - (request.user.role == User.ADMIN_ROLE or - self.object.course.author == request.user)): + if not request.user.has_access(self.object): raise Http404 return response diff --git a/apps/school/models.py b/apps/school/models.py index ed1b42ab..1e1c6df6 100644 --- a/apps/school/models.py +++ b/apps/school/models.py @@ -48,7 +48,12 @@ class SchoolSchedule(models.Model): def is_online(self): end_at = datetime.combine(now().today(), self.start_at) + timedelta(hours=2) - return self.start_at <= now().time() and end_at.time() >= now().time() and self.weekday == now().isoweekday() + return ( + self.start_at <= now().time() and + end_at.time() >= now().time() and + self.weekday == now().isoweekday() and + self.current_live_lesson() + ) def current_live_lesson(self): now_time = now() @@ -68,6 +73,16 @@ class SchoolSchedule(models.Model): ).first() return live_lesson + def online_coming_soon(self): + now_time = now() + return ( + school_schedule.start_at > now_time.time() and + ( + datetime.combine(datetime.today(), self.start_at) - timedelta(hours=12) + ).time() <= now_time.time() and + self.current_live_lesson() + ) + @property def start_at_humanize(self): return arrow.get(datetime.combine(datetime.today(), self.start_at), settings.TIME_ZONE).humanize(locale='ru') if self.start_at else None diff --git a/apps/school/views.py b/apps/school/views.py index ae9b64f0..fe7b47cd 100644 --- a/apps/school/views.py +++ b/apps/school/views.py @@ -61,27 +61,8 @@ class LiveLessonsDetailView(DetailView): 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() - ): + if not request.user.has_access(self.object): raise Http404 - return response @@ -120,24 +101,11 @@ class SchoolView(TemplateView): online = False else: end_at = datetime.combine(now_time.today(), school_schedule.start_at) - online = ( - school_schedule.start_at <= now_time.time() and - (end_at + timedelta(hours=2)).time() >= now_time.time() and - school_schedule.current_live_lesson() - ) + online = school_schedule.is_online() if self.request.user.is_authenticated: - school_payment = SchoolPayment.objects.filter( - user=self.request.user, - status__in=[ - Pingback.PINGBACK_TYPE_REGULAR, - Pingback.PINGBACK_TYPE_GOODWILL, - Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, - ], - date_start__lte=date_now, - date_end__gte=date_now - ) - school_payment_exists = school_payment.exists() - school_schedules_purchased = school_payment.annotate( + schoolpayment_queryset = self.request.user.school_payments() + school_payment_exists = schoolpayment_queryset.exists() + school_schedules_purchased = schoolpayment_queryset.annotate( joined_weekdays=Func(F('weekdays'), function='unnest',) ).values_list('joined_weekdays', flat=True).distinct() else: @@ -145,7 +113,7 @@ class SchoolView(TemplateView): school_schedules_purchased = [] if school_payment_exists and is_previous: live_lessons = LiveLesson.objects.filter( - date__gte=school_payment.last().date_start, + date__gte=schoolpayment_queryset.last().date_start, date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()], deactivated_at__isnull=True, ) @@ -163,10 +131,11 @@ class SchoolView(TemplateView): 'min_school_price': SchoolSchedule.objects.aggregate(Min('month_price'))['month_price__min'], 'school_schedules': SchoolSchedule.objects.all(), 'school_schedules_purchased': school_schedules_purchased, - 'subscription_ends': school_payment.filter(add_days=False).first().date_end if school_payment_exists else None, + 'subscription_ends': schoolpayment_queryset.filter(add_days=False).first().date_end if school_payment_exists else None, }) return context + class SummerSchoolView(TemplateView): template_name = 'school/summer_school.html' @@ -181,39 +150,14 @@ class SummerSchoolView(TemplateView): online = False else: end_at = datetime.combine(now_time.today(), school_schedule.start_at) - online = ( - school_schedule.start_at <= now_time.time() and - (end_at + timedelta(hours=2)).time() >= now_time.time() and - school_schedule.current_live_lesson() - ) + online = school_schedule.is_online() if self.request.user.is_authenticated: - school_payment = SchoolPayment.objects.filter( - user=self.request.user, - status__in=[ - Pingback.PINGBACK_TYPE_REGULAR, - Pingback.PINGBACK_TYPE_GOODWILL, - Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, - ], - date_start__lte=date_now, - date_end__gte=date_now - ) - school_payment_exists = school_payment.exists() - - school_payment_future = SchoolPayment.objects.filter( - user=self.request.user, - status__in=[ - Pingback.PINGBACK_TYPE_REGULAR, - Pingback.PINGBACK_TYPE_GOODWILL, - Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, - ], - date_start__gte=date_now, - date_end__gte=date_now - ) - + schoolpayment_queryset = self.request.user.school_payments() + school_payment_exists = schoolpayment_queryset.exists() + school_payment_future = self.request.user.school_payments() school_payment_exists_future = school_payment_future.exists() school_purchased_future = school_payment_future.last() - - school_schedules_purchased = school_payment.annotate( + school_schedules_purchased = schoolpayment_queryset.annotate( joined_weekdays=Func(F('weekdays'), function='unnest',) ).values_list('joined_weekdays', flat=True).distinct() else: @@ -223,7 +167,7 @@ class SummerSchoolView(TemplateView): school_schedules_purchased = [] if school_payment_exists and is_previous: live_lessons = LiveLesson.objects.filter( - date__gte=school_payment.last().date_start, + date__gte=schoolpayment_queryset.last().date_start, date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()], deactivated_at__isnull=True, ) @@ -243,7 +187,7 @@ class SummerSchoolView(TemplateView): 'school_schedules': SchoolSchedule.objects.all(), 'school_schedules_purchased': school_schedules_purchased, 'school_purchased_future': school_purchased_future, - 'subscription_ends': school_payment.filter(add_days=False).first().date_end if school_payment_exists else None, + 'subscription_ends': schoolpayment_queryset.filter(add_days=False).first().date_end if school_payment_exists else None, }) return context diff --git a/apps/user/models.py b/apps/user/models.py index 7391b0c8..6ed6f447 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -1,5 +1,6 @@ from json import dumps from rest_framework.authtoken.models import Token +from paymentwall import Pingback from phonenumber_field.modelfields import PhoneNumberField from django.db import models @@ -11,8 +12,8 @@ from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from api.v1 import serializers -from apps.notification.utils import send_email +from apps.notification.utils import send_email from apps.user.tasks import user_to_mixpanel @@ -103,6 +104,46 @@ class User(AbstractUser): commission = aggregate.get('commission__sum') or 0 return amount - commission + def school_payments(self): + from apps.payment.models import SchoolPayment + schoolpayment_queryset = SchoolPayment.objects.filter( + user=self, + date_start__lte=now().date(), + date_end__gte=now().date(), + status__in=[ + Pingback.PINGBACK_TYPE_REGULAR, + Pingback.PINGBACK_TYPE_GOODWILL, + Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED, + ] + ) + return schoolpayment_queryset + + def has_access(self, resource): + from apps.course.models import Course, Lesson + from apps.school.models import SchoolSchedule, LiveLesson + from apps.payment.models import CoursePayment + if isinstance(resource, Course): + return True + elif isinstance(resource, Lesson): + if not self.is_active: + return False + if resource.course.author and (resource.course.author == self or resource.course.author.role == User.ADMIN_ROLE): + return True + try: + CoursePayment.objects.get(course=resource.course, user=self) + except CoursePayment.DoesNotExist: + return False + else: + return True + elif isinstance(resource, SchoolSchedule): + isoweekday = resource.weekday + schoolpayment_queryset = self.school_payments().filter(weekdays__contains=[isoweekday]) + return schoolpayment_queryset.exists() or self.role == User.ADMIN_ROLE + elif isinstance(resource, LiveLesson): + isoweekday = resource.date.isoweekday() + schoolpayment_queryset = self.school_payments().filter(weekdays__contains=[isoweekday]) + return schoolpayment_queryset.exists() or self.role == User.ADMIN_ROLE + @receiver(post_save, sender=User) def create_auth_token(sender, instance=None, created=False, **kwargs): diff --git a/project/views.py b/project/views.py index 17395e62..17c23078 100644 --- a/project/views.py +++ b/project/views.py @@ -1,6 +1,7 @@ from datetime import datetime, timedelta +from itertools import chain -from django.db.models import Min +from django.db.models import Min, Func, F from django.contrib.auth import get_user_model from django.views.generic import TemplateView from django.utils.timezone import now @@ -30,37 +31,17 @@ class IndexView(TemplateView): online_coming_soon = False school_schedule = None else: - end_at = datetime.combine(now_time.today(), school_schedule.start_at) - online = ( - school_schedule.start_at <= now_time.time() and - (end_at + timedelta(hours=2)).time() >= now_time.time() and - school_schedule.current_live_lesson() - ) - online_coming_soon = ( - school_schedule.start_at > now_time.time() and - ( - datetime.combine(datetime.today(), school_schedule.start_at) - timedelta(hours=12) - ).time() <= now_time.time() and - school_schedule.current_live_lesson() - ) + online = school_schedule.is_online() + online_coming_soon = school_schedule.online_coming_soon() date_now = now_time.date() if self.request.user.is_authenticated: - school_payment = SchoolPayment.objects.filter( - user=self.request.user, - date_start__lte=date_now, - date_end__gte=date_now - ) - school_payment_exists = school_payment.exists() - school_schedules_purchased = school_payment.values_list('weekdays', flat=True) - school_schedules_purchased = school_schedules_purchased[0] if school_schedules_purchased else [] - - school_payment_future = SchoolPayment.objects.filter( - user=self.request.user, - date_start__gte=date_now, - date_end__gte=date_now - ) - + schoolpayment_queryset = self.request.user.school_payments() + school_payment_exists = schoolpayment_queryset.exists() + school_schedules_purchased = schoolpayment_queryset.annotate( + joined_weekdays=Func(F('weekdays'), function='unnest',) + ).values_list('joined_weekdays', flat=True).distinct() + school_payment_future = self.request.user.school_payments() school_payment_exists_future = school_payment_future.exists() school_purchased_future = school_payment_future.last() @@ -69,7 +50,6 @@ class IndexView(TemplateView): school_payment_exists_future = False school_purchased_future = False school_schedules_purchased = [] - context.update({ 'online': online, 'online_coming_soon': online_coming_soon, @@ -80,8 +60,8 @@ class IndexView(TemplateView): 'school_schedules': SchoolSchedule.objects.all(), 'school_schedules_purchased': school_schedules_purchased, 'teachers': User.objects.filter(role=User.TEACHER_ROLE, show_in_mainpage=True), - 'subscription_ends': school_payment.filter(add_days=False).first().date_end if school_payment_exists else None, - 'subscription_ends_humanize': school_payment.filter(add_days=False).first().date_end_humanize if school_payment_exists else None, + 'subscription_ends': schoolpayment_queryset.filter(add_days=False).first().date_end if school_payment_exists else None, + 'subscription_ends_humanize': schoolpayment_queryset.filter(add_days=False).first().date_end_humanize if school_payment_exists else None, 'school_purchased_future': school_purchased_future, 'is_purchased_future': school_payment_exists_future,