From c28f7fcaeb8704dde10997fb52f1e1fe98299bad Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Thu, 5 Jul 2018 14:56:56 +0300 Subject: [PATCH 1/7] LIL-561. Refactoring code --- apps/school/models.py | 17 ++++++++++++++++- apps/user/models.py | 44 ++++++++++++++++++++++++++++++++++++++++++- project/views.py | 31 +++++++++--------------------- 3 files changed, 68 insertions(+), 24 deletions(-) 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/user/models.py b/apps/user/models.py index 7391b0c8..f5c8b3a2 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,47 @@ 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_assess(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..b42c7153 100644 --- a/project/views.py +++ b/project/views.py @@ -1,3 +1,5 @@ +from time import time +import decimal from datetime import datetime, timedelta from django.db.models import Min @@ -31,28 +33,14 @@ class IndexView(TemplateView): 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) + schoolpayment_queryset = self.request.user.school_payments() + school_payment_exists = schoolpayment_queryset.exists() + school_schedules_purchased = schoolpayment_queryset.values_list('weekdays', flat=True) school_schedules_purchased = school_schedules_purchased[0] if school_schedules_purchased else [] school_payment_future = SchoolPayment.objects.filter( @@ -69,7 +57,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 +67,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, From b67f8a143c68cec49893acb175dbfc2bc4e84d89 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Thu, 5 Jul 2018 15:36:35 +0300 Subject: [PATCH 2/7] Refactoring schoolpayment_queryset --- project/views.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/project/views.py b/project/views.py index b42c7153..2bf46b4d 100644 --- a/project/views.py +++ b/project/views.py @@ -1,6 +1,5 @@ -from time import time -import decimal from datetime import datetime, timedelta +from itertools import chain from django.db.models import Min from django.contrib.auth import get_user_model @@ -32,7 +31,6 @@ 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.is_online() online_coming_soon = school_schedule.online_coming_soon() @@ -40,15 +38,12 @@ class IndexView(TemplateView): if self.request.user.is_authenticated: schoolpayment_queryset = self.request.user.school_payments() school_payment_exists = schoolpayment_queryset.exists() - school_schedules_purchased = schoolpayment_queryset.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 + school_schedules_purchased = list( + chain.from_iterable( + schoolpayment_queryset.values_list('weekdays', flat=True) + ) ) - + school_payment_future = self.request.user.school_payments() school_payment_exists_future = school_payment_future.exists() school_purchased_future = school_payment_future.last() From 16749e68ddcd3626f016bdb0946f694b5f587937 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Thu, 5 Jul 2018 15:49:16 +0300 Subject: [PATCH 3/7] Refactoring code --- apps/school/views.py | 86 ++++++++------------------------------------ apps/user/models.py | 1 - project/views.py | 8 ++--- 3 files changed, 18 insertions(+), 77 deletions(-) diff --git a/apps/school/views.py b/apps/school/views.py index ae9b64f0..d2e0bdbb 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_assess(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 f5c8b3a2..0d1e5eed 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -145,7 +145,6 @@ class User(AbstractUser): 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): if ( diff --git a/project/views.py b/project/views.py index 2bf46b4d..cfe34194 100644 --- a/project/views.py +++ b/project/views.py @@ -38,11 +38,9 @@ class IndexView(TemplateView): if self.request.user.is_authenticated: schoolpayment_queryset = self.request.user.school_payments() school_payment_exists = schoolpayment_queryset.exists() - school_schedules_purchased = list( - chain.from_iterable( - schoolpayment_queryset.values_list('weekdays', flat=True) - ) - ) + 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() From 93f18f69738b9417b4d265d4eff5241552538bdd Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Thu, 5 Jul 2018 17:34:05 +0300 Subject: [PATCH 4/7] Updare perms --- apps/course/views.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/apps/course/views.py b/apps/course/views.py index 90957d68..ef24d492 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_assess(self.object): + raise Http404 return super().get(request) def get_context_data(self): @@ -190,13 +189,10 @@ 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_assess(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: @@ -290,9 +286,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_assess(self.object): raise Http404 return response From b1e591b882caf61dd26c2d40073b09ec54597922 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Thu, 5 Jul 2018 17:35:06 +0300 Subject: [PATCH 5/7] Fix imports --- project/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/views.py b/project/views.py index cfe34194..17c23078 100644 --- a/project/views.py +++ b/project/views.py @@ -1,7 +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 From 022ddb6a5f3f285baa42a016ad383c452f42678b Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Fri, 6 Jul 2018 17:05:15 +0300 Subject: [PATCH 6/7] Update perms --- apps/course/views.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/course/views.py b/apps/course/views.py index ef24d492..b722003c 100644 --- a/apps/course/views.py +++ b/apps/course/views.py @@ -197,14 +197,7 @@ class CourseView(DetailView): 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_assess(self.object) context['pending'] = self.object.payments.filter( user=self.request.user, status=Pingback.PINGBACK_TYPE_RISK_UNDER_REVIEW, From d130f1918a6be6d3b2089b21547350bbd82d19ed Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Fri, 6 Jul 2018 19:18:40 +0300 Subject: [PATCH 7/7] Fix stupid typos --- apps/course/views.py | 8 ++++---- apps/school/views.py | 2 +- apps/user/models.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/course/views.py b/apps/course/views.py index b722003c..d4598354 100644 --- a/apps/course/views.py +++ b/apps/course/views.py @@ -167,7 +167,7 @@ class CourseEditView(TemplateView): self.object = Course.objects.create( author=request.user, ) - if not request.user.has_assess(self.object): + if not request.user.has_access(self.object): raise Http404 return super().get(request) @@ -189,7 +189,7 @@ 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.has_assess(self.object)): + (request.user.is_authenticated and request.user.has_access(self.object)): raise Http404 return response @@ -197,7 +197,7 @@ class CourseView(DetailView): context = super().get_context_data(**kwargs) if self.request.user.is_authenticated: context['next'] = self.request.GET.get('next', None) - context['paid'] = self.request.user.has_assess(self.object) + 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, @@ -279,7 +279,7 @@ class LessonView(DetailView): def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) - if not request.user.has_assess(self.object): + if not request.user.has_access(self.object): raise Http404 return response diff --git a/apps/school/views.py b/apps/school/views.py index d2e0bdbb..fe7b47cd 100644 --- a/apps/school/views.py +++ b/apps/school/views.py @@ -61,7 +61,7 @@ class LiveLessonsDetailView(DetailView): def get(self, request, pk=None): response = super().get(request, pk=pk) - if not request.user.has_assess(self.object): + if not request.user.has_access(self.object): raise Http404 return response diff --git a/apps/user/models.py b/apps/user/models.py index 0d1e5eed..6ed6f447 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -118,7 +118,7 @@ class User(AbstractUser): ) return schoolpayment_queryset - def has_assess(self, resource): + 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