This commit is contained in:
Borgal
2025-11-16 21:13:04 +01:00
parent aeb2d87cf5
commit 1b9ba22bb5
11 changed files with 1104 additions and 234 deletions

277
export.php Executable file
View File

@@ -0,0 +1,277 @@
<?php
// define('DOMILI_ALLOW_WEB', true); // Zum Testen im Browser einkommentieren
if (php_sapi_name() !== 'cli' && !defined('DOMILI_ALLOW_WEB')) {
die('Zugriff verweigert.');
}
require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/inc/db.php';
use Dompdf\Dompdf;
use Dompdf\Options;
date_default_timezone_set('Europe/Berlin');
// === 1. Berichtsmonat ===
$berichtsMonatEnde = new DateTime('last day of last month');
$berichtsMonatBeginn = new DateTime('first day of last month');
// === 2. Letzter Jahresabschluss ===
$last_closing = '2020-01-01';
$res = mysqli_query($conn, "SELECT MAX(closing_date) AS last_date FROM penalty_closings");
if ($res && ($row = mysqli_fetch_assoc($res)) && !is_null($row['last_date'])) {
$last_closing = $row['last_date'];
}
// === 3. Alle Benutzer ===
$alleBenutzer = [];
$resUsers = mysqli_query($conn, "SELECT id, username FROM users ORDER BY username");
while ($row = mysqli_fetch_assoc($resUsers)) {
$alleBenutzer[$row['id']] = $row['username'];
}
$userIds = array_keys($alleBenutzer);
// === 4. Alle relevanten Daten (nur completed + attended=1) ===
$bisDatum = $berichtsMonatEnde->format('Y-m-d');
$stmt = mysqli_prepare($conn, "
SELECT m.id AS meeting_id, m.meeting_date,
mt.user_id, mt.wore_color, mt.paid
FROM meetings m
LEFT JOIN meeting_teilnehmer mt ON m.id = mt.meeting_id AND mt.attended = 1
WHERE m.meeting_date <= ? AND m.is_completed = 1
ORDER BY m.meeting_date
");
mysqli_stmt_bind_param($stmt, 's', $bisDatum);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$alleMeetingsMitTeilnehmern = [];
while ($row = mysqli_fetch_assoc($result)) {
$alleMeetingsMitTeilnehmern[] = $row;
}
mysqli_stmt_close($stmt);
// === 5. Meetings des Berichtsmonats mit Farben ===
$stmtMeta = mysqli_prepare($conn, "
SELECT id, meeting_date, reason, color_id
FROM meetings
WHERE meeting_date >= ? AND meeting_date <= ? AND is_completed = 1
ORDER BY meeting_date
");
$startDate = $berichtsMonatBeginn->format('Y-m-d');
$endDate = $berichtsMonatEnde->format('Y-m-d');
mysqli_stmt_bind_param($stmtMeta, 'ss', $startDate, $endDate);
mysqli_stmt_execute($stmtMeta);
$resultMeta = mysqli_stmt_get_result($stmtMeta);
$berichtsMeetingsMeta = [];
while ($row = mysqli_fetch_assoc($resultMeta)) {
$color_id = (int)$row['color_id'];
$colorStmt = mysqli_prepare($conn, "SELECT name FROM colors WHERE id = ?");
mysqli_stmt_bind_param($colorStmt, 'i', $color_id);
mysqli_stmt_execute($colorStmt);
$colorRes = mysqli_stmt_get_result($colorStmt);
$colorName = '';
if ($cRow = mysqli_fetch_assoc($colorRes)) {
$colorName = $cRow['name'];
}
mysqli_stmt_close($colorStmt);
$berichtsMeetingsMeta[] = [
'id' => $row['id'],
'meeting_date' => $row['meeting_date'],
'reason' => $row['reason'],
'color_name' => $colorName
];
}
mysqli_stmt_close($stmtMeta);
// === 6. Für jedes Meeting: alle Benutzer mit allen Werten ===
$gruppiert = [];
foreach ($berichtsMeetingsMeta as $meta) {
$mid = $meta['id'];
$meetingDatum = new DateTime($meta['meeting_date']);
$gruppiert[$mid] = [
'datum' => $meta['meeting_date'],
'reason' => $meta['reason'],
'color_name' => $meta['color_name'],
'teilnehmer' => []
];
foreach ($userIds as $uid) {
$username = $alleBenutzer[$uid];
$teilgenommen = false;
$wore_color = null;
$paid_this = false;
foreach ($alleMeetingsMitTeilnehmern as $mt) {
if ($mt['meeting_id'] == $mid && $mt['user_id'] == $uid) {
$teilgenommen = true;
$wore_color = !empty($mt['wore_color']);
$paid_this = !empty($mt['paid']);
break;
}
}
// Kumulierte Werte bis zu diesem Meeting
$strafenGesamt = 0;
$offeneStrafen = 0;
$teilnahmenGesamt = 0;
$rechnungenGesamt = 0;
foreach ($alleMeetingsMitTeilnehmern as $mt) {
if ($mt['user_id'] != $uid || is_null($mt['user_id'])) continue;
$mDatum = new DateTime($mt['meeting_date']);
if ($mDatum > $meetingDatum) continue;
$teilnahmenGesamt++;
if (!$mt['wore_color']) {
$strafenGesamt++;
if ($mt['meeting_date'] >= $last_closing) {
$offeneStrafen++;
}
}
if (!empty($mt['paid'])) {
$rechnungenGesamt++;
}
}
$userNameAnzeige = htmlspecialchars($username);
if ($paid_this) {
$userNameAnzeige .= ' <span class="paid-symbol">€</span>';
}
if (!$teilgenommen) {
$farbeSymbol = '';
} else {
$farbeSymbol = $wore_color ? '✓' : '✗';
}
$gruppiert[$mid]['teilnehmer'][] = [
'username' => $userNameAnzeige,
'farbe_symbol' => $farbeSymbol,
'teilgenommen' => $teilgenommen,
'offene_strafen' => $offeneStrafen,
'strafen_gesamt' => $strafenGesamt,
'teilnahmen_gesamt' => $teilnahmenGesamt,
'rechnungen_gesamt' => $rechnungenGesamt
];
}
}
// === 7. Gesamt offene Strafen ===
$gesamtOffen = 0;
foreach ($alleMeetingsMitTeilnehmern as $mt) {
if (!is_null($mt['user_id']) && !$mt['wore_color'] && $mt['meeting_date'] >= $last_closing) {
$gesamtOffen++;
}
}
// === 8. PDF-Pfad ===
@mkdir(__DIR__ . '/backups', 0755, true);
$baseName = 'DoMiLi_Backup_' . $berichtsMonatBeginn->format('Y-m');
$counter = 0;
$outputPath = __DIR__ . '/backups/' . $baseName . '.pdf';
while (file_exists($outputPath)) {
$counter++;
$outputPath = __DIR__ . '/backups/' . $baseName . '_' . $counter . '.pdf';
}
// === 9. HTML mit allen Anforderungen ===
$html = '
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body { font-family: DejaVu Sans, Arial, sans-serif; font-size: 9pt; }
h1 { font-size: 14pt; margin-bottom: 14pt; }
h2 { font-size: 11pt; margin: 12pt 0 8pt 0; }
.strafkasse { font-weight: bold; margin: 0 0 14pt 0; padding: 6pt; background-color: #f9f9f9; border: 1px solid #ccc; }
table { width: 100%; border-collapse: collapse; margin-bottom: 12pt; }
th, td { border: 1px solid #333; padding: 4pt 6pt; text-align: left; }
th { background-color: #f0f0f0; font-weight: bold; }
.paid-symbol { color: red; font-weight: bold; }
.color-ok { color: green; }
.color-fail { color: red; }
.page-break { page-break-after: always; }
.meta { margin-top: 20pt; font-size: 8pt; color: #555; }
</style>
</head>
<body>
<h1>DoMiLi Monatliches Backup</h1>
<h2>Zeitraum: ' . $berichtsMonatBeginn->format('F Y') . '</h2>
<div class="strafkasse">Strafkasse: ' . $gesamtOffen . ' €</div>';
if (empty($berichtsMeetingsMeta)) {
$html .= '<p>Keine abgeschlossenen Meetings im Berichtsmonat.</p>';
} else {
$meetingCount = 0;
foreach ($gruppiert as $meeting) {
if ($meetingCount > 0 && $meetingCount % 3 === 0) {
$html .= '<div class="page-break"></div>';
}
$meetingCount++;
$meetingDatum = new DateTime($meeting['datum']);
$html .= '<h3>' . $meetingDatum->format('d.m.Y') . ' ' . htmlspecialchars($meeting['reason']) . ' (' . htmlspecialchars($meeting['color_name']) . ')</h3>';
$html .= '<table>
<thead>
<tr>
<th>Benutzer*</th>
<th>Farbe getragen</th>
<th>offene Strafen (in €)</th>
<th>Strafen gesamt</th>
<th>Teilnahmen gesamt</th>
<th>Rechnung gesamt</th>
</tr>
</thead>
<tbody>';
foreach ($meeting['teilnehmer'] as $t) {
if ($t['farbe_symbol'] === '✓') {
$farbeHtml = '<span class="color-ok">✓</span>';
} elseif ($t['farbe_symbol'] === '✗') {
$farbeHtml = '<span class="color-fail">✗</span>';
} else {
$farbeHtml = $t['farbe_symbol'];
}
$html .= '<tr>
<td>' . $t['username'] . '</td>
<td>' . $farbeHtml . '</td>
<td>' . $t['offene_strafen'] . '</td>
<td>' . $t['strafen_gesamt'] . '</td>
<td>' . $t['teilnahmen_gesamt'] . '</td>
<td>' . $t['rechnungen_gesamt'] . '</td>
</tr>';
}
$html .= '</tbody></table>';
}
}
$html .= '
<div class="meta">
<p>Erstellt am: ' . date('d.m.Y') . '</p>
<p><em>* = "€" hat Restaurant-Rechnung bezahlt</em></p>
</div>
</body>
</html>';
// === 10. PDF erzeugen ===
$options = new Options();
$options->set('defaultFont', 'DejaVu Sans');
$dompdf = new Dompdf($options);
$dompdf->loadHtml($html);
$dompdf->setPaper('A4', 'portrait');
$dompdf->render();
file_put_contents($outputPath, $dompdf->output());
echo "✅ PDF erfolgreich gespeichert: " . $outputPath . "\n";