Inital
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
//Since this page writes to a session, initialise it here
|
||||
session_start();
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && $_POST["action"] == "PDF anzeigen") {
|
||||
|
||||
// Weiterleitung zur createPDF.php mit den Parametern
|
||||
$userId = $_POST["user"];
|
||||
$selectedMonth = $_POST["month"];
|
||||
$monthYear = explode("/", $selectedMonth);
|
||||
$month = $monthYear[0];
|
||||
$year = $monthYear[1];
|
||||
// Weiterleitung zur createPDF.php mit den Parametern
|
||||
# echo "Location: createPDF.php?id=$userId&month=$month&year=$year";
|
||||
header("Location: createPDF.php?id=$userId&month=$month&year=$year");
|
||||
exit();
|
||||
|
||||
}
|
||||
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
|
||||
// Monate für den Dropdown-Menü erhalten
|
||||
try {
|
||||
$months_stmt = $pdo->prepare("SELECT DISTINCT MONTH(timestamp_datetime) as month, YEAR(timestamp_datetime) as year FROM timestamps WHERE employee_id = ? ORDER BY timestamp_datetime DESC");
|
||||
$months_stmt->bindParam(1, $user_id);
|
||||
$months_stmt->execute();
|
||||
$months = $months_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
$selectedMonth = $_POST['month'] ?? '';
|
||||
#$selectedYear = $_POST['year'] ?? '';
|
||||
|
||||
// Zeiten für den ausgewählten Monat erhalten
|
||||
if ($selectedMonth ) {
|
||||
|
||||
try {
|
||||
$selectedYear = explode('/',$selectedMonth)[1];
|
||||
$times_stmt = $pdo->prepare("SELECT timestamp_datetime, timestamp_type FROM timestamps WHERE employee_id = ? AND MONTH(timestamp_datetime) = ? AND YEAR(timestamp_datetime) = ? ORDER BY timestamp_datetime ASC");
|
||||
$times_stmt->bindParam(1, $user_id);
|
||||
$times_stmt->bindParam(2, $selectedMonth);
|
||||
$times_stmt->bindParam(3, $selectedYear);
|
||||
$times_stmt->execute();
|
||||
$times = $times_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
// Gruppieren der Zeiten nach Tagen
|
||||
$groupedTimes = [];
|
||||
foreach ($times as $time) {
|
||||
$date = date('Y-m-d', strtotime($time['timestamp_datetime']));
|
||||
$groupedTimes[$date][] = $time;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<h2>Zeitenübersicht</h2>
|
||||
|
||||
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
|
||||
<div class="form-group">
|
||||
<label for="month">Monat auswählen:</label>
|
||||
<select name="month" id="month" class="form-control">
|
||||
<?php foreach ($months as $month): ?>
|
||||
<option value="<?php echo $month['month'] . '/' . $month['year']; ?>" <?php if ($month['month'] == $selectedMonth && $month['year'] == $selectedYear) echo 'selected'; ?>>
|
||||
<?php echo $month['month'] . '/' . $month['year']; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<br><br>
|
||||
<input type="submit" value="Zeiten anzeigen" class="btn btn-primary btn-lg">
|
||||
<!-- Button zum Anzeigen der PDF -->
|
||||
<input type="submit" name="action" value="PDF anzeigen" class="btn btn-primary btn-lg" formtarget="_blank">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if ($selectedMonth): ?>
|
||||
|
||||
|
||||
|
||||
|
||||
<table class="table table-striped table-hover">
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Typ</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
<?php foreach ($groupedTimes as $date => $times): ?>
|
||||
<tr>
|
||||
<td><?php echo date('d.m.Y', strtotime($date)); ?></td>
|
||||
<td>
|
||||
<?php foreach ($times as $time): ?>
|
||||
<div><?php echo date('H:i:s', strtotime($time['timestamp_datetime'])) . ' - ' . $time['timestamp_type']; ?></div>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Hier können Sie Aktionen für jeden Tag hinzufügen, z.B. Bearbeiten/Löschen des gesamten Tages -->
|
||||
<a href="editDayEntries.php?employee_id=<?php echo $user_id; ?>&datum=<?php echo date('Y-m-d', strtotime($time['timestamp_datetime'])); ?>" class="btn btn-primary">Anpassen</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
//Since this page writes to a session, initialise it here
|
||||
session_start();
|
||||
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
// Überprüfen, welcher Button geklickt wurde
|
||||
if ($_POST["action"] == "PDF anzeigen") {
|
||||
// Weiterleitung zur createPDF.php mit den Parametern
|
||||
$userId = $_POST["user"];
|
||||
$selectedMonth = $_POST["month"];
|
||||
$monthYear = explode("/", $selectedMonth);
|
||||
$month = $monthYear[0];
|
||||
$year = $monthYear[1];
|
||||
// Weiterleitung zur createPDF.php mit den Parametern
|
||||
# echo "Location: createPDF.php?id=$userId&month=$month&year=$year";
|
||||
header("Location: createPDF.php?id=$userId&month=$month&year=$year");
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<?php
|
||||
// Starten der Session, falls noch nicht geschehen
|
||||
if(session_status() === PHP_SESSION_NONE) session_start();
|
||||
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
|
||||
// Benutzer aus der Datenbank erhalten
|
||||
try {
|
||||
$users_stmt = $pdo->prepare("SELECT id,vorname, nachname FROM users WHERE zeiterfassung='1' ORDER BY nachname ASC");
|
||||
$users_stmt->execute();
|
||||
$users = $users_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
// Monate für den Dropdown-Menü erhalten
|
||||
try {
|
||||
// Hier sollte die Abfrage angepasst werden, um auf den ausgewählten Benutzer zu filtern
|
||||
$months_stmt = $pdo->prepare("SELECT DISTINCT MONTH(timestamp_datetime) as month, YEAR(timestamp_datetime) as year FROM timestamps ORDER BY timestamp_datetime DESC");
|
||||
#$months_stmt->bindParam(1, $user_id);
|
||||
$months_stmt->execute();
|
||||
$months = $months_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
$selectedUser = $_POST['user'] ?? $user_id; // Standardmäßig der angemeldete Benutzer
|
||||
$selectedMonth = $_POST['month'] ?? '';
|
||||
|
||||
// Zeiten für den ausgewählten Monat und Benutzer erhalten
|
||||
if ($selectedMonth && $selectedUser) {
|
||||
try {
|
||||
$selectedYear = explode('/',$selectedMonth)[1];
|
||||
$times_stmt = $pdo->prepare("SELECT timestamp_datetime, timestamp_type FROM timestamps WHERE employee_id = ? AND MONTH(timestamp_datetime) = ? AND YEAR(timestamp_datetime) = ? ORDER BY timestamp_datetime ASC");
|
||||
$times_stmt->bindParam(1, $selectedUser);
|
||||
$times_stmt->bindParam(2, explode('/', $selectedMonth)[0]); // Monat extrahieren
|
||||
$times_stmt->bindParam(3, $selectedYear);
|
||||
$times_stmt->execute();
|
||||
$times = $times_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
// Gruppieren der Zeiten nach Tagen
|
||||
$groupedTimes = [];
|
||||
foreach ($times as $time) {
|
||||
$date = date('Y-m-d', strtotime($time['timestamp_datetime']));
|
||||
$groupedTimes[$date][] = $time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<h2>Zeitenübersicht</h2>
|
||||
|
||||
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
|
||||
<div class="form-group">
|
||||
<label for="user">Benutzer auswählen:</label>
|
||||
<select name="user" id="user" class="form-control">
|
||||
<?php foreach ($users as $user): ?>
|
||||
<option value="<?php echo $user['id']; ?>" <?php if ($user['id'] == $selectedUser) echo 'selected'; ?>>
|
||||
<?php echo htmlspecialchars($user['vorname']); ?> <?php echo htmlspecialchars($user['nachname']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="month">Monat auswählen:</label>
|
||||
<select name="month" id="month" class="form-control">
|
||||
<?php foreach ($months as $month): ?>
|
||||
<option value="<?php echo $month['month'] . '/' . $month['year']; ?>" <?php if ($month['month'] . '/' . $month['year'] == $selectedMonth) echo 'selected'; ?>>
|
||||
<?php echo $month['month'] . '/' . $month['year']; ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<br>
|
||||
<input type="submit" value="Zeiten anzeigen" class="btn btn-primary btn-lg">
|
||||
<!-- Button zum Anzeigen der PDF -->
|
||||
<input type="submit" name="action" value="PDF anzeigen" class="btn btn-primary btn-lg" formtarget="_blank">
|
||||
|
||||
</form>
|
||||
|
||||
<?php if ($selectedMonth && $selectedUser): ?>
|
||||
<table class="table table-striped table-hover">
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Typ</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
<?php foreach ($groupedTimes as $date => $times): ?>
|
||||
<tr>
|
||||
<td><?php echo date('d.m.Y', strtotime($date)); ?></td>
|
||||
<td>
|
||||
<?php foreach ($times as $time): ?>
|
||||
<div><?php echo date('H:i:s', strtotime($time['timestamp_datetime'])) . ' - ' . $time['timestamp_type']; ?></div>
|
||||
<?php endforeach; ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="editDayEntries.php?employee_id=<?php echo $selectedUser; ?>&datum=<?php echo date('Y-m-d', strtotime($time['timestamp_datetime'])); ?>" class="btn btn-primary">Anpassen</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('./../admin/tcpdf/tcpdf.php');
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
$user = check_user();
|
||||
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
<h2 class="mb-4">Zeitbuchungsfehler Auswertung</h2>
|
||||
|
||||
<?php
|
||||
|
||||
// Benutzer aus der Datenbank erhalten
|
||||
try {
|
||||
$users_stmt = $pdo->prepare("SELECT id,vorname, nachname FROM users WHERE zeiterfassung='1' ORDER BY nachname ASC");
|
||||
$users_stmt->execute();
|
||||
$users = $users_stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
foreach($users AS $user){
|
||||
|
||||
|
||||
try {
|
||||
// Holen Sie die fehlerhaften Zeitbuchungen des Mitarbeiters aus der Datenbank
|
||||
$query = "
|
||||
SELECT
|
||||
DATE(timestamp_datetime) as datum,
|
||||
SUM(CASE WHEN timestamp_type = 'KOMMEN' THEN 1 ELSE 0 END) as kommen_count,
|
||||
SUM(CASE WHEN timestamp_type = 'GEHEN' THEN 1 ELSE 0 END) as gehen_count
|
||||
FROM
|
||||
timestamps
|
||||
WHERE
|
||||
employee_id = :employee_id
|
||||
GROUP BY
|
||||
DATE(timestamp_datetime)
|
||||
HAVING
|
||||
kommen_count != gehen_count";
|
||||
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->bindParam(':employee_id', $user["id"], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$fehlerhafteTage = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$query2 = "
|
||||
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);";
|
||||
|
||||
$stmt = $pdo->prepare($query2);
|
||||
$stmt->bindParam(':employee_id', $user["id"], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll();
|
||||
|
||||
$invalidDates = [];
|
||||
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$query1 = "
|
||||
SELECT
|
||||
vorname,
|
||||
nachname
|
||||
FROM
|
||||
users
|
||||
WHERE
|
||||
id = :employee_id
|
||||
ORDER BY
|
||||
nachname
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($query1);
|
||||
$stmt->bindParam(':employee_id', $user["id"], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$userdaten = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
foreach ($userdaten as $usertag){
|
||||
echo "<h5>" . $usertag["vorname"] . " " . $usertag["nachname"] . "</h5>";
|
||||
|
||||
}
|
||||
|
||||
|
||||
foreach ($result as $row) {
|
||||
if (!isValidSequence($row["day_sequence"])) {
|
||||
$invalidDates[] = $row["datum"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?php if (!empty($invalidDates)): ?>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Fehler</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($invalidDates as $date): ?>
|
||||
<tr>
|
||||
<td><?php echo date('d.m.Y', strtotime($date)); ?></td>
|
||||
<td>Fehlerhafte Daten</td>
|
||||
<td>
|
||||
<a href="editDayEntries.php?employee_id=<?php echo $user['id']; ?>&datum=<?php echo $date; ?>" class="btn btn-warning">Anpassen</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info" role="alert">
|
||||
Keine Zeitbuchungsfehler gefunden.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
// API: returns JSON events for FullCalendar
|
||||
session_start();
|
||||
require_once(__DIR__ . '/../inc/config.inc.php');
|
||||
require_once(__DIR__ . '/../inc/functions.inc.php');
|
||||
|
||||
// Enable full error reporting for API debugging
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
|
||||
$user = check_user();
|
||||
$isAdmin = is_admin_user();
|
||||
|
||||
$start = $_GET['start'] ?? null; // expected ISO date
|
||||
$end = $_GET['end'] ?? null;
|
||||
$onlyApproved = isset($_GET['only_approved']) && ($_GET['only_approved'] == '1' || $_GET['only_approved'] === 'true');
|
||||
// public allows non-admin users to request all *approved* vacations (team view)
|
||||
$public = isset($_GET['public']) && ($_GET['public'] == '1' || $_GET['public'] === 'true');
|
||||
// include_rejected if set to 1 will return rejected entries; default behavior: do not return rejected for regular users
|
||||
$includeRejected = isset($_GET['include_rejected']) && ($_GET['include_rejected'] == '1' || $_GET['include_rejected'] === 'true');
|
||||
// only_personal forces the API to return only the current user's vacations (useful even if the user is admin)
|
||||
$onlyPersonal = isset($_GET['only_personal']) && ($_GET['only_personal'] == '1' || $_GET['only_personal'] === 'true');
|
||||
// public_all when used with public=1 returns all non-rejected team vacations (approved + beantragt)
|
||||
$publicAll = isset($_GET['public_all']) && ($_GET['public_all'] == '1' || $_GET['public_all'] === 'true');
|
||||
|
||||
if (!$start || !$end) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'start and end required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$events = [];
|
||||
try {
|
||||
$branch = 'unknown';
|
||||
$debugMode = isset($_GET['debug']) && ($_GET['debug'] == '1' || $_GET['debug'] === 'true');
|
||||
|
||||
// Vacations: support a personal-only mode, admin mode, and public/team mode
|
||||
if ($onlyPersonal) {
|
||||
$branch = 'onlyPersonal';
|
||||
if ($onlyApproved) {
|
||||
$branch = 'onlyPersonal_onlyApproved';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
if ($includeRejected) {
|
||||
$branch = 'onlyPersonal_includeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
$branch = 'onlyPersonal_excludeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) != 'abgelehnt') ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
}
|
||||
}
|
||||
} elseif ($isAdmin) {
|
||||
$branch = 'admin';
|
||||
if ($onlyApproved) {
|
||||
$branch = 'admin_onlyApproved';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
// By default admins see genehmigt + beantragt; include_rejected=1 can override
|
||||
if ($includeRejected) {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) IN ('genehmigt','beantragt')) ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$branch = 'public_or_regular';
|
||||
if ($public && $onlyApproved) {
|
||||
$branch = 'public_onlyApproved';
|
||||
// public team view: show all approved vacations (read-only)
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} elseif ($public && $publicAll) {
|
||||
$branch = 'public_publicAll';
|
||||
// public team view: explicitly show only approved (genehmigt) and pending (beantragt) vacations
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) IN ('genehmigt','beantragt')) ORDER BY v.start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
} else {
|
||||
if ($onlyApproved) {
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND LOWER(TRIM(v.status)) = 'genehmigt' ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
// By default exclude rejected ('abgelehnt') for regular users; include if include_rejected=1
|
||||
if ($includeRejected) {
|
||||
$branch = 'regular_includeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
} else {
|
||||
$branch = 'regular_excludeRejected';
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname FROM vacations v JOIN users u ON v.user_id = u.id WHERE v.user_id = ? AND v.start_date <= ? AND v.end_date >= ? AND (v.status IS NULL OR LOWER(TRIM(v.status)) != 'abgelehnt') ORDER BY v.start_date");
|
||||
$stmt->execute([$_SESSION['userid'], $end, $start]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$vacations = $stmt->fetchAll();
|
||||
|
||||
// If debug mode is enabled, prepare meta information
|
||||
if ($debugMode) {
|
||||
$rawStatuses = array_map(function($r){ return $r['status'] ?? null; }, $vacations);
|
||||
$meta = [
|
||||
'branch' => $branch,
|
||||
'count' => count($vacations),
|
||||
'raw_statuses' => $rawStatuses
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($vacations as $v) {
|
||||
// Normalize status: collapse whitespace (including NBSP), trim, lowercase
|
||||
if (isset($v['status'])) {
|
||||
$normalized = preg_replace('/\s+/u', ' ', $v['status']);
|
||||
$status = mb_strtolower(trim($normalized));
|
||||
} else {
|
||||
$status = '';
|
||||
}
|
||||
// Defensive filter: do not expose rejected ('abgelehnt') entries to non-admins
|
||||
if (!$isAdmin && !$includeRejected && mb_stripos($status, 'abgelehnt') !== false) {
|
||||
continue;
|
||||
}
|
||||
$isApproved = (mb_stripos($status, 'genehmigt') !== false);
|
||||
if ($isAdmin) {
|
||||
$title = $v['vorname'] . ' ' . $v['nachname'] . ' (' . ($v['status'] ?? 'beantragt') . ')';
|
||||
} else {
|
||||
$title = $isApproved ? 'Urlaub' : 'Urlaubsantrag';
|
||||
}
|
||||
// Safely compute end date; fallback to start_date if invalid
|
||||
try {
|
||||
$endInclusive = (new DateTime($v['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
} catch (Exception $e) {
|
||||
$endInclusive = $v['start_date'];
|
||||
}
|
||||
$events[] = [
|
||||
'id' => 'vac_' . $v['id'],
|
||||
'title' => $title,
|
||||
'start' => $v['start_date'],
|
||||
'end' => $endInclusive,
|
||||
'allDay' => true,
|
||||
'color' => ($isApproved) ? '#28a745' : '#ffc107',
|
||||
'extendedProps' => [
|
||||
'type' => 'user',
|
||||
'user_id' => $v['user_id'],
|
||||
'status' => $v['status'],
|
||||
'comment' => $v['comment_user'] ?? ''
|
||||
]
|
||||
];
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$payload = ['error' => $ex->getMessage(), 'branch' => $branch, 'trace' => $ex->getTraceAsString()];
|
||||
echo json_encode($payload);
|
||||
exit;
|
||||
}
|
||||
|
||||
} catch (Exception $ex) {
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
$payload = ['error' => $ex->getMessage(), 'branch' => $branch, 'trace' => $ex->getTraceAsString()];
|
||||
echo json_encode($payload);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Company holidays (visible to all)
|
||||
$stmt = $pdo->prepare("SELECT * FROM company_holidays WHERE start_date <= ? AND end_date >= ? ORDER BY start_date");
|
||||
$stmt->execute([$end, $start]);
|
||||
$holidays = $stmt->fetchAll();
|
||||
|
||||
foreach ($holidays as $h) {
|
||||
$endInclusive = (new DateTime($h['end_date']))->modify('+1 day')->format('Y-m-d');
|
||||
$events[] = [
|
||||
'id' => 'com_' . $h['id'],
|
||||
'title' => $h['description'] ?: 'Betriebsurlaub',
|
||||
'start' => $h['start_date'],
|
||||
'end' => $endInclusive,
|
||||
'allDay' => true,
|
||||
'color' => '#007bff',
|
||||
'extendedProps' => [
|
||||
'type' => 'company',
|
||||
'description' => $h['description']
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
if ($debugMode) {
|
||||
echo json_encode(['events' => $events, 'meta' => $meta]);
|
||||
} else {
|
||||
echo json_encode($events);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
$user = check_user();
|
||||
if (!is_admin_user()) {
|
||||
die('Zugriff verweigert. Nur Chefs dürfen Anträge genehmigen.');
|
||||
}
|
||||
|
||||
// Handle approve/reject actions
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['id']) && isset($_POST['action'])) {
|
||||
$id = (int)$_POST['id'];
|
||||
$action = $_POST['action'];
|
||||
|
||||
if ($action === 'approve') {
|
||||
$stmt = $pdo->prepare("UPDATE vacations SET status = 'genehmigt', approved_by = ?, approved_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['userid'], $id]);
|
||||
} elseif ($action === 'reject') {
|
||||
$stmt = $pdo->prepare("UPDATE vacations SET status = 'abgelehnt', approved_by = ?, approved_at = NOW() WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['userid'], $id]);
|
||||
} elseif ($action === 'delete' && is_admin_user()) {
|
||||
$del = $pdo->prepare("DELETE FROM vacations WHERE id = ?");
|
||||
$del->execute([$id]);
|
||||
}
|
||||
|
||||
header('Location: approveVacation.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
include 'header.php';
|
||||
|
||||
// List pending and recent requests
|
||||
$stmt = $pdo->prepare("SELECT v.*, u.vorname, u.nachname, u.email FROM vacations v JOIN users u ON v.user_id = u.id ORDER BY v.created_at DESC");
|
||||
$stmt->execute();
|
||||
$requests = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Urlaubsanträge - Genehmigung</h2>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Von</th>
|
||||
<th>Bis</th>
|
||||
<th>Tage</th>
|
||||
<th>Kommentar</th>
|
||||
<th>Status</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($requests as $r): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($r['vorname'] . ' ' . $r['nachname']); ?></td>
|
||||
<td><?php echo $r['start_date']; ?></td>
|
||||
<td><?php echo $r['end_date']; ?></td>
|
||||
<td><?php echo $r['days']; ?></td>
|
||||
<td><?php echo htmlspecialchars($r['comment_user']); ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if ($r['status'] === 'beantragt' || $r['status'] === null) {
|
||||
echo '<span class="badge badge-warning">Beantragt</span>';
|
||||
} elseif ($r['status'] === 'genehmigt') {
|
||||
echo '<span class="badge badge-success">Genehmigt</span>';
|
||||
} else {
|
||||
echo '<span class="badge badge-danger">Abgelehnt</span>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($r['status'] !== 'genehmigt'): ?>
|
||||
<form method="post" style="display:inline-block; margin-right:6px;">
|
||||
<input type="hidden" name="id" value="<?php echo $r['id']; ?>">
|
||||
<input type="hidden" name="action" value="approve">
|
||||
<button class="btn btn-sm btn-success" type="submit">Genehmigen</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($r['status'] !== 'abgelehnt'): ?>
|
||||
<form method="post" style="display:inline-block;">
|
||||
<input type="hidden" name="id" value="<?php echo $r['id']; ?>">
|
||||
<input type="hidden" name="action" value="reject">
|
||||
<button class="btn btn-sm btn-danger" type="submit">Ablehnen</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<form method="post" style="display:inline-block; margin-left:6px;" onsubmit="return confirm('Wirklich löschen?');">
|
||||
<input type="hidden" name="id" value="<?php echo $r['id']; ?>">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<button class="btn btn-sm btn-outline-danger" type="submit">Löschen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php';
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Stempelkarten-System</h2>
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
#$mitarbeiterId = $_GET['employee_id'] ?? null;
|
||||
#$gewaehlterTag = $_GET['datum'] ?? null;
|
||||
$mitarbeiterId = $_SESSION['userid']; // Angenommen, die Mitarbeiter-ID kommt aus der Session
|
||||
$gewaehlterMonat = '2024-01'; // Format: YYYY-MM
|
||||
$tageImMonat = date('t', strtotime($gewaehlterMonat . '-01'));
|
||||
|
||||
$zeitenProTag = [];
|
||||
|
||||
for($tag = 1; $tag <= $tageImMonat; $tag++) {
|
||||
$datum = $gewaehlterMonat . '-' . str_pad($tag, 2, '0', STR_PAD_LEFT);
|
||||
echo $datum . "<br>";
|
||||
// Abfrage für alle Zeitstempel des Tages
|
||||
$query = "
|
||||
SELECT timestamp_type, timestamp_datetime
|
||||
FROM timestamps
|
||||
WHERE employee_id = :employee_id AND DATE(timestamp_datetime) = :datum
|
||||
ORDER BY timestamp_datetime
|
||||
";
|
||||
try {
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->bindParam(':employee_id', $mitarbeiterId, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':datum', $datum);
|
||||
$stmt->execute();
|
||||
$zeitstempel = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo $zeitstempel;
|
||||
} catch(PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
$fruehesteKommenZeit = null;
|
||||
$spaetesteGehenZeit = null;
|
||||
$gesamtarbeitszeit = new DateInterval('PT0S');
|
||||
$gesamtpausenzeit = new DateInterval('PT0S');
|
||||
$letzterGehenZeitstempel = null;
|
||||
echo "test";
|
||||
foreach ($zeitstempel as $index => $eintrag) {
|
||||
$zeit = new DateTime($eintrag['timestamp_datetime']);
|
||||
echo "test2";
|
||||
if ($eintrag['timestamp_type'] === 'KOMMEN') {
|
||||
echo "test3";
|
||||
if ($fruehesteKommenZeit === null || $zeit < $fruehesteKommenZeit) {
|
||||
$fruehesteKommenZeit = $zeit;
|
||||
}
|
||||
if ($letzterGehenZeitstempel) {
|
||||
$pause = $letzterGehenZeitstempel->diff($zeit);
|
||||
$gesamtpausenzeit = $gesamtpausenzeit->add($pause);
|
||||
}
|
||||
} else if ($eintrag['timestamp_type'] === 'GEHEN') {
|
||||
if ($spaetesteGehenZeit === null || $zeit > $spaetesteGehenZeit) {
|
||||
$spaetesteGehenZeit = $zeit;
|
||||
}
|
||||
$letzterGehenZeitstempel = $zeit;
|
||||
}
|
||||
}
|
||||
|
||||
if ($fruehesteKommenZeit && $spaetesteGehenZeit) {
|
||||
$gesamtarbeitszeit = $fruehesteKommenZeit->diff($spaetesteGehenZeit)->subtract($gesamtpausenzeit);
|
||||
}
|
||||
#echo $gesamtarbeitszeit;
|
||||
$zeitenProTag[$datum] = [
|
||||
'fruehesteKommenZeit' => $fruehesteKommenZeit ? $fruehesteKommenZeit->format('H:i:s') : '',
|
||||
'spaetesteGehenZeit' => $spaetesteGehenZeit ? $spaetesteGehenZeit->format('H:i:s') : '',
|
||||
'gesamtarbeitszeit' => $gesamtarbeitszeit->format('%H:%I:%S'),
|
||||
'gesamtpausenzeit' => $gesamtpausenzeit->format('%H:%I:%S')
|
||||
];
|
||||
}
|
||||
|
||||
// Ausgabe der Ergebnisse für Testzwecke
|
||||
echo '<pre>';
|
||||
print_r($zeitenProTag);
|
||||
echo '</pre>';
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
$user = check_user();
|
||||
if (!is_admin_user()) {
|
||||
die('Zugriff verweigert. Nur Chefs dürfen Betriebsurlaub verwalten.');
|
||||
}
|
||||
|
||||
// Create table if not exists (optional helper)
|
||||
// Administrators can also run the SQL directly in DB. This is just a convenience.
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['start_date']) && isset($_POST['end_date'])) {
|
||||
$start = $_POST['start_date'];
|
||||
$end = $_POST['end_date'];
|
||||
$desc = trim($_POST['description'] ?? 'Betriebsurlaub');
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO company_holidays (start_date, end_date, description, created_by) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$start, $end, $desc, $_SESSION['userid']]);
|
||||
|
||||
header('Location: company_holidays.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
include 'header.php';
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM company_holidays ORDER BY start_date DESC");
|
||||
$stmt->execute();
|
||||
$holidays = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Betriebsurlaub verwalten</h2>
|
||||
|
||||
<form method="post" class="form-inline mb-3">
|
||||
<div class="form-group mr-2">
|
||||
<label>Von:</label>
|
||||
<input type="date" name="start_date" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group mr-2">
|
||||
<label>Bis:</label>
|
||||
<input type="date" name="end_date" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group mr-2">
|
||||
<label>Beschreibung:</label>
|
||||
<input type="text" name="description" class="form-control" placeholder="z. B. Betriebsurlaub Weihnachten">
|
||||
</div>
|
||||
<button class="btn btn-primary">Hinzufügen</button>
|
||||
</form>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Von</th>
|
||||
<th>Bis</th>
|
||||
<th>Beschreibung</th>
|
||||
<th>Erstellt von</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($holidays as $h): ?>
|
||||
<tr>
|
||||
<td><?php echo $h['start_date']; ?></td>
|
||||
<td><?php echo $h['end_date']; ?></td>
|
||||
<td><?php echo htmlspecialchars($h['description']); ?></td>
|
||||
<td><?php
|
||||
$s = $pdo->prepare("SELECT vorname, nachname FROM users WHERE id = ?");
|
||||
$s->execute([$h['created_by']]);
|
||||
$u = $s->fetch();
|
||||
echo htmlspecialchars($u['vorname'] . ' ' . $u['nachname']);
|
||||
?></td>
|
||||
<td>
|
||||
<form method="post" action="deleteCompanyHoliday.php" onsubmit="return confirm('Betriebsurlaub wirklich löschen?');">
|
||||
<input type="hidden" name="id" value="<?php echo intval($h['id']); ?>">
|
||||
<button class="btn btn-sm btn-danger">Löschen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php';
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('./../admin/tcpdf/tcpdf.php');
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user = check_user();
|
||||
|
||||
if($_GET['id'] && $user["admin"] == 1){
|
||||
$user_id = $_GET['id'];
|
||||
}else{
|
||||
$user_id = $_SESSION['userid'];
|
||||
}
|
||||
|
||||
$mitarbeiterName = ""; // Holen Sie den Namen des Mitarbeiters aus der Datenbank
|
||||
$firmaName = "Praxis Creutzburg"; // Setzen Sie den Firmennamen
|
||||
|
||||
|
||||
$selectedMonth = $_GET['month'] ?? date('m'); // Monat vom Benutzer oder aktueller Monat
|
||||
$selectedYear = $_GET['year'] ?? date('Y'); // Jahr vom Benutzer oder aktuelles Jahr
|
||||
|
||||
$selectedMonthSQL = str_pad($selectedMonth, 2, '0', STR_PAD_LEFT);
|
||||
|
||||
#echo $selectedMonthSQL;
|
||||
|
||||
try {
|
||||
|
||||
$query2 = "
|
||||
SELECT
|
||||
DATE(timestamp_datetime) AS datum,
|
||||
GROUP_CONCAT(timestamp_type ORDER BY timestamp_datetime) AS day_sequence
|
||||
FROM
|
||||
timestamps
|
||||
WHERE
|
||||
employee_id = :employee_id AND
|
||||
MONTH(timestamp_datetime) = :selectedMonth AND
|
||||
YEAR(timestamp_datetime) = :selectedYear
|
||||
GROUP BY
|
||||
DATE(timestamp_datetime);";
|
||||
|
||||
$stmt = $pdo->prepare($query2);
|
||||
$stmt->bindParam(':employee_id', $user_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':selectedMonth', $selectedMonth, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':selectedYear', $selectedYear, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll();
|
||||
|
||||
#$invalidDates = [];
|
||||
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
foreach ($result as $row) {
|
||||
|
||||
if (!isValidSequence($row["day_sequence"])) {
|
||||
$fehlerhafteTage[] = $row["datum"];
|
||||
}
|
||||
}
|
||||
|
||||
if ($fehlerhafteTage){
|
||||
|
||||
include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Stempelkarten-System</h2>
|
||||
<?php
|
||||
|
||||
echo "<h1>Fehlzeiten erkannt</h1><br><h4>Bitte erst beheben.</h4><br>";
|
||||
|
||||
?>
|
||||
|
||||
<a href="index.php" class="btn btn-info btn-lg btn-block">Zurück</a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php';
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
// Holen Sie den Namen des Mitarbeiters aus der Datenbank
|
||||
$user_stmt = $pdo->prepare("SELECT vorname, nachname FROM users WHERE id = ?");
|
||||
$user_stmt->bindParam(1, $user_id);
|
||||
$user_stmt->execute();
|
||||
$user = $user_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($user) {
|
||||
$mitarbeiterName = $user['vorname'] . ' ' . $user['nachname'];
|
||||
} else {
|
||||
die("Mitarbeiter nicht gefunden.");
|
||||
}
|
||||
|
||||
// Holen Sie die Zeiten des Mitarbeiters aus der Datenbank
|
||||
$times_stmt = $pdo->prepare("SELECT
|
||||
DATE(timestamp_datetime) AS day,
|
||||
MIN(CASE WHEN timestamp_type = 'KOMMEN' THEN timestamp_datetime END) AS first_come,
|
||||
MAX(CASE WHEN timestamp_type = 'GEHEN' THEN timestamp_datetime END) AS last_go,
|
||||
|
||||
SEC_TO_TIME(SUM(
|
||||
CASE
|
||||
WHEN timestamp_type = 'GEHEN' THEN UNIX_TIMESTAMP(timestamp_datetime)
|
||||
WHEN timestamp_type = 'KOMMEN' THEN -UNIX_TIMESTAMP(timestamp_datetime)
|
||||
ELSE 0
|
||||
END
|
||||
)) AS total_time,
|
||||
SEC_TO_TIME(
|
||||
TIME_TO_SEC(
|
||||
SEC_TO_TIME(
|
||||
UNIX_TIMESTAMP(
|
||||
MAX(CASE WHEN timestamp_type = 'GEHEN' THEN timestamp_datetime END)
|
||||
) - UNIX_TIMESTAMP(
|
||||
MIN(CASE WHEN timestamp_type = 'KOMMEN' THEN timestamp_datetime END)
|
||||
)
|
||||
)
|
||||
) - TIME_TO_SEC(SEC_TO_TIME(SUM(
|
||||
CASE
|
||||
WHEN timestamp_type = 'GEHEN' THEN UNIX_TIMESTAMP(timestamp_datetime)
|
||||
WHEN timestamp_type = 'KOMMEN' THEN -UNIX_TIMESTAMP(timestamp_datetime)
|
||||
ELSE 0
|
||||
END
|
||||
)))
|
||||
) AS difference_between_total_time_and_pause_time
|
||||
FROM
|
||||
timestamps
|
||||
WHERE
|
||||
employee_id = :employee_id AND
|
||||
MONTH(timestamp_datetime) = :month AND
|
||||
YEAR(timestamp_datetime) = :year
|
||||
GROUP BY
|
||||
DATE(timestamp_datetime)");
|
||||
|
||||
$times_stmt->bindParam(':employee_id', $user_id, PDO::PARAM_INT);
|
||||
$times_stmt->bindParam(':month', $selectedMonth, PDO::PARAM_INT);
|
||||
$times_stmt->bindParam(':year', $selectedYear, PDO::PARAM_INT);
|
||||
$times_stmt->execute();
|
||||
// Ergebnisse abrufen
|
||||
#$result = $times_stmt->fetchAll();
|
||||
|
||||
#if (count($result) > 0) {
|
||||
|
||||
// Erstellen eines leeren Arrays, um die gesammelten Daten zu speichern
|
||||
$times_data = [];
|
||||
|
||||
// Schleife durch die Ergebnisse der Abfrage und Speichern der Daten in einem assoziativen Array mit dem Tag als Schlüssel
|
||||
while ($row = $times_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$day = date('d', strtotime($row['day']));
|
||||
$times_data[$day] = $row;
|
||||
}
|
||||
|
||||
|
||||
// Erstellen des PDF-Dokuments
|
||||
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
|
||||
|
||||
$pdf->SetCreator(PDF_CREATOR);
|
||||
$pdf->SetAuthor($mitarbeiterName);
|
||||
$pdf->SetTitle('Arbeitszeiten');
|
||||
$pdf->SetSubject('Arbeitszeiten von ' . $mitarbeiterName);
|
||||
|
||||
$pdf->AddPage();
|
||||
$stempdate = $selectedYear . "-" . $selectedMonth . "-1" ;
|
||||
$date = new DateTime($stempdate);
|
||||
|
||||
// the international date formater object
|
||||
$formatter = new IntlDateFormatter(
|
||||
"de-DE",
|
||||
IntlDateFormatter::LONG,
|
||||
IntlDateFormatter::NONE,
|
||||
"Europe/Berlin",
|
||||
IntlDateFormatter::GREGORIAN,
|
||||
"MMMM"
|
||||
);
|
||||
|
||||
// Konvertieren Sie die Monatsnummer in einen Monatsnamen
|
||||
#$dateObj = DateTime::createFromFormat('!m', $selectedMonth);
|
||||
$monthName = $formatter->format($date); // z.B. March
|
||||
|
||||
|
||||
|
||||
$html = '<h1>Arbeitszeiten - ' . $firmaName . '</h1>';
|
||||
$html .= '<h2>Mitarbeiter: ' . $mitarbeiterName . '</h2>';
|
||||
$html .= '<h3>Monat: ' . $monthName . ' ' . $selectedYear . '</h3>';
|
||||
$html .= '<table border="1" style="font-size:14px;" width=100%>';
|
||||
$html .= '<tr><th style="width: 7%;">Tag</th><th style="width: 12%;">Start</th><th style="width: 12%;">Pause</th><th style="width: 12%;">Ende</th><th>Gesamtzeit</th><th style="width: 20%;font-size:12px;">aufgezeichnet am:</th><th style="width: 23%;">Bemerkung</th></tr>';
|
||||
|
||||
// Schleife durch die Tage 1-31
|
||||
for ($day = 1; $day <= 31; $day++) {
|
||||
|
||||
$daytwo = str_pad($day, 2, '0', STR_PAD_LEFT);
|
||||
// Überprüfen, ob Daten für diesen Tag vorhanden sind
|
||||
if (isset($times_data[$daytwo])) {
|
||||
// Daten für diesen Tag aus dem Array abrufen
|
||||
$row = $times_data[$daytwo];
|
||||
|
||||
$html .= '<tr><td>' . $day . '</td><td>' . date('H:i:s', strtotime($row['first_come'])) . '</td><td>' . $row['difference_between_total_time_and_pause_time'] . '</td><td>' . date('H:i:s', strtotime($row['last_go'])) . '</td><td>' . $row['total_time'] . '</td><td>' . date('d.m.Y', strtotime($row['day'])) . '</td><td></td></tr>';
|
||||
list($hours, $minutes, $seconds) = explode(':', $row["total_time"]);
|
||||
$totalSeconds += $hours * 3600 + $minutes * 60 + $seconds;
|
||||
|
||||
|
||||
} else {
|
||||
// Wenn keine Daten für diesen Tag vorhanden sind, eine leere Zeile ausgeben
|
||||
$html .= '<tr><td>' . $day . '</td><td></td><td></td><td></td><td></td><td></td><td></td></tr>';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// Umwandeln der gesamten Sekunden zurück in Stunden, Minuten, Sekunden
|
||||
$hours = floor($totalSeconds / 3600);
|
||||
$mins = floor($totalSeconds / 60 % 60);
|
||||
$secs = floor($totalSeconds % 60);
|
||||
$totalTime = sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
|
||||
|
||||
#echo "Gesamtzeit über alle Tage: " . $totalTime;
|
||||
$html .= '<tr><td></td><td></td><td></td><td><b>Gesamt</b></td><td><b>' . $totalTime .'</b></td><td></td><td></td></tr>';
|
||||
|
||||
$html .= '</table>';
|
||||
|
||||
$pdf->writeHTML($html, true, false, true, false, '');
|
||||
|
||||
$pdf->Output('Arbeitszeiten_' . $user['nachname'] . '_' . $selectedYear . '_' . $selectedMonth . '.pdf', 'I');
|
||||
#} else {
|
||||
# echo "Keine Ergebnisse gefunden";
|
||||
#}
|
||||
|
||||
|
||||
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?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);
|
||||
echo 'Zugriff verweigert.';
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['id'])) {
|
||||
http_response_code(400);
|
||||
echo 'Ungültige Anfrage.';
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = intval($_POST['id']);
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM company_holidays WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
header('Location: company_holidays.php');
|
||||
exit;
|
||||
?>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php"); // Stellen Sie sicher, dass die Datenbankkonfiguration korrekt ist
|
||||
require_once("inc/functions.inc.php"); // Enthält Funktionen für die Benutzerauthentifizierung und mehr
|
||||
|
||||
// Überprüfen, ob der Benutzer angemeldet ist
|
||||
$user = check_user();
|
||||
|
||||
include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<?php
|
||||
try {
|
||||
// Überprüfen, ob die erforderlichen POST-Daten vorhanden sind
|
||||
if (isset($_GET['timestamp_id'])) {
|
||||
// Die timestamp_id aus dem POST-Array holen
|
||||
$timestamp_id = $_GET['timestamp_id'];
|
||||
|
||||
// SQL-Abfrage zum Löschen der Buchung
|
||||
$sql = "DELETE FROM timestamps WHERE timestamp_id = :timestamp_id";
|
||||
|
||||
// Vorbereiten der SQL-Abfrage
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Binden von Parametern
|
||||
$stmt->bindParam(':timestamp_id', $timestamp_id, PDO::PARAM_INT);
|
||||
|
||||
// Ausführen der vorbereiteten Abfrage
|
||||
$stmt->execute();
|
||||
|
||||
// Erfolgreich gelöscht
|
||||
echo "Buchung erfolgreich gelöscht";
|
||||
} else {
|
||||
// Fehler, wenn timestamp_id nicht im POST-Array gefunden wurde
|
||||
echo "Fehler: timestamp_id nicht gefunden";
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
// Fehler beim Verbindungsaufbau oder bei der Abfrage
|
||||
echo "Fehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php"); // Stellen Sie sicher, dass die Datenbankkonfiguration korrekt ist
|
||||
require_once("inc/functions.inc.php"); // Enthält Funktionen für die Benutzerauthentifizierung und mehr
|
||||
|
||||
// Überprüfen, ob der Benutzer angemeldet ist
|
||||
$user = check_user();
|
||||
|
||||
try {
|
||||
// Überprüfen, ob die erforderlichen POST-Daten vorhanden sind
|
||||
if (isset($_POST['timestamp_id'])) {
|
||||
// Die timestamp_id aus dem POST-Array holen
|
||||
$timestamp_id = $_POST['timestamp_id'];
|
||||
|
||||
// SQL-Abfrage zum Löschen der Buchung
|
||||
$sql = "DELETE FROM buchungen WHERE timestamp_id = :timestamp_id";
|
||||
|
||||
// Vorbereiten der SQL-Abfrage
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Binden von Parametern
|
||||
$stmt->bindParam(':timestamp_id', $timestamp_id, PDO::PARAM_INT);
|
||||
|
||||
// Ausführen der vorbereiteten Abfrage
|
||||
$stmt->execute();
|
||||
|
||||
// Erfolgreich gelöscht
|
||||
echo "Buchung erfolgreich gelöscht";
|
||||
} else {
|
||||
// Fehler, wenn timestamp_id nicht im POST-Array gefunden wurde
|
||||
echo "Fehler: timestamp_id nicht gefunden";
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
// Fehler beim Verbindungsaufbau oder bei der Abfrage
|
||||
echo "Fehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
$user = check_user();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['id'])) {
|
||||
http_response_code(400);
|
||||
die('Bad request');
|
||||
}
|
||||
|
||||
$id = (int)$_POST['id'];
|
||||
$referer = $_POST['referer'] ?? 'urlaubsantrag.php';
|
||||
|
||||
// Fetch vacation to verify ownership
|
||||
$stmt = $pdo->prepare("SELECT user_id, status FROM vacations WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$vac = $stmt->fetch();
|
||||
|
||||
if (!$vac) {
|
||||
die('Urlaubseintrag nicht gefunden.');
|
||||
}
|
||||
|
||||
$isAdmin = is_admin_user();
|
||||
|
||||
if (!$isAdmin && $vac['user_id'] != $_SESSION['userid']) {
|
||||
die('Zugriff verweigert.');
|
||||
}
|
||||
|
||||
// Allow deletion for admins or owner
|
||||
$del = $pdo->prepare("DELETE FROM vacations WHERE id = ?");
|
||||
$del->execute([$id]);
|
||||
|
||||
header('Location: ' . $referer);
|
||||
exit();
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Stempelkarten-System</h2>
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
#$user_id = $_SESSION['userid'];
|
||||
|
||||
$user_id = $_GET['employee_id'] ?? null;
|
||||
$datum = $_GET['datum'] ?? null;
|
||||
|
||||
if ($user_id && $datum) {
|
||||
try {
|
||||
// Holen Sie alle Zeitbuchungen des Tages für den Mitarbeiter
|
||||
$query = "SELECT * FROM timestamps WHERE employee_id = :employee_id AND DATE(timestamp_datetime) = :datum ORDER BY timestamp_datetime ASC";
|
||||
$stmt = $pdo->prepare($query);
|
||||
$stmt->bindParam(':employee_id', $user_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':datum', $datum);
|
||||
$stmt->execute();
|
||||
$buchungen = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
die("Fehler: Mitarbeiter-ID oder Datum fehlt.");
|
||||
}
|
||||
|
||||
// ... [Hier könnten Sie PHP-Code für die Bearbeitung der Buchungen hinzufügen]
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tageseinträge bearbeiten</title>
|
||||
<!-- ... [Bootstrap-CSS und optional JavaScript] -->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<h3>Tageseinträge bearbeiten - <?php echo date('d.m.Y', strtotime($datum)); ?></h3>
|
||||
|
||||
<!-- Formular zum Bearbeiten der Zeitbuchungen -->
|
||||
<form id="mainForm" action="saveDayEntries.php" method="post">
|
||||
<input type="hidden" name="employee_id" value="<?php echo $user_id; ?>">
|
||||
<input type="hidden" name="datum" value="<?php echo $datum; ?>">
|
||||
<?php foreach ($buchungen as $index => $buchung): ?>
|
||||
<div class="form-group" id="entry_<?php echo $buchung['timestamp_id']; ?>">
|
||||
<label>Zeitbuchung <?php echo $index + 1; ?>:</label>
|
||||
<input type="datetime-local" class="form-control" name="buchungen[<?php echo $buchung['timestamp_id']; ?>][timestamp_datetime]" value="<?php echo $buchung['timestamp_datetime']; ?>">
|
||||
<select class="form-control" name="buchungen[<?php echo $buchung['timestamp_id']; ?>][timestamp_type]">
|
||||
<option value="KOMMEN" <?php if ($buchung['timestamp_type'] == 'KOMMEN') echo 'selected'; ?>>KOMMEN</option>
|
||||
<option value="GEHEN" <?php if ($buchung['timestamp_type'] == 'GEHEN') echo 'selected'; ?>>GEHEN</option>
|
||||
</select>
|
||||
|
||||
<a href="deleteDayEntry.php?timestamp_id=<?php echo $buchung['timestamp_id']; ?>" class="btn btn-danger">Löschen</a>
|
||||
|
||||
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<div id="newEnty"></div>
|
||||
<button type="submit" class="btn btn-primary">Speichern</button>
|
||||
</form>
|
||||
<br>
|
||||
<button onclick="addEntry()" class="btn btn-success">Neue Buchung hinzufügen</button>
|
||||
<br><br>
|
||||
<button type="button" class="btn btn-secondary" onclick="history.back();">Zurück</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
let entryIndex = <?php echo count($buchungen); ?>;
|
||||
function addEntry() {
|
||||
entryIndex++;
|
||||
const container = document.createElement('div');
|
||||
container.className = 'form-group';
|
||||
container.innerHTML = `
|
||||
<label>Zeitbuchung ${entryIndex}:</label>
|
||||
<input type="datetime-local" class="form-control" name="buchungen[new_${entryIndex}][timestamp_datetime]" placeholder="YYYY-MM-DD HH:MM:SS">
|
||||
<select class="form-control" name="buchungen[new_${entryIndex}][timestamp_type]">
|
||||
<option value="KOMMEN">KOMMEN</option>
|
||||
<option value="GEHEN">GEHEN</option>
|
||||
</select>
|
||||
|
||||
`;
|
||||
document.getElementById('newEnty').appendChild(container);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$employee_id = $_POST['employee_id'];
|
||||
$datum = $_POST['datum'];
|
||||
$kommen_count = $_POST['kommen_count'];
|
||||
$gehen_count = $_POST['gehen_count'];
|
||||
|
||||
// Hier sollte die Logik implementiert werden, um die Anzahl der 'KOMMEN' und 'GEHEN' Buchungen anzupassen
|
||||
// Beachten Sie, dass dies komplex sein kann, da Sie eventuell existierende Buchungen entfernen oder neue hinzufügen müssen
|
||||
|
||||
// Nach der Bearbeitung, leiten Sie den Benutzer zurück zur 'zeitfehlerAuswertung.php'
|
||||
header("Location: zeitfehlerAuswertung.php");
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<?php
|
||||
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
|
||||
$id = $_GET['id'];
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$mitarbeiter = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$mitarbeiter) {
|
||||
die('Mitarbeiter nicht gefunden!');
|
||||
}
|
||||
} else {
|
||||
die('Ungültige Anfrage!');
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$email = $_POST['email'];
|
||||
$vorname = $_POST['vorname'];
|
||||
$nachname = $_POST['nachname'];
|
||||
$card_id = $_POST['card_id'] ?? '';
|
||||
$card2_id = $_POST['card2_id'] ?? '';
|
||||
$worker = $_POST['worker'] ?? 0;
|
||||
|
||||
$sql = "UPDATE users SET email=?, vorname=?, nachname=?, worker=?, admin=?, zeiterfassung=?, card_id=?, card2_id=? WHERE id=?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$email, $vorname, $nachname, $_POST['worker'], $_POST['admin'], $_POST['zeiterfassung'], $card_id, $card2_id, $id]);
|
||||
|
||||
// Zusatzaktion für users_worker
|
||||
if ($worker == 1) {
|
||||
// Prüfen, ob der Eintrag schon existiert
|
||||
$checkSql = "SELECT COUNT(*) FROM users_worker WHERE userid = ?";
|
||||
$checkStmt = $pdo->prepare($checkSql);
|
||||
$checkStmt->execute([$id]);
|
||||
$exists = $checkStmt->fetchColumn();
|
||||
|
||||
if ($exists == 0) {
|
||||
// Eintrag hinzufügen
|
||||
$insertSql = "INSERT INTO users_worker (workerid, userid) VALUES (?, ?)";
|
||||
$insertStmt = $pdo->prepare($insertSql);
|
||||
$insertStmt->execute([$id, $id]);
|
||||
}
|
||||
} else {
|
||||
// Eintrag löschen
|
||||
$deleteSql = "DELETE FROM users_worker WHERE userid = ?";
|
||||
$deleteStmt = $pdo->prepare($deleteSql);
|
||||
$deleteStmt->execute([$id]);
|
||||
}
|
||||
|
||||
echo "<br><div class='alert alert-success' role='alert'>Mitarbeiter erfolgreich aktualisiert.</div>";
|
||||
// Optional: Umleitung
|
||||
// header('Location: index.php');
|
||||
}else{
|
||||
?>
|
||||
|
||||
<div class="container mt-5">
|
||||
<h2>Mitarbeiter bearbeiten</h2>
|
||||
<form action="" method="post" class="mt-3">
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="text" class="form-control" name="email" id="email" value="<?php echo htmlspecialchars($mitarbeiter['email']); ?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="vorname">Vorname</label>
|
||||
<input type="text" class="form-control" name="vorname" id="vorname" value="<?php echo htmlspecialchars($mitarbeiter['vorname']); ?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nachname">Nachname</label>
|
||||
<input type="text" class="form-control" name="nachname" id="nachname" value="<?php echo htmlspecialchars($mitarbeiter['nachname']); ?>" required>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="zeiterfassung" id="zeiterfassung" value="1" <?php if($mitarbeiter['zeiterfassung']== "1") echo 'checked'; ?>>
|
||||
<label class="form-check-label" for="zeiterfassung">Zeiterfassung</label>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="worker" id="worker" value="1" <?php if($mitarbeiter['worker'] == "1") echo 'checked'; ?>>
|
||||
<label class="form-check-label" for="worker">Worker</label>
|
||||
</div>
|
||||
<div class="form-group form-check">
|
||||
<input type="checkbox" class="form-check-input" name="admin" id="admin" value="1" <?php if($mitarbeiter['admin']== "1") echo 'checked'; ?>>
|
||||
<label class="form-check-label" for="admin">Admin</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="card_id">Card ID</label>
|
||||
<input type="text" class="form-control" name="card_id" id="card_id" value="<?php echo htmlspecialchars($mitarbeiter['card_id']); ?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="card2_id">Card2 ID</label>
|
||||
<input type="text" class="form-control" name="card2_id" id="card2_id" value="<?php echo htmlspecialchars($mitarbeiter['card2_id']); ?>">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Aktualisieren</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="container mt-5">
|
||||
<?php
|
||||
echo "<td><a class='btn btn-primary btn-sm' href='editworkerpassword.php?id=" . $mitarbeiter['id'] . "'>Passwort des Mitarbeiters ändern</a></td>";
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<div class="container mt-5">
|
||||
<button type="button" class="btn btn-secondary" onclick="window.location.href='showworker.php';">Zurück</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<?php
|
||||
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
|
||||
$id = $_GET['id'];
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$mitarbeiter = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$mitarbeiter) {
|
||||
die('Mitarbeiter nicht gefunden!');
|
||||
}
|
||||
} else {
|
||||
die('Ungültige Anfrage!');
|
||||
}
|
||||
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
if(isset($_GET['send'])) {
|
||||
$passwort = $_POST['passwort'];
|
||||
$passwort2 = $_POST['passwort2'];
|
||||
|
||||
if($passwort != $passwort2) {
|
||||
$msg = "Bitte identische Passwörter eingeben";
|
||||
} else { //Speichere neues Passwort und lösche den Code
|
||||
$passworthash = password_hash($passwort, PASSWORD_DEFAULT);
|
||||
$statement = $pdo->prepare("UPDATE users SET passwort = :passworthash, passwortcode = NULL, passwortcode_time = NULL WHERE id = :userid");
|
||||
$result = $statement->execute(array('passworthash' => $passworthash, 'userid'=> $id ));
|
||||
|
||||
if($result) {
|
||||
echo "<br><div class='alert alert-success' role='alert'>Das Passwort des Mitarbeiters wurde erfolgreich aktualisiert.</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optional: Umleitung
|
||||
// header('Location: index.php');
|
||||
}else{
|
||||
?>
|
||||
|
||||
<div class="container small-container-500">
|
||||
|
||||
<h1>Neues Passwort vergeben</h1>
|
||||
|
||||
<?php echo "<h3>Passwort von Mitarbeiter: " . htmlspecialchars($mitarbeiter['vorname']) . " " . htmlspecialchars($mitarbeiter['nachname']) . " ändern.</h3>" ?>
|
||||
|
||||
<form action="?send=1&id=<?php echo htmlentities($_GET['id']); ?>" method="post">
|
||||
<label for="passwort">Bitte gib ein neues Passwort ein:</label><br>
|
||||
<input type="password" id="passwort" name="passwort" class="form-control" required><br>
|
||||
|
||||
<label for="passwort2">Passwort erneut eingeben:</label><br>
|
||||
<input type="password" id="passwort2" name="passwort2" class="form-control" required><br>
|
||||
|
||||
<input type="submit" value="Passwort speichern" class="btn btn-lg btn-primary btn-block">
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" onclick="history.back();">Zurück</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('./../admin/tcpdf/tcpdf.php');
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user = check_user();
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
$query2 = "
|
||||
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);";
|
||||
|
||||
$stmt = $pdo->prepare($query2);
|
||||
$stmt->bindParam(':employee_id', $user["id"], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll();
|
||||
|
||||
$invalidDates = [];
|
||||
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
|
||||
<div class="container">
|
||||
<h2 class="mb-4">Zeitbuchungsfehler Auswertung</h2>
|
||||
<?php
|
||||
|
||||
foreach ($result as $row) {
|
||||
if (!isValidSequence($row["day_sequence"])) {
|
||||
$invalidDates[] = $row["datum"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<?php if (!empty($invalidDates)): ?>
|
||||
<table class="table table-striped">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Fehler</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($invalidDates as $date): ?>
|
||||
<tr>
|
||||
<td><?php echo date('d.m.Y', strtotime($date)); ?></td>
|
||||
<td>Fehlerhafte KOMMEN/GEHEN Buchung</td>
|
||||
<td>
|
||||
<a href="editDayEntries.php?employee_id=<?php echo $user['id']; ?>&datum=<?php echo $date; ?>" class="btn btn-warning">Anpassen</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php else: ?>
|
||||
<div class="alert alert-info" role="alert">
|
||||
Keine Zeitbuchungsfehler gefunden.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,7 @@
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery, Popper.js, Bootstrap JS -->
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.4.2/dist/umd/popper.min.js"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Ihre Webseite</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
<?php
|
||||
// Ensure $user is available without changing authentication behavior elsewhere
|
||||
if (!isset($user)) {
|
||||
if (isset($_SESSION['userid']) && isset($pdo)) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['userid']]);
|
||||
$user = $stmt->fetch();
|
||||
} else {
|
||||
// Minimal default to avoid notices when not logged in
|
||||
$user = ['admin' => 0, 'zeiterfassung' => 0];
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<a class="navbar-brand" href="#">Zeiterfassung</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="index.php">Startseite</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="ZeitenAnzeige.php">Zeitübersicht</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="fehlbuchungen.php">Fehlbuchungen</a>
|
||||
</li>
|
||||
|
||||
<!-- Urlaub Dropdown -->
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="urlaubDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Urlaub
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="urlaubDropdown">
|
||||
<a class="dropdown-item" href="urlaubsantrag.php">Urlaubsantrag</a>
|
||||
<a class="dropdown-item" href="my_vacations_calendar.php">Mein Urlaubskalender</a>
|
||||
<a class="dropdown-item" href="vacations_calendar_all.php">Team Urlaubskalender</a>
|
||||
<?php if (is_admin_user()) : ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="vacations_overview.php">Urlaubsübersicht</a>
|
||||
<a class="dropdown-item" href="approveVacation.php">Urlaubsanträge genehmigen</a>
|
||||
<a class="dropdown-item" href="company_holidays.php">Betriebsurlaub</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<!-- Verwaltung Dropdown (Admin only) -->
|
||||
<?php if (is_admin_user()) : ?>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="adminDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
Verwaltung
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="adminDropdown">
|
||||
<a class="dropdown-item" href="alleZeitenanzeige.php">Alle Zeitbuchungen</a>
|
||||
<a class="dropdown-item" href="allefehlbuchungen.php">Alle Fehlbuchungen</a>
|
||||
<a class="dropdown-item" href="showworker.php">Mitarbeiterverwaltung</a>
|
||||
</div>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
|
||||
<!-- optional right-side user area -->
|
||||
<ul class="navbar-nav">
|
||||
<?php if (isset($user['vorname'])): ?>
|
||||
<li class="nav-item"><span class="navbar-text text-light mr-3"><?php echo htmlspecialchars($user['vorname']); ?></span></li>
|
||||
<li class="nav-item"><a class="nav-link" href="logout.php">Abmelden</a></li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item"><a class="nav-link" href="login.php">Anmelden</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<?php
|
||||
// Enforce zeiterfassung permission if present on pages that expect it
|
||||
if (isset($user['zeiterfassung']) && $user['zeiterfassung'] != 1) {
|
||||
die("Keine Rechte für die Zeiterfassung");
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
|
||||
//Datenbankverbindung
|
||||
$dbhost = "mysql2fda.netcup.net";
|
||||
$dbuser = "k25330_pracreutz";
|
||||
$dbpassword = "be4K8DSASDA2y";
|
||||
$dbname = "k25330_pracreutz";
|
||||
|
||||
// SQL Datum festlegen
|
||||
$sqltoday = date("Y-m-d");
|
||||
#$sqlyesterday = date("Y-m-d", strtotime("-1 day", $sqltoday ));
|
||||
#$yesterday = Date('Y-m-d', strtotime('-1 day'));
|
||||
#$yesteryesterday = Date('Y-m-d', strtotime('-2 days'));
|
||||
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
];
|
||||
|
||||
|
||||
$pdo = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpassword, $options);
|
||||
|
||||
|
||||
#$conn = new mysqli($dbhost,$dbuser,$dbpassword,$dbname);
|
||||
?>
|
||||
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
include_once("password.inc.php");
|
||||
|
||||
/**
|
||||
* Checks that the user is logged in.
|
||||
* @return Returns the row of the logged in user
|
||||
*/
|
||||
function check_user() {
|
||||
global $pdo;
|
||||
|
||||
if(!isset($_SESSION['userid']) && isset($_COOKIE['identifier']) && isset($_COOKIE['securitytoken'])) {
|
||||
$identifier = $_COOKIE['identifier'];
|
||||
$securitytoken = $_COOKIE['securitytoken'];
|
||||
|
||||
$statement = $pdo->prepare("SELECT * FROM securitytokens WHERE identifier = :identifier");
|
||||
$result = $statement->execute(array('identifier' => $identifier));
|
||||
$securitytoken_row = $statement->fetch();
|
||||
//echo $securitytoken;
|
||||
|
||||
if(sha1($securitytoken) !== $securitytoken_row['securitytoken']) {
|
||||
//Vermutlich wurde der Security Token gestohlen
|
||||
//Hier ggf. eine Warnung o.ä. anzeigen
|
||||
echo 'In der letzte Sitzung nicht abgemeldet oder neuer/anderen Browser genutzt.<br><br><br>';
|
||||
} else { //Token war korrekt
|
||||
//Setze neuen Token
|
||||
$neuer_securitytoken = random_string();
|
||||
$insert = $pdo->prepare("UPDATE securitytokens SET securitytoken = :securitytoken WHERE identifier = :identifier");
|
||||
$insert->execute(array('securitytoken' => sha1($neuer_securitytoken), 'identifier' => $identifier));
|
||||
setcookie("identifier",$identifier,time()+(3600*24*365)); //1 Jahr Gültigkeit
|
||||
setcookie("securitytoken",$neuer_securitytoken,time()+(3600*24*365)); //1 Jahr Gültigkeit
|
||||
|
||||
//Logge den Benutzer ein
|
||||
$_SESSION['userid'] = $securitytoken_row['user_id'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!isset($_SESSION['userid'])) {
|
||||
die('Bitte zuerst <a href="login.php" >einloggen</a>');
|
||||
}
|
||||
|
||||
|
||||
$statement = $pdo->prepare("SELECT * FROM users WHERE id = :id");
|
||||
$result = $statement->execute(array('id' => $_SESSION['userid']));
|
||||
$user = $statement->fetch();
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user is checked in, else false
|
||||
*/
|
||||
function is_checked_in() {
|
||||
return isset($_SESSION['userid']);
|
||||
}
|
||||
|
||||
function is_checked_in_index() {
|
||||
if( isset($_SESSION['userid']) || isset($_COOKIE['identifier'])){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random string
|
||||
*/
|
||||
function random_string() {
|
||||
if(function_exists('openssl_random_pseudo_bytes')) {
|
||||
$bytes = openssl_random_pseudo_bytes(16);
|
||||
$str = bin2hex($bytes);
|
||||
} else if(function_exists('mcrypt_create_iv')) {
|
||||
$bytes = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
|
||||
$str = bin2hex($bytes);
|
||||
} else {
|
||||
//Replace your_secret_string with a string of your choice (>12 characters)
|
||||
$str = md5(uniqid('your_secret_string', true));
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URL to the site without the script name
|
||||
*/
|
||||
function getSiteURL() {
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
|
||||
return $protocol.$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs an error message and stops the further exectution of the script.
|
||||
*/
|
||||
function error($error_msg) {
|
||||
include("templates/header.inc.php");
|
||||
include("templates/error.inc.php");
|
||||
include("templates/footer.inc.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft, ob der Benutzer administrator ist
|
||||
*/
|
||||
function check_admin() {
|
||||
global $pdo;
|
||||
|
||||
if(isset($_SESSION['userid'])) {
|
||||
$statement = $pdo->prepare("SELECT userid FROM users_admin WHERE userid = :id");
|
||||
$statement->execute(array('id' => $_SESSION['userid']));
|
||||
$count = $statement->rowCount();
|
||||
|
||||
if($count == 1){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Non-invasive admin check that prefers the `users.admin` flag but
|
||||
* falls back to the legacy `users_admin` table. Does not modify
|
||||
* `check_user()` behavior.
|
||||
*/
|
||||
function is_admin_user() {
|
||||
global $pdo;
|
||||
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prefer the admin flag in users table (supports BIT(1) or TINYINT)
|
||||
$stmt = $pdo->prepare("SELECT admin FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['userid']]);
|
||||
$row = $stmt->fetch();
|
||||
if ($row && !empty($row['admin'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fallback to legacy users_admin table
|
||||
$statement = $pdo->prepare("SELECT userid FROM users_admin WHERE userid = :id");
|
||||
$statement->execute(array('id' => $_SESSION['userid']));
|
||||
return ($statement->rowCount() == 1);
|
||||
}
|
||||
/**
|
||||
* Prüft, ob der Benutzer Bearbeiter ist
|
||||
*/
|
||||
function check_worker() {
|
||||
global $pdo;
|
||||
|
||||
if(isset($_SESSION['userid'])) {
|
||||
$statement = $pdo->prepare("SELECT userid FROM users_worker WHERE userid = :id");
|
||||
$statement->execute(array('id' => $_SESSION['userid']));
|
||||
$count = $statement->rowCount();
|
||||
|
||||
if($count == 1){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function isValidSequence($sequence) {
|
||||
$events = explode(',', $sequence);
|
||||
$previousType = null;
|
||||
|
||||
foreach ($events as $type) {
|
||||
if ($previousType === $type) {
|
||||
// Ein Fehler, wenn zwei gleiche Typen aufeinanderfolgen
|
||||
return false;
|
||||
}
|
||||
$previousType = $type;
|
||||
}
|
||||
|
||||
// Überprüfen Sie, ob die Sequenz mit einem KOMMEN beginnt und einem GEHEN endet
|
||||
return $events[0] === 'KOMMEN' && end($events) === 'GEHEN';
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
/**
|
||||
* A Compatibility library with PHP 5.5's simplified password hashing API.
|
||||
*
|
||||
* @author Anthony Ferrara <ircmaxell@php.net>
|
||||
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||
* @copyright 2012 The Authors
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
if (!defined('PASSWORD_BCRYPT')) {
|
||||
/**
|
||||
* PHPUnit Process isolation caches constants, but not function declarations.
|
||||
* So we need to check if the constants are defined separately from
|
||||
* the functions to enable supporting process isolation in userland
|
||||
* code.
|
||||
*/
|
||||
define('PASSWORD_BCRYPT', 1);
|
||||
define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);
|
||||
define('PASSWORD_BCRYPT_DEFAULT_COST', 10);
|
||||
}
|
||||
|
||||
if (!function_exists('password_hash')) {
|
||||
|
||||
/**
|
||||
* Hash the password using the specified algorithm
|
||||
*
|
||||
* @param string $password The password to hash
|
||||
* @param int $algo The algorithm to use (Defined by PASSWORD_* constants)
|
||||
* @param array $options The options for the algorithm to use
|
||||
*
|
||||
* @return string|false The hashed password, or false on error.
|
||||
*/
|
||||
function password_hash($password, $algo, array $options = array()) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_hash to function", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (is_null($password) || is_int($password)) {
|
||||
$password = (string) $password;
|
||||
}
|
||||
if (!is_string($password)) {
|
||||
trigger_error("password_hash(): Password must be a string", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (!is_int($algo)) {
|
||||
trigger_error("password_hash() expects parameter 2 to be long, " . gettype($algo) . " given", E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$resultLength = 0;
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
$cost = PASSWORD_BCRYPT_DEFAULT_COST;
|
||||
if (isset($options['cost'])) {
|
||||
$cost = (int) $options['cost'];
|
||||
if ($cost < 4 || $cost > 31) {
|
||||
trigger_error(sprintf("password_hash(): Invalid bcrypt cost parameter specified: %d", $cost), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// The length of salt to generate
|
||||
$raw_salt_len = 16;
|
||||
// The length required in the final serialization
|
||||
$required_salt_len = 22;
|
||||
$hash_format = sprintf("$2y$%02d$", $cost);
|
||||
// The expected length of the final crypt() output
|
||||
$resultLength = 60;
|
||||
break;
|
||||
default:
|
||||
trigger_error(sprintf("password_hash(): Unknown password hashing algorithm: %s", $algo), E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
$salt_req_encoding = false;
|
||||
if (isset($options['salt'])) {
|
||||
switch (gettype($options['salt'])) {
|
||||
case 'NULL':
|
||||
case 'boolean':
|
||||
case 'integer':
|
||||
case 'double':
|
||||
case 'string':
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
case 'object':
|
||||
if (method_exists($options['salt'], '__tostring')) {
|
||||
$salt = (string) $options['salt'];
|
||||
break;
|
||||
}
|
||||
case 'array':
|
||||
case 'resource':
|
||||
default:
|
||||
trigger_error('password_hash(): Non-string salt parameter supplied', E_USER_WARNING);
|
||||
return null;
|
||||
}
|
||||
if (PasswordCompat\binary\_strlen($salt) < $required_salt_len) {
|
||||
trigger_error(sprintf("password_hash(): Provided salt is too short: %d expecting %d", PasswordCompat\binary\_strlen($salt), $required_salt_len), E_USER_WARNING);
|
||||
return null;
|
||||
} elseif (0 == preg_match('#^[a-zA-Z0-9./]+$#D', $salt)) {
|
||||
$salt_req_encoding = true;
|
||||
}
|
||||
} else {
|
||||
$buffer = '';
|
||||
$buffer_valid = false;
|
||||
if (function_exists('mcrypt_create_iv') && !defined('PHALANGER')) {
|
||||
$buffer = mcrypt_create_iv($raw_salt_len, MCRYPT_DEV_URANDOM);
|
||||
if ($buffer) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && function_exists('openssl_random_pseudo_bytes')) {
|
||||
$strong = false;
|
||||
$buffer = openssl_random_pseudo_bytes($raw_salt_len, $strong);
|
||||
if ($buffer && $strong) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
}
|
||||
if (!$buffer_valid && @is_readable('/dev/urandom')) {
|
||||
$file = fopen('/dev/urandom', 'r');
|
||||
$read = 0;
|
||||
$local_buffer = '';
|
||||
while ($read < $raw_salt_len) {
|
||||
$local_buffer .= fread($file, $raw_salt_len - $read);
|
||||
$read = PasswordCompat\binary\_strlen($local_buffer);
|
||||
}
|
||||
fclose($file);
|
||||
if ($read >= $raw_salt_len) {
|
||||
$buffer_valid = true;
|
||||
}
|
||||
$buffer = str_pad($buffer, $raw_salt_len, "\0") ^ str_pad($local_buffer, $raw_salt_len, "\0");
|
||||
}
|
||||
if (!$buffer_valid || PasswordCompat\binary\_strlen($buffer) < $raw_salt_len) {
|
||||
$buffer_length = PasswordCompat\binary\_strlen($buffer);
|
||||
for ($i = 0; $i < $raw_salt_len; $i++) {
|
||||
if ($i < $buffer_length) {
|
||||
$buffer[$i] = $buffer[$i] ^ chr(mt_rand(0, 255));
|
||||
} else {
|
||||
$buffer .= chr(mt_rand(0, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
$salt = $buffer;
|
||||
$salt_req_encoding = true;
|
||||
}
|
||||
if ($salt_req_encoding) {
|
||||
// encode string with the Base64 variant used by crypt
|
||||
$base64_digits =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
$bcrypt64_digits =
|
||||
'./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
$base64_string = base64_encode($salt);
|
||||
$salt = strtr(rtrim($base64_string, '='), $base64_digits, $bcrypt64_digits);
|
||||
}
|
||||
$salt = PasswordCompat\binary\_substr($salt, 0, $required_salt_len);
|
||||
|
||||
$hash = $hash_format . $salt;
|
||||
|
||||
$ret = crypt($password, $hash);
|
||||
|
||||
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != $resultLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get information about the password hash. Returns an array of the information
|
||||
* that was used to generate the password hash.
|
||||
*
|
||||
* array(
|
||||
* 'algo' => 1,
|
||||
* 'algoName' => 'bcrypt',
|
||||
* 'options' => array(
|
||||
* 'cost' => PASSWORD_BCRYPT_DEFAULT_COST,
|
||||
* ),
|
||||
* )
|
||||
*
|
||||
* @param string $hash The password hash to extract info from
|
||||
*
|
||||
* @return array The array of information about the hash.
|
||||
*/
|
||||
function password_get_info($hash) {
|
||||
$return = array(
|
||||
'algo' => 0,
|
||||
'algoName' => 'unknown',
|
||||
'options' => array(),
|
||||
);
|
||||
if (PasswordCompat\binary\_substr($hash, 0, 4) == '$2y$' && PasswordCompat\binary\_strlen($hash) == 60) {
|
||||
$return['algo'] = PASSWORD_BCRYPT;
|
||||
$return['algoName'] = 'bcrypt';
|
||||
list($cost) = sscanf($hash, "$2y$%d$");
|
||||
$return['options']['cost'] = $cost;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the password hash needs to be rehashed according to the options provided
|
||||
*
|
||||
* If the answer is true, after validating the password using password_verify, rehash it.
|
||||
*
|
||||
* @param string $hash The hash to test
|
||||
* @param int $algo The algorithm used for new password hashes
|
||||
* @param array $options The options array passed to password_hash
|
||||
*
|
||||
* @return boolean True if the password needs to be rehashed.
|
||||
*/
|
||||
function password_needs_rehash($hash, $algo, array $options = array()) {
|
||||
$info = password_get_info($hash);
|
||||
if ($info['algo'] !== (int) $algo) {
|
||||
return true;
|
||||
}
|
||||
switch ($algo) {
|
||||
case PASSWORD_BCRYPT:
|
||||
$cost = isset($options['cost']) ? (int) $options['cost'] : PASSWORD_BCRYPT_DEFAULT_COST;
|
||||
if ($cost !== $info['options']['cost']) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a password against a hash using a timing attack resistant approach
|
||||
*
|
||||
* @param string $password The password to verify
|
||||
* @param string $hash The hash to verify against
|
||||
*
|
||||
* @return boolean If the password matches the hash
|
||||
*/
|
||||
function password_verify($password, $hash) {
|
||||
if (!function_exists('crypt')) {
|
||||
trigger_error("Crypt must be loaded for password_verify to function", E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$ret = crypt($password, $hash);
|
||||
if (!is_string($ret) || PasswordCompat\binary\_strlen($ret) != PasswordCompat\binary\_strlen($hash) || PasswordCompat\binary\_strlen($ret) <= 13) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$status = 0;
|
||||
for ($i = 0; $i < PasswordCompat\binary\_strlen($ret); $i++) {
|
||||
$status |= (ord($ret[$i]) ^ ord($hash[$i]));
|
||||
}
|
||||
|
||||
return $status === 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace PasswordCompat\binary {
|
||||
|
||||
if (!function_exists('PasswordCompat\\binary\\_strlen')) {
|
||||
|
||||
/**
|
||||
* Count the number of bytes in a string
|
||||
*
|
||||
* We cannot simply use strlen() for this, because it might be overwritten by the mbstring extension.
|
||||
* In this case, strlen() will count the number of *characters* based on the internal encoding. A
|
||||
* sequence of bytes might be regarded as a single multibyte character.
|
||||
*
|
||||
* @param string $binary_string The input string
|
||||
*
|
||||
* @internal
|
||||
* @return int The number of bytes
|
||||
*/
|
||||
function _strlen($binary_string) {
|
||||
if (function_exists('mb_strlen')) {
|
||||
return mb_strlen($binary_string, '8bit');
|
||||
}
|
||||
return strlen($binary_string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a substring based on byte limits
|
||||
*
|
||||
* @see _strlen()
|
||||
*
|
||||
* @param string $binary_string The input string
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
*
|
||||
* @internal
|
||||
* @return string The substring
|
||||
*/
|
||||
function _substr($binary_string, $start, $length) {
|
||||
if (function_exists('mb_substr')) {
|
||||
return mb_substr($binary_string, $start, $length, '8bit');
|
||||
}
|
||||
return substr($binary_string, $start, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if current PHP version is compatible with the library
|
||||
*
|
||||
* @return boolean the check result
|
||||
*/
|
||||
function check() {
|
||||
static $pass = NULL;
|
||||
|
||||
if (is_null($pass)) {
|
||||
if (function_exists('crypt')) {
|
||||
$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
|
||||
$test = crypt("password", $hash);
|
||||
$pass = $test == $hash;
|
||||
} else {
|
||||
$pass = false;
|
||||
}
|
||||
}
|
||||
return $pass;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Stempelkarten-System</h2>
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
try {
|
||||
// Benutzerinformationen basierend auf der gespeicherten Benutzer-ID abrufen
|
||||
$stmt = $pdo->prepare("SELECT vorname FROM users WHERE id = ?");
|
||||
$stmt->bindParam(1, $user_id);
|
||||
$stmt->execute();
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
|
||||
if ($user) {
|
||||
// Logik für das Setzen des Zeitstempels
|
||||
$stmt = $pdo->prepare("SELECT COUNT(CASE WHEN timestamp_type = 'KOMMEN' THEN 1 ELSE NULL END) AS AnzahlKommen, COUNT(CASE WHEN timestamp_type = 'GEHEN' THEN 1 ELSE NULL END) AS AnzahlGehen FROM timestamps WHERE employee_id = ? AND DATE(timestamp_datetime) = CURDATE()");
|
||||
$stmt->bindParam(1, $user_id);
|
||||
$stmt->execute();
|
||||
$timestamp_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$timestamp_type = $timestamp_data['AnzahlKommen'] > $timestamp_data['AnzahlGehen'] ? "GEHEN" : "KOMMEN";
|
||||
|
||||
// Zeitstempel hinzufügen
|
||||
$insert_stmt = $pdo->prepare("INSERT INTO timestamps (employee_id, timestamp_type, timestamp_datetime, timestamp_endpoint) VALUES (?, ?, NOW(), 1)");
|
||||
$insert_stmt->bindParam(1, $user_id);
|
||||
$insert_stmt->bindParam(2, $timestamp_type);
|
||||
$insert_stmt->execute();
|
||||
|
||||
if ($insert_stmt->rowCount() > 0) {
|
||||
echo '<div class="text-center p-3 my-3 border border-success rounded bg-light text-success font-weight-bold">Zeitstempel für ' . $user['vorname'] . " erfolgreich gesetzt: " . $timestamp_type . "</div>";
|
||||
} else {
|
||||
echo "Fehler beim Speichern des Zeitstempels.";
|
||||
}
|
||||
} else {
|
||||
echo "Benutzer nicht gefunden.";
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
$aktueller_status = "Unbekannt";
|
||||
$letzte_aktion_zeit = "N/A";
|
||||
|
||||
try {
|
||||
// Abfragen des letzten Status und der Zeit des Mitarbeiters
|
||||
$status_stmt = $pdo->prepare("SELECT timestamp_type, timestamp_datetime FROM timestamps WHERE employee_id = ? ORDER BY timestamp_datetime DESC LIMIT 1");
|
||||
$status_stmt->bindParam(1, $user_id);
|
||||
$status_stmt->execute();
|
||||
$status_data = $status_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($status_data) {
|
||||
$aktueller_status = $status_data['timestamp_type'];
|
||||
$letzte_aktion_zeit = $status_data['timestamp_datetime'];
|
||||
}
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
$query2 = "
|
||||
SELECT
|
||||
DATE(timestamp_datetime) AS datum,
|
||||
GROUP_CONCAT(timestamp_type ORDER BY timestamp_datetime) AS day_sequence
|
||||
FROM
|
||||
timestamps
|
||||
WHERE
|
||||
employee_id = :employee_id AND
|
||||
DATE(timestamp_datetime) != CURDATE()
|
||||
GROUP BY
|
||||
DATE(timestamp_datetime);";
|
||||
|
||||
$stmt = $pdo->prepare($query2);
|
||||
$stmt->bindParam(':employee_id', $user["id"], PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
$result = $stmt->fetchAll();
|
||||
|
||||
#$invalidDates = [];
|
||||
|
||||
} catch(PDOException $e) {
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
|
||||
|
||||
foreach ($result as $row) {
|
||||
if (!isValidSequence($row["day_sequence"])) {
|
||||
$fehlerhafteTage[] = $row["datum"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#print_r($fehlerhafteTage);
|
||||
|
||||
?>
|
||||
|
||||
<br>
|
||||
<?php if ($fehlerhafteTage): ?>
|
||||
<div class="text-center p-3 my-3 border border-danger rounded bg-light text-danger font-weight-bold">
|
||||
<p class="mb-0">Es gibt ein Buchungsproblem! <a href="fehlbuchungen.php">Zur Anpassung</a></p>
|
||||
</div>
|
||||
|
||||
<?php endif;
|
||||
?>
|
||||
|
||||
|
||||
<p class="mb-0">Aktueller Status: <?php
|
||||
if ($aktueller_status == "GEHEN") {
|
||||
echo '<div class="text-center p-3 my-3 border border-warning rounded bg-light text-warning font-weight-bold">ABWESEND</div>';
|
||||
} elseif ($aktueller_status == 'KOMMEN') {
|
||||
echo '<div class="text-center p-3 my-3 border border-success rounded bg-light text-success font-weight-bold">ANWESEND</div>';
|
||||
} else {
|
||||
// Wenn weder "GEHEN" noch "KOMMEN" ist, handle es entsprechend
|
||||
echo '<div class="text-center p-3 my-3 border border-danger rounded bg-light text-danger font-weight-bold">Unbekannter Status</div>';
|
||||
}
|
||||
|
||||
?></p>
|
||||
|
||||
<div class="text-center p-3 my-3 border border-info rounded ">
|
||||
<p class="mb-0">Letzte Stempelzeit: <?php echo $letzte_aktion_zeit; ?></p>
|
||||
</div>
|
||||
|
||||
|
||||
<br><br>
|
||||
|
||||
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
|
||||
<input type="submit" value="Stempeln" class="btn btn-info btn-lg btn-block">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
$error_msg = "";
|
||||
if(isset($_POST['email']) && isset($_POST['passwort'])) {
|
||||
$email = $_POST['email'];
|
||||
$passwort = $_POST['passwort'];
|
||||
|
||||
$statement = $pdo->prepare("SELECT * FROM users WHERE email = :email");
|
||||
$result = $statement->execute(array('email' => $email));
|
||||
$user = $statement->fetch();
|
||||
|
||||
//Überprüfung des Passworts
|
||||
if ($user !== false && password_verify($passwort, $user['passwort'])) {
|
||||
$_SESSION['userid'] = $user['id'];
|
||||
|
||||
//Möchte der Nutzer angemeldet beleiben?
|
||||
if(isset($_POST['angemeldet_bleiben'])) {
|
||||
$identifier = random_string();
|
||||
$securitytoken = random_string();
|
||||
|
||||
$insert = $pdo->prepare("INSERT INTO securitytokens (user_id, identifier, securitytoken) VALUES (:user_id, :identifier, :securitytoken)");
|
||||
$insert->execute(array('user_id' => $user['id'], 'identifier' => $identifier, 'securitytoken' => sha1($securitytoken)));
|
||||
setcookie("identifier",$identifier,time()+(3600*24*365)); //Valid for 1 year
|
||||
#$_COOKIE['identifier'] = $identifier;
|
||||
setcookie("securitytoken",$securitytoken,time()+(3600*24*365)); //Valid for 1 year
|
||||
#$_COOKIE['securitytoken'] = $securitytoken;
|
||||
|
||||
}
|
||||
|
||||
echo "<script>window.location.href='index.php';</script>";
|
||||
//header("location: index.php");
|
||||
exit;
|
||||
} else {
|
||||
$error_msg = "E-Mail oder Passwort war ungültig<br><br>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$email_value = "";
|
||||
if(isset($_POST['email']))
|
||||
$email_value = htmlentities($_POST['email']);
|
||||
|
||||
include("templates/header.inc.php");
|
||||
?>
|
||||
<div class="container small-container-330 form-signin">
|
||||
<form action="login.php" method="post">
|
||||
<h2 class="form-signin-heading">Login</h2>
|
||||
|
||||
<?php
|
||||
if(isset($error_msg) && !empty($error_msg)) {
|
||||
echo $error_msg;
|
||||
}
|
||||
?>
|
||||
<label for="inputEmail" class="sr-only">E-Mail</label>
|
||||
<input type="email" name="email" id="inputEmail" class="form-control" placeholder="E-Mail" value="<?php echo $email_value; ?>" required autofocus>
|
||||
<label for="inputPassword" class="sr-only">Passwort</label>
|
||||
<input type="password" name="passwort" id="inputPassword" class="form-control" placeholder="Passwort" required>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" value="remember-me" name="angemeldet_bleiben" value="1" checked> Angemeldet bleiben
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
|
||||
<br>
|
||||
<a href="passwortvergessen.php">Passwort vergessen</a>
|
||||
</form>
|
||||
|
||||
</div> <!-- /container -->
|
||||
|
||||
|
||||
<?php
|
||||
include("templates/footer.inc.php")
|
||||
?>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
unset($_SESSION['userid']);
|
||||
|
||||
//Remove Cookies
|
||||
setcookie("identifier","",time()-(3600*24*365));
|
||||
setcookie("securitytoken","",time()-(3600*24*365));
|
||||
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
include("templates/header.inc.php");
|
||||
?>
|
||||
|
||||
<div class="container main-container">
|
||||
Der Logout war erfolgreich. <a href="login.php">Zurück zum Login</a>.
|
||||
</div>
|
||||
<?php
|
||||
include("templates/footer.inc.php")
|
||||
?>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
$user = check_user();
|
||||
// personal calendar available to any logged-in user
|
||||
|
||||
include 'header.php';
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Mein Urlaubskalender</h2>
|
||||
<div id="calendar"></div>
|
||||
<br>
|
||||
<div>
|
||||
<span class="badge badge-success">genehmigt</span>
|
||||
<span class="badge badge-warning">beantragt</span>
|
||||
<span class="badge badge-primary">Betriebsurlaub</span>
|
||||
</div>
|
||||
<br>
|
||||
<div id="eventDetails" style="display:none;">
|
||||
<h4>Details</h4>
|
||||
<div id="detailsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css' rel='stylesheet' />
|
||||
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js'></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
firstDay: 1,
|
||||
height: 650,
|
||||
events: function(info, successCallback, failureCallback) {
|
||||
var url = 'api/vacations.php?start=' + info.startStr + '&end=' + info.endStr + '&only_personal=1';
|
||||
fetch(url).then(function(res){ return res.json(); }).then(function(data){ successCallback(data); }).catch(function(err){ failureCallback(err); });
|
||||
},
|
||||
eventClick: function(info) {
|
||||
var ev = info.event;
|
||||
var props = ev.extendedProps;
|
||||
var html = '<strong>' + ev.title + '</strong><br>' + ev.start.toLocaleDateString() + ' - ' + (new Date(ev.end).toLocaleDateString()) + '<br>';
|
||||
if (props.type === 'user') {
|
||||
html += 'Status: ' + (props.status || '') + '<br>';
|
||||
html += 'Kommentar: ' + (props.comment || '') + '<br>';
|
||||
} else if (props.type === 'company') {
|
||||
html += 'Beschreibung: ' + (props.description || '') + '<br>';
|
||||
}
|
||||
document.getElementById('detailsContent').innerHTML = html;
|
||||
document.getElementById('eventDetails').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h2>Stempelkarten-System</h2>
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$employee_id = $_POST['employee_id'];
|
||||
$datum = $_POST['datum'];
|
||||
$buchungen = $_POST['buchungen'];
|
||||
$deleted_entries = $_POST['deleted_entries']; // IDs der zu löschenden Einträge
|
||||
|
||||
// Überprüfen, ob alle Termineinträge für denselben Tag sind
|
||||
foreach ($buchungen as $timestamp_id => $buchung) {
|
||||
if (date('Y-m-d', strtotime($buchung['timestamp_datetime'])) !== $datum) {
|
||||
die("Fehler: Nicht alle Termineinträge sind für denselben Tag.");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Löschvorgänge durchführen
|
||||
foreach ($deleted_entries as $deleted_id) {
|
||||
$delete_query = "DELETE FROM timestamps WHERE timestamp_id = :timestamp_id AND employee_id = :employee_id";
|
||||
$stmt = $pdo->prepare($delete_query);
|
||||
$stmt->bindParam(':timestamp_id', $deleted_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':employee_id', $employee_id, PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
// Speichern oder Aktualisieren der Buchungen
|
||||
foreach ($buchungen as $timestamp_id => $buchung) {
|
||||
if (strpos($timestamp_id, 'new_') !== false) {
|
||||
// Neue Buchung hinzufügen
|
||||
$insert_query = "INSERT INTO timestamps (employee_id, timestamp_type, timestamp_datetime) VALUES (:employee_id, :timestamp_type, :timestamp_datetime)";
|
||||
$stmt = $pdo->prepare($insert_query);
|
||||
} else {
|
||||
// Bestehende Buchung aktualisieren
|
||||
$update_query = "UPDATE timestamps SET timestamp_type = :timestamp_type, timestamp_datetime = :timestamp_datetime WHERE timestamp_id = :timestamp_id AND employee_id = :employee_id";
|
||||
$stmt = $pdo->prepare($update_query);
|
||||
$stmt->bindParam(':timestamp_id', $timestamp_id, PDO::PARAM_INT);
|
||||
}
|
||||
|
||||
$stmt->bindParam(':employee_id', $employee_id, PDO::PARAM_INT);
|
||||
$stmt->bindParam(':timestamp_type', $buchung['timestamp_type']);
|
||||
$stmt->bindParam(':timestamp_datetime', $buchung['timestamp_datetime']);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo "Änderungen erfolgreich gespeichert.";
|
||||
} catch(PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
echo "Datenbankfehler: " . $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
die("Ungültige Anfrage.");
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
//Überprüfe, dass der User eingeloggt ist
|
||||
//Der Aufruf von check_user() muss in alle internen Seiten eingebaut sein
|
||||
$user = check_user();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
|
||||
<?php
|
||||
// Überprüfen, ob eine Benutzer-ID in der Session vorhanden ist
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
if($user["admin"] != 1){
|
||||
die("Kein Admin-Rechte.");
|
||||
}
|
||||
// Bearbeitungslogik
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['email'])) {
|
||||
$email = $_POST['email'];
|
||||
$vorname = $_POST['vorname'];
|
||||
$nachname = $_POST['nachname'];
|
||||
|
||||
// Füge neuen Mitarbeiter hinzu
|
||||
$sql = "INSERT INTO users (email, vorname, nachname) VALUES (?, ?, ?)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$email, $vorname, $nachname]);
|
||||
|
||||
|
||||
echo "<br><div class='alert alert-success' role='alert'>Vorgang erfolgreich ausgeführt.</div>";
|
||||
}
|
||||
|
||||
// Abfrage der Mitarbeiterdaten
|
||||
$sql = "SELECT id, email, vorname, nachname, zeiterfassung, worker, admin, card_id, card2_id FROM users";
|
||||
$stmt = $pdo->query($sql);
|
||||
?>
|
||||
|
||||
<div class="container mt-5">
|
||||
<h2>Mitarbeiterliste</h2>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead class="thead-light">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Email</th>
|
||||
<th>Vorname</th>
|
||||
<th>Nachname</th>
|
||||
<th>Zeiterfassung</th>
|
||||
<th>worker</th>
|
||||
<th>Admin</th>
|
||||
<th>Card ID</th>
|
||||
<th>Card2 ID</th>
|
||||
<th>Aktionen</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
echo "<tr>";
|
||||
echo "<td>" . htmlspecialchars($row['id']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['email']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['vorname']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['nachname']) . "</td>";
|
||||
echo "<td>" ;
|
||||
if($row['zeiterfassung'] == "1"){echo "Ja";}
|
||||
echo "</td>";
|
||||
echo "<td>" ;
|
||||
if($row['worker'] == "1"){echo "Ja";}
|
||||
echo "</td>";
|
||||
echo "<td>" ;
|
||||
if($row['admin'] == "1"){echo "Ja";}
|
||||
echo "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['card_id']) . "</td>";
|
||||
echo "<td>" . htmlspecialchars($row['card2_id']) . "</td>";
|
||||
echo "<td><a class='btn btn-primary btn-sm' href='editworker.php?id=" . $row["id"] . "'>Bearbeiten</a></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2>Neuen Mitarbeiter hinzufügen</h2>
|
||||
<form action="" method="post" >
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="text" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="vorname">Vorname</label>
|
||||
<input type="text" class="form-control" id="vorname" name="vorname" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="nachname">Nachname</label>
|
||||
<input type="text" class="form-control" id="nachname" name="nachname" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-success">Hinzufügen</button>
|
||||
</form>
|
||||
|
||||
|
||||
<br>
|
||||
<button type="button" class="btn btn-secondary" onclick="history.back();">Zurück</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
$user = check_user();
|
||||
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
if ($_SESSION['admin'] != 1) {
|
||||
die("Kein Zugriff.");
|
||||
}
|
||||
|
||||
$admin_id = $_SESSION['userid'];
|
||||
$message = "";
|
||||
|
||||
/* ===== Antrag bearbeiten ===== */
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['vacation_id'])) {
|
||||
|
||||
$vacation_id = (int)$_POST['vacation_id'];
|
||||
$action = $_POST['action'];
|
||||
$comment_admin = trim($_POST['comment_admin']);
|
||||
|
||||
if ($action == "genehmigen") {
|
||||
$status = "genehmigt";
|
||||
} elseif ($action == "ablehnen") {
|
||||
$status = "abgelehnt";
|
||||
} else {
|
||||
die("Ungültige Aktion.");
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE vacations
|
||||
SET status = ?,
|
||||
approved_by = ?,
|
||||
approved_at = NOW()
|
||||
WHERE id = ?
|
||||
");
|
||||
$stmt->execute([$status, $admin_id, $vacation_id]);
|
||||
|
||||
$message = "Antrag erfolgreich aktualisiert.";
|
||||
}
|
||||
|
||||
/* ===== Offene Anträge laden ===== */
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT v.*, u.vorname, u.nachname
|
||||
FROM vacations v
|
||||
JOIN users u ON u.id = v.user_id
|
||||
WHERE v.status = 'beantragt'
|
||||
ORDER BY v.start_date ASC
|
||||
");
|
||||
$stmt->execute();
|
||||
$antraege = $stmt->fetchAll();
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<h2>Urlaubsanträge genehmigen</h2>
|
||||
|
||||
<?php if ($message): ?>
|
||||
<div class="alert alert-success"><?php echo $message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (count($antraege) == 0): ?>
|
||||
<div class="alert alert-info">Keine offenen Anträge.</div>
|
||||
<?php else: ?>
|
||||
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Von</th>
|
||||
<th>Bis</th>
|
||||
<th>Tage</th>
|
||||
<th>Kommentar</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($antraege as $a): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($a['vorname'] . " " . $a['nachname']); ?></td>
|
||||
<td><?php echo $a['start_date']; ?></td>
|
||||
<td><?php echo $a['end_date']; ?></td>
|
||||
<td><?php echo $a['days']; ?></td>
|
||||
<td><?php echo htmlspecialchars($a['comment_user']); ?></td>
|
||||
<td>
|
||||
|
||||
<form method="post" style="display:inline;">
|
||||
<input type="hidden" name="vacation_id" value="<?php echo $a['id']; ?>">
|
||||
<input type="hidden" name="action" value="genehmigen">
|
||||
<button type="submit" class="btn btn-success btn-sm">
|
||||
Genehmigen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form method="post" style="display:inline;">
|
||||
<input type="hidden" name="vacation_id" value="<?php echo $a['id']; ?>">
|
||||
<input type="hidden" name="action" value="ablehnen">
|
||||
<button type="submit" class="btn btn-danger btn-sm">
|
||||
Ablehnen
|
||||
</button>
|
||||
</form>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</table>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,178 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once("inc/config.inc.php");
|
||||
require_once("inc/functions.inc.php");
|
||||
|
||||
$user = check_user();
|
||||
|
||||
if (!isset($_SESSION['userid'])) {
|
||||
die("Kein Benutzer angemeldet.");
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['userid'];
|
||||
$message = "";
|
||||
$error = "";
|
||||
|
||||
function calculateWorkingDays($start, $end) {
|
||||
$start = new DateTime($start);
|
||||
$end = new DateTime($end);
|
||||
$end->modify('+1 day');
|
||||
|
||||
$interval = new DateInterval('P1D');
|
||||
$period = new DatePeriod($start, $interval, $end);
|
||||
|
||||
$workingDays = 0;
|
||||
|
||||
foreach ($period as $day) {
|
||||
if ($day->format('N') < 6) { // 1 (Mo) - 5 (Fr)
|
||||
$workingDays++;
|
||||
}
|
||||
}
|
||||
|
||||
return $workingDays;
|
||||
}
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
|
||||
$start_date = $_POST['start_date'];
|
||||
$end_date = $_POST['end_date'];
|
||||
$comment = trim($_POST['comment']);
|
||||
|
||||
if (empty($start_date) || empty($end_date)) {
|
||||
$error = "Bitte beide Datumsfelder ausfüllen.";
|
||||
} elseif ($start_date > $end_date) {
|
||||
$error = "Enddatum liegt vor dem Startdatum.";
|
||||
} elseif ($start_date < date("Y-m-d")) {
|
||||
$error = "Urlaub kann nicht in der Vergangenheit beantragt werden.";
|
||||
} else {
|
||||
|
||||
// Überschneidung prüfen
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT COUNT(*) FROM vacations
|
||||
WHERE user_id = ?
|
||||
AND status != 'abgelehnt'
|
||||
AND (
|
||||
(start_date BETWEEN ? AND ?)
|
||||
OR (end_date BETWEEN ? AND ?)
|
||||
OR (? BETWEEN start_date AND end_date)
|
||||
)
|
||||
");
|
||||
$stmt->execute([$user_id, $start_date, $end_date, $start_date, $end_date, $start_date]);
|
||||
$exists = $stmt->fetchColumn();
|
||||
|
||||
if ($exists > 0) {
|
||||
$error = "Der Zeitraum überschneidet sich mit einem bestehenden Antrag.";
|
||||
} else {
|
||||
|
||||
$days = calculateWorkingDays($start_date, $end_date);
|
||||
|
||||
$insert = $pdo->prepare("
|
||||
INSERT INTO vacations (user_id, start_date, end_date, days, comment_user)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
");
|
||||
|
||||
$insert->execute([$user_id, $start_date, $end_date, $days, $comment]);
|
||||
|
||||
$message = "Urlaubsantrag erfolgreich eingereicht ($days Werktage).";
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php include 'header.php'; ?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
|
||||
<h2>Urlaubsantrag</h2>
|
||||
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($message): ?>
|
||||
<div class="alert alert-success"><?php echo $message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="post">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Von:</label>
|
||||
<input type="date" name="start_date" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Bis:</label>
|
||||
<input type="date" name="end_date" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Kommentar (optional):</label>
|
||||
<textarea name="comment" class="form-control"></textarea>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<button type="submit" class="btn btn-primary btn-block">
|
||||
Urlaub beantragen
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Meine Anträge</h4>
|
||||
|
||||
<?php
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT * FROM vacations
|
||||
WHERE user_id = ?
|
||||
ORDER BY created_at DESC
|
||||
");
|
||||
$stmt->execute([$user_id]);
|
||||
$antraege = $stmt->fetchAll();
|
||||
?>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<tr>
|
||||
<th>Von</th>
|
||||
<th>Bis</th>
|
||||
<th>Tage</th>
|
||||
<th>Status</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($antraege as $a): ?>
|
||||
<tr>
|
||||
<td><?php echo $a['start_date']; ?></td>
|
||||
<td><?php echo $a['end_date']; ?></td>
|
||||
<td><?php echo $a['days']; ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if ($a['status'] == 'beantragt') {
|
||||
echo '<span class="badge badge-warning">Beantragt</span>';
|
||||
} elseif ($a['status'] == 'genehmigt') {
|
||||
echo '<span class="badge badge-success">Genehmigt</span>';
|
||||
} else {
|
||||
echo '<span class="badge badge-danger">Abgelehnt</span>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td>
|
||||
<form method="post" action="deleteVacation.php" onsubmit="return confirm('Wirklich löschen?');">
|
||||
<input type="hidden" name="id" value="<?php echo $a['id']; ?>">
|
||||
<input type="hidden" name="referer" value="urlaubsantrag.php">
|
||||
<button type="submit" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
$user = check_user();
|
||||
if (!is_admin_user()) {
|
||||
die('Zugriff verweigert. Nur Chefs dürfen den Kalender sehen.');
|
||||
}
|
||||
|
||||
include 'header.php';
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Team Urlaubskalender</h2>
|
||||
<div id="calendar"></div>
|
||||
<br>
|
||||
<div>
|
||||
<span class="badge badge-success">genehmigt</span>
|
||||
<span class="badge badge-warning">beantragt</span>
|
||||
<span class="badge badge-primary">Betriebsurlaub</span>
|
||||
</div>
|
||||
<br>
|
||||
<div id="eventDetails" style="display:none;">
|
||||
<h4>Details</h4>
|
||||
<div id="detailsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css' rel='stylesheet' />
|
||||
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js'></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
firstDay: 1,
|
||||
height: 650,
|
||||
events: function(info, successCallback, failureCallback) {
|
||||
var url = 'api/vacations.php?start=' + info.startStr + '&end=' + info.endStr;
|
||||
fetch(url).then(function(res){ return res.json(); }).then(function(data){ successCallback(data); }).catch(function(err){ failureCallback(err); });
|
||||
},
|
||||
eventClick: function(info) {
|
||||
var ev = info.event;
|
||||
var props = ev.extendedProps;
|
||||
var html = '<strong>' + ev.title + '</strong><br>' + ev.start.toLocaleDateString() + ' - ' + (new Date(ev.end).toLocaleDateString()) + '<br>';
|
||||
if (props.type === 'user') {
|
||||
html += 'Status: ' + (props.status || '') + '<br>';
|
||||
html += 'Kommentar: ' + (props.comment || '') + '<br>';
|
||||
} else if (props.type === 'company') {
|
||||
html += 'Beschreibung: ' + (props.description || '') + '<br>';
|
||||
}
|
||||
document.getElementById('detailsContent').innerHTML = html;
|
||||
document.getElementById('eventDetails').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
// allow any logged-in user to view the team calendar (read-only)
|
||||
$user = check_user();
|
||||
|
||||
include 'header.php';
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Team Urlaubskalender</h2>
|
||||
<div id="calendar"></div>
|
||||
<br>
|
||||
<div>
|
||||
<span class="badge badge-success">genehmigt</span>
|
||||
<span class="badge badge-primary">Betriebsurlaub</span>
|
||||
</div>
|
||||
<br>
|
||||
<div id="eventDetails" style="display:none;">
|
||||
<h4>Details</h4>
|
||||
<div id="detailsContent"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.css' rel='stylesheet' />
|
||||
<script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.3/main.min.js'></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var calendarEl = document.getElementById('calendar');
|
||||
|
||||
var calendar = new FullCalendar.Calendar(calendarEl, {
|
||||
initialView: 'dayGridMonth',
|
||||
firstDay: 1,
|
||||
height: 650,
|
||||
events: function(info, successCallback, failureCallback) {
|
||||
var url = 'api/vacations.php?start=' + info.startStr + '&end=' + info.endStr + '&public=1&public_all=1';
|
||||
fetch(url).then(function(res){ return res.json(); }).then(function(data){ successCallback(data); }).catch(function(err){ failureCallback(err); });
|
||||
},
|
||||
eventClick: function(info) {
|
||||
var ev = info.event;
|
||||
var props = ev.extendedProps;
|
||||
var html = '<strong>' + ev.title + '</strong><br>' + ev.start.toLocaleDateString() + ' - ' + (new Date(ev.end).toLocaleDateString()) + '<br>';
|
||||
if (props.type === 'user') {
|
||||
html += 'Mitarbeiter-ID: ' + (props.user_id || '') + '<br>';
|
||||
} else if (props.type === 'company') {
|
||||
html += 'Beschreibung: ' + (props.description || '') + '<br>';
|
||||
}
|
||||
document.getElementById('detailsContent').innerHTML = html;
|
||||
document.getElementById('eventDetails').style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
calendar.render();
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once('inc/config.inc.php');
|
||||
require_once('inc/functions.inc.php');
|
||||
|
||||
$user = check_user();
|
||||
if (!is_admin_user()) {
|
||||
die('Zugriff verweigert. Nur Chefs dürfen die Urlaubsübersicht sehen.');
|
||||
}
|
||||
|
||||
include 'header.php';
|
||||
|
||||
// Jahr für Auswertung
|
||||
$year = date('Y');
|
||||
|
||||
// Lade alle Mitarbeiter
|
||||
$stmt = $pdo->prepare("SELECT id, vorname, nachname, email, urlaubstage FROM users ORDER BY nachname, vorname");
|
||||
$stmt->execute();
|
||||
$users = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h2>Urlaubsübersicht (<?php echo $year; ?>)</h2>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Mitarbeiter</th>
|
||||
<th>Email</th>
|
||||
<th>Anspruch</th>
|
||||
<th>Genutzt (<?php echo $year; ?>)</th>
|
||||
<th>Verbleibend</th>
|
||||
<th>Ausstehend</th>
|
||||
<th>Bevorstehende Urlaube</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($users as $u):
|
||||
$uid = $u['id'];
|
||||
|
||||
// Genutzte Tage (genehmigt) im Jahr
|
||||
$s = $pdo->prepare("SELECT IFNULL(SUM(days),0) AS used FROM vacations WHERE user_id = ? AND status = 'genehmigt' AND YEAR(start_date) = ?");
|
||||
$s->execute([$uid, $year]);
|
||||
$used = (int)$s->fetchColumn();
|
||||
|
||||
// Ausstehende Anträge
|
||||
$p = $pdo->prepare("SELECT COUNT(*) FROM vacations WHERE user_id = ? AND status = 'beantragt'");
|
||||
$p->execute([$uid]);
|
||||
$pending = (int)$p->fetchColumn();
|
||||
|
||||
// Bevorstehende Urlaube (nächste 5)
|
||||
$n = $pdo->prepare("SELECT start_date, end_date, days, status FROM vacations WHERE user_id = ? AND end_date >= CURDATE() ORDER BY start_date LIMIT 5");
|
||||
$n->execute([$uid]);
|
||||
$upcoming = $n->fetchAll();
|
||||
|
||||
$entitlement = isset($u['urlaubstage']) ? (int)$u['urlaubstage'] : 0;
|
||||
$remaining = $entitlement - $used;
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($u['vorname'] . ' ' . $u['nachname']); ?></td>
|
||||
<td><?php echo htmlspecialchars($u['email']); ?></td>
|
||||
<td><?php echo $entitlement; ?></td>
|
||||
<td><?php echo $used; ?></td>
|
||||
<td><?php echo $remaining; ?></td>
|
||||
<td><?php echo $pending; ?></td>
|
||||
<td>
|
||||
<?php if (count($upcoming) == 0) { echo '-'; } else {
|
||||
foreach ($upcoming as $up) {
|
||||
echo htmlspecialchars($up['start_date'] . ' → ' . $up['end_date'] . ' (' . $up['days'] . 'd) ' . ' [' . $up['status'] . ']');
|
||||
echo '<br>';
|
||||
}
|
||||
} ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>Hinweis: Ansprüche werden aus dem Feld <strong>users.urlaubstage</strong> gelesen. Falls dieses Feld leer ist, bitte in der Nutzerverwaltung pflegen.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<?php include 'footer.php'; ?>
|
||||
Reference in New Issue
Block a user