Files
praxis-creutzburg-web/inc/functions.impfen.inc.php
T
2026-03-20 17:13:38 +01:00

305 lines
12 KiB
PHP

<?php
if (!function_exists('impfTableExists')) {
function impfTableExists(PDO $pdo, string $table): bool
{
$st = $pdo->prepare("SHOW TABLES LIKE :table");
$st->execute(['table' => $table]);
return (bool)$st->fetchColumn();
}
}
if (!function_exists('impfTableHasColumn')) {
function impfTableHasColumn(PDO $pdo, string $table, string $column): bool
{
static $cache = [];
$cacheKey = $table . '.' . $column;
if (array_key_exists($cacheKey, $cache)) {
return $cache[$cacheKey];
}
$st = $pdo->prepare("SHOW COLUMNS FROM `" . $table . "` LIKE :column");
$st->execute(['column' => $column]);
$cache[$cacheKey] = (bool)$st->fetch(PDO::FETCH_ASSOC);
return $cache[$cacheKey];
}
}
if (!function_exists('impfWeekdayName')) {
function impfWeekdayName(int $day): string
{
$map = [
1 => 'Montag',
2 => 'Dienstag',
3 => 'Mittwoch',
4 => 'Donnerstag',
5 => 'Freitag',
6 => 'Samstag',
7 => 'Sonntag',
];
return $map[$day] ?? 'Unbekannt';
}
}
if (!function_exists('impfWorkflowEnsureTables')) {
function impfWorkflowEnsureTables(PDO $pdo): void
{
$pdo->exec("CREATE TABLE IF NOT EXISTS impfstoff_workflow (
impfstoff_id INT NOT NULL,
dosen_pro_flasche INT NOT NULL,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (impfstoff_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
$pdo->exec("CREATE TABLE IF NOT EXISTS impfstoff_wochenplan (
plan_id INT NOT NULL AUTO_INCREMENT,
impfstoff_id INT NOT NULL,
wochentag TINYINT NOT NULL,
start TIME NOT NULL,
ende TIME NOT NULL,
impfortid INT NOT NULL,
aktiv TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (plan_id),
INDEX idx_impfstoff_wochenplan_impfstoff (impfstoff_id),
INDEX idx_impfstoff_wochenplan_wochentag (wochentag)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
$pdo->exec("CREATE TABLE IF NOT EXISTS impf_zeitraum (
zeitraum_id INT NOT NULL AUTO_INCREMENT,
bezeichnung VARCHAR(120) NOT NULL DEFAULT '',
wochentag TINYINT NOT NULL,
start TIME NOT NULL,
ende TIME NOT NULL,
impfortid INT NOT NULL,
aktiv TINYINT NOT NULL DEFAULT 1,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (zeitraum_id),
INDEX idx_impf_zeitraum_wochentag (wochentag),
INDEX idx_impf_zeitraum_impfort (impfortid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
if (!impfTableHasColumn($pdo, 'impf_zeitraum', 'bezeichnung')) {
$pdo->exec("ALTER TABLE impf_zeitraum ADD COLUMN bezeichnung VARCHAR(120) NOT NULL DEFAULT '' AFTER zeitraum_id");
}
$pdo->exec("CREATE TABLE IF NOT EXISTS impf_zeitraum_impfstoff (
zeitraum_id INT NOT NULL,
impfstoff_id INT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (zeitraum_id, impfstoff_id),
INDEX idx_impf_zeitraum_impfstoff_impfstoff (impfstoff_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
impfWorkflowMigrateLegacyPlans($pdo);
}
}
if (!function_exists('impfWorkflowMigrateLegacyPlans')) {
function impfWorkflowMigrateLegacyPlans(PDO $pdo): void
{
if (!impfTableExists($pdo, 'impfstoff_wochenplan')) {
return;
}
$stLegacy = $pdo->query("SELECT plan_id, impfstoff_id, wochentag, start, ende, impfortid, aktiv
FROM impfstoff_wochenplan");
$legacyRows = $stLegacy ? $stLegacy->fetchAll(PDO::FETCH_ASSOC) : [];
if (empty($legacyRows)) {
return;
}
$manageTransaction = !$pdo->inTransaction();
if ($manageTransaction) {
$pdo->beginTransaction();
}
try {
$stFindZeitraum = $pdo->prepare("SELECT zeitraum_id
FROM impf_zeitraum
WHERE wochentag = :wochentag
AND start = :start
AND ende = :ende
AND impfortid = :impfortid
AND aktiv = :aktiv
LIMIT 1");
$stInsertZeitraum = $pdo->prepare("INSERT INTO impf_zeitraum
(bezeichnung, wochentag, start, ende, impfortid, aktiv)
VALUES
('', :wochentag, :start, :ende, :impfortid, :aktiv)");
$stInsertMap = $pdo->prepare("INSERT INTO impf_zeitraum_impfstoff
(zeitraum_id, impfstoff_id)
VALUES
(:zeitraum_id, :impfstoff_id)
ON DUPLICATE KEY UPDATE impfstoff_id = VALUES(impfstoff_id)");
foreach ($legacyRows as $row) {
$params = [
'wochentag' => (int)$row['wochentag'],
'start' => (string)$row['start'],
'ende' => (string)$row['ende'],
'impfortid' => (int)$row['impfortid'],
'aktiv' => (int)$row['aktiv'],
];
$stFindZeitraum->execute($params);
$zeitraumId = (int)($stFindZeitraum->fetchColumn() ?: 0);
if ($zeitraumId <= 0) {
$stInsertZeitraum->execute($params);
$zeitraumId = (int)$pdo->lastInsertId();
}
if ($zeitraumId > 0 && (int)$row['impfstoff_id'] > 0) {
$stInsertMap->execute([
'zeitraum_id' => $zeitraumId,
'impfstoff_id' => (int)$row['impfstoff_id'],
]);
}
}
if ($manageTransaction) {
$pdo->commit();
}
} catch (Throwable $e) {
if ($manageTransaction && $pdo->inTransaction()) {
$pdo->rollBack();
}
throw $e;
}
}
}
if (!function_exists('impfCsvToIntList')) {
function impfCsvToIntList(?string $csv): array
{
if ($csv === null || trim($csv) === '') {
return [];
}
$werte = array_filter(array_map('trim', explode(',', $csv)), static function ($wert): bool {
return $wert !== '';
});
return array_values(array_map('intval', $werte));
}
}
if (!function_exists('impfZeitraumLabel')) {
function impfZeitraumLabel(array $zeitraum): string
{
$zeitText = impfWeekdayName((int)$zeitraum['wochentag']) . ' ' . substr((string)$zeitraum['start'], 0, 5) . '-' . substr((string)$zeitraum['ende'], 0, 5);
$ort = trim((string)($zeitraum['anzeigename'] ?? '') . ' - ' . (string)($zeitraum['adresse'] ?? ''));
$ortText = trim($ort, " -");
if ($ortText !== '') {
$zeitText .= ' (' . $ortText . ')';
}
$bezeichnung = trim((string)($zeitraum['bezeichnung'] ?? ''));
if ($bezeichnung !== '') {
return $bezeichnung . ': ' . $zeitText;
}
return $zeitText;
}
}
if (!function_exists('impfGetZeitraumRows')) {
function impfGetZeitraumRows(PDO $pdo, bool $onlyActive = true): array
{
$sql = "SELECT z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
o.anzeigename, o.adresse,
GROUP_CONCAT(DISTINCT m.impfstoff_id ORDER BY m.impfstoff_id SEPARATOR ',') AS impfstoff_ids,
GROUP_CONCAT(DISTINCT i.impfname ORDER BY i.impfname SEPARATOR '||') AS impfstoff_namen
FROM impf_zeitraum z
LEFT JOIN impfort o ON o.ortid = z.impfortid
LEFT JOIN impf_zeitraum_impfstoff m ON m.zeitraum_id = z.zeitraum_id
LEFT JOIN impfstoff i ON i.impfid = m.impfstoff_id";
if ($onlyActive) {
$sql .= " WHERE z.aktiv = 1";
}
$sql .= " GROUP BY z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at, o.anzeigename, o.adresse
ORDER BY z.wochentag, z.start, z.ende, z.bezeichnung, z.zeitraum_id";
$st = $pdo->prepare($sql);
$st->execute();
$rows = $st->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$row) {
$row['impfstoff_id_list'] = impfCsvToIntList($row['impfstoff_ids'] ?? null);
$row['impfstoff_name_list'] = [];
if (!empty($row['impfstoff_namen'])) {
$row['impfstoff_name_list'] = array_values(array_filter(explode('||', (string)$row['impfstoff_namen']), static function ($name): bool {
return trim((string)$name) !== '';
}));
}
$row['label'] = impfZeitraumLabel($row);
}
unset($row);
return $rows;
}
}
if (!function_exists('impfLoadZeitraumById')) {
function impfLoadZeitraumById(PDO $pdo, int $zeitraumId, bool $onlyActive = true): ?array
{
if ($zeitraumId <= 0) {
return null;
}
$sql = "SELECT z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
o.anzeigename, o.adresse,
GROUP_CONCAT(DISTINCT m.impfstoff_id ORDER BY m.impfstoff_id SEPARATOR ',') AS impfstoff_ids,
GROUP_CONCAT(DISTINCT i.impfname ORDER BY i.impfname SEPARATOR '||') AS impfstoff_namen
FROM impf_zeitraum z
LEFT JOIN impfort o ON o.ortid = z.impfortid
LEFT JOIN impf_zeitraum_impfstoff m ON m.zeitraum_id = z.zeitraum_id
LEFT JOIN impfstoff i ON i.impfid = m.impfstoff_id
WHERE z.zeitraum_id = :zeitraum_id";
if ($onlyActive) {
$sql .= " AND z.aktiv = 1";
}
$sql .= " GROUP BY z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at, o.anzeigename, o.adresse
LIMIT 1";
$st = $pdo->prepare($sql);
$st->execute(['zeitraum_id' => $zeitraumId]);
$row = $st->fetch(PDO::FETCH_ASSOC);
if (!$row) {
return null;
}
$row['impfstoff_id_list'] = impfCsvToIntList($row['impfstoff_ids'] ?? null);
$row['impfstoff_name_list'] = [];
if (!empty($row['impfstoff_namen'])) {
$row['impfstoff_name_list'] = array_values(array_filter(explode('||', (string)$row['impfstoff_namen']), static function ($name): bool {
return trim((string)$name) !== '';
}));
}
$row['label'] = impfZeitraumLabel($row);
return $row;
}
}
if (!function_exists('impfGetZeitraeumeByImpfstoff')) {
function impfGetZeitraeumeByImpfstoff(PDO $pdo, bool $onlyActive = true): array
{
$zeitraeume = impfGetZeitraumRows($pdo, $onlyActive);
$result = [];
foreach ($zeitraeume as $zeitraum) {
foreach ($zeitraum['impfstoff_id_list'] as $impfstoffId) {
if (!isset($result[$impfstoffId])) {
$result[$impfstoffId] = [];
}
$result[$impfstoffId][] = $zeitraum;
}
}
return $result;
}
}