154 lines
5.6 KiB
Python
154 lines
5.6 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 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})
|