M5: Sammelerfassung (Striche/Einzahlungen) tenant-nativ machen
stricheintragen.php und einzahlung.php lasen ihren Mitarbeiter-Picker bisher direkt aus der global unscoped kl_Mitarbeiter-Tabelle. Fuer jeden Mandanten ausser dem Default-Mandanten zeigte das fremde Namen und Schreiben schlug (sicher, aber unverstaendlich) am Tenant-Check in ledger_mirror_legacy_* fehl. - Picker kommt jetzt aus participants (tenant-scoped), Formularfelder nutzen participant_id statt MitarbeiterID. - Schreibpfad pro Teilnehmer: mit legacy_mitarbeiter_id (Default-Mandant) weiterhin Dual-Write nach kl_Kaffeeverbrauch/kl_Einzahlungen plus Ledger-Spiegelung; ohne Legacy-Verknuepfung (jeder andere Mandant) direkt ueber neue ledger_record_consumption()/ledger_record_payment(). - Vorderseite/Rueckseite-Filter (100-Tage-Regel) bleiben fuer den Default-Mandanten exakt auf der bisherigen Legacy-Logik; andere Mandanten nutzen die neue ledger_fetch_participants_by_window_marks() mit tenant_settings.sheet_window_days. - Nebenbei behoben: einzahlung.php verlinkte auf ?aktion=... statt ?action=..., wodurch die Vorderseite/Rueckseite-Buttons nie griffen. Preis-pro-Strich-Vorbelegung kommt jetzt aus tenant_settings statt der seit M3 nicht mehr gepflegten kl_config-Tabelle. - Live getestet: isolierter Test-Mandant, Picker zeigt nur eigene Teilnehmer, Buchungen rein Ledger-nativ mit korrektem Saldo, 10-Striche- Schwelle korrekt sortiert, Default-Mandant-Dual-Write weiterhin gruen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+110
-74
@@ -43,30 +43,102 @@ if (!$hasAccess) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert die Mitarbeiter/Teilnehmerliste fuer die Vorder-/Rueckseiten- oder
|
||||
* Alle-Auswahl. Fuer den Default-Mandanten bleibt die Fensterlogik exakt wie
|
||||
* im Legacy-Bestand (Anker ist das juengste Datum in kl_Kaffeeverbrauch);
|
||||
* andere Mandanten haben keine Legacy-Historie und nutzen die
|
||||
* Ledger-native Fensterpruefung mit dem konfigurierten Listenfenster.
|
||||
*
|
||||
* @return list<array>
|
||||
*/
|
||||
function stricheintragen_fetch_participants(PDO $pdo, int $tenantId, string $action): array
|
||||
{
|
||||
$isDefault = ledger_is_default_tenant($pdo, $tenantId);
|
||||
|
||||
if ($isDefault && $action === 'vorderseite') {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT M.MitarbeiterID
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATE_SUB((SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CURDATE()), INTERVAL 100 DAY)
|
||||
AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID
|
||||
HAVING SUM(V.AnzahlStriche) >= 10"
|
||||
);
|
||||
$legacyIds = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
|
||||
return ledger_fetch_participant_summaries($pdo, $tenantId, ['legacy_mitarbeiter_ids' => $legacyIds]);
|
||||
}
|
||||
|
||||
if ($isDefault && $action === 'rueckseite') {
|
||||
$stmt = $pdo->query(
|
||||
"SELECT M.MitarbeiterID
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATE_SUB((SELECT MAX(Datum) FROM kl_Kaffeeverbrauch), INTERVAL 100 DAY)
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10"
|
||||
);
|
||||
$legacyIds = array_map('intval', $stmt->fetchAll(PDO::FETCH_COLUMN));
|
||||
|
||||
return ledger_fetch_participant_summaries($pdo, $tenantId, ['legacy_mitarbeiter_ids' => $legacyIds]);
|
||||
}
|
||||
|
||||
if (!$isDefault && ($action === 'vorderseite' || $action === 'rueckseite')) {
|
||||
$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;
|
||||
|
||||
// Verarbeitung des Formulars, wenn es gesendet wurde
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$hatGespeichert = true;
|
||||
$kostenproStrich = floatval($_POST["kostenproStrich"] ?? 0);
|
||||
$datum = date("Y-m-d H:i:s"); // Das aktuelle Datum verwenden
|
||||
$eingetragen = 0;
|
||||
$fehlgeschlagen = false;
|
||||
$unitPriceCents = (int)round($kostenproStrich * 100);
|
||||
$datum = date("Y-m-d H:i:s");
|
||||
|
||||
// Legacy-Verknuepfung je Teilnehmer vorab laden, damit pro Zeile
|
||||
// entschieden werden kann, ob (Default-Mandant) zusaetzlich in
|
||||
// kl_Kaffeeverbrauch 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;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
$insert = $pdo->prepare(
|
||||
$insertLegacy = $pdo->prepare(
|
||||
"INSERT INTO kl_Kaffeeverbrauch (MitarbeiterID, AnzahlStriche, Kosten, KostenproStrich, Datum) VALUES (?, ?, ?, ?, ?)"
|
||||
);
|
||||
|
||||
foreach ($_POST["anzahlStriche"] ?? [] as $mitarbeiterID => $anzahlStriche) {
|
||||
$mitarbeiterID = (int)$mitarbeiterID;
|
||||
foreach ($_POST["anzahlStriche"] ?? [] as $participantId => $anzahlStriche) {
|
||||
$participantId = (int)$participantId;
|
||||
$anzahlStriche = (int)$anzahlStriche;
|
||||
if ($mitarbeiterID <= 0 || $anzahlStriche === 0) {
|
||||
if ($participantId <= 0 || $anzahlStriche === 0 || !array_key_exists($participantId, $legacyMap)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kosten = $anzahlStriche * $kostenproStrich;
|
||||
$insert->execute([$mitarbeiterID, $anzahlStriche, $kosten, $kostenproStrich, $datum]);
|
||||
$legacyConsumptionId = (int)$pdo->lastInsertId();
|
||||
ledger_mirror_legacy_consumption($pdo, $tenantId, $legacyConsumptionId);
|
||||
$legacyMitarbeiterId = $legacyMap[$participantId];
|
||||
if ($legacyMitarbeiterId !== null) {
|
||||
$kosten = $anzahlStriche * $kostenproStrich;
|
||||
$insertLegacy->execute([$legacyMitarbeiterId, $anzahlStriche, $kosten, $kostenproStrich, $datum]);
|
||||
$legacyConsumptionId = (int)$pdo->lastInsertId();
|
||||
ledger_mirror_legacy_consumption($pdo, $tenantId, $legacyConsumptionId);
|
||||
} else {
|
||||
ledger_record_consumption($pdo, $tenantId, $participantId, $anzahlStriche, $unitPriceCents, 'manual_bulk');
|
||||
}
|
||||
$eingetragen++;
|
||||
}
|
||||
|
||||
@@ -78,55 +150,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$fehlgeschlagen = true;
|
||||
}
|
||||
|
||||
if ($fehlgeschlagen) {
|
||||
echo "Die Einträge konnten nicht gespeichert werden.";
|
||||
} else {
|
||||
echo $eingetragen . " Einträge erfolgreich hinzugefügt.";
|
||||
}
|
||||
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
}elseif($_SERVER["REQUEST_METHOD"] == "GET" AND isset($_GET["action"])){
|
||||
|
||||
if($_GET["action"] == "vorderseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID
|
||||
WHERE V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch WHERE Datum < CAST(GETDATE() AS DATE))) AND M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING SUM(V.AnzahlStriche) >= 10
|
||||
ORDER BY Name;";
|
||||
|
||||
}elseif( $_GET["action"] == "rueckseite"){
|
||||
|
||||
$sqlMitarbeiter = "SELECT M.MitarbeiterID, M.Name, M.Email
|
||||
FROM kl_Mitarbeiter M
|
||||
LEFT JOIN kl_Kaffeeverbrauch V ON M.MitarbeiterID = V.MitarbeiterID AND V.Datum >= DATEADD(DAY, -100, (SELECT MAX(Datum) FROM kl_Kaffeeverbrauch))
|
||||
WHERE M.aktiv = 1
|
||||
GROUP BY M.MitarbeiterID, M.Name, M.Email
|
||||
HAVING COALESCE(SUM(V.AnzahlStriche), 0) < 10
|
||||
ORDER BY M.Name;";
|
||||
}elseif($_GET["action"] == "alle"){
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
}
|
||||
|
||||
}else{
|
||||
// Mitarbeiter aus der Datenbank abrufen und nach Namen sortieren
|
||||
$sqlMitarbeiter = "SELECT MitarbeiterID, Name FROM kl_Mitarbeiter WHERE aktiv = 1 ORDER BY Name";
|
||||
|
||||
|
||||
$action = 'alle';
|
||||
} else {
|
||||
$action = (string)($_GET['action'] ?? 'alle');
|
||||
}
|
||||
$stmtMitarbeiter = sqlsrv_query($conn, $sqlMitarbeiter);
|
||||
|
||||
// Kosten pro Strich auslesen
|
||||
$sqlKostenproStrich = "SELECT KostenproStrich FROM kl_config ";
|
||||
$stmtKostenproStrich = sqlsrv_query($conn, $sqlKostenproStrich);
|
||||
$row = sqlsrv_fetch_array($stmtKostenproStrich, SQLSRV_FETCH_ASSOC);
|
||||
$KostenproStrichtemp = $row["KostenproStrich"];
|
||||
$KostenproStrich = number_format($KostenproStrichtemp, 2, '.', '');
|
||||
$mitarbeiter = stricheintragen_fetch_participants($pdo, $tenantId, $action);
|
||||
$settings = saas_fetch_tenant_settings($pdo, $tenantId);
|
||||
$kostenproStrichAnzeige = number_format(($settings['mark_price_cents'] ?? 20) / 100, 2, '.', '');
|
||||
|
||||
?>
|
||||
|
||||
@@ -140,54 +171,59 @@ $KostenproStrich = number_format($KostenproStrichtemp, 2, '.', '');
|
||||
<body>
|
||||
|
||||
<h2>Anzahl der Striche für alle Mitarbeiter</h2>
|
||||
|
||||
<?php if ($hatGespeichert): ?>
|
||||
<?php if ($fehlgeschlagen): ?>
|
||||
<div class="hint-box error"><p>Die Einträge konnten nicht gespeichert werden.</p></div>
|
||||
<?php else: ?>
|
||||
<div class="hint-box success"><p><?php echo (int)$eingetragen; ?> Einträge erfolgreich hinzugefügt.</p></div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<ul class="actions">
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="vorderseite">
|
||||
<button type="submit">Vorderseite</button>
|
||||
</form>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="rueckseite">
|
||||
<button type="submit">Rückseite</button>
|
||||
</form>
|
||||
</form>
|
||||
</li>
|
||||
<li>
|
||||
<form action="stricheintragen.php" method="get">
|
||||
<input type="hidden" name="action" value="alle">
|
||||
<button type="submit">Alle</button>
|
||||
</form>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
|
||||
<?php echo app_csrf_field(); ?>
|
||||
<?php
|
||||
|
||||
|
||||
echo "<label for='kostenproStrich'>Kosten pro Strich:</label>
|
||||
<input type='number' name='kostenproStrich' step='0.01' value='" . $KostenproStrich . "'><br>";
|
||||
|
||||
<input type='number' name='kostenproStrich' step='0.01' value='" . saas_html($kostenproStrichAnzeige) . "'><br>";
|
||||
|
||||
echo "<table>";
|
||||
echo " <tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Anzahl Striche</th>
|
||||
</tr>";
|
||||
|
||||
// Iteriere über alle Mitarbeiter
|
||||
while ($row = sqlsrv_fetch_array($stmtMitarbeiter, SQLSRV_FETCH_ASSOC)) {
|
||||
$mitarbeiterID = $row["MitarbeiterID"];
|
||||
$mitarbeiterName = $row["Name"];
|
||||
foreach ($mitarbeiter as $teilnehmer) {
|
||||
$participantId = $teilnehmer['participant_id'];
|
||||
$name = saas_html($teilnehmer['display_name']);
|
||||
echo "<tr>";
|
||||
|
||||
// Formularfeld für die Anzahl der Striche
|
||||
echo "<td><label for='anzahlStriche[$mitarbeiterID]'>$mitarbeiterName:</label></td>";
|
||||
echo "<td><input type='number' name='anzahlStriche[$mitarbeiterID]' ></td>";
|
||||
echo "<td><label for='anzahlStriche[$participantId]'>$name:</label></td>";
|
||||
echo "<td><input type='number' name='anzahlStriche[$participantId]' ></td>";
|
||||
echo "</tr>";
|
||||
|
||||
}
|
||||
echo "</table>";
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<button type="submit">Eintragen</button>
|
||||
|
||||
Reference in New Issue
Block a user