Files
awo-hamburg-intranet/module/intranet/organigramm.inc.php

603 lines
24 KiB
PHP
Raw Normal View History

2026-02-17 14:56:23 +01:00
<?php
/**
* Organigramm-Ausgabe:
* - Landesvorstand (Mandant) inkl. Stabsstellen (role_id=42) NICHT anzeigen
* - Bereiche inkl. Stabsstellen (role_id=42 mit main_department_id)
* - Fachbereiche inkl. Stabsstellen (role_id=42 mit main_bereich_id)
* - Einrichtungen (unverändert)
*/
$svg = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-person-fill" viewBox="0 0 16 16">
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6"/>
</svg>';
$SHOW_INTERMEDIATE_STABSTELLEN = true;
$BEREICH_STAB_ROLES = [43, 25];
function getPersonByRole($mandant_id, $role_id)
{
global $svg;
if (!isset($GLOBALS['mysql_con'])) {
return "<div class=\"og_card person_card\">Fehler: Keine Datenbankverbindung</div>";
}
$query = "SELECT main_contact.id, main_contact.name, main_role.description
FROM main_contact_department
INNER JOIN main_contact ON main_contact_department.main_contact_id = main_contact.id
INNER JOIN main_role ON main_contact_department.main_role_id = main_role.id
WHERE main_contact_department.main_role_id = ?
AND main_contact_department.main_mandant_id = ?
LIMIT 1;";
if ($stmt = mysqli_prepare($GLOBALS['mysql_con'], $query)) {
mysqli_stmt_bind_param($stmt, "ii", $role_id, $mandant_id);
mysqli_stmt_execute($stmt);
mysqli_stmt_bind_result($stmt, $contact_id, $name, $role);
if (mysqli_stmt_fetch($stmt)) {
mysqli_stmt_close($stmt);
$url = "/awo/de/profil/?contact=" . (int) $contact_id;
return "<div class=\"og_card person_card\">
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($name) . "</a></div>
<span>" . htmlspecialchars($role) . "</span>
</div>";
} else {
mysqli_stmt_close($stmt);
return "<div class=\"og_card person_card\">Keine Person gefunden</div>";
}
} else {
return "<div class=\"og_card person_card\">Fehler: Abfrage konnte nicht ausgeführt werden</div>";
}
}
function getPersonsByLevel($mandant_id, $level, $level_id)
{
switch ($level) {
case 'bereich':
$column = 'main_department_id';
$role_id = 9;
break;
case 'fachbereich':
$column = 'main_bereich_id';
$role_id = 10;
break;
case 'einrichtung':
$column = 'main_einricht_id';
$role_id = 8;
break;
default:
return [];
}
$query = "SELECT DISTINCT
main_contact.id AS contact_id,
main_contact.name,
main_role.description AS role
FROM main_contact_department
INNER JOIN main_contact
ON main_contact_department.main_contact_id = main_contact.id
INNER JOIN main_role
ON main_contact_department.main_role_id = main_role.id
WHERE main_contact_department.main_mandant_id = ?
AND main_contact_department.$column = ?
AND main_contact_department.main_role_id = ?";
$persons = [];
if ($stmt = mysqli_prepare($GLOBALS['mysql_con'], $query)) {
mysqli_stmt_bind_param($stmt, "iii", $mandant_id, $level_id, $role_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
$persons[] = $row;
}
mysqli_stmt_close($stmt);
}
return $persons;
}
/**
* Holt Stabsstellen kontextbezogen.
* - 'mandant' keine Stabsstellen
* - 'bereich' NUR Rolle 43 (Bereichsstabstelle)
* - 'fachbereich' Rolle 42
*/
function getStaffByContext($mandant_id, $level, $level_id = null)
{
if ($level === 'mandant') {
return [];
}
switch ($level) {
case 'bereich':
$column = 'main_department_id';
$roleFilter = 43; // <- HIER: Bereichsstabstelle
break;
case 'fachbereich':
$column = 'main_bereich_id';
$roleFilter = 42; // <- wie bisher
break;
default:
return [];
}
$sql = "SELECT DISTINCT
main_contact.id AS contact_id,
main_contact.name,
main_role.description AS role,
COALESCE(f.description, '') AS fachbereich_name
FROM main_contact_department
INNER JOIN main_contact
ON main_contact_department.main_contact_id = main_contact.id
INNER JOIN main_role
ON main_contact_department.main_role_id = main_role.id
LEFT JOIN organogramm_space f
ON main_contact_department.main_bereich_id = f.id
WHERE main_contact_department.main_mandant_id = ?
AND main_contact_department.$column = ?
AND main_contact_department.main_role_id = ?";
$persons = [];
if ($stmt = mysqli_prepare($GLOBALS['mysql_con'], $sql)) {
// WICHTIG: jetzt "iii" (3 ints) wegen zusätzlichem Rollen-Parameter
mysqli_stmt_bind_param($stmt, "iii", $mandant_id, $level_id, $roleFilter);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
$persons[] = $row;
}
mysqli_stmt_close($stmt);
}
return $persons;
}
/**
* Liefert alle Stabsstellen (role_id = 42) für einen Mandanten,
* die NICHT direkt auf Mandantsebene hängen, sondern einer Ebene zugeordnet sind
* (d. h. mit Department- oder Fachbereichsbezug).
* Diese Liste wird als "Zwischenebene" zwischen Mandant und Bereichen angezeigt.
*/
function getAllStaffBetween($mandant_id)
{
$sql = "SELECT DISTINCT
mcd.main_contact_id AS contact_id,
c.name AS name,
r.description AS role,
d.description AS department_name,
f.description AS fachbereich_name
FROM main_contact_department mcd
INNER JOIN main_contact c ON mcd.main_contact_id = c.id
INNER JOIN main_role r ON mcd.main_role_id = r.id
LEFT JOIN main_department d ON mcd.main_department_id = d.id
LEFT JOIN organogramm_space f ON mcd.main_bereich_id = f.id
WHERE mcd.main_mandant_id = ?
AND mcd.main_role_id = 42
AND (
mcd.main_department_id IS NOT NULL
OR mcd.main_bereich_id IS NOT NULL
)
ORDER BY
COALESCE(d.description, ''), COALESCE(f.description, ''), c.name";
$persons = [];
if ($stmt = mysqli_prepare($GLOBALS['mysql_con'], $sql)) {
mysqli_stmt_bind_param($stmt, "i", $mandant_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
$persons[] = $row;
}
mysqli_stmt_close($stmt);
}
return $persons;
}
/**
* Holt alle Personen für die Assistenz-Box neben dem Landesvorstand
* Filter: department=39, bereich=29, role=25 (fix laut Anforderung)
*/
function getAssistantsForTopLevel($mandant_id)
{
$sql = "SELECT DISTINCT
mcd.main_contact_id AS contact_id,
c.name AS name,
r.description AS role
FROM main_contact_department mcd
INNER JOIN main_contact c ON mcd.main_contact_id = c.id
INNER JOIN main_role r ON mcd.main_role_id = r.id
WHERE mcd.main_mandant_id = ?
AND mcd.main_department_id = 39
AND mcd.main_bereich_id = 29
AND mcd.main_role_id = 25
ORDER BY c.name ASC";
$persons = [];
if ($stmt = mysqli_prepare($GLOBALS['mysql_con'], $sql)) {
mysqli_stmt_bind_param($stmt, "i", $mandant_id);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
while ($row = mysqli_fetch_assoc($result)) {
$persons[] = $row;
}
mysqli_stmt_close($stmt);
}
return $persons;
}
// === Mapping aus der DB laden ===
// 1) Fachbereich → Bereich
$deptForFach = [];
$res = mysqli_query($GLOBALS['mysql_con'], "
SELECT fachbereich_id, department_id
FROM main_department_fachbereich
");
while ($row = mysqli_fetch_assoc($res)) {
$deptForFach[(int) $row['fachbereich_id']] = (int) $row['department_id'];
}
// 2) Einrichtung → Fachbereich
$fachForEinr = [];
$res = mysqli_query($GLOBALS['mysql_con'], "
SELECT einrichtung_id, fachbereich_id
FROM main_fachbereich_einrichtung
");
while ($row = mysqli_fetch_assoc($res)) {
$fachForEinr[(int) $row['einrichtung_id']] = (int) $row['fachbereich_id'];
}
?>
<style>
.stabstellen_cards {
display: flex;
white-space: nowrap;
gap: 1rem;
}
.stabstellen_cards .og_card.person_card.staff {
border: 1px solid var(--border);
white-space: normal;
padding: 10px;
}
.stabstellen_cards .staff:before {
content: "";
width: 1px;
height: 30px;
background: var(--border);
position: absolute;
left: 50%;
transform: translateX(-50%);
top: -30px;
z-index: 9999;
}
.mandant_row {
display: flex;
align-items: center;
gap: 1rem;
}
.og_card.mandant {
flex: 1;
z-index: 2;
}
.mandant_row .assistant {
border: 1px solid var(--border);
padding: 10px;
}
.mandant_row .assistant:before {
content: '';
width: 100%;
height: 1px;
background: var(--border);
position: absolute;
left: -100%;
top: 50%;
transform: translateY(-50%);
z-index: 1;
}
.bereich_container.level .og_card_group {
padding-block-start: 1rem;
}
.bereich_container.level h3 {
margin: 0;
}
</style>
<div class="organigramm">
<!-- Mandant + Assistenz (nebeneinander) -->
<div class="mandant level">
<div class="mandant_row">
<!-- Landesvorstand -->
<div class="og_card mandant">
<h3>
AWO Landesverband Hamburg e.V.
</h3>
<?= getPersonByRole(1, 1) ?>
<?php
// Stabsstellen auf Mandantsebene bleibt leer
$staff = getStaffByContext(1, 'mandant');
if (!empty($staff)) {
echo "<div class='person_cards staff_cards'>";
foreach ($staff as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card staff'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role'] . (isset($p['fachbereich_name']) && $p['fachbereich_name'] !== '' ? ' ' . $p['fachbereich_name'] : '')) . "</span>
</div>";
}
echo "</div>";
}
?>
</div>
<!-- Assistenz neben dem Landesvorstand -->
<?php
$assistants = getAssistantsForTopLevel(1); // 1 = Mandant AWO LV HH
if (!empty($assistants)):
?>
<div class="person_cards">
<?php foreach ($assistants as $a):
$url = "/awo/de/profil/?contact=" . (int) $a['contact_id'];
?>
<div class="og_card person_card assistant">
<div><?= $svg ?> <a target="_blank"
href="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($a['name']) ?></a></div>
<span class="role_span"><?= htmlspecialchars($a['role']) ?></span>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
<?php if (!empty($SHOW_INTERMEDIATE_STABSTELLEN)): ?>
<?php
$allStaff = getAllStaffBetween(1); // 1 = Mandant AWO LV HH
if (!empty($allStaff)):
?>
<div class="level intermediate_staff">
<div class="og_card_group">
<div class="stabstellen_cards">
<?php foreach ($allStaff as $p):
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
// Kontextlabel: bevorzugt Fachbereich, sonst Department, sonst leer
$context = '';
if (!empty($p['fachbereich_name'])) {
$context = ' ' . $p['fachbereich_name'];
} elseif (!empty($p['department_name'])) {
$context = ' ' . $p['department_name'];
}
?>
<div class="og_card person_card staff">
<div><?= $svg ?> <a target="_blank"
href="<?= htmlspecialchars($url) ?>"><?= htmlspecialchars($p['name']) ?></a></div>
<span class="role_span"><?= htmlspecialchars($p['role'] . $context) ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
<!-- Bereiche -->
<div class="bereich_container level">
<h3>Bereiche</h3>
<div class="og_card_group">
<?php
$deptQuery = "SELECT id, description
FROM main_department
WHERE state = 1
ORDER BY description ASC";
$deptResult = mysqli_query($GLOBALS['mysql_con'], $deptQuery);
while ($dept = mysqli_fetch_assoc($deptResult)) {
echo "<div class='og_card department' data-dept-id='{$dept['id']}'>";
echo "<div class='card_description'>";
echo htmlspecialchars($dept['description']);
echo "</div>";
// Verantwortliche Personen auf Bereichsebene
$persons = getPersonsByLevel(1, 'bereich', $dept['id']);
foreach ($persons as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role']) . "</span>
</div>";
}
// Stabsstellen auf Bereichsebene (werden per JS initial versteckt)
$staff = getStaffByContext(1, 'bereich', $dept['id']);
if (!empty($staff)) {
echo "<div class='person_cards staff_cards'>";
foreach ($staff as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card staff'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role'] . (isset($p['fachbereich_name']) && $p['fachbereich_name'] !== '' ? ' ' . $p['fachbereich_name'] : '')) . "</span>
</div>";
}
echo "</div>";
}
echo "</div>";
}
?>
</div>
</div>
<!-- Fachbereiche -->
<div class="fachbereich_container level">
<h3>Fachbereiche</h3>
<div class="og_card_group">
<?php
$fachQuery = "SELECT id, description
FROM organogramm_space
ORDER BY description ASC";
$fachResult = mysqli_query($GLOBALS['mysql_con'], $fachQuery);
while ($fach = mysqli_fetch_assoc($fachResult)) {
$deptIdForFach = $deptForFach[$fach['id']] ?? 0;
echo "<div class='og_card department fachbereich' data-fach-id='{$fach['id']}' data-dept-id='{$deptIdForFach}'>";
echo "<div class='card_description'>";
echo htmlspecialchars($fach['description']);
echo "</div>";
echo "<div class='person_cards'>";
// Verantwortliche Personen auf Fachbereichsebene
$persons = getPersonsByLevel(1, 'fachbereich', $fach['id']);
foreach ($persons as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role']) . "</span>
</div>";
}
echo "</div>";
// Stabsstellen auf Fachbereichsebene (werden per JS initial versteckt)
$staff = getStaffByContext(1, 'fachbereich', $fach['id']);
if (!empty($staff)) {
echo "<div class='person_cards staff_cards'>";
foreach ($staff as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card staff'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role'] . (isset($p['fachbereich_name']) && $p['fachbereich_name'] !== '' ? ' ' . $p['fachbereich_name'] : '')) . "</span>
</div>";
}
echo "</div>";
}
echo "</div>";
}
?>
</div>
</div>
<!-- Einrichtungen -->
<div class="einrichtung_container level">
<h3>Einrichtungen</h3>
<div class="og_card_group">
<?php
$einrQuery = "SELECT id, description
FROM organigramm_einricht
ORDER BY description ASC";
$einrResult = mysqli_query($GLOBALS['mysql_con'], $einrQuery);
while ($einr = mysqli_fetch_assoc($einrResult)) {
$fachIdForEinr = $fachForEinr[$einr['id']] ?? 0;
echo "<div class='og_card department einrichtung' data-einricht-id='{$einr['id']}' data-fach-id='{$fachIdForEinr}'>";
echo "<div class='card_description'>";
echo htmlspecialchars($einr['description']);
echo "</div>";
echo "<div class='person_cards'>";
$persons = getPersonsByLevel(1, 'einrichtung', $einr['id']);
foreach ($persons as $p) {
$url = "/awo/de/profil/?contact=" . (int) $p['contact_id'];
echo "<div class='og_card person_card'>
<div>$svg <a target='_blank' href=\"{$url}\">" . htmlspecialchars($p['name']) . "</a></div>
<span class='role_span'>" . htmlspecialchars($p['role']) . "</span>
</div>";
}
echo "</div>";
echo "</div>";
}
?>
</div>
</div>
</div>
<!-- jQuery Skript -->
<script>
$(document).ready(function () {
// Initial: Alle Fachbereiche, Einrichtungen und Stabsstellen ausblenden.
$(".fachbereich, .einrichtung, .staff_cards, .fachbereich_container.level h3, .einrichtung_container.level h3").hide();
// Klick auf Bereich: zeigt zugeordnete Fachbereiche UND die Bereichs-Stabsstellen
$(".bereich_container .og_card.department").on("click", function () {
var deptId = $(this).data("dept-id");
if (!deptId) return;
if ($(this).hasClass("active")) {
// Zuklappen
$(this).removeClass("active");
$(this).find(".staff_cards").hide();
// Alles unterhalb ausblenden
$(".fachbereich, .einrichtung").hide();
// Überschriften ausblenden
$(".fachbereich_container.level h3").hide();
$(".einrichtung_container.level h3").hide();
} else {
// Anderen Zustand zurücksetzen
$(".bereich_container .og_card.department").removeClass("active");
$(this).addClass("active");
// Alles andere ausblenden
$(".fachbereich, .einrichtung, .bereich_container .staff_cards").hide();
// Zugehörige Fachbereiche einblenden
var $visibleFach = $(".fachbereich").filter(function () {
return $(this).data("dept-id") == deptId;
}).show();
// Stabsstellen im aktuell geöffneten Bereich einblenden
$(this).find(".staff_cards").show();
// h3 Fachbereiche nur zeigen, wenn es sichtbare Fachbereiche gibt
if ($visibleFach.length > 0) {
$(".fachbereich_container.level h3").show();
} else {
$(".fachbereich_container.level h3").hide();
}
// Einrichtungen (und deren h3) beim Wechsel des Bereichs erstmal komplett verstecken
$(".einrichtung").hide();
$(".einrichtung_container.level h3").hide();
}
});
// Klick auf Fachbereich: zeigt zugeordnete Einrichtungen UND die Fachbereichs-Stabsstellen
$(document).on("click", ".fachbereich", function (e) {
var fachId = $(this).data("fach-id");
if (!fachId) return;
if ($(this).hasClass("active")) {
// Zuklappen
$(this).removeClass("active");
$(this).find(".staff_cards").hide();
// Einrichtungen ausblenden
$(".einrichtung").hide();
// h3 Einrichtungen ausblenden
$(".einrichtung_container.level h3").hide();
} else {
// Anderen Fachbereich zurücksetzen
$(".fachbereich").removeClass("active");
$(this).addClass("active");
// Alles andere ausblenden
$(".einrichtung, .fachbereich_container .staff_cards").hide();
// Zugehörige Einrichtungen einblenden
var $visibleEinr = $(".einrichtung").filter(function () {
return $(this).data("fach-id") == fachId;
}).show();
// Stabsstellen im aktuell geöffneten Fachbereich einblenden
$(this).find(".staff_cards").show();
// h3 Einrichtungen nur zeigen, wenn es sichtbare Einrichtungen gibt
if ($visibleEinr.length > 0) {
$(".einrichtung_container.level h3").show();
} else {
$(".einrichtung_container.level h3").hide();
}
}
e.stopPropagation();
});
});
</script>