Merge branch 'develop'

This commit is contained in:
Nathan Chapman 2021-02-08 20:29:05 -07:00
commit 03642b3adc
15 changed files with 65 additions and 33 deletions

View File

@ -2,6 +2,7 @@ from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class Department(models.Model):
name = models.CharField(max_length=200)

View File

@ -10,7 +10,7 @@
{% elif user.instructor %}
<p>{{ user.instructor.department }}</p>
{% endif %}
{% if periods %}
{% if periods and periods.total %}
<p>Total clocked hours: <strong>{{ periods.total|timedelta_format }}</strong></p>
{% endif %}
<p>

View File

@ -2,6 +2,8 @@ from datetime import datetime
from django.db import models
from django.urls import reverse
from accounts.models import Student
from django.db.models.signals import post_save
from django.dispatch import receiver
class Code(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
@ -46,3 +48,10 @@ class Period(models.Model):
if self.clocked_out != None:
self.duration = self.clocked_out - self.clocked_in
super(Period, self).save(*args, **kwargs)
@receiver(post_save, sender=Period)
def auto_clockin_student(sender, instance, created, **kwargs):
if created:
instance.student.is_clocked_in = True
instance.student.current_period_id = instance.pk
instance.student.save()

View File

@ -7,7 +7,7 @@
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="clock-in/out">
<input type="submit" value="Submit">
</form>
</section>
{% endblock %}

View File

@ -93,7 +93,9 @@
{% for student in student_list %}
<tr>
<td>{{ student.user.first_name }} {{ student.user.last_name }}</td>
{% if student.total_hours %}
<td><strong>{{ student.total_hours|timedelta_format }}</strong></td>
{% endif %}
</tr>
{% empty %}
<tr><td colspan="2">No periods yet.</td></tr>

View File

@ -20,7 +20,11 @@
</section>
<section class="student__attendance attendance">
<h2 class="attendance__title">Attendance log</h2>
<p class="attendance__total">Total hours for the month: <strong>{{ period_total.total|timedelta_format:2 }}</strong> <small>(Does not include current session.)</small></p>
{% if monthly_total.duration %}
<p class="attendance__total">Total hours for the month: <strong>{{ monthly_total.duration|timedelta_format }}</strong>
<small>(Does not include current session.)</small>
</p>
{% endif %}
{% include 'attendance/_student_periods.html' %}
<p>
<a class="action-button" href="{% url 'period-list' %}">See previous →</a>

View File

@ -2,9 +2,13 @@
{% load static %}
{% block content %}
<form method="post">
<section class="panel">
<h1>Delete Session</h1>
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm">
</form>
<input type="submit" value="Confirm"> or
<a href="{% url 'period-detail' object.pk %}">Cancel</a>
</form>
</section>
{% endblock %}

View File

@ -1,26 +1,32 @@
{% extends 'application.html' %}
{% load timedelta_filter %}
{% block content %}
<h1>Period</h1>
<section>
<header>
<section class="period panel">
<h1>Session</h1>
<header class="period__header">
<a href="{% url 'attendance-overview' %}">← Back</a>
<div>
<a href="{% url 'period-update' period.id %}">Edit</a>
<a href="{% url 'period-delete' period.id %}">Delete</a>
</div>
</header>
<dl>
<dl class="period__data">
<dt>Student</dt>
<dd>{{ period.student }}</dd>
<dt>Clocked in</dt>
<dd>{{ period.clocked_in }}</dd>
{% if period.clocked_out %}
<dt>Clocked out</dt>
<dd>{{ period.clocked_out }}</dd>
{% else %}
<dt>Not clocked out.</dt>
{% endif %}
{% if period.duration %}
<dt>Duration</dt>
<dd>{{ period.duration }}</dd>
<dd>{{ period.duration|timedelta_format }} hours</dd>
{% endif %}
</dl>
</section>
{% endblock %}

View File

@ -3,7 +3,7 @@
{% block content %}
<section class="period panel">
<h1>Generate Period</h1>
<h1>Session</h1>
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}

View File

@ -16,19 +16,11 @@ 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_queryset(self):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['user'] = self.request.user
@ -50,13 +42,13 @@ class AttendanceOverview(LoginRequiredMixin, TemplateView):
student = self.request.user.student
# sum all duration fields for student
context['period_total'] = Period.objects.filter(
context['monthly_total'] = Period.objects.filter(
student = student
).filter(
clocked_in__year=timezone.now().year
).filter(
clocked_in__month=timezone.now().month
).aggregate(total=Sum('duration'))
).aggregate(duration=Sum('duration'))
context['period_list'] = Period.objects.filter(
student=student
@ -74,7 +66,6 @@ class AttendanceUpdateView(LoginRequiredMixin, FormView):
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)
@ -86,8 +77,8 @@ class AttendanceUpdateView(LoginRequiredMixin, FormView):
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
period = student.period_set.create(student=student, clocked_in=timezone.now(), station_number=station_number)
student.current_period_id = period.pk
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.')

View File

@ -5,18 +5,18 @@
<article class="home">
<header class="panel">
<h1>Welcome to<br>
Btech Time Tracker</h1>
BTech Time Tracker</h1>
<h2>Know exactly how many hours you've clocked, anytime, anywhere.</h2>
</header>
<section>
<section class="home__section">
<h3>No more paper</h3>
<p>No more reading bad handwriting or putting the wrong date or time.</p>
</section>
<section>
<section class="home__section">
<h3>No more questions</h3>
<p>No more asking your instructor, or being asked by your student how many hours they have.</p>
</section>
<section>
<section class="home__section">
<h3>No more manual entry</h3>
<p>We invented computers to do that for us.</p>
</section>

View File

@ -2,4 +2,8 @@
h1, h2 {
text-align: center;
}
&__section {
margin: 0 1rem;
}
}

View File

@ -0,0 +1,6 @@
.period {
&__header {
display: flex;
justify-content: space-between;
}
}

View File

@ -8,6 +8,11 @@ class TimezoneMiddleware:
def __call__(self, request):
tzname = request.session.get('django_timezone')
if request.user.is_authenticated:
if hasattr(request.user, 'instructor'):
tzname = request.user.instructor.timezone
if hasattr(request.user, 'student'):
tzname = request.user.student.timezone
if tzname:
timezone.activate(pytz.timezone(tzname))
else:

View File

@ -149,4 +149,4 @@ MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
LOGIN_REDIRECT_URL = '/accounts/timezone/'
LOGIN_REDIRECT_URL = '/attendance/'