roosterwijs/backend/modules/uren/views.py

133 lines
4.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Urenoverzicht: berekent lesuren per groep/vak en per leerling.
Roosterblokken zijn wekelijks: per schooljaar telt een blok zo vaak mee als er
lesdagen op die weekdag zijn (vrije dagen/vakanties/studiedagen tellen niet mee),
minus de keren dat het blok via een uitzondering vervalt.
"""
from datetime import timedelta
from rest_framework.decorators import api_view
from rest_framework.response import Response
from core.models import KalenderDag, Persoon, Roosterblok, Rol, Schooljaar, Subgroep, Tijdslot
def _duur_uren(ts):
s, e = ts.start_tijd, ts.eind_tijd
return ((e.hour * 60 + e.minute) - (s.hour * 60 + s.minute)) / 60.0
@api_view(["GET"])
def urenoverzicht(request):
sjid = request.query_params.get("schooljaar")
if not sjid:
return Response({"detail": "Geef een schooljaar op."}, status=400)
try:
sj = Schooljaar.objects.get(pk=sjid)
except Schooljaar.DoesNotExist:
return Response({"detail": "Schooljaar niet gevonden."}, status=404)
# Lesdagen per weekdag (mavr), vrije dagen uitgezonderd.
vrije = set(KalenderDag.objects.filter(schooljaar=sj).values_list("datum", flat=True))
lesdagen = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0}
d = sj.start_datum
while d <= sj.eind_datum:
wd = d.weekday()
if wd <= 4 and d not in vrije:
lesdagen[wd] += 1
d += timedelta(days=1)
blokken = list(
Roosterblok.objects.filter(schooljaar=sj)
.select_related("tijdslot", "activiteit", "groep", "subgroep", "leerling", "leerling__groep")
.prefetch_related("uitzonderingen")
)
subgroepen = {s.id: s for s in Subgroep.objects.prefetch_related("leden").all()}
sub_leden = {sid: set(s.leden.values_list("id", flat=True)) for sid, s in subgroepen.items()}
leerlingen = list(Persoon.objects.filter(rol=Rol.LEERLING).select_related("groep"))
def occurrences(blok):
wd = blok.tijdslot.dag
basis = lesdagen.get(wd, 0)
weg = 0
for u in blok.uitzonderingen.all():
if u.vervalt and sj.start_datum <= u.datum <= sj.eind_datum and u.datum.weekday() == wd and u.datum not in vrije:
weg += 1
return max(basis - weg, 0)
def groep_van_blok(b):
if b.groep_id:
return b.groep
if b.subgroep_id:
s = subgroepen.get(b.subgroep_id)
return s.groep if s else None
if b.leerling_id:
return b.leerling.groep
return None
blok_uren = {}
groep_map = {}
for b in blokken:
u = _duur_uren(b.tijdslot) * occurrences(b)
blok_uren[b.id] = u
g = groep_van_blok(b)
if g:
gm = groep_map.setdefault(g.id, {"naam": g.naam, "vakken": {}})
gm["vakken"][b.activiteit.naam] = gm["vakken"].get(b.activiteit.naam, 0) + u
per_groep = []
for gm in groep_map.values():
vakken = [{"vak": k, "uren": round(v, 1)} for k, v in sorted(gm["vakken"].items())]
per_groep.append({
"groep": gm["naam"],
"totaal": round(sum(x["uren"] for x in vakken), 1),
"vakken": vakken,
})
per_groep.sort(key=lambda x: x["groep"])
# Stage-uren (module optioneel).
stages = []
alle_ts = []
try:
from modules.stage.models import Stage
alle_ts = list(Tijdslot.objects.all())
stages = list(Stage.objects.filter(actief=True))
except Exception:
pass
per_leerling = []
for l in leerlingen:
vakken = {}
for b in blokken:
hoort = (
(b.groep_id and l.groep_id == b.groep_id)
or (b.subgroep_id and l.id in sub_leden.get(b.subgroep_id, set()))
or (b.leerling_id == l.id)
)
if hoort:
vakken[b.activiteit.naam] = vakken.get(b.activiteit.naam, 0) + blok_uren[b.id]
stage_uren = 0
for st in stages:
if st.leerling_id != l.id:
continue
for ts in alle_ts:
if st.dekt_tijdslot(ts):
stage_uren += _duur_uren(ts) * lesdagen.get(ts.dag, 0)
vak_list = [{"vak": k, "uren": round(v, 1)} for k, v in sorted(vakken.items())]
totaal = sum(x["uren"] for x in vak_list) + stage_uren
if vak_list or stage_uren:
per_leerling.append({
"leerling": l.volledige_naam,
"groep": l.groep.naam if l.groep else None,
"vakken": vak_list,
"stage_uren": round(stage_uren, 1),
"totaal": round(totaal, 1),
})
per_leerling.sort(key=lambda x: x["leerling"])
return Response({
"schooljaar": sj.naam,
"lesdagen": lesdagen,
"per_groep": per_groep,
"per_leerling": per_leerling,
})