2021-02-06 10:17:04 -07:00

172 lines
6.3 KiB
Python

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 accounts.models import Instructor, Student
from .models import Code, Period
from .forms import AttendanceUpdateForm, PeriodForm
# EXAMPLE PERMISSION MIXIN
# class MyView(PermissionRequiredMixin, View):
# permission_required = 'polls.add_choice'
# # Or multiple of permissions:
# permission_required = ('polls.view_choice', 'polls.change_choice')
# 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['period_total'] = Period.objects.filter(
student = student
).filter(
clocked_in__year=timezone.now().year
).filter(
clocked_in__month=timezone.now().month
).aggregate(total=Sum('duration'))
context['period_list'] = Period.objects.filter(
student=student
).filter(
clocked_in__year=timezone.now().year
).filter(
clocked_in__month=timezone.now().month
).order_by('-clocked_in')
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):
# update checked in
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:
student.is_clocked_in=False
period = student.period_set.get(pk=student.current_period_id)
period.clocked_out=timezone.now()
student.save()
period.save()
messages.add_message(self.request, messages.INFO, f'{student.user.first_name} {student.user.last_name} clocked out.')
else:
c_p = student.period_set.create(student=student, clocked_in=timezone.now(), station_number=station_number)
student.current_period_id = c_p.id
student.is_clocked_in=True
student.save()
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'
# When editing a period, check if it matches the current period of the student and clock them out
def form_valid(self, form):
student = form.instance.student
if form.instance.id == student.current_period_id:
student.is_clocked_in = False
student.save()
return super().form_valid(form)
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})