Files
omsorg/omsorgWeb/mitarbeiter-app/pages/fahrtstrecken.php
T
Felix KemmlerandClaude Sonnet 5 ffa2c4a9e7
Docker-Images bauen und veröffentlichen / build (, omsorgCore/Dockerfile, omsorgcore) (push) Successful in 16s
Docker-Images bauen und veröffentlichen / build (, omsorgWeb/Dockerfile, omsorgweb) (push) Successful in 5s
Docker-Images bauen und veröffentlichen / build (, omsorgapp/Dockerfile, omsorgapp) (push) Successful in 19s
Add kilometer-based Fahrtkosten billing, self-service distance entry, role deletion
- Facility: TravelCostMode (Pauschale/ProKilometer) + TravelCostPerKm, alongside
  the existing flat rate; fixes FacilityService.UpdateAsync silently dropping all
  Konditionen fields on update.
- New EmployeeFacilityDistance (Mitarbeiter x Einrichtung -> km) with full
  office-side CRUD in omsorgapp, plus a self-service endpoint/UI so field staff
  can maintain their own commute distance via OMSORG Connect (new
  ModuleType.EmployeeFacilityDistances, Own-scope, no Facilities access needed).
- Roles can now be deleted (blocked with a 409 while still assigned to a user).
- Fix employeesApi.js missing the Date-object conversion for dateOfBirth/entryDate/
  exitDate that crashed employee creation whenever a date was filled in; add a
  clear/remove control for those date fields.
- Requirements: flesh out FR-REC-3 with a staged Akquise cadence, add FR-REC-5/6
  for CRM feature scope and success metrics.
- Regenerate api-client-ts and api-client-php for all of the above.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 20:15:42 +02:00

