Kein Zugriff"; include "footer.php"; exit; } /** * Liefert die Mitarbeiter/Teilnehmerliste fuer die Vorder-/Rueckseiten- oder * Alle-Auswahl. Siehe stricheintragen.php fuer dieselbe Logik: Default- * Mandant nutzt die Legacy-Historie, andere Mandanten die Ledger-native * Fensterpruefung mit dem konfigurierten Listenfenster. * * @return list */ function einzahlung_fetch_participants(PDO $pdo, int $tenantId, string $action): array { $isDefault = ledger_is_default_tenant($pdo, $tenantId); if ($action === 'vorderseite' || $action === 'rueckseite') { if ($isDefault) { $vergleich = $action === 'vorderseite' ? '>= 10' : '< 10'; $join = $action === 'vorderseite' ? 'JOIN' : 'LEFT JOIN'; $stmt = $pdo->query( "SELECT M.MitarbeiterID FROM kl_Mitarbeiter M {$join} kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATE_SUB(NOW(), INTERVAL 100 DAY) WHERE M.aktiv = 1 GROUP BY M.MitarbeiterID HAVING COALESCE(SUM(V.AnzahlStriche), 0) {$vergleich}" ); $legacyIds = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN)); return ledger_fetch_participant_summaries($pdo, $tenantId, ['legacy_mitarbeiter_ids' => $legacyIds]); } $settings = saas_fetch_tenant_settings($pdo, $tenantId); $windowDays = $settings['sheet_window_days'] ?? 100; return ledger_fetch_participants_by_window_marks($pdo, $tenantId, $windowDays, $action === 'vorderseite'); } return ledger_fetch_participant_summaries($pdo, $tenantId, ['active_only' => true]); } $eingetragen = 0; $fehlgeschlagen = false; $hatGespeichert = false; $validierungsFehler = []; $eingaben = []; // Obergrenze je Einzahlungszeile. Faengt Groessenordnungs-Tippfehler ab // (z. B. 500 statt 5,00); groessere Betraege lassen sich in mehreren // Schritten eintragen. const EINZAHLUNG_MAX_BETRAG = 1000.00; // Verarbeitung des Formulars, wenn es gesendet wurde if ($_SERVER["REQUEST_METHOD"] == "POST" ) { $hatGespeichert = true; $datum = date("Y-m-d H:i:s"); // Das aktuelle Datum verwenden // Legacy-Verknuepfung je Teilnehmer vorab laden, damit pro Zeile // entschieden werden kann, ob (Default-Mandant) zusaetzlich in // kl_Einzahlungen geschrieben oder (jeder andere Mandant) direkt ins // Ledger gebucht wird. $legacyMap = []; $stmt = $pdo->prepare('SELECT id, legacy_mitarbeiter_id FROM participants WHERE tenant_id = ?'); $stmt->execute([$tenantId]); foreach ($stmt->fetchAll() as $row) { $legacyMap[(int)$row['id']] = $row['legacy_mitarbeiter_id'] !== null ? (int)$row['legacy_mitarbeiter_id'] : null; } // Namen fuer verstaendliche Fehlermeldungen. $namen = []; $stmtNamen = $pdo->prepare('SELECT id, display_name FROM participants WHERE tenant_id = ?'); $stmtNamen->execute([$tenantId]); foreach ($stmtNamen->fetchAll() as $row) { $namen[(int)$row['id']] = (string)$row['display_name']; } // Erst alle Zeilen einsammeln und pruefen, dann buchen. Schlaegt eine // Zeile fehl, wird gar nichts gebucht - sonst waere nach einem Tippfehler // unklar, was schon drin ist und was nicht. $zuBuchen = []; foreach ($_POST["anzahlBetrag"] ?? [] as $participantId => $anzahlBetrag) { $participantId = (int)$participantId; if ($participantId <= 0 || !array_key_exists($participantId, $legacyMap)) { continue; } $rohBetrag = trim((string)$anzahlBetrag); $bemerkung = trim((string)($_POST['bemerkung'][$participantId] ?? '')); $eingaben[$participantId] = ['betrag' => $rohBetrag, 'bemerkung' => $bemerkung]; if ($rohBetrag === '') { // Leere Zeile: nur meckern, wenn trotzdem eine Bemerkung dransteht // (sonst hat jemand getippt und den Betrag vergessen). if ($bemerkung !== '') { $validierungsFehler[] = sprintf( '%s: Es wurde eine Bemerkung ohne Betrag angegeben.', $namen[$participantId] ?? ('Teilnehmer ' . $participantId) ); } continue; } $anzahlBetrag = floatval(str_replace(',', '.', $rohBetrag)); if ($anzahlBetrag == 0.0) { continue; } $name = $namen[$participantId] ?? ('Teilnehmer ' . $participantId); // Abzuege muessen begruendet werden, sonst ist spaeter nicht mehr // nachvollziehbar, warum jemandem Geld abgezogen wurde. if ($anzahlBetrag < 0 && $bemerkung === '') { $validierungsFehler[] = sprintf( '%s: Bei einem Abzug (negativer Betrag) ist eine Bemerkung Pflicht.', $name ); continue; } // Groessenordnungs-Tippfehler abfangen (500 statt 5,00). if (abs($anzahlBetrag) > EINZAHLUNG_MAX_BETRAG) { $validierungsFehler[] = sprintf( '%s: %s € übersteigt die Plausibilitätsgrenze von %s €. Bitte prüfen oder in mehreren Schritten eintragen.', $name, number_format($anzahlBetrag, 2, ',', '.'), number_format(EINZAHLUNG_MAX_BETRAG, 2, ',', '.') ); continue; } $zuBuchen[$participantId] = [ 'betrag' => $anzahlBetrag, 'bemerkung' => $bemerkung !== '' ? $bemerkung : null, ]; } if ($validierungsFehler !== []) { $action = 'alle'; } else { try { $pdo->beginTransaction(); $insertLegacy = $pdo->prepare( "INSERT INTO kl_Einzahlungen (MitarbeiterID, Betrag, Bemerkung, Datum) VALUES (?, ?, ?, ?)" ); foreach ($zuBuchen as $participantId => $zeile) { $legacyMitarbeiterId = $legacyMap[$participantId]; if ($legacyMitarbeiterId !== null) { $insertLegacy->execute([$legacyMitarbeiterId, $zeile['betrag'], $zeile['bemerkung'], $datum]); $legacyPaymentId = (int)$pdo->lastInsertId(); ledger_mirror_legacy_payment($pdo, $tenantId, $legacyPaymentId); } else { ledger_record_payment( $pdo, $tenantId, $participantId, (int)round($zeile['betrag'] * 100), 'manual_bulk', $saasUser['user_id'] ?? null, $zeile['bemerkung'] ); } $eingetragen++; } $pdo->commit(); $eingaben = []; // Erfolgreich gebucht: Formular wieder leeren. } catch (Throwable $e) { if ($pdo->inTransaction()) { $pdo->rollBack(); } $fehlgeschlagen = true; } $action = 'alle'; } } else { $action = (string)($_GET['action'] ?? 'alle'); } $mitarbeiter = einzahlung_fetch_participants($pdo, $tenantId, $action); ?>

Einzahlungen für alle Mitarbeiter

Es wurde nichts gebucht. Bitte korrigiere zuerst:

Die Einzahlungen konnten nicht gespeichert werden.

Einträge erfolgreich hinzugefügt.

In der Bemerkung könnt ihr festhalten, worum es bei einer Buchung ging. Ein negativer Betrag bucht einen Abzug (z. B. Auszahlung bei Austritt oder eine Erstattung) und braucht deshalb immer eine Bemerkung.

Wurde dagegen schlicht falsch eingetragen, ist ein Abzug der falsche Weg: Die Auswertung zählt sonst beide Buchungen als Umsatz. Solche Fehler stattdessen unter Letzte Einträge stornieren.

"> "; echo " Mitarbeiter Betrag Bemerkung "; foreach ($mitarbeiter as $teilnehmer) { $participantId = (int)$teilnehmer['participant_id']; $name = saas_html($teilnehmer['display_name']); // Nach einem Validierungsfehler die Eingaben stehen lassen. $betragWert = saas_html($eingaben[$participantId]['betrag'] ?? ''); $bemerkungWert = saas_html($eingaben[$participantId]['bemerkung'] ?? ''); echo ""; echo ""; echo ""; echo ""; echo ""; } echo ""; ?>