Files
awo-hamburg-intranet/module/intranet/organigramm.inc.php
2026-02-17 14:56:23 +01:00

603 lines
24 KiB
PHP
Raw Permalink 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
/**
* 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>