feat(backoffice): exportação CSV nas listagens, com audit

Novo helper csv_export() (config/functions.php): CSV Excel-friendly (BOM UTF-8
+ ';') e cada exportação fica no audit_log (RGPD: exportar dados pessoais tem
de ser rastreável). Botão "Exportar CSV" em todas as listagens do backoffice:
equipa, eventos, galerias, ginásios, horário, mensalidades, modalidades,
horário de funcionamento e lixeira (pedidos de inscrição e aulas experimentais
já tinham). Fecha a metade "exportação com permissões e audit" do item 6.9
(a única parte que o relatório considera ganho real à escala atual).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
andreandClaude Fable 5 committed 2026-09-25 23:43:41 +01:00
1 parent 33158381bb
commit 116817e2de
10 files changed
+122 -4

No files matched your search

+21
View File
@@ -100,6 +100,27 @@ function format_date_pt(string $date): string {
return (new DateTime($date))->format('d/m/Y');
}
// ─── CSV export (backoffice listings) ────────────────────────────────────────
// Excel-friendly CSV (UTF-8 BOM + ';'). Every export is recorded in the audit
// log — RGPD requires personal-data exports to be traceable.
function csv_export(string $type, string $filename, string $summary, array $header, array $rows): void {
audit('export.' . $type, [
'target_type' => $type,
'target_label' => 'CSV (' . count($rows) . ' registos)',
'summary' => $summary,
]);
header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename="' . $filename . '-' . date('Y-m-d') . '.csv"');
$out = fopen('php://output', 'w');
fwrite($out, "\xEF\xBB\xBF");
fputcsv($out, $header, ';', '"', '');
foreach ($rows as $row) {
fputcsv($out, $row, ';', '"', '');
}
fclose($out);
exit;
}
// ─── Email template loader ────────────────────────────────────────────────────
// {{placeholder}} HTML bodies under templates/emails/. Built locally, delivered
// by id.andmore.pt via the enqueue_email()/flush_message() façade.