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

108 lines
4.6 KiB
Python

from flask import Blueprint, render_template, request, jsonify, make_response, flash
from io import BytesIO # <-- Deze regel lost de NameError op
from xhtml2pdf import pisa
from datetime import datetime
from services.smartschool_api import SmartschoolService
from config import Config
from database import execute_query
from tenancy import per_school
from blueprints.auth import login_required
from rechten import recht_vereist
smartschool_bp = Blueprint("/ss",__name__)
# Eén Smartschool-client per school (met het webservice-wachtwoord van die school)
ss_service = per_school(lambda: SmartschoolService(
platform=Config.SS_API_PLATFORM,
webservice_pwd=Config.SS_API_PW
))
@smartschool_bp.route('/smartschool', methods=['GET', 'POST'])
@login_required
@recht_vereist('smartschool')
def smartschool():
results = []
query = (request.form.get('query') or '').strip()
if request.method == 'POST' and query:
# 1) Exact internnummer of gebruikersnaam: rechtstreeks bij Smartschool
try:
user_data = ss_service.get_student_details(query)
except Exception as e:
user_data = None
flash(f"Smartschool is niet bereikbaar of nog niet ingesteld voor deze school ({e}).", "error")
if user_data:
results = [user_data]
else:
# 2) Deel van een naam, voornaam of gebruikersnaam: zoeken in de leerlingen van PIVOT
results = zoek_leerlingen_lokaal(query)
return render_template('smartschool_beheer.html', results=results, query=query)
MAX_RESULTATEN = 25
def zoek_leerlingen_lokaal(query):
"""Leerlingen uit de tabel Leerlingen (gevuld door de Informat-sync) die op de zoekterm lijken.
Geeft dicts met dezelfde sleutels als Smartschool (internnummer, voornaam, naam, gebruikersnaam)."""
zoek = f"%{query}%"
rows = execute_query(
"SELECT Internnummer, Voornaam, Naam, Gebruikersnaam FROM Leerlingen "
"WHERE Internnummer = %s OR Gebruikersnaam LIKE %s OR Voornaam LIKE %s OR Naam LIKE %s "
" OR CONCAT_WS(' ', Voornaam, Naam) LIKE %s OR CONCAT_WS(' ', Naam, Voornaam) LIKE %s "
"ORDER BY Naam, Voornaam LIMIT %s",
(query, zoek, zoek, zoek, zoek, zoek, MAX_RESULTATEN))
return [{'internnummer': r['Internnummer'], 'voornaam': r['Voornaam'] or '', 'naam': r['Naam'] or '',
'gebruikersnaam': r['Gebruikersnaam'] or ''} for r in rows]
@smartschool_bp.route('/smartschool/reset', methods=['POST'])
@login_required
@recht_vereist('smartschool')
def smartschool_reset():
identifier = request.form.get('username')
new_pass = request.form.get('new_password')
acc_type = int(request.form.get('account_type', 0))
generate_pdf = request.form.get('generate_pdf') == 'true'
display_name = request.form.get('display_name') # Ontvang de naam uit de browser
result = ss_service.reset_password(identifier, new_pass, acc_type)
if result == "0":
if generate_pdf:
# We gebruiken de display_name die we van de frontend hebben gekregen
# Voor de e-mail label kunnen we nog steeds student details ophalen indien nodig
student_data = ss_service.get_student_details(identifier)
email_label = student_data.get('gebruikersnaam') if acc_type == 0 else f"Co-account van {student_data['voornaam']}"
rendered_html = render_template(
'pdf_template_leerling.html',
naam=display_name,
datum=datetime.now().strftime("%d/%m/%Y"),
email=email_label,
wachtwoord=new_pass
)
pdf_out = BytesIO()
pisa_status = pisa.CreatePDF(rendered_html, dest=pdf_out)
if pisa_status.err:
return jsonify({"status": "error", "message": "PDF generatie mislukt"})
pdf_out.seek(0)
response = make_response(pdf_out.read())
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = f'attachment; filename=Account_{identifier}.pdf'
return response
return jsonify({"status": "success"})
return jsonify({"status": "error", "message": f"Code {result}"})
@smartschool_bp.route('/smartschool/coaccounts', methods=['POST'])
@login_required
@recht_vereist('smartschool')
def smartschool_coaccounts():
username = request.form.get('username')
# Gebruik de nieuwe parser functie
co_accounts = ss_service.get_co_accounts_from_details(username)
return jsonify({"status": "success", "accounts": co_accounts})