from datetime import datetime, timedelta from django.contrib.auth import get_user_model from django.contrib.auth.decorators import login_required, user_passes_test from django.db.utils import IntegrityError from django.db.models import Min, F, Func, Q from django.http import Http404 from django.shortcuts import get_object_or_404 from django.utils.decorators import method_decorator from django.utils.timezone import now from django.views.generic import ListView, UpdateView, TemplateView, DetailView from apps.course.models import Course from apps.payment.models import SchoolPayment from .models import LiveLesson, SchoolSchedule User = get_user_model() def is_admin_or_teacher(function=None, login_url=None): actual_decorator = user_passes_test( lambda u: u.role in [User.ADMIN_ROLE, User.TEACHER_ROLE], login_url=login_url ) if function: return actual_decorator(function) return actual_decorator @method_decorator([login_required, is_admin_or_teacher], name='dispatch') class LiveLessonsView(ListView): model = LiveLesson template_name = 'school/livelessons_list.html' def get_queryset(self): date_range = Q( date__range=[ (now() - timedelta(days=7)).date(), (now() + timedelta(days=10)).date(), ] ) queryset = LiveLesson.objects.filter(date_range) if queryset.count() < 17: start_date = now() - timedelta(days=7) for i in range(18): try: LiveLesson.objects.create( date=(start_date + timedelta(days=i)).date(), ) except IntegrityError: pass queryset = LiveLesson.objects.filter(date_range) return queryset @method_decorator(login_required, name='dispatch') class LiveLessonsDetailView(DetailView): model = LiveLesson template_name = 'school/livelesson_detail.html' def get(self, request, pk=None): response = super().get(request, pk=pk) try: school_payment = SchoolPayment.objects.get( user=request.user, date_start__lte=now(), date_end__gte=now() ) 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() ): raise Http404 return response @method_decorator([login_required, is_admin_or_teacher], name='dispatch') class LiveLessonEditView(TemplateView): template_name = 'course/course_edit.html' def get(self, request, pk=None): if pk: self.object = get_object_or_404(LiveLesson, pk=pk) else: self.object = LiveLesson.objects.create() return super().get(request) def get_context_data(self): context = super().get_context_data() context['object'] = self.object context['live'] = 'true' return context class SchoolView(TemplateView): template_name = 'school/school.html' def get_context_data(self): context = super().get_context_data() is_previous = 'is_previous' in self.request.GET date_now = now().date() now_time = now() try: school_schedule = SchoolSchedule.objects.get(weekday=now_time.isoweekday()) except SchoolSchedule.DoesNotExist: 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() ) 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.annotate( joined_weekdays=Func(F('weekdays'), function='unnest',) ).values_list('joined_weekdays', flat=True).distinct() else: school_payment_exists = False school_schedules_purchased = [] if school_payment_exists and is_previous: live_lessons = LiveLesson.objects.filter( date__gte=school_payment.last().date_start, date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()], deactivated_at__isnull=True, ) live_lessons_exists = live_lessons.exists() else: live_lessons = None live_lessons_exists = False context.update({ 'online': online, 'live_lessons': live_lessons, 'live_lessons_exists': live_lessons_exists, 'is_previous': is_previous, 'course_items': Course.objects.filter(status=Course.PUBLISHED)[:6], 'is_purchased': school_payment_exists, 'min_school_price': SchoolSchedule.objects.aggregate(Min('month_price'))['month_price__min'], 'school_schedules': SchoolSchedule.objects.annotate( calk=F('weekday') - now().isoweekday(), weight=(7 + F('calk') % 7) % 7, ).order_by('weight'), 'school_schedules_purchased': school_schedules_purchased, 'subscription_ends': school_payment.filter(add_days=False).first().date_end if school_payment_exists else None, }) return context class SchoolSchedulesPrintView(TemplateView): template_name = 'school/schedules_print.html' def get_context_data(self): context = super().get_context_data() context['school_schedules'] = SchoolSchedule.objects.all() return context