101 lines
3.7 KiB
Python
101 lines
3.7 KiB
Python
import csv
|
|
import io
|
|
|
|
from django.http import HttpResponse
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.response import Response
|
|
|
|
from core.audit import audit_log
|
|
from core.models import Afwezigheid, Groep, Persoon, Roosterblok
|
|
from core.permissions import CoreDataPermission, StaffDataPermission, module_permission_class
|
|
|
|
ImportExportModuleEnabled = module_permission_class("importexport")
|
|
|
|
|
|
def _doel_naam(blok):
|
|
if blok.groep_id:
|
|
return blok.groep.naam
|
|
if blok.subgroep_id:
|
|
return blok.subgroep.naam
|
|
if blok.leerling_id:
|
|
return blok.leerling.volledige_naam
|
|
return ""
|
|
|
|
|
|
EXPORTS = {
|
|
"personen": (
|
|
["id", "voornaam", "achternaam", "rol", "groep"],
|
|
lambda: Persoon.objects.select_related("groep").all(),
|
|
lambda p: [p.id, p.voornaam, p.achternaam, p.rol, p.groep.naam if p.groep_id else ""],
|
|
),
|
|
"groepen": (
|
|
["id", "naam", "actief"],
|
|
lambda: Groep.objects.all(),
|
|
lambda g: [g.id, g.naam, g.actief],
|
|
),
|
|
"roosterblokken": (
|
|
["id", "schooljaar", "tijdslot", "activiteit", "doel_type", "doel", "begeleiders"],
|
|
lambda: Roosterblok.objects.select_related(
|
|
"schooljaar", "tijdslot", "activiteit", "groep", "subgroep", "leerling"
|
|
).prefetch_related("begeleiders"),
|
|
lambda b: [
|
|
b.id,
|
|
b.schooljaar.naam,
|
|
str(b.tijdslot),
|
|
b.activiteit.naam,
|
|
b.doel_type,
|
|
_doel_naam(b),
|
|
", ".join(p.volledige_naam for p in b.begeleiders.all()),
|
|
],
|
|
),
|
|
"afwezigheden": (
|
|
["id", "persoon", "start_datum", "eind_datum", "reden"],
|
|
lambda: Afwezigheid.objects.select_related("persoon").all(),
|
|
lambda a: [a.id, a.persoon.volledige_naam, a.start_datum, a.eind_datum, a.reden],
|
|
),
|
|
}
|
|
|
|
|
|
@api_view(["GET"])
|
|
@permission_classes([StaffDataPermission, ImportExportModuleEnabled])
|
|
def export_csv(request, resource):
|
|
if resource not in EXPORTS:
|
|
return Response({"detail": "Onbekende export."}, status=404)
|
|
headers, queryset_factory, row_factory = EXPORTS[resource]
|
|
response = HttpResponse(content_type="text/csv; charset=utf-8")
|
|
response["Content-Disposition"] = f'attachment; filename="{resource}.csv"'
|
|
response.write("\ufeff")
|
|
writer = csv.writer(response)
|
|
writer.writerow(headers)
|
|
for obj in queryset_factory():
|
|
writer.writerow(row_factory(obj))
|
|
audit_log(request, "export", f"CSV:{resource}")
|
|
return response
|
|
|
|
|
|
@api_view(["POST"])
|
|
@permission_classes([CoreDataPermission, ImportExportModuleEnabled])
|
|
def import_personen(request):
|
|
tekst = request.data.get("csv") or ""
|
|
if not tekst.strip():
|
|
return Response({"detail": "CSV-inhoud ontbreekt."}, status=400)
|
|
reader = csv.DictReader(io.StringIO(tekst))
|
|
aangemaakt = 0
|
|
meldingen = []
|
|
for nummer, row in enumerate(reader, start=2):
|
|
voornaam = (row.get("voornaam") or row.get("Voornaam") or "").strip()
|
|
achternaam = (row.get("achternaam") or row.get("Achternaam") or "").strip()
|
|
rol = (row.get("rol") or row.get("Rol") or "leerling").strip()
|
|
groep_naam = (row.get("groep") or row.get("Groep") or "").strip()
|
|
if not voornaam and not achternaam:
|
|
continue
|
|
groep = None
|
|
if groep_naam:
|
|
groep, _ = Groep.objects.get_or_create(naam=groep_naam)
|
|
try:
|
|
Persoon.objects.create(voornaam=voornaam, achternaam=achternaam, rol=rol, groep=groep)
|
|
aangemaakt += 1
|
|
except Exception as exc:
|
|
meldingen.append(f"Rij {nummer}: {exc}")
|
|
audit_log(request, "import", "Persoon", {"aangemaakt": aangemaakt, "meldingen": len(meldingen)})
|
|
return Response({"aangemaakt": aangemaakt, "meldingen": meldingen})
|