M5 Kaffeeliste read-only auf Ledger umstellen
- kaffeeliste.php aus ledger_fetch_participant_summaries lesen lassen - Legacy-Teilnehmerlinks ueber legacy_mitarbeiter_id erhalten - Sidebar-Zugriff fuer Legacy-Admin und SaaS-Rollen trennen - Smoke-Test um konkrete Ledger-Werte und Inaktiv-Ausschluss erweitern - M5-App-Kern-Doku ergaenzen
This commit is contained in:
+5
-3
@@ -101,7 +101,7 @@ function ledger_fetch_tenant_totals(PDO $pdo, int $tenantId, ?int $year = null):
|
|||||||
* - participant_ids: list<int>
|
* - participant_ids: list<int>
|
||||||
* - email_norms: list<string>
|
* - email_norms: list<string>
|
||||||
*
|
*
|
||||||
* @return list<array{participant_id: int, tenant_id: int, display_name: string, email: ?string, email_norm: ?string, paypal_name: ?string, active: bool, total_payments_cents: int, total_costs_cents: int, total_marks: int, balance_cents: int, year_payments_cents: int, year_costs_cents: int, year_marks: int}>
|
* @return list<array{participant_id: int, tenant_id: int, legacy_mitarbeiter_id: ?int, display_name: string, email: ?string, email_norm: ?string, paypal_name: ?string, active: bool, total_payments_cents: int, total_costs_cents: int, total_marks: int, balance_cents: int, year_payments_cents: int, year_costs_cents: int, year_marks: int}>
|
||||||
*/
|
*/
|
||||||
function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $options = []): array
|
function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $options = []): array
|
||||||
{
|
{
|
||||||
@@ -140,6 +140,7 @@ function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $opti
|
|||||||
SELECT
|
SELECT
|
||||||
p.id AS participant_id,
|
p.id AS participant_id,
|
||||||
p.tenant_id,
|
p.tenant_id,
|
||||||
|
p.legacy_mitarbeiter_id,
|
||||||
p.display_name,
|
p.display_name,
|
||||||
p.email,
|
p.email,
|
||||||
p.email_norm,
|
p.email_norm,
|
||||||
@@ -158,7 +159,7 @@ function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $opti
|
|||||||
AND le.participant_id = p.id
|
AND le.participant_id = p.id
|
||||||
AND le.voided_at IS NULL
|
AND le.voided_at IS NULL
|
||||||
WHERE " . implode(' AND ', $where) . "
|
WHERE " . implode(' AND ', $where) . "
|
||||||
GROUP BY p.id, p.tenant_id, p.display_name, p.email, p.email_norm, p.paypal_name, p.active
|
GROUP BY p.id, p.tenant_id, p.legacy_mitarbeiter_id, p.display_name, p.email, p.email_norm, p.paypal_name, p.active
|
||||||
ORDER BY p.display_name, p.id";
|
ORDER BY p.display_name, p.id";
|
||||||
|
|
||||||
$stmt = $pdo->prepare($sql);
|
$stmt = $pdo->prepare($sql);
|
||||||
@@ -169,6 +170,7 @@ function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $opti
|
|||||||
$summaries[] = [
|
$summaries[] = [
|
||||||
'participant_id' => (int)$row['participant_id'],
|
'participant_id' => (int)$row['participant_id'],
|
||||||
'tenant_id' => (int)$row['tenant_id'],
|
'tenant_id' => (int)$row['tenant_id'],
|
||||||
|
'legacy_mitarbeiter_id' => $row['legacy_mitarbeiter_id'] !== null ? (int)$row['legacy_mitarbeiter_id'] : null,
|
||||||
'display_name' => (string)$row['display_name'],
|
'display_name' => (string)$row['display_name'],
|
||||||
'email' => $row['email'] !== null ? (string)$row['email'] : null,
|
'email' => $row['email'] !== null ? (string)$row['email'] : null,
|
||||||
'email_norm' => $row['email_norm'] !== null ? (string)$row['email_norm'] : null,
|
'email_norm' => $row['email_norm'] !== null ? (string)$row['email_norm'] : null,
|
||||||
@@ -188,7 +190,7 @@ function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $opti
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array{participant_id: int, tenant_id: int, display_name: string, email: ?string, email_norm: ?string, paypal_name: ?string, active: bool, total_payments_cents: int, total_costs_cents: int, total_marks: int, balance_cents: int, year_payments_cents: int, year_costs_cents: int, year_marks: int}|null
|
* @return array{participant_id: int, tenant_id: int, legacy_mitarbeiter_id: ?int, display_name: string, email: ?string, email_norm: ?string, paypal_name: ?string, active: bool, total_payments_cents: int, total_costs_cents: int, total_marks: int, balance_cents: int, year_payments_cents: int, year_costs_cents: int, year_marks: int}|null
|
||||||
*/
|
*/
|
||||||
function ledger_fetch_participant_summary(PDO $pdo, int $tenantId, int $participantId, ?int $year = null): ?array
|
function ledger_fetch_participant_summary(PDO $pdo, int $tenantId, int $participantId, ?int $year = null): ?array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ Installation aus `.local/` verwendet werden.
|
|||||||
## Aktueller Pruefstatus
|
## Aktueller Pruefstatus
|
||||||
|
|
||||||
- M4 Ledger-Migration: gruen mit 73 Assertions.
|
- M4 Ledger-Migration: gruen mit 73 Assertions.
|
||||||
- M4 Ledger-Service: gruen mit 102 Assertions.
|
- M4 Ledger-Service: gruen mit 110 Assertions.
|
||||||
- M3 SaaS-Basis: weiterhin gruen.
|
- M3 SaaS-Basis: weiterhin gruen.
|
||||||
- M3 Tenant-Aufloesung: weiterhin gruen.
|
- M3 Tenant-Aufloesung: weiterhin gruen.
|
||||||
- M3 Passwort/E-Mail: weiterhin gruen.
|
- M3 Passwort/E-Mail: weiterhin gruen.
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# M5 App-Kern
|
||||||
|
|
||||||
|
Stand: 2026-07-14
|
||||||
|
|
||||||
|
M5 stellt die operativen App-Seiten schrittweise auf das neue tenant-sichere
|
||||||
|
Modell um. Der Start erfolgt bewusst read-only, damit Summen, Links und
|
||||||
|
Darstellung gegen die bestehende Legacy-Oberflaeche vergleichbar bleiben.
|
||||||
|
|
||||||
|
## Ziel
|
||||||
|
|
||||||
|
- Kernseiten aus `app/ledger.php` lesen lassen.
|
||||||
|
- Bestehendes Tabellenlayout und Bediengefuehl erhalten.
|
||||||
|
- Schreibende Legacy-Flows erst nach stabiler Leseparitaet umstellen.
|
||||||
|
- Tenant-Kontext serverseitig bestimmen, nicht aus Formularfeldern.
|
||||||
|
|
||||||
|
## Umgesetzter erster Schritt
|
||||||
|
|
||||||
|
Umgesetzte Datei:
|
||||||
|
|
||||||
|
```text
|
||||||
|
kaffeeliste.php
|
||||||
|
```
|
||||||
|
|
||||||
|
Umgesetzter Umfang:
|
||||||
|
|
||||||
|
- Die Gesamtuebersicht liest aktive Teilnehmer aus
|
||||||
|
`ledger_fetch_participant_summaries()`.
|
||||||
|
- Angezeigte Werte bleiben fachlich gleich: aktueller Stand, Gesamtausgabe,
|
||||||
|
Gesamtstriche und Gesamteinzahlungen.
|
||||||
|
- Links zur bestehenden `teilnehmerauswertung.php` bleiben ueber
|
||||||
|
`participants.legacy_mitarbeiter_id` erhalten.
|
||||||
|
- Owner, Admin und Treasurer duerfen die SaaS-Ansicht lesen.
|
||||||
|
- Der lokale Legacy-/Dev-Admin-Fallback nutzt nur ohne SaaS-Session den
|
||||||
|
Default-Tenant.
|
||||||
|
- Die Sidebar zeigt Legacy-Schreibseiten weiterhin nur fuer Legacy-Admins;
|
||||||
|
Ledger-Leseansichten sind fuer passende SaaS-Rollen sichtbar.
|
||||||
|
- Export, letzte Eintraege, CSV-Upload und Info-Mail bleiben noch Legacy-Flows.
|
||||||
|
|
||||||
|
## Noch offen
|
||||||
|
|
||||||
|
- `teilnehmerauswertung.php` lesend auf Ledger umstellen.
|
||||||
|
- `index.php` Dashboard lesend auf Ledger umstellen.
|
||||||
|
- Schreibseiten `stricheintragen.php` und `einzahlung.php` erst danach mit
|
||||||
|
Storno-/Reversal-Strategie vorbereiten.
|
||||||
|
- Export, Mail und Jahresprozesse bleiben M6-Themen.
|
||||||
|
|
||||||
|
## Aktueller Pruefstatus
|
||||||
|
|
||||||
|
- M4 Ledger-Migration: gruen mit 73 Assertions.
|
||||||
|
- M4 Ledger-Service: gruen mit 110 Assertions.
|
||||||
|
- Golden Master: gruen mit 104 Assertions.
|
||||||
|
- HTTP-Smoke: gruen mit 23 geprueften Seiten.
|
||||||
@@ -305,7 +305,7 @@ Uebersicht:
|
|||||||
| M2 | Technisches Fundament | Abgeschlossen: Migrationen, Bootstrap, Session, CSRF-Helper und Legacy-Schreibseitenschutz stehen |
|
| M2 | Technisches Fundament | Abgeschlossen: Migrationen, Bootstrap, Session, CSRF-Helper und Legacy-Schreibseitenschutz stehen |
|
||||||
| M3 | SaaS-Basis | Abgeschlossen: Tenants, User, Registrierung, Login, Rollen, Mail-Links und zentrale Mandantenauswahl funktionieren |
|
| M3 | SaaS-Basis | Abgeschlossen: Tenants, User, Registrierung, Login, Rollen, Mail-Links und zentrale Mandantenauswahl funktionieren |
|
||||||
| M4 | Datenmigration | Gestartet: Ledger-Tabelle, Legacy-Backfill, Paritaetscheck, Ledger-Service und Preview sind umgesetzt |
|
| M4 | Datenmigration | Gestartet: Ledger-Tabelle, Legacy-Backfill, Paritaetscheck, Ledger-Service und Preview sind umgesetzt |
|
||||||
| M5 | App-Kern | Dashboard, Striche, Einzahlungen, Mitglieder und Liste laufen |
|
| M5 | App-Kern | Gestartet: Gesamtuebersicht liest read-only aus dem Ledger |
|
||||||
| M6 | Betriebsflows | Import, Export, Mail und Jahresprozesse sind auditierbar |
|
| M6 | Betriebsflows | Import, Export, Mail und Jahresprozesse sind auditierbar |
|
||||||
| M7 | Landingpage | Public-Seite und Auth-Seiten sind im gemeinsamen Stil nutzbar; spaetere Ausbaustufen folgen |
|
| M7 | Landingpage | Public-Seite und Auth-Seiten sind im gemeinsamen Stil nutzbar; spaetere Ausbaustufen folgen |
|
||||||
| M8 | Haertung | Betrieb, Datenschutz, Monitoring und Isolation sind geprueft |
|
| M8 | Haertung | Betrieb, Datenschutz, Monitoring und Isolation sind geprueft |
|
||||||
@@ -509,7 +509,8 @@ Schritte:
|
|||||||
- Eigene Stricherfassung umsetzen.
|
- Eigene Stricherfassung umsetzen.
|
||||||
- Zahlungs-/PayPal-Bereich umsetzen.
|
- Zahlungs-/PayPal-Bereich umsetzen.
|
||||||
- Mitgliederverwaltung tenant- und rollenbasiert umsetzen.
|
- Mitgliederverwaltung tenant- und rollenbasiert umsetzen.
|
||||||
- Gesamtuebersicht umsetzen.
|
- Gesamtuebersicht umsetzen: erster read-only Stand in `kaffeeliste.php`
|
||||||
|
erledigt.
|
||||||
- Letzte Eintraege und Korrekturen als Storno statt Delete umsetzen.
|
- Letzte Eintraege und Korrekturen als Storno statt Delete umsetzen.
|
||||||
- Hinweise als tenant-spezifische Notices umsetzen.
|
- Hinweise als tenant-spezifische Notices umsetzen.
|
||||||
|
|
||||||
@@ -517,6 +518,7 @@ Ergebnis:
|
|||||||
|
|
||||||
- Ein Kunde kann seine Kaffeeliste operativ nutzen.
|
- Ein Kunde kann seine Kaffeeliste operativ nutzen.
|
||||||
- App sieht weiterhin nach bestehender Kaffeeliste aus.
|
- App sieht weiterhin nach bestehender Kaffeeliste aus.
|
||||||
|
- Erster M5-Stand ist in `docs/m5-app-kern.md` dokumentiert.
|
||||||
|
|
||||||
Abhaengigkeiten:
|
Abhaengigkeiten:
|
||||||
|
|
||||||
|
|||||||
+19
-2
@@ -15,13 +15,31 @@
|
|||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
$saasNavUser = function_exists('saas_current_user') ? saas_current_user() : null;
|
||||||
|
$saasCanUseLedgerNav = $saasNavUser !== null
|
||||||
|
&& function_exists('saas_user_has_role')
|
||||||
|
&& saas_user_has_role(['owner', 'admin', 'treasurer'], $saasNavUser);
|
||||||
|
$legacyCanUseAdminNav = checkKaffeelisteAdmin($conn, $mailadress);
|
||||||
|
|
||||||
|
if($legacyCanUseAdminNav){
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<li><a href="einzahlung.php">Einzahlung eintragen</a></li>
|
<li><a href="einzahlung.php">Einzahlung eintragen</a></li>
|
||||||
<li><a href="stricheintragen.php"> Striche eintragen</a></li>
|
<li><a href="stricheintragen.php"> Striche eintragen</a></li>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<?php
|
||||||
|
if($saasCanUseLedgerNav || $legacyCanUseAdminNav){
|
||||||
|
?>
|
||||||
<li><a href="kaffeeliste.php">Kaffeeliste anzeigen</a></li>
|
<li><a href="kaffeeliste.php">Kaffeeliste anzeigen</a></li>
|
||||||
<li><a href="ledger-preview.php">Ledger Preview</a></li>
|
<li><a href="ledger-preview.php">Ledger Preview</a></li>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<?php
|
||||||
|
if($legacyCanUseAdminNav){
|
||||||
|
?>
|
||||||
<li><a href="mitarbeiterverwalten.php">Mitglieder verwalten</a></li>
|
<li><a href="mitarbeiterverwalten.php">Mitglieder verwalten</a></li>
|
||||||
<li><a href="hinweise.php">Hinweise verwalten</a></li>
|
<li><a href="hinweise.php">Hinweise verwalten</a></li>
|
||||||
|
|
||||||
@@ -35,7 +53,6 @@ if(checkKaffeelisteAdmin($conn, $mailadress)){
|
|||||||
?>
|
?>
|
||||||
<li><a href="faq.php">FAQ Kaffeeliste</a></li>
|
<li><a href="faq.php">FAQ Kaffeeliste</a></li>
|
||||||
<?php
|
<?php
|
||||||
$saasNavUser = function_exists('saas_current_user') ? saas_current_user() : null;
|
|
||||||
if ($saasNavUser !== null) {
|
if ($saasNavUser !== null) {
|
||||||
?>
|
?>
|
||||||
<li><a href="konto.php">Kundenkonto</a></li>
|
<li><a href="konto.php">Kundenkonto</a></li>
|
||||||
|
|||||||
+108
-128
@@ -1,148 +1,128 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
include "functions.php";
|
include "functions.php";
|
||||||
|
require_once __DIR__ . "/app/ledger.php";
|
||||||
|
|
||||||
|
$pdo = app_db_pdo();
|
||||||
|
$saasUser = saas_current_user($pdo);
|
||||||
|
$tenantId = 0;
|
||||||
|
$hasAccess = false;
|
||||||
|
|
||||||
|
function kaffeeliste_default_tenant(PDO $pdo): ?array
|
||||||
|
{
|
||||||
|
$tenantSlug = getenv('M4_DEFAULT_TENANT_SLUG');
|
||||||
|
if ($tenantSlug === false || trim($tenantSlug) === '') {
|
||||||
|
$tenantSlug = getenv('M3_DEFAULT_TENANT_SLUG');
|
||||||
|
}
|
||||||
|
$tenantSlug = $tenantSlug !== false && trim($tenantSlug) !== ''
|
||||||
|
? trim($tenantSlug)
|
||||||
|
: 'default';
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare('SELECT id, name, slug FROM tenants WHERE slug = ? LIMIT 1');
|
||||||
|
$stmt->execute([$tenantSlug]);
|
||||||
|
$tenant = $stmt->fetch();
|
||||||
|
|
||||||
|
return $tenant !== false ? $tenant : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function kaffeeliste_money(int $cents): string
|
||||||
|
{
|
||||||
|
return saas_format_money_cents($cents) . ' €';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($saasUser !== null && saas_user_has_role(['owner', 'admin', 'treasurer'], $saasUser)) {
|
||||||
|
$tenantId = (int)$saasUser['tenant_id'];
|
||||||
|
$hasAccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$hasAccess && $saasUser === null && checkKaffeelisteAdmin($conn, $mailadress)) {
|
||||||
|
$tenant = kaffeeliste_default_tenant($pdo);
|
||||||
|
if ($tenant !== null) {
|
||||||
|
$tenantId = (int)$tenant['id'];
|
||||||
|
$hasAccess = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$participants = $hasAccess
|
||||||
|
? ledger_fetch_participant_summaries($pdo, $tenantId, ['active_only' => true])
|
||||||
|
: [];
|
||||||
|
|
||||||
include "header.php";
|
include "header.php";
|
||||||
include "headerline.php";
|
include "headerline.php";
|
||||||
include "nav.php";
|
include "nav.php";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<!-- Banner -->
|
|
||||||
<section id="banner">
|
|
||||||
<div class="content">
|
|
||||||
|
|
||||||
|
<section id="banner">
|
||||||
|
<div class="content">
|
||||||
<?php
|
<?php
|
||||||
if(checkKaffeelisteAdmin($conn, $mailadress)){
|
if ($hasAccess) {
|
||||||
|
?>
|
||||||
|
<h2>Aktive Mitarbeiter mit Gesamtstand</h2>
|
||||||
|
<br>
|
||||||
|
<ul class="actions">
|
||||||
|
<li>
|
||||||
|
<form action="exportKaffeeliste.php" method="get">
|
||||||
|
<button type="submit">Kaffeeliste exportieren</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<form action="letzteneintraege.php" method="get">
|
||||||
|
<button type="submit">Letzten Einträge</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<form action="csvupload.php" method="get">
|
||||||
|
<button type="submit">CSV Upload</button>
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
// Funktion zum Berechnen der Gesamtausgabe und Gesamtstriche pro Mitarbeiter
|
<br>
|
||||||
function berechneGesamtausgabe($mitarbeiterID, $conn) {
|
<table border="1" class="table table-striped table-bordered">
|
||||||
// Gesamtausgabe für Kaffeeverbrauch pro Mitarbeiter
|
<tr>
|
||||||
$sqlAusgabe = "SELECT SUM(Kosten) AS Gesamtausgabe FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
<th>Name</th>
|
||||||
$stmtAusgabe = sqlsrv_query($conn, $sqlAusgabe, array($mitarbeiterID));
|
<th>E-Mail</th>
|
||||||
$rowAusgabe = sqlsrv_fetch_array($stmtAusgabe, SQLSRV_FETCH_ASSOC);
|
<th>Aktueller Stand</th>
|
||||||
$gesamtausgabe = $rowAusgabe['Gesamtausgabe'] ?? 0;
|
<th>Gesamtausgabe (€)</th>
|
||||||
|
<th>Gesamtstriche</th>
|
||||||
return $gesamtausgabe;
|
<th>Gesamteinzahlungen</th>
|
||||||
}
|
</tr>
|
||||||
|
<?php
|
||||||
// Funktion zum Berechnen der Gesamtstriche pro Mitarbeiter
|
foreach ($participants as $participant) {
|
||||||
function berechneGesamtstriche($mitarbeiterID, $conn) {
|
$legacyId = $participant['legacy_mitarbeiter_id'];
|
||||||
// Gesamtstriche pro Mitarbeiter
|
$name = saas_html($participant['display_name']);
|
||||||
$sqlStriche = "SELECT SUM(AnzahlStriche) AS Gesamtstriche FROM kl_Kaffeeverbrauch WHERE MitarbeiterID = ?";
|
$email = saas_html((string)($participant['email'] ?? ''));
|
||||||
$stmtStriche = sqlsrv_query($conn, $sqlStriche, array($mitarbeiterID));
|
$balance = kaffeeliste_money((int)$participant['balance_cents']);
|
||||||
$rowStriche = sqlsrv_fetch_array($stmtStriche, SQLSRV_FETCH_ASSOC);
|
$totalCosts = kaffeeliste_money((int)$participant['total_costs_cents']);
|
||||||
$gesamtstriche = $rowStriche['Gesamtstriche'] ?? 0;
|
$totalMarks = number_format((int)$participant['total_marks'], 0, ',', '.');
|
||||||
|
$totalPayments = kaffeeliste_money((int)$participant['total_payments_cents']);
|
||||||
return $gesamtstriche;
|
|
||||||
}
|
|
||||||
// Funktion zum Berechnen der Gesamteinzahlungen pro Mitarbeiter
|
|
||||||
function berechneGesamteinzahlungen($mitarbeiterID, $conn) {
|
|
||||||
// Gesamteinzahlungen pro Mitarbeiter
|
|
||||||
$sqlEinzahlungen = "SELECT SUM(Betrag) AS Gesamteinzahlungen FROM kl_Einzahlungen WHERE MitarbeiterID = ?";
|
|
||||||
$stmtEinzahlungen = sqlsrv_query($conn, $sqlEinzahlungen, array($mitarbeiterID));
|
|
||||||
$rowEinzahlungen = sqlsrv_fetch_array($stmtEinzahlungen, SQLSRV_FETCH_ASSOC);
|
|
||||||
$gesamteinzahlungen = $rowEinzahlungen['Gesamteinzahlungen'] ?? 0;
|
|
||||||
|
|
||||||
return $gesamteinzahlungen;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mitglieder aus der Datenbank abrufen
|
|
||||||
$sqlMitglieder = "SELECT MitarbeiterID, Name, Email FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
|
||||||
$stmtMitglieder = sqlsrv_query($conn, $sqlMitglieder);
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Kaffeeliste - Aktive Mitarbeiter mit Gesamtstand</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>Aktive Mitarbeiter mit Gesamtstand</h2>
|
|
||||||
<br>
|
|
||||||
<ul class="actions">
|
|
||||||
<li>
|
|
||||||
<form action="exportKaffeeliste.php" method="get">
|
|
||||||
<button type="submit">Kaffeeliste exportieren</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<form action="letzteneintraege.php" method="get">
|
|
||||||
<button type="submit">Letzten Einträge</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<form action="csvupload.php" method="get">
|
|
||||||
<button type="submit">CSV Upload</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<table border="1" class="table table-striped table-bordered">
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>E-Mail</th>
|
|
||||||
<th>Aktueller Stand</th>
|
|
||||||
<th>Gesamtausgabe (€)</th>
|
|
||||||
<th>Gesamtstriche</th>
|
|
||||||
<th>Gesamteinzahlungen</th>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<?php
|
|
||||||
|
|
||||||
while ($row = sqlsrv_fetch_array($stmtMitglieder, SQLSRV_FETCH_ASSOC)) {
|
|
||||||
$mitarbeiterID = $row['MitarbeiterID'];
|
|
||||||
$name = $row['Name'];
|
|
||||||
$email = $row['Email'];
|
|
||||||
|
|
||||||
$gesamtausgabe = berechneGesamtausgabe($mitarbeiterID, $conn);
|
|
||||||
$gesamtstriche = berechneGesamtstriche($mitarbeiterID, $conn);
|
|
||||||
|
|
||||||
$gesamteinzahlungen = berechneGesamteinzahlungen($mitarbeiterID, $conn);
|
|
||||||
|
|
||||||
$differenztemp = $gesamteinzahlungen - $gesamtausgabe;
|
|
||||||
$differenz = number_format($differenztemp, 2, ',', '.');
|
|
||||||
$gesamtausgabe = number_format($gesamtausgabe, 2, ',', '.');
|
|
||||||
$gesamteinzahlungen = number_format($gesamteinzahlungen, 2, ',', '.');
|
|
||||||
$gesamtstriche = number_format($gesamtstriche, 0, ',', '.');
|
|
||||||
|
|
||||||
echo "<tr>";
|
|
||||||
echo "<td><a href=teilnehmerauswertung.php?user_id=$mitarbeiterID>{$name}</a></td>";
|
|
||||||
echo "<td>{$email}</td>";
|
|
||||||
echo "<td>{$differenz} €</td>";
|
|
||||||
echo "<td>{$gesamtausgabe} €</td>";
|
|
||||||
echo "<td>{$gesamtstriche}</td>";
|
|
||||||
echo "<td>{$gesamteinzahlungen} €</td>";
|
|
||||||
|
|
||||||
echo "</tr>";
|
|
||||||
|
|
||||||
|
echo "<tr>";
|
||||||
|
if ($legacyId !== null) {
|
||||||
|
echo "<td><a href=\"teilnehmerauswertung.php?user_id=" . (int)$legacyId . "\">{$name}</a></td>";
|
||||||
|
} else {
|
||||||
|
echo "<td>{$name}</td>";
|
||||||
}
|
}
|
||||||
|
echo "<td>{$email}</td>";
|
||||||
|
echo "<td>{$balance}</td>";
|
||||||
|
echo "<td>{$totalCosts}</td>";
|
||||||
|
echo "<td>{$totalMarks}</td>";
|
||||||
|
echo "<td>{$totalPayments}</td>";
|
||||||
|
echo "</tr>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</table>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
?>
|
<form action="mailversenden.php" method="get">
|
||||||
</table>
|
<button type="submit">Info-Mail versenden</button>
|
||||||
<br><br>
|
</form>
|
||||||
|
|
||||||
<form action="mailversenden.php" method="get">
|
|
||||||
<button type="submit">Info-Mail versenden</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
}else{
|
} else {
|
||||||
echo "<h2>Kein Zugriff</h2>";
|
echo "<h2>Kein Zugriff</h2>";
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
</div>
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<?php include "footer.php"; ?>
|
<?php include "footer.php"; ?>
|
||||||
|
|||||||
@@ -106,6 +106,13 @@ foreach ($expected as $email => $expectedSummary) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m4_service_assert(
|
||||||
|
"ledger service {$email} keeps legacy member id",
|
||||||
|
$summariesByEmail[$email]['legacy_mitarbeiter_id'] !== null,
|
||||||
|
$failures,
|
||||||
|
$passes
|
||||||
|
);
|
||||||
|
|
||||||
foreach ($keyMap as $expectedKey => $actualKey) {
|
foreach ($keyMap as $expectedKey => $actualKey) {
|
||||||
m4_service_assert_equal(
|
m4_service_assert_equal(
|
||||||
"ledger service {$email} {$expectedKey}",
|
"ledger service {$email} {$expectedKey}",
|
||||||
|
|||||||
+20
-1
@@ -29,7 +29,18 @@ $checks = [
|
|||||||
[
|
[
|
||||||
'label' => 'Kaffeeliste',
|
'label' => 'Kaffeeliste',
|
||||||
'path' => 'kaffeeliste.php',
|
'path' => 'kaffeeliste.php',
|
||||||
'contains' => ['Aktive Mitarbeiter'],
|
'contains' => [
|
||||||
|
'Aktive Mitarbeiter',
|
||||||
|
'teilnehmerauswertung.php?user_id=',
|
||||||
|
'GM Negativ',
|
||||||
|
'gm-negative@test.local',
|
||||||
|
'-2,00 €',
|
||||||
|
'GM Positiv',
|
||||||
|
'23,60 €',
|
||||||
|
'GM Ohne Buchungen',
|
||||||
|
'0,00 €',
|
||||||
|
],
|
||||||
|
'not_contains' => ['GM Inaktiv'],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'label' => 'Ledger Preview',
|
'label' => 'Ledger Preview',
|
||||||
@@ -221,6 +232,14 @@ foreach ($checks as $check) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (($check['not_contains'] ?? []) as $needle) {
|
||||||
|
if (str_contains($response['body'], $needle)) {
|
||||||
|
$failures[] = "{$label}: unexpected text found: {$needle}";
|
||||||
|
echo "FAIL {$label}\n";
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$passes++;
|
$passes++;
|
||||||
echo "PASS {$label}\n";
|
echo "PASS {$label}\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user