From 36fb17ac3256bcdd673c3a649b13013e1c1b1b34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20Gla=CC=88ser?= Date: Sun, 20 Sep 2026 11:04:13 +0200 Subject: [PATCH] Veranstalter strikt von Lieferanten trennen --- .../0028_market_organizer_inheritance.sql | 61 +++++------- .../market_management_hermes_mcp_api.md | 4 +- .../market_management_technisches_konzept.md | 6 +- modules/erp/kontakte/service.php | 70 -------------- modules/market_management/mcp.php | 8 +- modules/market_management/service.php | 96 ++++++++++++++----- modules/shared/auth/ui/home.php | 8 +- public/api/market-definition.php | 11 +-- public/index.php | 2 +- 9 files changed, 114 insertions(+), 152 deletions(-) diff --git a/db/migrations/0028_market_organizer_inheritance.sql b/db/migrations/0028_market_organizer_inheritance.sql index 57bb45d..d0e2c0d 100644 --- a/db/migrations/0028_market_organizer_inheritance.sql +++ b/db/migrations/0028_market_organizer_inheritance.sql @@ -1,44 +1,33 @@ BEGIN; -ALTER TABLE party_role - DROP CONSTRAINT chk_party_role_code; +CREATE TABLE market_organizer ( + id BIGSERIAL PRIMARY KEY, + name TEXT NOT NULL, + email TEXT, + phone TEXT, + status TEXT NOT NULL DEFAULT 'active', + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW(), + CONSTRAINT chk_market_organizer_status CHECK (status IN ('active', 'inactive')) +); -ALTER TABLE party_role - ADD CONSTRAINT chk_party_role_code - CHECK (role_code IN ('manufacturer', 'market_organizer')); +CREATE UNIQUE INDEX uq_market_organizer_name ON market_organizer (LOWER(TRIM(name))); + +INSERT INTO market_organizer (name) +VALUES ('Beispielveranstalter 1'); ALTER TABLE market_definition - ADD COLUMN organizer_party_id BIGINT; + ADD COLUMN organizer_id BIGINT; -UPDATE market_definition m -SET organizer_party_id = source.organization_contact_id -FROM ( - SELECT o.market_definition_id, MIN(oo.organization_contact_id) AS organization_contact_id - FROM market_occurrence o - INNER JOIN market_occurrence_organizer oo ON oo.occurrence_id = o.id - GROUP BY o.market_definition_id -) source -WHERE source.market_definition_id = m.id; - -DO $$ -BEGIN - IF EXISTS (SELECT 1 FROM market_definition WHERE organizer_party_id IS NULL) THEN - RAISE EXCEPTION 'Alle bestehenden Märkte benötigen vor der Migration einen Veranstalter.'; - END IF; -END $$; +UPDATE market_definition +SET organizer_id = (SELECT id FROM market_organizer WHERE name = 'Beispielveranstalter 1'); ALTER TABLE market_definition - ALTER COLUMN organizer_party_id SET NOT NULL, - ADD CONSTRAINT fk_market_definition_organizer_party - FOREIGN KEY (organizer_party_id) REFERENCES party(id) ON DELETE RESTRICT; + ALTER COLUMN organizer_id SET NOT NULL, + ADD CONSTRAINT fk_market_definition_organizer + FOREIGN KEY (organizer_id) REFERENCES market_organizer(id) ON DELETE RESTRICT; -CREATE INDEX idx_market_definition_organizer_party - ON market_definition(organizer_party_id); - -INSERT INTO party_role (party_id, role_code) -SELECT DISTINCT organizer_party_id, 'market_organizer' -FROM market_definition -ON CONFLICT (party_id, role_code) DO NOTHING; +CREATE INDEX idx_market_definition_organizer ON market_definition (organizer_id); ALTER TABLE market_occurrence_organizer ADD COLUMN contact_person_name TEXT, @@ -52,6 +41,10 @@ SET contact_person_name = NULLIF(TRIM(CONCAT_WS(' ', c.first_name, c.last_name)) FROM contact c WHERE c.id = oo.contact_person_id; +ALTER TABLE market_occurrence_organizer + DROP COLUMN organization_contact_id, + DROP COLUMN contact_person_id; + INSERT INTO market_occurrence_organizer (occurrence_id, contact_person_name, created_at, updated_at) SELECT o.id, NULL, NOW(), NOW() FROM market_occurrence o @@ -59,8 +52,4 @@ WHERE NOT EXISTS ( SELECT 1 FROM market_occurrence_organizer oo WHERE oo.occurrence_id = o.id ); -ALTER TABLE market_occurrence_organizer - DROP COLUMN organization_contact_id, - DROP COLUMN contact_person_id; - COMMIT; diff --git a/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md b/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md index 9ede661..4bc89a4 100644 --- a/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md +++ b/docs/modules/market_management/konzepte/market_management_hermes_mcp_api.md @@ -97,7 +97,7 @@ Das Ergebnis steht bei `tools/call` als JSON im Textinhalt des ersten - optional: `include_archived` - liefert Marktdurchführungen inklusive Markttagen, Kosten und berechneten Verkaufswerten - `market_management.create_market` - - erforderlich: `name`, `category_id`, `organizer_party_id` + - erforderlich: `name`, `category_id`, `organizer_id` - `market_management.list_market_organizers` - liefert aktive Veranstalterorganisationen - `market_management.create_market_organizer` @@ -178,7 +178,7 @@ Weitere mögliche Tagesfelder sind `stand_start_time`, `stand_end_time`, ### Veranstalter und Kosten -- Veranstalter werden am Markt über `organizer_party_id` gesetzt und von den +- Veranstalter werden am Markt über `organizer_id` gesetzt und von den Durchführungen geerbt. Marktdurchführungen können nur `contact_person_name`, `contact_email` und `contact_phone` ändern. - `market_management.delete_organizer` diff --git a/docs/modules/market_management/konzepte/market_management_technisches_konzept.md b/docs/modules/market_management/konzepte/market_management_technisches_konzept.md index adccbfe..38e4116 100644 --- a/docs/modules/market_management/konzepte/market_management_technisches_konzept.md +++ b/docs/modules/market_management/konzepte/market_management_technisches_konzept.md @@ -84,7 +84,7 @@ Normativ: - jeder Markt besitzt genau einen eindeutigen Namen - jeder Markt besitzt genau eine Kategorie -- jeder Markt besitzt genau einen verpflichtenden Veranstalter aus dem Kontaktmodul +- jeder Markt besitzt genau einen verpflichtenden Veranstalter aus dem eigenen Markt-Veranstalterregister - jeder Markt kann eine optionale Website-URL der Veranstaltung besitzen - der Markt enthält keine Durchführungs-, Kontakt-, Kosten-, Zahlungs- oder Erlösdaten @@ -119,8 +119,8 @@ Normativ: - die Tabelle enthält die durchführungsbezogene Kontaktperson als Freitext sowie optionale E-Mail und Telefonnummer - jede Durchführung besitzt genau einen lokalen Kontaktdatensatz -- der Veranstalter selbst wird ausschließlich über `market_definition.organizer_party_id` vom Markt geerbt -- Veranstalterorganisationen werden im Kontaktmodul über die Rolle `market_organizer` verwaltet +- der Veranstalter selbst wird ausschließlich über `market_definition.organizer_id` vom Markt geerbt +- Veranstalter werden ausschließlich im Markt-Veranstalterregister verwaltet und nicht aus Lieferanten oder Kunden abgeleitet ### 3.5 `market_occurrence_day` diff --git a/modules/erp/kontakte/service.php b/modules/erp/kontakte/service.php index 8a3f224..f046e07 100644 --- a/modules/erp/kontakte/service.php +++ b/modules/erp/kontakte/service.php @@ -166,76 +166,6 @@ function get_party_options(PDO $pdo): array ); } -function get_market_organizer_options(PDO $pdo): array -{ - $stmt = $pdo->query( - "SELECT p.id, p.name, p.email, p.phone - FROM party p - INNER JOIN party_role pr ON pr.party_id = p.id AND pr.role_code = 'market_organizer' - WHERE p.status = 'active' - ORDER BY p.name ASC, p.id ASC" - ); - - return $stmt->fetchAll() ?: []; -} - -function get_market_organizer_reference(PDO $pdo, int $partyId): ?array -{ - $stmt = $pdo->prepare( - "SELECT p.id, p.name, p.email, p.phone - FROM party p - INNER JOIN party_role pr ON pr.party_id = p.id AND pr.role_code = 'market_organizer' - WHERE p.id = :id AND p.status = 'active'" - ); - $stmt->execute([':id' => $partyId]); - $party = $stmt->fetch(); - - return is_array($party) ? $party : null; -} - -function create_market_organizer(PDO $pdo, string $name, ?string $email = null, ?string $phone = null): array -{ - $name = trim($name); - $email = $email !== null ? trim($email) : null; - $phone = $phone !== null ? trim($phone) : null; - if ($name === '') { - throw new InvalidArgumentException('Veranstaltername fehlt.'); - } - - $pdo->beginTransaction(); - try { - $stmt = $pdo->prepare( - "SELECT id, name, email, phone FROM party WHERE LOWER(TRIM(name)) = LOWER(:name) LIMIT 1 FOR UPDATE" - ); - $stmt->execute([':name' => $name]); - $party = $stmt->fetch(); - if (!is_array($party)) { - $stmt = $pdo->prepare( - "INSERT INTO party (type, name, email, phone, status, created_at, updated_at) - VALUES ('customer', :name, :email, :phone, 'active', NOW(), NOW()) - RETURNING id, name, email, phone" - ); - $stmt->execute([':name' => $name, ':email' => $email ?: null, ':phone' => $phone ?: null]); - $party = $stmt->fetch(); - } - if (!is_array($party)) { - throw new RuntimeException('Veranstalter konnte nicht angelegt werden.'); - } - $role = $pdo->prepare( - "INSERT INTO party_role (party_id, role_code) VALUES (:party_id, 'market_organizer') - ON CONFLICT (party_id, role_code) DO NOTHING" - ); - $role->execute([':party_id' => (int) $party['id']]); - $pdo->commit(); - return (array) $party; - } catch (Throwable $error) { - if ($pdo->inTransaction()) { - $pdo->rollBack(); - } - throw $error; - } -} - function get_contact_options(PDO $pdo): array { $stmt = $pdo->query( diff --git a/modules/market_management/mcp.php b/modules/market_management/mcp.php index 98d8e80..ab9ff92 100644 --- a/modules/market_management/mcp.php +++ b/modules/market_management/mcp.php @@ -73,8 +73,8 @@ function market_management_mcp_tools(): array ['name' => 'market_management.search_markets', 'description' => 'Märkte suchen', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], ['name' => 'market_management.search_occurrences', 'description' => 'Marktdurchführungen suchen und auflisten', 'inputSchema' => ['type' => 'object', 'properties' => $searchProperties]], ['name' => 'market_management.get_market', 'description' => 'Markt mit Marktdurchführungen lesen', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'include_archived' => ['type' => 'boolean']]]], - ['name' => 'market_management.create_market', 'description' => 'Markt mit verpflichtendem Veranstalter, Kategorie und optionaler Website-URL anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['name', 'category_id', 'organizer_party_id'], 'properties' => ['name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'organizer_party_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], - ['name' => 'market_management.update_market', 'description' => 'Markt inklusive Veranstalter und Website-URL ändern', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'organizer_party_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], + ['name' => 'market_management.create_market', 'description' => 'Markt mit verpflichtendem Veranstalter, Kategorie und optionaler Website-URL anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['name', 'category_id', 'organizer_id'], 'properties' => ['name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'organizer_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], + ['name' => 'market_management.update_market', 'description' => 'Markt inklusive Veranstalter und Website-URL ändern', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'organizer_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]], ['name' => 'market_management.archive_market', 'description' => 'Markt archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer']]]], ['name' => 'market_management.reactivate_market', 'description' => 'Markt reaktivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer']]]], ['name' => 'market_management.list_categories', 'description' => 'Bestehende Kategorien lesen', 'inputSchema' => ['type' => 'object', 'properties' => []]], @@ -268,8 +268,8 @@ function market_management_mcp_call(PDO $pdo, string $tool, array $arguments): a false ), 'market_management.list_categories' => market_management_list_categories($pdo), - 'market_management.list_market_organizers' => get_market_organizer_options($pdo), - 'market_management.create_market_organizer' => create_market_organizer( + 'market_management.list_market_organizers' => market_management_list_organizers($pdo), + 'market_management.create_market_organizer' => market_management_create_organizer( $pdo, (string) ($arguments['name'] ?? ''), $arguments['email'] ?? null, diff --git a/modules/market_management/service.php b/modules/market_management/service.php index 1516058..529f99b 100644 --- a/modules/market_management/service.php +++ b/modules/market_management/service.php @@ -1,8 +1,6 @@ query( + "SELECT id, name, email, phone + FROM market_organizer + WHERE status = 'active' + ORDER BY name ASC, id ASC" + )->fetchAll() ?: []; +} + +function market_management_get_organizer(PDO $pdo, int $organizerId): ?array +{ + $stmt = $pdo->prepare( + "SELECT id, name, email, phone + FROM market_organizer + WHERE id = :id AND status = 'active'" + ); + $stmt->execute([':id' => $organizerId]); + $organizer = $stmt->fetch(); + return is_array($organizer) ? $organizer : null; +} + +function market_management_create_organizer(PDO $pdo, string $name, ?string $email = null, ?string $phone = null): array +{ + $name = trim($name); + if ($name === '') { + throw new InvalidArgumentException('Veranstaltername fehlt.'); + } + $stmt = $pdo->prepare( + 'INSERT INTO market_organizer (name, email, phone) + VALUES (:name, :email, :phone) + RETURNING id, name, email, phone' + ); + $stmt->execute([':name' => $name, ':email' => $email ?: null, ':phone' => $phone ?: null]); + return (array) $stmt->fetch(); +} + function market_management_require_positive_id(mixed $value, string $field): int { if (!is_int($value) && !ctype_digit((string) $value)) { @@ -212,7 +247,7 @@ function market_management_create_market(PDO $pdo, array $input): array { $name = trim((string) ($input['name'] ?? '')); $categoryId = market_management_require_positive_id($input['category_id'] ?? null, 'category_id'); - $organizerPartyId = market_management_require_positive_id($input['organizer_party_id'] ?? null, 'organizer_party_id'); + $organizerId = market_management_require_positive_id($input['organizer_id'] ?? null, 'organizer_id'); $websiteUrl = market_management_optional_url($input, 'website_url'); if ($name === '') { @@ -221,16 +256,16 @@ function market_management_create_market(PDO $pdo, array $input): array if (!market_management_category_exists($pdo, $categoryId)) { throw new InvalidArgumentException('category_id verweist nicht auf eine aktive Kategorie.'); } - if (get_market_organizer_reference($pdo, $organizerPartyId) === null) { - throw new InvalidArgumentException('organizer_party_id verweist nicht auf einen aktiven Veranstalter.'); + if (market_management_get_organizer($pdo, $organizerId) === null) { + throw new InvalidArgumentException('organizer_id verweist nicht auf einen aktiven Veranstalter.'); } $stmt = $pdo->prepare( - 'INSERT INTO market_definition (name, category_id, organizer_party_id, website_url) - VALUES (:name, :category_id, :organizer_party_id, :website_url) - RETURNING id, name, category_id, organizer_party_id, website_url, archived_at, created_at, updated_at' + 'INSERT INTO market_definition (name, category_id, organizer_id, website_url) + VALUES (:name, :category_id, :organizer_id, :website_url) + RETURNING id, name, category_id, organizer_id, website_url, archived_at, created_at, updated_at' ); - $stmt->execute([':name' => $name, ':category_id' => $categoryId, ':organizer_party_id' => $organizerPartyId, ':website_url' => $websiteUrl]); + $stmt->execute([':name' => $name, ':category_id' => $categoryId, ':organizer_id' => $organizerId, ':website_url' => $websiteUrl]); return (array) $stmt->fetch(); } @@ -298,18 +333,18 @@ function market_management_search_markets(PDO $pdo, array $input): array } $stmt = $pdo->prepare( - 'SELECT m.id, m.name, m.category_id, m.organizer_party_id, m.website_url, c.code AS category_code, c.name AS category_name, + 'SELECT m.id, m.name, m.category_id, m.organizer_id, m.website_url, c.code AS category_code, c.name AS category_name, p.name AS organizer_name, m.archived_at, m.created_at, m.updated_at, MIN(d.date) AS earliest_date, MAX(d.date) AS latest_date, COUNT(DISTINCT o.id) AS occurrence_count FROM market_definition m INNER JOIN market_category c ON c.id = m.category_id - INNER JOIN party p ON p.id = m.organizer_party_id + INNER JOIN market_organizer p ON p.id = m.organizer_id LEFT JOIN market_occurrence o ON o.market_definition_id = m.id AND ' . $occurrenceArchivePredicate . ' LEFT JOIN market_occurrence_day d ON d.occurrence_id = o.id WHERE ' . ($where === [] ? 'TRUE' : implode(' AND ', $where)) . ' - GROUP BY m.id, m.category_id, m.organizer_party_id, c.code, c.name, p.name + GROUP BY m.id, m.category_id, m.organizer_id, c.code, c.name, p.name ORDER BY ' . $sortColumn . ' ' . $sortDirection . ', m.id ASC LIMIT :limit OFFSET :offset' ); @@ -324,12 +359,12 @@ function market_management_get_market(PDO $pdo, int $marketId, bool $includeArch { $marketArchivePredicate = $includeArchived ? 'TRUE' : 'm.archived_at IS NULL'; $stmt = $pdo->prepare( - 'SELECT m.id, m.name, m.category_id, m.organizer_party_id, m.website_url, c.code AS category_code, c.name AS category_name, + 'SELECT m.id, m.name, m.category_id, m.organizer_id, m.website_url, c.code AS category_code, c.name AS category_name, p.name AS organizer_name, m.archived_at, m.created_at, m.updated_at FROM market_definition m INNER JOIN market_category c ON c.id = m.category_id - INNER JOIN party p ON p.id = m.organizer_party_id + INNER JOIN market_organizer p ON p.id = m.organizer_id WHERE m.id = :id AND ' . $marketArchivePredicate ); $stmt->execute([':id' => $marketId]); @@ -367,7 +402,7 @@ function market_management_get_market(PDO $pdo, int $marketId, bool $includeArch function market_management_list_active_market_definitions(PDO $pdo): array { $stmt = $pdo->query( - 'SELECT m.id, m.name, m.category_id, m.organizer_party_id, c.name AS category_name + 'SELECT m.id, m.name, m.category_id, m.organizer_id, c.name AS category_name FROM market_definition m INNER JOIN market_category c ON c.id = m.category_id WHERE m.archived_at IS NULL @@ -501,13 +536,13 @@ function market_management_update_market(PDO $pdo, int $marketId, array $input): $sets[] = 'category_id = :category_id'; $params[':category_id'] = $categoryId; } - if (array_key_exists('organizer_party_id', $input)) { - $organizerPartyId = market_management_require_positive_id($input['organizer_party_id'], 'organizer_party_id'); - if (get_market_organizer_reference($pdo, $organizerPartyId) === null) { - throw new InvalidArgumentException('organizer_party_id verweist nicht auf einen aktiven Veranstalter.'); + if (array_key_exists('organizer_id', $input)) { + $organizerId = market_management_require_positive_id($input['organizer_id'], 'organizer_id'); + if (market_management_get_organizer($pdo, $organizerId) === null) { + throw new InvalidArgumentException('organizer_id verweist nicht auf einen aktiven Veranstalter.'); } - $sets[] = 'organizer_party_id = :organizer_party_id'; - $params[':organizer_party_id'] = $organizerPartyId; + $sets[] = 'organizer_id = :organizer_id'; + $params[':organizer_id'] = $organizerId; } if (array_key_exists('website_url', $input)) { $sets[] = 'website_url = :website_url'; @@ -520,7 +555,7 @@ function market_management_update_market(PDO $pdo, int $marketId, array $input): $sets[] = 'updated_at = NOW()'; $stmt = $pdo->prepare( 'UPDATE market_definition SET ' . implode(', ', $sets) . ' WHERE id = :id - RETURNING id, name, category_id, organizer_party_id, website_url, archived_at, created_at, updated_at' + RETURNING id, name, category_id, organizer_id, website_url, archived_at, created_at, updated_at' ); $stmt->execute($params); $market = $stmt->fetch(); @@ -536,7 +571,7 @@ function market_management_set_market_archive(PDO $pdo, int $marketId, bool $arc 'UPDATE market_definition SET archived_at = ' . ($archive ? 'COALESCE(archived_at, NOW())' : 'NULL') . ', updated_at = NOW() WHERE id = :id - RETURNING id, name, category_id, organizer_party_id, website_url, archived_at, created_at, updated_at' + RETURNING id, name, category_id, organizer_id, website_url, archived_at, created_at, updated_at' ); $stmt->execute([':id' => $marketId]); $market = $stmt->fetch(); @@ -748,7 +783,7 @@ function market_management_get_occurrence(PDO $pdo, int $occurrenceId, bool $inc if (is_array($organizer)) { $market = market_management_get_market($pdo, (int) $occurrence['market_definition_id'], true); $organizer['organization'] = is_array($market) - ? get_market_organizer_reference($pdo, (int) $market['organizer_party_id']) + ? market_management_get_organizer($pdo, (int) $market['organizer_id']) : null; $organizer['contact_person'] = [ 'first_name' => (string) ($organizer['contact_person_name'] ?? ''), @@ -758,14 +793,23 @@ function market_management_get_occurrence(PDO $pdo, int $occurrenceId, bool $inc ]; } $occurrence['organizer'] = is_array($organizer) ? $organizer : null; - $occurrence['organizer_party_id'] = is_array($occurrence['organizer']) && is_array($occurrence['organizer']['organization'] ?? null) + $occurrence['organizer_id'] = is_array($occurrence['organizer']) && is_array($occurrence['organizer']['organization'] ?? null) ? (int) $occurrence['organizer']['organization']['id'] : null; + $contactPersonName = (string) ($occurrence['organizer']['contact_person_name'] ?? ''); + $occurrence['contact_person_id'] = $contactPersonName; $referenceData = market_management_list_reference_data($pdo, []); $occurrence['reference_options'] = [ 'categories' => market_management_list_categories($pdo), 'municipalities' => $referenceData['municipalities'] ?? [], - 'market_organizers' => get_market_organizer_options($pdo), + 'market_organizers' => market_management_list_organizers($pdo), + 'parties' => market_management_list_organizers($pdo), + 'contacts' => $contactPersonName === '' ? [] : [[ + 'id' => $contactPersonName, + 'first_name' => $contactPersonName, + 'last_name' => '', + 'party_name' => '', + ]], ]; $costs = $pdo->prepare('SELECT * FROM market_occurrence_cost_item WHERE occurrence_id = :occurrence_id ORDER BY id ASC'); $costs->execute([':occurrence_id' => $occurrenceId]); diff --git a/modules/shared/auth/ui/home.php b/modules/shared/auth/ui/home.php index b8afeb6..468b591 100644 --- a/modules/shared/auth/ui/home.php +++ b/modules/shared/auth/ui/home.php @@ -187,7 +187,7 @@ function auth_render_market_definitions_content(array $marketTable): string $marketName = (string) ($row['name'] ?? ''); $organizerName = (string) ($row['organizer_name'] ?? ''); $html[] = '
'; - $html[] = ''; + $html[] = ''; $html[] = '
' . auth_escape_html((string) ($row['category_name'] ?? $row['category_code'] ?? '')) . '
'; $html[] = '
' . auth_escape_html($organizerName) . '
'; $html[] = '
' . auth_escape_html($websiteValue) . '
'; @@ -201,7 +201,7 @@ function auth_render_market_definitions_content(array $marketTable): string foreach ($categories as $category) { $html[] = ''; } - $html[] = '