Schließung aller offnen Fehler

This commit is contained in:
2026-03-30 20:46:08 +02:00
parent 016753293c
commit 7388b5b379
2 changed files with 176 additions and 1 deletions
+28
View File
@@ -12,6 +12,10 @@ if (!isset($_SESSION['userid'])) {
$user_id = $_SESSION['userid']; $user_id = $_SESSION['userid'];
$user = check_user(); $user = check_user();
if (!is_admin_user()) {
die("Keine Rechte fuer diese Ansicht.");
}
?> ?>
<?php include 'header.php'; ?> <?php include 'header.php'; ?>
@@ -25,6 +29,13 @@ $user = check_user();
<div class="container"> <div class="container">
<h2 class="mb-4">Zeitbuchungsfehler Auswertung</h2> <h2 class="mb-4">Zeitbuchungsfehler Auswertung</h2>
<?php if (!empty($_SESSION['time_error_close_result'])): ?>
<?php $closeResult = $_SESSION['time_error_close_result']; unset($_SESSION['time_error_close_result']); ?>
<div class="alert alert-<?php echo htmlspecialchars($closeResult['type'], ENT_QUOTES, 'UTF-8'); ?>" role="alert">
<?php echo htmlspecialchars($closeResult['message'], ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<?php <?php
// Benutzer aus der Datenbank erhalten // Benutzer aus der Datenbank erhalten
@@ -132,6 +143,23 @@ foreach($users AS $user){
<?php if (!empty($invalidDates)): ?> <?php if (!empty($invalidDates)): ?>
<form action="closeEmployeeTimeErrors.php" method="post" class="form-inline mb-3">
<input type="hidden" name="employee_id" value="<?php echo (int)$user['id']; ?>">
<label class="mr-2" for="hours_to_close_<?php echo (int)$user['id']; ?>">Fehlbuchungen automatisch schliessen mit</label>
<input
type="number"
step="0.25"
min="0.25"
class="form-control mr-2"
id="hours_to_close_<?php echo (int)$user['id']; ?>"
name="hours_to_close"
value="8"
required
>
<span class="mr-2">Stunden</span>
<button type="submit" class="btn btn-primary">Alle schliessen</button>
</form>
<table class="table table-striped"> <table class="table table-striped">
<thead class="thead-dark"> <thead class="thead-dark">
<tr> <tr>
+147
View File
@@ -0,0 +1,147 @@
<?php
session_start();
require_once("inc/config.inc.php");
require_once("inc/functions.inc.php");
$user = check_user();
if (!is_admin_user()) {
http_response_code(403);
die("Keine Berechtigung.");
}
if ($_SERVER["REQUEST_METHOD"] !== "POST") {
die("Ungueltige Anfrage.");
}
$employeeId = isset($_POST['employee_id']) ? (int)$_POST['employee_id'] : 0;
$hoursRaw = isset($_POST['hours_to_close']) ? str_replace(',', '.', trim((string)$_POST['hours_to_close'])) : '';
$hoursToClose = is_numeric($hoursRaw) ? (float)$hoursRaw : 0.0;
if ($employeeId <= 0) {
$_SESSION['time_error_close_result'] = [
'type' => '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;