From 7388b5b3798c9b0118319559dbdbb8057fb5a80b Mon Sep 17 00:00:00 2001 From: Clemens Creutzburg Date: Mon, 30 Mar 2026 20:46:08 +0200 Subject: [PATCH] =?UTF-8?q?Schlie=C3=9Fung=20aller=20offnen=20Fehler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- zeiterfassung/allefehlbuchungen.php | 30 ++++- zeiterfassung/closeEmployeeTimeErrors.php | 147 ++++++++++++++++++++++ 2 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 zeiterfassung/closeEmployeeTimeErrors.php diff --git a/zeiterfassung/allefehlbuchungen.php b/zeiterfassung/allefehlbuchungen.php index 48598c7..5a3f7d5 100644 --- a/zeiterfassung/allefehlbuchungen.php +++ b/zeiterfassung/allefehlbuchungen.php @@ -12,6 +12,10 @@ if (!isset($_SESSION['userid'])) { $user_id = $_SESSION['userid']; $user = check_user(); +if (!is_admin_user()) { + die("Keine Rechte fuer diese Ansicht."); +} + ?> @@ -25,6 +29,13 @@ $user = check_user();

Zeitbuchungsfehler Auswertung

+ + + + + +
+ + + + Stunden + +
+ @@ -167,4 +195,4 @@ foreach($users AS $user){ - \ No newline at end of file + diff --git a/zeiterfassung/closeEmployeeTimeErrors.php b/zeiterfassung/closeEmployeeTimeErrors.php new file mode 100644 index 0000000..1350e2c --- /dev/null +++ b/zeiterfassung/closeEmployeeTimeErrors.php @@ -0,0 +1,147 @@ + 'danger', + 'message' => 'Es wurde kein gueltiger Mitarbeiter uebergeben.', + ]; + header("Location: allefehlbuchungen.php"); + exit; +} + +if ($hoursToClose <= 0) { + $_SESSION['time_error_close_result'] = [ + 'type' => 'danger', + 'message' => 'Bitte eine gueltige Stundenanzahl groesser als 0 angeben.', + ]; + header("Location: allefehlbuchungen.php"); + exit; +} + +try { + $stmt = $pdo->prepare("SELECT id, vorname, nachname FROM users WHERE id = :employee_id LIMIT 1"); + $stmt->bindValue(':employee_id', $employeeId, PDO::PARAM_INT); + $stmt->execute(); + $employee = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$employee) { + throw new RuntimeException('Mitarbeiter wurde nicht gefunden.'); + } + + $stmt = $pdo->prepare( + "SELECT + DATE(timestamp_datetime) AS datum, + GROUP_CONCAT(timestamp_type ORDER BY timestamp_datetime) AS day_sequence + FROM timestamps + WHERE employee_id = :employee_id + GROUP BY DATE(timestamp_datetime) + ORDER BY datum ASC" + ); + $stmt->bindValue(':employee_id', $employeeId, PDO::PARAM_INT); + $stmt->execute(); + $days = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $invalidDates = []; + foreach ($days as $day) { + if (!isValidSequence((string)$day['day_sequence'])) { + $invalidDates[] = (string)$day['datum']; + } + } + + if (empty($invalidDates)) { + $_SESSION['time_error_close_result'] = [ + 'type' => 'info', + 'message' => 'Es wurden keine offenen Fehlbuchungen fuer den Mitarbeiter gefunden.', + ]; + header("Location: allefehlbuchungen.php"); + exit; + } + + $pdo->beginTransaction(); + + $insertedDates = []; + $skippedDates = []; + $secondsToClose = (int)round($hoursToClose * 3600); + + $lastEntryStmt = $pdo->prepare( + "SELECT timestamp_type, timestamp_datetime + FROM timestamps + WHERE employee_id = :employee_id + AND DATE(timestamp_datetime) = :datum + ORDER BY timestamp_datetime DESC, timestamp_id DESC + LIMIT 1" + ); + + $insertStmt = $pdo->prepare( + "INSERT INTO timestamps (employee_id, timestamp_type, timestamp_datetime, timestamp_endpoint) + VALUES (:employee_id, 'GEHEN', :timestamp_datetime, 0)" + ); + + foreach ($invalidDates as $invalidDate) { + $lastEntryStmt->bindValue(':employee_id', $employeeId, PDO::PARAM_INT); + $lastEntryStmt->bindValue(':datum', $invalidDate); + $lastEntryStmt->execute(); + $lastEntry = $lastEntryStmt->fetch(PDO::FETCH_ASSOC); + + if (!$lastEntry || (string)$lastEntry['timestamp_type'] !== 'KOMMEN') { + $skippedDates[] = $invalidDate; + continue; + } + + $closeTimestamp = (new DateTimeImmutable((string)$lastEntry['timestamp_datetime'])) + ->modify('+' . $secondsToClose . ' seconds') + ->format('Y-m-d H:i:s'); + + $insertStmt->bindValue(':employee_id', $employeeId, PDO::PARAM_INT); + $insertStmt->bindValue(':timestamp_datetime', $closeTimestamp); + $insertStmt->execute(); + + $insertedDates[] = $invalidDate; + } + + $pdo->commit(); + + $message = count($insertedDates) . ' Fehlbuchungstage fuer ' + . $employee['vorname'] . ' ' . $employee['nachname'] + . ' wurden mit ' . rtrim(rtrim(number_format($hoursToClose, 2, '.', ''), '0'), '.') + . ' Stunden geschlossen.'; + + if (!empty($skippedDates)) { + $message .= ' ' . count($skippedDates) . ' Tage konnten nicht automatisch geschlossen werden.'; + } + + $_SESSION['time_error_close_result'] = [ + 'type' => !empty($insertedDates) ? 'success' : 'warning', + 'message' => $message, + ]; +} catch (Throwable $e) { + if ($pdo->inTransaction()) { + $pdo->rollBack(); + } + + $_SESSION['time_error_close_result'] = [ + 'type' => 'danger', + 'message' => 'Automatisches Schliessen fehlgeschlagen: ' . $e->getMessage(), + ]; +} + +header("Location: allefehlbuchungen.php"); +exit;