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

97 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
"""Leerlingfacturatie: facturen en creditnota's van de leerlingen van de actieve school (Informat Rekeningen API)."""
import csv
import io
import time
from datetime import date
from flask import Blueprint, render_template, request, Response, redirect, url_for, flash
from blueprints.auth import login_required
from rechten import recht_vereist
from services.facturatie_service import FacturatieService, FacturatieFout, schooljaren
from tenancy import huidige_school
facturatie_bp = Blueprint('facturatie', __name__)
STATUS_LABELS = {'open': 'Open', 'gedeeltelijk': 'Gedeeltelijk betaald', 'betaald': 'Betaald', 'credit': 'Creditnota'}
def _schooljaar():
jaren = schooljaren()
gekozen = request.args.get('schooljaar') or ''
return gekozen if gekozen in jaren else jaren[0], jaren
@facturatie_bp.route("/", methods=["GET"])
@login_required
@recht_vereist('leerlingfacturatie')
def overzicht():
school = huidige_school()
schooljaar, jaren = _schooljaar()
rijen, groepen, fout, opgehaald = [], [], None, None
if not school.heeft('INFORMAT_ID', 'INFORMAT_SECRET'):
fout = "Informat is nog niet ingesteld voor deze school (🔌 Koppelingen › Informat)."
else:
try:
rijen, groepen, t = FacturatieService().facturen(schooljaar, vernieuw=bool(request.args.get('vernieuw')))
opgehaald = time.strftime('%d-%m-%Y %H:%M', time.localtime(t))
except FacturatieFout as e:
fout = str(e)
except Exception as e:
fout = f"Facturen ophalen mislukt: {e}"
return render_template("facturatie.html", rijen=rijen, groepen=groepen, fout=fout, opgehaald=opgehaald,
schooljaar=schooljaar, jaren=jaren, school_naam=school.naam, labels=STATUS_LABELS,
today=date.today())
@facturatie_bp.route("/pdf/<toegangsgroep>/<invoice_id>", methods=["GET"])
@login_required
@recht_vereist('leerlingfacturatie')
def pdf(toegangsgroep, invoice_id):
try:
inhoud = FacturatieService().pdf(toegangsgroep, invoice_id)
except FacturatieFout as e:
flash(str(e), "error")
return redirect(url_for('facturatie.overzicht', schooljaar=request.args.get('schooljaar')))
except Exception as e:
flash(f"De PDF kon niet opgehaald worden: {e}", "error")
return redirect(url_for('facturatie.overzicht', schooljaar=request.args.get('schooljaar')))
naam = (request.args.get('naam') or 'factuur').replace('"', '')
return Response(inhoud, mimetype='application/pdf',
headers={'Content-Disposition': f'inline; filename="{naam}.pdf"'})
@facturatie_bp.route("/export.csv", methods=["GET"])
@login_required
@recht_vereist('leerlingfacturatie')
def export():
"""CSV met dezelfde filters als de tabel: ?schooljaar=&groep=&status=&zoek="""
schooljaar, _ = _schooljaar()
try:
rijen, _, _ = FacturatieService().facturen(schooljaar)
except Exception as e:
flash(str(e), "error")
return redirect(url_for('facturatie.overzicht', schooljaar=schooljaar))
groep, status = request.args.get('groep') or '', request.args.get('status') or ''
zoek = (request.args.get('zoek') or '').strip().lower()
if groep:
rijen = [r for r in rijen if str(r['groep_id']) == groep]
if status == 'onbetaald':
rijen = [r for r in rijen if r['status'] in ('open', 'gedeeltelijk')]
elif status:
rijen = [r for r in rijen if r['status'] == status]
if zoek:
rijen = [r for r in rijen if zoek in ' '.join(str(r[k]) for k in ('naam', 'voornaam', 'stamnummer', 'klas', 'groep', 'ogm')).lower()]
bedrag = lambda x: f"{x:.2f}".replace('.', ',')
datum = lambda d: d.strftime('%d/%m/%Y') if d else ''
buf = io.StringIO()
w = csv.writer(buf, delimiter=';')
w.writerow(['Naam', 'Voornaam', 'Stamnummer', 'Klas', 'Factuurgroep', 'Soort', 'Datum', 'Vervaldag', 'Totaal', 'Betaald',
'Open', 'Status', 'Gestructureerde mededeling'])
for r in rijen:
w.writerow([r['naam'], r['voornaam'], r['stamnummer'], r['klas'], r['groep'], 'Creditnota' if r['type'] == 'CREDIT_NOTE' else 'Factuur',
datum(r['datum']), datum(r['vervaldag']), bedrag(r['totaal'] * r['teken']), bedrag(r['betaald'] * r['teken']), bedrag(r['open'] * r['teken']),
STATUS_LABELS.get(r['status'], r['status']), r['ogm']])
return Response('' + buf.getvalue(), mimetype='text/csv; charset=utf-8', headers={
'Content-Disposition': f"attachment; filename=Facturen_{huidige_school().code}_{schooljaar}_{date.today():%Y%m%d}.csv"})