823 lines
31 KiB
PHP
823 lines
31 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('impfTableHasIndex')) {
|
|
function impfTableHasIndex(PDO $pdo, string $table, string $index): bool
|
|
{
|
|
$st = $pdo->prepare("SHOW INDEX FROM `" . $table . "` WHERE Key_name = :index_name");
|
|
$st->execute(['index_name' => $index]);
|
|
return (bool)$st->fetch(PDO::FETCH_ASSOC);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfEnsureTable')) {
|
|
function impfEnsureTable(PDO $pdo, string $table, string $createSql): void
|
|
{
|
|
if (impfTableExists($pdo, $table)) {
|
|
return;
|
|
}
|
|
|
|
$pdo->exec($createSql);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfNormalizeZeitraumIds')) {
|
|
function impfNormalizeZeitraumIds($zeitraumIds): array
|
|
{
|
|
if ($zeitraumIds === null) {
|
|
return [];
|
|
}
|
|
|
|
if (!is_array($zeitraumIds)) {
|
|
$zeitraumIds = [$zeitraumIds];
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($zeitraumIds as $zeitraumId) {
|
|
$zeitraumId = (int)$zeitraumId;
|
|
if ($zeitraumId <= 0 || isset($result[$zeitraumId])) {
|
|
continue;
|
|
}
|
|
$result[$zeitraumId] = $zeitraumId;
|
|
}
|
|
|
|
return array_values($result);
|
|
}
|
|
}
|
|
|
|
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('impfLimitLabelLength')) {
|
|
function impfLimitLabelLength(string $text, int $maxLength = 50): string
|
|
{
|
|
$text = trim($text);
|
|
if ($text === '') {
|
|
return $text;
|
|
}
|
|
|
|
if (function_exists('mb_strimwidth')) {
|
|
return rtrim(mb_strimwidth($text, 0, $maxLength, '...', 'UTF-8'));
|
|
}
|
|
|
|
if (strlen($text) <= $maxLength) {
|
|
return $text;
|
|
}
|
|
|
|
return rtrim(substr($text, 0, max(0, $maxLength - 3))) . '...';
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfWorkflowEnsureTables')) {
|
|
function impfWorkflowEnsureTables(PDO $pdo): void
|
|
{
|
|
impfEnsureTable($pdo, 'impf_workflow_meta', "CREATE TABLE impf_workflow_meta (
|
|
meta_key VARCHAR(100) NOT NULL,
|
|
meta_value VARCHAR(255) NOT NULL DEFAULT '',
|
|
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (meta_key)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
|
|
|
|
impfEnsureTable($pdo, 'impfstoff_workflow', "CREATE TABLE 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");
|
|
|
|
impfEnsureTable($pdo, 'impfstoff_wochenplan', "CREATE TABLE 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");
|
|
|
|
impfEnsureTable($pdo, 'impf_zeitraum', "CREATE TABLE 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");
|
|
}
|
|
|
|
impfEnsureTable($pdo, 'impf_zeitraum_impfstoff', "CREATE TABLE 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");
|
|
|
|
impfEnsureTable($pdo, 'warteliste_zeitraum', "CREATE TABLE warteliste_zeitraum (
|
|
warteid INT NOT NULL,
|
|
zeitraum_id INT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (warteid, zeitraum_id),
|
|
INDEX idx_warteliste_zeitraum_zeitraum (zeitraum_id)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3");
|
|
|
|
if (impfTableExists($pdo, 'warteliste_zeitraum') && !impfTableHasIndex($pdo, 'warteliste_zeitraum', 'idx_warteliste_zeitraum_zeitraum')) {
|
|
$pdo->exec("ALTER TABLE warteliste_zeitraum ADD INDEX idx_warteliste_zeitraum_zeitraum (zeitraum_id)");
|
|
}
|
|
|
|
if (impfTableExists($pdo, 'warteliste') && !impfTableHasColumn($pdo, 'warteliste', 'zeitraum_id')) {
|
|
$pdo->exec("ALTER TABLE warteliste ADD COLUMN zeitraum_id INT NULL AFTER impfenzeitraum");
|
|
}
|
|
if (impfTableExists($pdo, 'warteliste') && !impfTableHasIndex($pdo, 'warteliste', 'idx_warteliste_zeitraum')) {
|
|
$pdo->exec("ALTER TABLE warteliste ADD INDEX idx_warteliste_zeitraum (zeitraum_id)");
|
|
}
|
|
|
|
impfWorkflowMigrateLegacyPlans($pdo);
|
|
impfWorkflowMigrateLegacyWartelisteZeitraeume($pdo);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfWorkflowGetMeta')) {
|
|
function impfWorkflowGetMeta(PDO $pdo, string $key): ?string
|
|
{
|
|
$st = $pdo->prepare("SELECT meta_value
|
|
FROM impf_workflow_meta
|
|
WHERE meta_key = :meta_key
|
|
LIMIT 1");
|
|
$st->execute(['meta_key' => $key]);
|
|
$value = $st->fetchColumn();
|
|
return ($value === false) ? null : (string)$value;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfWorkflowSetMeta')) {
|
|
function impfWorkflowSetMeta(PDO $pdo, string $key, string $value): void
|
|
{
|
|
$st = $pdo->prepare("INSERT INTO impf_workflow_meta (meta_key, meta_value)
|
|
VALUES (:meta_key, :meta_value)
|
|
ON DUPLICATE KEY UPDATE meta_value = VALUES(meta_value)");
|
|
$st->execute([
|
|
'meta_key' => $key,
|
|
'meta_value' => $value,
|
|
]);
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfWorkflowMigrateLegacyPlans')) {
|
|
function impfWorkflowMigrateLegacyPlans(PDO $pdo): void
|
|
{
|
|
if (impfWorkflowGetMeta($pdo, 'legacy_wochenplan_migrated') === '1') {
|
|
return;
|
|
}
|
|
|
|
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)) {
|
|
impfWorkflowSetMeta($pdo, 'legacy_wochenplan_migrated', '1');
|
|
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'],
|
|
]);
|
|
}
|
|
}
|
|
|
|
impfWorkflowSetMeta($pdo, 'legacy_wochenplan_migrated', '1');
|
|
|
|
if ($manageTransaction) {
|
|
$pdo->commit();
|
|
}
|
|
} catch (Throwable $e) {
|
|
if ($manageTransaction && $pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfWorkflowMigrateLegacyWartelisteZeitraeume')) {
|
|
function impfWorkflowMigrateLegacyWartelisteZeitraeume(PDO $pdo): void
|
|
{
|
|
if (!impfTableExists($pdo, 'warteliste') || !impfTableExists($pdo, 'warteliste_zeitraum')) {
|
|
return;
|
|
}
|
|
|
|
if (impfWorkflowGetMeta($pdo, 'legacy_warteliste_zeitraeume_migrated') === '1') {
|
|
return;
|
|
}
|
|
|
|
$manageTransaction = !$pdo->inTransaction();
|
|
if ($manageTransaction) {
|
|
$pdo->beginTransaction();
|
|
}
|
|
|
|
try {
|
|
$pdo->exec("INSERT IGNORE INTO warteliste_zeitraum (warteid, zeitraum_id)
|
|
SELECT warteid, zeitraum_id
|
|
FROM warteliste
|
|
WHERE zeitraum_id IS NOT NULL
|
|
AND zeitraum_id > 0");
|
|
impfWorkflowSetMeta($pdo, 'legacy_warteliste_zeitraeume_migrated', '1');
|
|
|
|
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, bool $includeName = true): 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 . ')';
|
|
}
|
|
|
|
return impfLimitLabelLength($zeitText, 50);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfGetWartelistenFormOptions')) {
|
|
function impfGetWartelistenFormOptions(PDO $pdo): array
|
|
{
|
|
$impfstoffe = [];
|
|
$zeitfenster = [];
|
|
|
|
$stImpfstoffe = $pdo->prepare("SELECT r.impfstoff_id, i.impfname
|
|
FROM impfstoff_workflow r
|
|
INNER JOIN impfstoff i ON i.impfid = r.impfstoff_id
|
|
WHERE (i.aktiv = 1 OR i.aktivwarteliste = 1 OR i.aktivtermin = 1 OR i.aktivgrippe = 1)
|
|
AND r.dosen_pro_flasche > 0
|
|
ORDER BY i.impfname");
|
|
$stImpfstoffe->execute();
|
|
foreach ($stImpfstoffe->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
|
$impfstoffe[(int)$row['impfstoff_id']] = (string)$row['impfname'];
|
|
}
|
|
|
|
$zeitraeumeByImpfstoff = impfGetZeitraeumeByImpfstoff($pdo, true);
|
|
foreach ($zeitraeumeByImpfstoff as $impfstoffId => $zeitraeume) {
|
|
if (!isset($impfstoffe[$impfstoffId])) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($zeitraeume as $zeitraum) {
|
|
if (!isset($zeitfenster[$impfstoffId])) {
|
|
$zeitfenster[$impfstoffId] = [];
|
|
}
|
|
$zeitfenster[$impfstoffId][] = [
|
|
'id' => (int)$zeitraum['zeitraum_id'],
|
|
'label' => impfZeitraumLabel($zeitraum, false),
|
|
];
|
|
}
|
|
}
|
|
|
|
foreach (array_keys($impfstoffe) as $impfstoffId) {
|
|
if (empty($zeitfenster[$impfstoffId])) {
|
|
unset($impfstoffe[$impfstoffId]);
|
|
}
|
|
}
|
|
|
|
return [
|
|
'impfstoffe' => $impfstoffe,
|
|
'zeitfenster' => $zeitfenster,
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfGetWartelistenZeitraeume')) {
|
|
function impfGetWartelistenZeitraeume(PDO $pdo, int $warteid, bool $onlyActive = false): array
|
|
{
|
|
if ($warteid <= 0 || !impfTableExists($pdo, 'warteliste_zeitraum')) {
|
|
return [];
|
|
}
|
|
|
|
$sql = "SELECT z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
|
|
o.anzeigename, o.adresse
|
|
FROM warteliste_zeitraum wz
|
|
INNER JOIN impf_zeitraum z ON z.zeitraum_id = wz.zeitraum_id
|
|
LEFT JOIN impfort o ON o.ortid = z.impfortid
|
|
WHERE wz.warteid = :warteid";
|
|
if ($onlyActive) {
|
|
$sql .= " AND z.aktiv = 1";
|
|
}
|
|
$sql .= " ORDER BY z.wochentag, z.start, z.ende, z.bezeichnung, z.zeitraum_id";
|
|
|
|
$st = $pdo->prepare($sql);
|
|
$st->execute(['warteid' => $warteid]);
|
|
$rows = $st->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($rows as &$row) {
|
|
$row['label'] = impfZeitraumLabel($row);
|
|
}
|
|
unset($row);
|
|
|
|
if (!empty($rows)) {
|
|
return $rows;
|
|
}
|
|
|
|
$stFallback = $pdo->prepare("SELECT w.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
|
|
o.anzeigename, o.adresse
|
|
FROM warteliste w
|
|
LEFT JOIN impf_zeitraum z ON z.zeitraum_id = w.zeitraum_id
|
|
LEFT JOIN impfort o ON o.ortid = z.impfortid
|
|
WHERE w.warteid = :warteid
|
|
AND w.zeitraum_id IS NOT NULL
|
|
LIMIT 1");
|
|
$stFallback->execute(['warteid' => $warteid]);
|
|
$row = $stFallback->fetch(PDO::FETCH_ASSOC);
|
|
if (!$row) {
|
|
return [];
|
|
}
|
|
|
|
$row['label'] = impfZeitraumLabel($row);
|
|
return [$row];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfGetWartelistenZeitraeumeLabels')) {
|
|
function impfGetWartelistenZeitraeumeLabels(PDO $pdo, int $warteid, bool $onlyActive = false): array
|
|
{
|
|
$rows = impfGetWartelistenZeitraeume($pdo, $warteid, $onlyActive);
|
|
return array_values(array_map(static function (array $row): string {
|
|
return (string)($row['label'] ?? '');
|
|
}, $rows));
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfGetWartelistenZeitraeumeLabelsMap')) {
|
|
function impfGetWartelistenZeitraeumeLabelsMap(PDO $pdo, array $warteids, bool $onlyActive = false): array
|
|
{
|
|
$warteids = array_values(array_unique(array_filter(array_map('intval', $warteids), static function (int $warteid): bool {
|
|
return $warteid > 0;
|
|
})));
|
|
|
|
if (empty($warteids) || !impfTableExists($pdo, 'warteliste_zeitraum')) {
|
|
return [];
|
|
}
|
|
|
|
$result = [];
|
|
foreach ($warteids as $warteid) {
|
|
$result[$warteid] = [];
|
|
}
|
|
|
|
$placeholders = [];
|
|
$params = [];
|
|
foreach ($warteids as $index => $warteid) {
|
|
$key = 'wid' . $index;
|
|
$placeholders[] = ':' . $key;
|
|
$params[$key] = $warteid;
|
|
}
|
|
$inList = implode(', ', $placeholders);
|
|
|
|
$sql = "SELECT wz.warteid, z.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
|
|
o.anzeigename, o.adresse
|
|
FROM warteliste_zeitraum wz
|
|
INNER JOIN impf_zeitraum z ON z.zeitraum_id = wz.zeitraum_id
|
|
LEFT JOIN impfort o ON o.ortid = z.impfortid
|
|
WHERE wz.warteid IN (" . $inList . ")";
|
|
if ($onlyActive) {
|
|
$sql .= " AND z.aktiv = 1";
|
|
}
|
|
$sql .= " ORDER BY wz.warteid, z.wochentag, z.start, z.ende, z.bezeichnung, z.zeitraum_id";
|
|
|
|
$st = $pdo->prepare($sql);
|
|
$st->execute($params);
|
|
$rows = $st->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($rows as $row) {
|
|
$warteid = (int)($row['warteid'] ?? 0);
|
|
if ($warteid <= 0) {
|
|
continue;
|
|
}
|
|
$row['label'] = impfZeitraumLabel($row);
|
|
$result[$warteid][] = (string)$row['label'];
|
|
}
|
|
|
|
$missing = array_values(array_filter($warteids, static function (int $warteid) use ($result): bool {
|
|
return empty($result[$warteid]);
|
|
}));
|
|
|
|
if (empty($missing)) {
|
|
return $result;
|
|
}
|
|
|
|
$fallbackPlaceholders = [];
|
|
$fallbackParams = [];
|
|
foreach ($missing as $index => $warteid) {
|
|
$key = 'f_wid' . $index;
|
|
$fallbackPlaceholders[] = ':' . $key;
|
|
$fallbackParams[$key] = $warteid;
|
|
}
|
|
$fallbackInList = implode(', ', $fallbackPlaceholders);
|
|
|
|
$fallbackSql = "SELECT w.warteid, w.zeitraum_id, z.bezeichnung, z.wochentag, z.start, z.ende, z.impfortid, z.aktiv, z.created_at,
|
|
o.anzeigename, o.adresse
|
|
FROM warteliste w
|
|
LEFT JOIN impf_zeitraum z ON z.zeitraum_id = w.zeitraum_id
|
|
LEFT JOIN impfort o ON o.ortid = z.impfortid
|
|
WHERE w.warteid IN (" . $fallbackInList . ")
|
|
AND w.zeitraum_id IS NOT NULL";
|
|
if ($onlyActive) {
|
|
$fallbackSql .= " AND z.aktiv = 1";
|
|
}
|
|
|
|
$stFallback = $pdo->prepare($fallbackSql);
|
|
$stFallback->execute($fallbackParams);
|
|
$fallbackRows = $stFallback->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
foreach ($fallbackRows as $row) {
|
|
$warteid = (int)($row['warteid'] ?? 0);
|
|
if ($warteid <= 0) {
|
|
continue;
|
|
}
|
|
$row['label'] = impfZeitraumLabel($row);
|
|
$result[$warteid] = [(string)$row['label']];
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfSetWartelistenZeitraeume')) {
|
|
function impfSetWartelistenZeitraeume(PDO $pdo, int $warteid, $zeitraumIds): void
|
|
{
|
|
$zeitraumIds = impfNormalizeZeitraumIds($zeitraumIds);
|
|
if ($warteid <= 0) {
|
|
throw new InvalidArgumentException('Unguelige Wartelisten-ID.');
|
|
}
|
|
|
|
$manageTransaction = !$pdo->inTransaction();
|
|
if ($manageTransaction) {
|
|
$pdo->beginTransaction();
|
|
}
|
|
|
|
try {
|
|
$stDelete = $pdo->prepare("DELETE FROM warteliste_zeitraum WHERE warteid = :warteid");
|
|
$stDelete->execute(['warteid' => $warteid]);
|
|
|
|
if (!empty($zeitraumIds)) {
|
|
$stInsert = $pdo->prepare("INSERT INTO warteliste_zeitraum (warteid, zeitraum_id)
|
|
VALUES (:warteid, :zeitraum_id)");
|
|
foreach ($zeitraumIds as $zeitraumId) {
|
|
$stInsert->execute([
|
|
'warteid' => $warteid,
|
|
'zeitraum_id' => $zeitraumId,
|
|
]);
|
|
}
|
|
}
|
|
|
|
if ($manageTransaction) {
|
|
$pdo->commit();
|
|
}
|
|
} catch (Throwable $e) {
|
|
if ($manageTransaction && $pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!function_exists('impfCreateWaitlistEntryForPerson')) {
|
|
function impfCreateWaitlistEntryForPerson(
|
|
PDO $pdo,
|
|
int $personId,
|
|
int $impfstoffId,
|
|
$zeitraumIds,
|
|
int $impfart,
|
|
?string $letzteImpfung = null,
|
|
int $checked = 1
|
|
): array {
|
|
if ($personId <= 0) {
|
|
return [false, 'Keine gueltige Person uebergeben.', null];
|
|
}
|
|
if ($impfstoffId <= 0) {
|
|
return [false, 'Bitte einen Impfstoff auswaehlen.', null];
|
|
}
|
|
if ($impfart < 1 || $impfart > 4) {
|
|
return [false, 'Bitte eine gueltige Impfungsart auswaehlen.', null];
|
|
}
|
|
|
|
$zeitraumIds = impfNormalizeZeitraumIds($zeitraumIds);
|
|
if (empty($zeitraumIds)) {
|
|
return [false, 'Bitte mindestens ein Zeitfenster auswaehlen.', null];
|
|
}
|
|
|
|
$letzteImpfung = $letzteImpfung !== null ? trim($letzteImpfung) : null;
|
|
if ($impfart === 1) {
|
|
$letzteImpfung = null;
|
|
} elseif ($letzteImpfung === null || $letzteImpfung === '') {
|
|
return [false, 'Bitte das Datum der letzten Impfung angeben.', null];
|
|
} elseif (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $letzteImpfung)) {
|
|
return [false, 'Das Datum der letzten Impfung ist ungueltig.', null];
|
|
}
|
|
|
|
$stPerson = $pdo->prepare("SELECT person_id, patientenart, vorname, nachname
|
|
FROM persons
|
|
WHERE person_id = :pid
|
|
LIMIT 1");
|
|
$stPerson->execute(['pid' => $personId]);
|
|
$person = $stPerson->fetch(PDO::FETCH_ASSOC);
|
|
if (!$person) {
|
|
return [false, 'Die Person wurde nicht gefunden.', null];
|
|
}
|
|
|
|
$zeitraumRows = [];
|
|
$zeitraumLabels = [];
|
|
foreach ($zeitraumIds as $zeitraumId) {
|
|
$row = impfLoadZeitraumById($pdo, $zeitraumId, true);
|
|
if (!$row) {
|
|
return [false, 'Mindestens ein ausgewaehltes Zeitfenster ist nicht mehr verfuegbar.', null];
|
|
}
|
|
if (!in_array($impfstoffId, $row['impfstoff_id_list'] ?? [], true)) {
|
|
return [false, 'Impfstoff und Zeitfenster passen nicht zusammen.', null];
|
|
}
|
|
$zeitraumRows[$zeitraumId] = $row;
|
|
$zeitraumLabels[] = (string)$row['label'];
|
|
}
|
|
|
|
$stDup = $pdo->prepare("SELECT w.warteid
|
|
FROM warteliste w
|
|
LEFT JOIN warteliste_zeitraum wz ON wz.warteid = w.warteid
|
|
WHERE w.userid = :uid
|
|
AND w.checked IN (0, 1)
|
|
AND w.impfstoff = :impfstoff
|
|
AND w.impfart = :impfart
|
|
GROUP BY w.warteid
|
|
LIMIT 1");
|
|
$stDup->execute([
|
|
'uid' => $personId,
|
|
'impfstoff' => $impfstoffId,
|
|
'impfart' => $impfart,
|
|
]);
|
|
if ($stDup->fetchColumn()) {
|
|
return [false, 'Diese Anfrage ist fuer diese Person bereits auf der aktiven Warteliste vorhanden.', null];
|
|
}
|
|
|
|
$patientenart = ((int)($person['patientenart'] ?? 0) === 1) ? 1 : 0;
|
|
$hash = bin2hex(random_bytes(16));
|
|
$checkedValue = ($checked === 0) ? 0 : 1;
|
|
$primaerZeitraumId = (int)$zeitraumIds[0];
|
|
$impfenzeitraum = implode(' | ', $zeitraumLabels);
|
|
|
|
$manageTransaction = !$pdo->inTransaction();
|
|
if ($manageTransaction) {
|
|
$pdo->beginTransaction();
|
|
}
|
|
|
|
try {
|
|
$stInsert = $pdo->prepare("INSERT INTO warteliste
|
|
(userid, checked, hash, impfenangebot, impfstoff, Patientenart, Impfaufklaerung, WeitereFragen, impfart, impfenmit, letzteimpfung, impfenzeitraum, zeitraum_id, date_created)
|
|
VALUES
|
|
(:userid, :checked, :hash, 1, :impfstoff, :patientenart, 0, 0, :impfart, '', :letzteimpfung, :impfenzeitraum, :zeitraum_id, NOW())");
|
|
$stInsert->execute([
|
|
'userid' => $personId,
|
|
'checked' => $checkedValue,
|
|
'hash' => $hash,
|
|
'impfstoff' => $impfstoffId,
|
|
'patientenart' => $patientenart,
|
|
'impfart' => $impfart,
|
|
'letzteimpfung' => $letzteImpfung,
|
|
'impfenzeitraum' => $impfenzeitraum,
|
|
'zeitraum_id' => $primaerZeitraumId,
|
|
]);
|
|
|
|
$warteid = (int)$pdo->lastInsertId();
|
|
impfSetWartelistenZeitraeume($pdo, $warteid, $zeitraumIds);
|
|
|
|
if ($manageTransaction) {
|
|
$pdo->commit();
|
|
}
|
|
|
|
$personName = trim((string)$person['vorname'] . ' ' . (string)$person['nachname']);
|
|
return [true, 'Wartelistenplatz fuer ' . $personName . ' wurde gespeichert.', $warteid];
|
|
} catch (Throwable $e) {
|
|
if ($manageTransaction && $pdo->inTransaction()) {
|
|
$pdo->rollBack();
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
}
|