PIVOT 1.1.0

This commit is contained in:
marijn committed 2026-10-14 13:34:37 +02:00
commit 8a53234eb6
161 files changed
+31109

No files matched your search

+198
View File
@@ -0,0 +1,198 @@
{% extends "base.html" %}
{% block title %}{{ titel }}{% endblock %}
{% block page_title %}{{ titel }}{% endblock %}
{% block loader_text %}Bezig met tellen via Informat API...{% endblock %}
{% block content %}
<style>
.peil-form { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-bottom: 14px; }
.peil-form .field { margin: 0; }
.peil-form input[type=date] { min-width: 180px; }
.peildata { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 16px; padding: 0; list-style: none; }
.peildata a { display: inline-block; padding: 6px 12px; border: 1px solid var(--border); border-radius: 999px;
text-decoration: none; color: inherit; font-size: .9em; background: var(--surface); }
.peildata a.actief { border-color: var(--primary-color); color: var(--primary-color); font-weight: 700; }
.peildata a span { color: var(--text-muted, #64748b); font-weight: 400; margin-left: 4px; }
/* Campussen van een school met meerdere instellingsnummers */
tr.campus-rij td { background: var(--surface-muted); border-top: 0; padding-top: 6px; padding-bottom: 6px; font-size: .92em; }
tr.campus-rij td:first-child { padding-left: 32px; }
tr.campus-rij .campus-naam { color: var(--text-muted, #475569); }
tr.campus-rij td.text-right { color: var(--text-muted, #475569); font-weight: 600; }
/* Onderwijsniveau: kop en subtotaal per groep */
tr.niveau-kop td { background: var(--surface-muted); font-size: .78em; font-weight: 700; letter-spacing: .06em;
text-transform: uppercase; color: var(--text-muted, #475569); padding-top: 10px; padding-bottom: 10px; }
tr.subtotaal-rij td { background: color-mix(in srgb, var(--primary-color) 10%, transparent);
border-top: 2px solid var(--primary-color); font-weight: 700; color: var(--primary-color); }
tr.subtotaal-rij td.text-right { font-size: 1.15em; }
tr.totaal-rij td { background: var(--primary-color); color: #fff; font-weight: 800; font-size: 1.05em;
padding-top: 14px; padding-bottom: 14px; border: 0; }
tr.totaal-rij td.text-right { font-size: 1.3em; }
</style>
{# ---------- Telling op peildatum ---------- #}
<div class="card">
<div class="page-head">
<h2>📅 Telling op peildatum</h2>
{% if peildata %}
<a class="btn btn-light btn-sm" href="{{ url_for(ep ~ '.export_csv', alle=1, query=query or None) }}">⬇️ CSV alle peildata</a>
{% endif %}
</div>
<form method="POST" action="{{ url_for(ep ~ '.tel_peildatum') }}" class="peil-form" onsubmit="showLoader()">
<div class="field">
<label for="peildatum">Peildatum</label>
<input type="date" id="peildatum" name="peildatum" required
value="{{ (peildatum or vandaag).isoformat() }}">
</div>
<button type="submit">🔢 Tellen voor alle scholen</button>
</form>
{% if peildata %}
<ul class="peildata">
{% for p in peildata %}
<li><a href="{{ url_for(ep ~ '.' ~ pagina, peildatum=p.Peildatum.isoformat()) }}"
class="{{ 'actief' if peildatum and p.Peildatum == peildatum else '' }}">
{{ p.Peildatum.strftime('%d-%m-%Y') }}<span>{{ (p.Totaal or 0)|int }} {{ kort }}</span></a></li>
{% endfor %}
</ul>
{% endif %}
{% if telling %}
<div class="page-head" style="margin-bottom:10px">
<h3 style="margin:0">{{ eenheid }} op {{ peildatum.strftime('%d-%m-%Y') }}</h3>
<div class="actions">
<a class="btn btn-light btn-sm" href="{{ url_for(ep ~ '.export_csv', peildatum=peildatum.isoformat(), query=query or None) }}">⬇️ CSV-export</a>
<form method="POST" action="{{ url_for(ep ~ '.verwijder_peildatum') }}" style="margin:0"
onsubmit="return confirm('De telling van {{ peildatum.strftime('%d-%m-%Y') }} verwijderen?')">
<input type="hidden" name="peildatum" value="{{ peildatum.isoformat() }}">
<button type="submit" class="btn-sm btn-ghost">🗑️ Verwijderen</button>
</form>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>School</th>
<th class="text-right">{{ eenheid }}</th>
<th>Opgevraagd</th>
<th class="actions">Actie</th>
</tr>
</thead>
{% for g in telling_groepen %}
<tbody>
<tr class="niveau-kop"><td colspan="4">{{ g.label }}</td></tr>
{% for row in g.rijen %}
<tr>
<td><strong>{{ row.Naam_school }}</strong></td>
<td class="text-right"><span style="font-size: 1.1em; color: var(--primary-color); font-weight: 700;">{{ row.Aantal if row.Aantal is not none else '–' }}</span></td>
<td class="muted small">{% if row.Opgevraagd_op %}{{ row.Opgevraagd_op.strftime('%d-%m-%Y %H:%M') }}{% if row.Door %} · {{ row.Door }}{% endif %}{% else %}Niet geteld{% endif %}</td>
<td class="actions">
{% if row.Informat %}
<form method="POST" action="{{ url_for(ep ~ '.tel_peildatum') }}" onsubmit="showLoader()">
<input type="hidden" name="peildatum" value="{{ peildatum.isoformat() }}">
<input type="hidden" name="school_code" value="{{ row.Code }}">
<button type="submit" class="btn-sm btn-secondary">🔄 Opnieuw tellen</button>
</form>
{% else %}
<span class="muted small">Informat niet ingesteld</span>
{% endif %}
</td>
</tr>
{% for c in row.Campussen %}
<tr class="campus-rij">
<td><span class="campus-naam">↳ {{ c.naam }}</span></td>
<td class="text-right">{{ c.aantal }}</td>
<td colspan="2"></td>
</tr>
{% endfor %}
{% endfor %}
{% if g.code %}
<tr class="subtotaal-rij"><td>Subtotaal {{ g.label|lower }}</td><td class="text-right">{{ g.subtotaal }}</td><td colspan="2"></td></tr>
{% endif %}
</tbody>
{% endfor %}
<tfoot>
<tr class="totaal-rij"><td>Totaal scholengroep</td><td class="text-right">{{ telling_totaal }}</td><td colspan="2"></td></tr>
</tfoot>
</table>
</div>
{% endif %}
</div>
{# ---------- Huidig aantal ---------- #}
<div class="card">
<div class="page-head">
<h2>🏢 Scholengroep: huidig aantal</h2>
<div class="actions">
<a class="btn btn-light btn-sm" href="{{ url_for(ep ~ '.export_csv', query=query or None) }}">⬇️ CSV-export</a>
<form method="POST" action="{{ url_for(ep ~ '.sync_aanvragen') }}" onsubmit="showLoader()" style="margin:0">
<input type="hidden" name="alle" value="1">
<button type="submit" class="btn-sm btn-secondary">🔄 Alle scholen synchroniseren</button>
</form>
</div>
</div>
<form method="GET" action="{{ url_for(ep ~ '.' ~ pagina) }}" class="search-bar">
{% if peildatum %}<input type="hidden" name="peildatum" value="{{ peildatum.isoformat() }}">{% endif %}
<input type="text" name="query" placeholder="Zoek op schoolnaam..." value="{{ query or '' }}">
<button type="submit">🔍 Zoeken</button>
{% if query %}
<a href="{{ url_for(ep ~ '.' ~ pagina, peildatum=peildatum.isoformat() if peildatum else None) }}" class="btn btn-light">✕ Wissen</a>
{% endif %}
</form>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>School</th>
<th class="text-right">{{ eenheid }}</th>
<th>Laatste synchronisatie</th>
<th class="actions">Actie</th>
</tr>
</thead>
{% for g in groepen %}
<tbody>
<tr class="niveau-kop"><td colspan="4">{{ g.label }}</td></tr>
{% for row in g.rijen %}
<tr>
<td><strong>{{ row['Naam_school'] }}</strong></td>
<td class="text-right"><span style="font-size: 1.1em; color: var(--primary-color); font-weight: 700;">{{ row['Huidig'] }}</span></td>
<td>{{ row['Laatste_synchronisatie'] or 'Nog nooit' }}</td>
<td class="actions">
{% if row['Informat'] %}
<form method="POST" action="{{ url_for(ep ~ '.sync_aanvragen') }}" onsubmit="showLoader()">
<input type="hidden" name="school_code" value="{{ row['Code'] }}">
<button type="submit" class="btn-sm btn-secondary">🔄 Sync aanvragen</button>
</form>
{% else %}
<span class="muted small">Informat niet ingesteld</span>
{% endif %}
</td>
</tr>
{% for c in row['Campussen'] %}
<tr class="campus-rij">
<td><span class="campus-naam">↳ {{ c.naam }}</span></td>
<td class="text-right">{{ c.aantal }}</td>
<td colspan="2"></td>
</tr>
{% endfor %}
{% endfor %}
{% if g.code %}
<tr class="subtotaal-rij"><td>Subtotaal {{ g.label|lower }}</td><td class="text-right">{{ g.subtotaal }}</td><td colspan="2"></td></tr>
{% endif %}
</tbody>
{% else %}
<tbody><tr class="empty-row"><td colspan="4">Geen scholen gevonden.</td></tr></tbody>
{% endfor %}
{% if results %}
<tfoot>
<tr class="totaal-rij"><td>Totaal scholengroep</td><td class="text-right">{{ totaal }}</td><td colspan="2"></td></tr>
</tfoot>
{% endif %}
</table>
</div>
</div>
{% endblock %}