Skip to content
Snippets Groups Projects
Verified Commit f85f91b5 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Add person overview

parent e08075f9
No related branches found
No related tags found
1 merge request!80Resolve "Add student view with further information"
Pipeline #3401 passed
...@@ -69,6 +69,9 @@ class PersonalNote(ExtensibleModel): ...@@ -69,6 +69,9 @@ class PersonalNote(ExtensibleModel):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if self.excuse_type: if self.excuse_type:
self.excused = True self.excused = True
if not self.absent:
self.excused = False
self.excuse_type = None
super().save(*args, **kwargs) super().save(*args, **kwargs)
class Meta: class Meta:
......
{# -*- engine:django -*- #}
{% extends "core/base.html" %}
{% load week_helpers %}
{% load i18n %}
{% block browser_title %}{% blocktrans %}Class register: person{% endblocktrans %}{% endblock %}
{% block page_title %}
{% blocktrans with person=person %}
Class register overview for {{ person }}
{% endblocktrans %}
{% endblock %}
{% block content %}
<div class="row">
<div class="col s12 m12 l6">
<h5>{% trans "Unexcused absences" %}</h5>
<ul class="collection">
{% for note in unexcused_absences %}
{% period_to_date note.week note.lesson_period.period as note_date %}
<li class="collection-item">
<i class="material-icons left red-text">warning</i>
<p class="no-margin">{{ note_date }}, {{ note.lesson_period }}</p>
{% if note.remarks %}
<p class="no-margin"><em>{{ note.remarks }}</em></p>
{% endif %}
</li>
{% empty %}
<li class="collection-item flow-text">
{% trans "There are unexcused lessons." %}
</li>
{% endfor %}
</ul>
</div>
<div class="col s12 m12 l6">
<h5>{% trans "Relevant personal notes" %}</h5>
<ul class="collapsible">
<li>
<div>
<ul>
{% for note in personal_notes %}
{% ifchanged note.lesson_period.lesson.validity.school_term %}</ul></div></li>
<li {% if forloop.first %}class="active"{% endif %}>
<div class="collapsible-header"><i
class="material-icons">date_range</i>{{ note.lesson_period.lesson.validity.school_term }}</div>
<div class="collapsible-body">
<ul class="collection">
{% endifchanged %}
{% ifchanged note.week %}
<li class="collection-item">
<strong>{% blocktrans with week=note.week %}Week {{ week }}{% endblocktrans %}</strong>
</li>
{% endifchanged %}
{% period_to_date note.week note.lesson_period.period as note_date %}
{% ifchanged note_date %}
<li class="collection-item">
<form action="" method="post" class="right" style="margin-top: -7px;">
{% csrf_token %}
{% trans "Mark all as" %}
<input type="hidden" value="{{ note_date|date:"Y-m-d" }}" name="date">
<button type="submit" class="btn-flat" name="excuse_type" value="e">
{% trans "e" %}
</button>
{% for excuse_type in excuse_types %}
<button type="submit" class="btn-flat" value="{{ excuse_type.pk }}" name="excuse_type">
{{ excuse_type.short_name }}
</button>
{% endfor %}
</form>
<i class="material-icons left">schedule</i>
{{ note_date }}
</li>
{% endifchanged %}
<li class="collection-item">
<div class="row no-margin">
<div class="col s12 m1">
{{ note.lesson_period.period.period }}.
</div>
<div class="col s12 m4">
<i class="material-icons left">event_note</i>
{{ note.lesson_period.get_subject.name }},
{{ note.lesson_period.get_teacher_names }}
</div>
<div class="col s12 m7">
{% if note.absent and not note.excused %}
<form action="" method="post" class="right" style="margin-top: -7px;">
{% csrf_token %}
{% trans "Mark all as" %}
<input type="hidden" value="{{ note.pk }}" name="personal_note">
<button type="submit" class="btn-flat" name="excuse_type" value="e">
{% trans "e" %}
</button>
{% for excuse_type in excuse_types %}
<button type="submit" class="btn-flat" value="{{ excuse_type.pk }}" name="excuse_type">
{{ excuse_type.short_name }}
</button>
{% endfor %}
</form>
{% endif %}
{% if note.absent %}
<div class="chip red white-text">
{% trans 'Absent' %}
</div>
{% endif %}
{% if note.excused %}
<div class="chip green white-text">
{% if note.excuse_type %}
{{ note.excuse_type.name }}
{% else %}
{% trans 'Excused' %}
{% endif %}
</div>
{% endif %}
{% if note.late %}
<div class="chip orange white-text">
{% blocktrans with late=note.late %}{{ late }}' late{% endblocktrans %}
</div>
{% endif %}
{% for extra_mark in note.extra_marks.all %}
<div class="chip">{{ extra_mark.name }}</div>
{% endfor %}
<em>{{ note.remarks }}</em>
</div>
</li>
{% endfor %}
</li>
</ul>
</div>
</div>
{% endblock %}
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
<div class="row"> <div class="row">
<h4 class="col s12 m6">{% blocktrans with el=el week=week.week %}CW {{ week }}: {{ instance }}{% endblocktrans %} </h4> <h4 class="col s12 m6">{% blocktrans with el=el week=week.week %}CW {{ week }}:
{{ instance }}{% endblocktrans %} </h4>
{% include "chronos/partials/week_select.html" with wanted_week=week %} {% include "chronos/partials/week_select.html" with wanted_week=week %}
</div> </div>
...@@ -111,7 +112,9 @@ ...@@ -111,7 +112,9 @@
{% blocktrans %}Personal notes{% endblocktrans %} {% blocktrans %}Personal notes{% endblocktrans %}
</span> </span>
{% for person in persons %} {% for person in persons %}
<h5 class="card-title">{{ person.person.full_name }}</h5> <h5 class="card-title">
<a href="{% url "overview_person" person.person.pk %}">{{ person.person.full_name }}</a>
</h5>
<p class="card-text"> <p class="card-text">
{% trans "Absent" %}: {{ person.person.absences_count }} {% trans "Absent" %}: {{ person.person.absences_count }}
({{ person.person.unexcused_count }} {% trans "unexcused" %}) ({{ person.person.unexcused_count }} {% trans "unexcused" %})
......
...@@ -26,6 +26,8 @@ urlpatterns = [ ...@@ -26,6 +26,8 @@ urlpatterns = [
path( path(
"print/group/<int:id_>", views.full_register_group, name="full_register_group" "print/group/<int:id_>", views.full_register_group, name="full_register_group"
), ),
path("person/<int:id_>/", views.overview_person, name="overview_person"),
path("me/", views.overview_person, name="overview_me"),
path("absence/new", views.register_absence, name="register_absence"), path("absence/new", views.register_absence, name="register_absence"),
path("extra_marks/", views.ExtraMarkListView.as_view(), name="extra_marks"), path("extra_marks/", views.ExtraMarkListView.as_view(), name="extra_marks"),
path( path(
......
...@@ -20,7 +20,7 @@ from aleksis.apps.chronos.util.date import get_weeks_for_year, week_weekday_to_d ...@@ -20,7 +20,7 @@ from aleksis.apps.chronos.util.date import get_weeks_for_year, week_weekday_to_d
from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView from aleksis.core.mixins import AdvancedCreateView, AdvancedDeleteView, AdvancedEditView
from aleksis.core.models import Group, Person, SchoolTerm from aleksis.core.models import Group, Person, SchoolTerm
from aleksis.core.util import messages from aleksis.core.util import messages
from aleksis.core.util.core_helpers import get_site_preferences from aleksis.core.util.core_helpers import get_site_preferences, objectgetter_optional
from .forms import ( from .forms import (
ExcuseTypeForm, ExcuseTypeForm,
...@@ -30,7 +30,7 @@ from .forms import ( ...@@ -30,7 +30,7 @@ from .forms import (
RegisterAbsenceForm, RegisterAbsenceForm,
SelectForm, SelectForm,
) )
from .models import ExcuseType, ExtraMark, LessonDocumentation from .models import ExcuseType, ExtraMark, LessonDocumentation, PersonalNote
from .tables import ExcuseTypeTable, ExtraMarkTable from .tables import ExcuseTypeTable, ExtraMarkTable
...@@ -445,6 +445,84 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: ...@@ -445,6 +445,84 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse:
return render(request, "alsijil/print/full_register.html", context) return render(request, "alsijil/print/full_register.html", context)
def overview_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
context = {}
person = objectgetter_optional(Person, default_eval="request.user.person")(
request, id_
)
context["person"] = person
if request.method == "POST":
if request.POST.get("excuse_type"):
# Get excuse type
excuse_type = request.POST["excuse_type"]
found = False
if excuse_type == "e":
excuse_type = None
found = True
else:
try:
excuse_type = ExcuseType.objects.get(pk=int(excuse_type))
found = True
except (ExcuseType.DoesNotExist, ValueError):
pass
if found:
if request.POST.get("date"):
# Mark absences on date as excused
try:
date = datetime.strptime(
request.POST["date"], "%Y-%m-%d"
).date()
notes = person.personal_notes.filter(
week=date.isocalendar()[1],
lesson_period__period__weekday=date.weekday(),
lesson_period__lesson__validity__date_start__lte=date,
lesson_period__lesson__validity__date_end__gte=date,
absent=True,
excused=False,
)
notes.update(excused=True, excuse_type=excuse_type)
messages.success(
request, _("The absences have been marked as excused.")
)
except ValueError:
pass
elif request.POST.get("personal_note"):
# Mark specific absence as excused
try:
note = PersonalNote.objects.get(
pk=int(request.POST["personal_note"])
)
if note.absent:
note.excused = True
note.excuse_type = excuse_type
note.save()
messages.success(
request, _("The absence has been marked as excused.")
)
except (PersonalNote.DoesNotExist, ValueError):
pass
person.refresh_from_db()
unexcused_absences = person.personal_notes.filter(absent=True, excused=False)
context["unexcused_absences"] = unexcused_absences
personal_notes = person.personal_notes.filter(
Q(absent=True) | Q(late__gt=0) | ~Q(remarks="") | Q(extra_marks__isnull=False)
).order_by(
"-lesson_period__lesson__validity__date_start",
"-week",
"lesson_period__period__weekday",
"lesson_period__period__period",
)
context["personal_notes"] = personal_notes
context["excuse_types"] = ExcuseType.objects.all()
return render(request, "alsijil/class_register/person.html", context)
def register_absence(request: HttpRequest) -> HttpResponse: def register_absence(request: HttpRequest) -> HttpResponse:
context = {} context = {}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment