'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;