from django.shortcuts import render, reverse from django.db.models import Avg, Count, Min, Sum from django.db.models.functions import Round from django.urls import reverse_lazy from django.views.generic.base import TemplateView from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView from django.views.generic.detail import DetailView from django.views.generic.list import ListView from django.core.paginator import Paginator from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from django.utils import timezone from django.contrib import messages from django.contrib.auth.models import User from django.shortcuts import get_object_or_404 from accounts.models import Instructor, Student from .models import Code, Period from .forms import AttendanceUpdateForm, PeriodForm # OVERVIEW class AttendanceOverview(LoginRequiredMixin, TemplateView): template_name = 'attendance/attendance_overview.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['user'] = self.request.user if hasattr(self.request.user, 'instructor'): instructor = self.request.user.instructor context['student_list'] = Student.objects.filter( department=instructor.department ).annotate(total_hours=Sum('period__duration')) context['period_list'] = Period.objects.filter( student__department=instructor.department ).filter( clocked_in__year=timezone.now().year ).filter( clocked_in__month=timezone.now().month ) elif hasattr(self.request.user, 'student'): student = self.request.user.student # sum all duration fields for student context['monthly_total'] = Period.objects.filter( student = student ).filter( clocked_in__year=timezone.now().year ).filter( clocked_in__month=timezone.now().month ).aggregate(duration=Sum('duration')) context['period_list'] = Period.objects.filter( student=student ).filter( clocked_in__year=timezone.now().year ).filter( clocked_in__month=timezone.now().month ) if student.current_period_id != None: context['current_period'] = Period.objects.get(pk=student.current_period_id) return context class AttendanceUpdateView(LoginRequiredMixin, FormView): template_name = 'attendance/attendance_form.html' form_class = AttendanceUpdateForm def form_valid(self, form): student_number = form.cleaned_data['qr_string'].split(':')[0] station_number = form.cleaned_data['qr_string'].split(':')[1] student = Student.objects.get(student_number=student_number) if student.is_clocked_in: period = student.period_set.get(pk=student.current_period_id) period.clocked_out=timezone.now() period.save() messages.add_message(self.request, messages.INFO, f'{student.user.first_name} {student.user.last_name} clocked out.') else: period = student.period_set.create(student=student, clocked_in=timezone.now(), station_number=station_number) messages.add_message(self.request, messages.INFO, f'{student.user.first_name} {student.user.last_name} clocked in.') return super().form_valid(form) def get_success_url(self): return reverse('attendance-update') # PERIODS class PeriodListView(LoginRequiredMixin, ListView): model = Period paginate_by = 25 template_name = 'attendance/period_list.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if hasattr(self.request.user, 'student'): period_list = Period.objects.filter( student = self.request.user.student ) paginator = Paginator(period_list, 25) page_number = self.request.GET.get('page') page_obj = paginator.get_page(page_number) context['page_obj'] = page_obj return context class PeriodCreateView(LoginRequiredMixin, CreateView): model = Period form_class = PeriodForm template_name = 'attendance/period_form.html' class PeriodDetailView(LoginRequiredMixin, DetailView): model = Period template_name = 'attendance/period_detail.html' class PeriodUpdateView(LoginRequiredMixin, UpdateView): model = Period form_class = PeriodForm template_name = 'attendance/period_form.html' def get_success_url(self): pk = self.kwargs["pk"] return reverse('period-detail', kwargs={'pk': pk}) class PeriodDeleteView(LoginRequiredMixin, DeleteView): model = Period success_url = '/attendance' # CODES class CodeCreateView(LoginRequiredMixin, CreateView): model = Code fields = ['station_number'] template_name = 'attendance/code_form.html' def form_valid(self, form): form.instance.student = self.request.user.student return super().form_valid(form) class CodeDetailView(LoginRequiredMixin, DetailView): model = Code template_name = 'attendance/code_detail.html' class CodeUpdateView(LoginRequiredMixin, UpdateView): model = Code fields = ['station_number'] template_name = 'attendance/code_form.html' def get_success_url(self): pk = self.kwargs["pk"] return reverse('code-detail', kwargs={'pk': pk})