194 lines
7.5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once __DIR__ . '/../lib/auth.php';
require_once __DIR__ . '/../lib/layout.php';
require_login();
if (!has_permission('EmployeeFacilityDistances', 'View')) {
header('Location: dashboard.php');
exit;
}
$canCreate = has_permission('EmployeeFacilityDistances', 'Create');
$canEdit = has_permission('EmployeeFacilityDistances', 'Edit');
$error = '';
$success = false;
$editId = null;
$facilitiesResult = omsorgcore_my_facility_distances_facility_options(_omsorgcore_config(), $_SESSION['omsorgcore_access_token']);
$facilities = $facilitiesResult['ok'] ? $facilitiesResult['data'] : [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$mode = $_POST['mode'] ?? 'create';
$distanceKm = trim($_POST['distance_km'] ?? '');
if ($distanceKm === '' || !is_numeric($distanceKm) || (float) $distanceKm < 0) {
$error = 'Entfernung (km) ist erforderlich und darf nicht negativ sein.';
$editId = $mode === 'edit' ? ($_POST['distance_id'] ?? null) : null;
} elseif ($mode === 'edit') {
if (!$canEdit) {
// Server lehnt das ohnehin über [RequirePermission(EmployeeFacilityDistances, Edit)] ab -
// dieser Zweig greift nur, wenn jemand das Formular manuell postet, obwohl es clientseitig
// gar nicht angezeigt wurde.
$error = 'Keine Berechtigung, diese Entfernung zu bearbeiten.';
} else {
$distanceId = $_POST['distance_id'] ?? '';
$result = omsorgcore_my_facility_distances_update(_omsorgcore_config(), $_SESSION['omsorgcore_access_token'], $distanceId, ['distanceKm' => (float) $distanceKm]);
if ($result['ok']) {
header('Location: fahrtstrecken.php?updated=1');
exit;
}
$editId = $distanceId;
$error = $result['status'] === 403
? 'Keine Berechtigung, diese Entfernung zu bearbeiten.'
: (is_string($result['data'] ?? null) ? $result['data'] : 'Entfernung konnte nicht gespeichert werden.');
}
} elseif (!$canCreate) {
$error = 'Keine Berechtigung, eine Entfernung anzulegen.';
} else {
$facilityId = $_POST['facility_id'] ?? '';
if ($facilityId === '') {
$error = 'Einrichtung ist erforderlich.';
} else {
$result = omsorgcore_my_facility_distances_create(_omsorgcore_config(), $_SESSION['omsorgcore_access_token'], [
'facilityId' => $facilityId,
'distanceKm' => (float) $distanceKm,
]);
if ($result['ok']) {
$success = true;
} elseif ($result['status'] === 403) {
$error = 'Keine Berechtigung, eine Entfernung anzulegen.';
} else {
$error = is_string($result['data'] ?? null) ? $result['data'] : 'Entfernung konnte nicht angelegt werden.';
}
}
}
} elseif (isset($_GET['edit'])) {
$editId = $_GET['edit'];
}
$listResult = omsorgcore_my_facility_distances_list(_omsorgcore_config(), $_SESSION['omsorgcore_access_token']);
$distances = $listResult['ok'] ? $listResult['data'] : [];
$editDistance = null;
if ($editId !== null) {
foreach ($distances as $distance) {
if ($distance['id'] === $editId) {
$editDistance = $distance;
break;
}
}
// Fremde/ungültige Entfernung - Own-Scope-Filterung passiert serverseitig in
// omsorgcore_my_facility_distances_list, hier nur zusätzlich zurück zu "Neue Entfernung".
if ($editDistance === null) {
$editId = null;
}
}
$facilitiesWithoutDistance = array_values(array_filter($facilities, function ($facility) use ($distances) {
foreach ($distances as $distance) {
if ($distance['facilityId'] === $facility['id']) {
return false;
}
}
return true;
}));
layout_start('Fahrtstrecken Mitarbeiter-App', 'fahrtstrecken');
?>
<h1 class="main-title">Fahrtstrecken</h1>
<p class="hint" style="margin:-8px 0 20px">
Trage hier die Entfernung (einfache Strecke, km) von deinem Wohnort zu den Einrichtungen ein, bei denen du im Einsatz bist. Diese Angabe ist Grundlage für die kilometerbasierte Fahrtkostenabrechnung.
</p>
<div class="split-layout">
<div class="glass" style="padding:24px">
<h2 style="font-family:'KindelSerif',Georgia,serif;font-size:1.3rem;margin:0 0 18px">Meine Fahrtstrecken</h2>
<?php if (empty($distances)): ?>
<p>Noch keine Entfernung erfasst.</p>
<?php else: ?>
<?php foreach ($distances as $distance): ?>
<div style="padding:12px 0;border-bottom:1px solid rgba(0,0,0,.08)">
<b><?= e($distance['facilityName']) ?></b> — <?= e(number_format((float) $distance['distanceKm'], 1, ',', '.')) ?> km
<?php if ($canEdit): ?>
<div style="margin-top:6px">
<a href="fahrtstrecken.php?edit=<?= e($distance['id']) ?>">Bearbeiten</a>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<div class="glass" style="padding:24px">
<h2 style="font-family:'KindelSerif',Georgia,serif;font-size:1.3rem;margin:0 0 18px">
<?= $editDistance ? 'Entfernung bearbeiten' : 'Neue Entfernung' ?>
</h2>
<?php if ($success): ?>
<div class="hint" style="margin-bottom:16px">Entfernung wurde angelegt.</div>
<?php endif; ?>
<?php if (isset($_GET['updated'])): ?>
<div class="hint" style="margin-bottom:16px">Entfernung wurde aktualisiert.</div>
<?php endif; ?>
<?php if ($error): ?>
<div class="error" style="margin-bottom:16px"><?= e($error) ?></div>
<?php endif; ?>
<?php if ($editDistance): ?>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="mode" value="edit">
<input type="hidden" name="distance_id" value="<?= e($editDistance['id']) ?>">
<label>
Einrichtung
<input type="text" value="<?= e($editDistance['facilityName']) ?>" disabled>
</label>
<label>
Entfernung (km, einfache Strecke)
<input type="number" step="0.1" min="0" name="distance_km" value="<?= e($editDistance['distanceKm']) ?>" required>
</label>
<button type="submit" class="btn" style="width:100%;margin-top:6px">Änderungen speichern</button>
</form>
<p class="hint" style="text-align:center;margin-top:14px">
<a href="fahrtstrecken.php">Abbrechen</a>
</p>
<?php elseif ($canCreate): ?>
<?php if (empty($facilitiesWithoutDistance)): ?>
<p class="hint">Für alle Einrichtungen ist bereits eine Entfernung erfasst.</p>
<?php else: ?>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="mode" value="create">
<label>
Einrichtung
<select name="facility_id" required>
<option value="">— auswählen —</option>
<?php foreach ($facilitiesWithoutDistance as $facility): ?>
<option value="<?= e($facility['id']) ?>"><?= e($facility['name']) ?></option>
<?php endforeach; ?>
</select>
</label>
<label>
Entfernung (km, einfache Strecke)
<input type="number" step="0.1" min="0" name="distance_km" required>
</label>
<button type="submit" class="btn" style="width:100%;margin-top:6px">Entfernung anlegen</button>
</form>
<?php endif; ?>
<?php else: ?>
<p class="hint">Keine Berechtigung, eine Entfernung anzulegen.</p>
<?php endif; ?>
</div>
</div>
<?php
layout_end();