Files
Pivot/blueprints/students.py
2026-10-14 13:34:37 +02:00

190 lines
8.3 KiB
Python

from flask import Blueprint, render_template, request, session, redirect, url_for, flash
from database import execute_query, get_db_connection
from blueprints.auth import login_required
from rechten import recht_vereist
from services.google_service import GoogleAdminService
from services.sync_service import SyncService, InformatSmartschoolSync
from config import Config
students_bp = Blueprint('students', __name__)
#-----------------------------------------------
# --- ROUTE: INVENTARIS LEERLINGEN ---
#-----------------------------------------------
@students_bp.route('/inventaris', methods=["GET", "POST"])
@login_required
@recht_vereist('leerlingen_bekijken')
def inventaris_leerlingen():
query = request.form.get('query') if request.method == 'POST' else request.args.get('query')
toon_vertrokken = (request.form.get('vertrokken') if request.method == 'POST' else request.args.get('vertrokken')) == '1'
from services.sync_service import zorg_vertrokken_kolom
zorg_vertrokken_kolom()
# De basis-query waarin we de tabellen 'Leerlingen' (l) en 'Schooljaar' (s) aan elkaar koppelen
basis_sql = """
SELECT
l.Internnummer,
l.Gebruikersnaam,
l.Voornaam,
l.Naam,
l.SS_nummer,
l.Google_adres,
l.Vertrokken_op,
s.Schooljaar AS Schooljaar -- Hier halen we de tekst (bijv. '2025-2026') op!
FROM Leerlingen l
LEFT JOIN Schooljaar s ON l.Schooljaar_ID = s.Schooljaar_ID
"""
voorwaarden, params = [], []
if query:
voorwaarden.append("(l.Gebruikersnaam LIKE %s OR l.Internnummer LIKE %s OR l.Naam LIKE %s OR l.Voornaam LIKE %s)")
params += [f"%{query}%"] * 4
if not toon_vertrokken:
voorwaarden.append("l.Vertrokken_op IS NULL")
sql = basis_sql + (" WHERE " + " AND ".join(voorwaarden) if voorwaarden else "")
data = execute_query(sql, tuple(params))
vertrokken = (execute_query("SELECT COUNT(*) AS n FROM Leerlingen WHERE Vertrokken_op IS NOT NULL") or [{'n': 0}])[0]['n']
return render_template('Inventaris_Leerlingen.html', results=data, query=query,
toon_vertrokken=toon_vertrokken, aantal_vertrokken=vertrokken)
#----------------------------------------
# --- ROUTE: BEWERK GEBRUIKER ---
#----------------------------------------
@students_bp.route("/bewerk_gebruiker", methods=["POST"])
@login_required
@recht_vereist('leerlingen_bekijken')
def bewerk_gebruiker():
print("bewerken wordt uitgevoerd")
internnummer = request.form.get("internnummer")
gebruikersnaam = request.form.get("gebruikersnaam")
ss_nummer = request.form.get("ss_nummer")
google_adres = request.form.get('google_adres')
naam= request.form.get('naam')
voornaam= request.form.get('voornaam')
query = request.form.get("query", "")
if not internnummer:
flash("Fout: Geen internnummer ontvangen.", "error")
return redirect(url_for("students.inventaris_leerlingen"))
sql = "UPDATE Leerlingen SET Gebruikersnaam = %s, SS_nummer = %s, Google_adres = %s, Naam = %s, Voornaam= %s WHERE Internnummer = %s"
rows_affected = execute_query(sql, (gebruikersnaam, ss_nummer, google_adres, naam, voornaam, internnummer ), commit=True)
if rows_affected:
flash(f"Gegevens voor {internnummer} succesvol bijgewerkt!", "success")
else:
flash("Er zijn geen wijzigingen opgeslagen.", "info")
return redirect(url_for("students.inventaris_leerlingen", query=query))
#----------------------------------------------------
# --- ROUTE: SYNC GOOGLE ACCOUNTS ---
#----------------------------------------------------
@students_bp.route("/sync_google_accounts", methods=["GET", "POST"])
@login_required
@recht_vereist('leerlingen_synchroniseren')
def sync_google_accounts():
"""Maakt Google accounts aan voor leerlingen die er nog geen hebben."""
google = GoogleAdminService()
# Haal leerlingen op die nog geen email (SS_nummer) hebben
lln_zonder_mail = execute_query("SELECT Internnummer, Gebruikersnaam FROM Leerlingen WHERE SS_nummer IS NULL OR SS_nummer = ''")
created_count = 0
error_count = 0
for lln in lln_zonder_mail:
gebruikersnaam_db = lln['Gebruikersnaam']
# Splits naam (bijv: "Janssens.Jan")
if "." in gebruikersnaam_db:
achternaam, voornaam = gebruikersnaam_db.split(".", 1)
else:
achternaam, voornaam = gebruikersnaam_db, "lln"
# Genereer wachtwoord (bijv: 12345Jan)
password = f"{lln['Internnummer']}{voornaam.capitalize()}"
# Gebruik je service om de gebruiker aan te maken
success, message = google.create_user(
first_name=voornaam,
last_name=achternaam,
password=password,
org_unit_path=google.conf.OU_NEW_STUDENTS
)
if success:
# Update database met het nieuwe emailadres
email = f"{voornaam.lower()}.{achternaam.lower()}@{google.conf.SCHOOL_DOMAIN}"
execute_query("UPDATE Leerlingen SET SS_nummer = %s WHERE Internnummer = %s",
(email, lln['Internnummer']), commit=True)
created_count += 1
else:
print(f"Fout voor {gebruikersnaam_db}: {message}")
error_count += 1
flash(f"Sync voltooid: {created_count} accounts aangemaakt, {error_count} fouten.", "success")
return redirect(url_for("students.inventaris_leerlingen"))
#-------------------------------------------------------------------
# --- ROUTE: SYNC INFORMAT (Gebruikmakend van SyncService) ---
#-------------------------------------------------------------------
@students_bp.route("/sync_informat", methods=["GET", "POST"])
@login_required
@recht_vereist('leerlingen_synchroniseren')
def sync_informat():
"""Haalt de nieuwste leerlinggegevens op uit Informat."""
#syncer = SyncService()
syncer = InformatSmartschoolSync()
#success, result = syncer.sync_leerlingen_informat()
success, result = syncer.sync_actieve_leerlingen()
if success:
flash(f"Synchronisatie gelukt: {result['melding']}", "success")
if result.get('smartschool_fout'):
flash("Smartschool kon niet bevraagd worden, dus gebruikersnamen en Smartschool-nummers zijn niet "
f"aangepast (enkel de gegevens uit Informat). Reden: {result['smartschool_fout']}", "warning")
else:
flash(f"Synchronisatie mislukt: {result}", "error")
return redirect(url_for("students.inventaris_leerlingen"))
#-------------------------------------------------------------------
# --- Leerling manueel toevoegen
#-------------------------------------------------------------------
@students_bp.route('/registreer_leerling', methods=['POST'])
@login_required
@recht_vereist('leerlingen_synchroniseren')
def registreer_leerling():
print('Toevoegen gestart')
# 1. Haal de gegevens uit het formulier op
internnummer = request.form.get('inter_id')
gebruikersnaam = request.form.get('gebruikersnaam')
ss_nummer = request.form.get('ss_nummer')
google_adres = request.form.get('google_adres')
schooljaar_id= Config.SCHOOLYEAR[:4]
naam= request.form.get('naam')
voornaam= request.form.get('voornaam')
# 2. Validatie
if not internnummer or not gebruikersnaam:
flash('Zowel Internnummer als Gebruikersnaam zijn vereist.', 'danger')
return redirect(url_for('students.inventaris_leerlingen'))
# 3. Opslaan in de database
try:
# We gebruiken geparametriseerde queries (%s) om SQL-injectie te voorkomen
sql = "INSERT INTO Leerlingen (Internnummer, Gebruikersnaam, Naam, Voornaam, SS_nummer, Google_adres, Schooljaar_ID) " \
"VALUES (%s, %s, %s, %s, %s, %s, %s)"
params = (internnummer, gebruikersnaam,naam, voornaam, ss_nummer,google_adres, schooljaar_id)
execute_query(sql, params, commit=True)
flash(f'Leerling {gebruikersnaam} (ID: {internnummer}) succesvol toegevoegd aan de database!', 'success')
except Exception as e:
# Als bijvoorbeeld het internnummer al bestaat (Duplicate Entry)
print(f"Database error: {e}")
flash('Fout bij het registreren: Mogelijk bestaat dit Internnummer al.', 'danger')
# 4. Keer terug naar het overzicht
return redirect(url_for('students.inventaris_leerlingen'))