Ergaenze Website-URL am Marktstamm
This commit is contained in:
1 parent
d259c35000
commit
f9ffa5a6b6
7 files changed
+45
-12
No files matched your search
@@ -0,0 +1,10 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
ALTER TABLE market_definition
|
||||||
|
ADD COLUMN website_url TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE market_definition
|
||||||
|
ADD CONSTRAINT chk_market_definition_website_url
|
||||||
|
CHECK (website_url IS NULL OR website_url ~* '^https?://');
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -47,6 +47,7 @@ Ebene.
|
|||||||
|
|
||||||
- Marktname
|
- Marktname
|
||||||
- Marktart/Kategorie aus einer deterministischen Liste
|
- Marktart/Kategorie aus einer deterministischen Liste
|
||||||
|
- optionale Website-URL der Veranstaltung
|
||||||
|
|
||||||
### Durchführung
|
### Durchführung
|
||||||
|
|
||||||
|
|||||||
@@ -80,9 +80,10 @@ Das Ergebnis steht bei `tools/call` als JSON im Textinhalt des ersten
|
|||||||
- optional: `include_archived`
|
- optional: `include_archived`
|
||||||
- `market_management.create_market`
|
- `market_management.create_market`
|
||||||
- erforderlich: `name`, `category_id`
|
- erforderlich: `name`, `category_id`
|
||||||
|
- optional: `website_url` als HTTP(S)-URL der Veranstaltung
|
||||||
- `market_management.update_market`
|
- `market_management.update_market`
|
||||||
- erforderlich: `market_id`
|
- erforderlich: `market_id`
|
||||||
- änderbar: `name`, `category_id`
|
- änderbar: `name`, `category_id`, `website_url`
|
||||||
- `market_management.archive_market`
|
- `market_management.archive_market`
|
||||||
- erforderlich: `market_id`
|
- erforderlich: `market_id`
|
||||||
- `market_management.reactivate_market`
|
- `market_management.reactivate_market`
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ Normativ:
|
|||||||
|
|
||||||
- jeder Markt besitzt genau einen eindeutigen Namen
|
- jeder Markt besitzt genau einen eindeutigen Namen
|
||||||
- jeder Markt besitzt genau eine Kategorie
|
- jeder Markt besitzt genau eine Kategorie
|
||||||
|
- jeder Markt kann eine optionale Website-URL der Veranstaltung besitzen
|
||||||
- der Markt enthält keine Durchführungs-, Kontakt-, Kosten-, Zahlungs- oder
|
- der Markt enthält keine Durchführungs-, Kontakt-, Kosten-, Zahlungs- oder
|
||||||
Erlösdaten
|
Erlösdaten
|
||||||
- Markt und Durchführungen werden getrennt archiviert und reaktiviert
|
- Markt und Durchführungen werden getrennt archiviert und reaktiviert
|
||||||
@@ -142,7 +143,7 @@ Minimale Pflichtfelder:
|
|||||||
|
|
||||||
Über alle Statuswerte hinweg gelten nur diese Pflichtfelder:
|
Über alle Statuswerte hinweg gelten nur diese Pflichtfelder:
|
||||||
|
|
||||||
- Marktdefinition: `name`, `category_id`
|
- Marktdefinition: `name`, `category_id`; `website_url` ist optional
|
||||||
- Durchführung: `market_definition_id`, initialer Status `open`, mindestens ein
|
- Durchführung: `market_definition_id`, initialer Status `open`, mindestens ein
|
||||||
Durchführungstag
|
Durchführungstag
|
||||||
- Durchführungstag: `occurrence_id`, `date`
|
- Durchführungstag: `occurrence_id`, `date`
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ Der zentrale Marktstamm enthält ausschließlich:
|
|||||||
|
|
||||||
- Marktname
|
- Marktname
|
||||||
- Marktart/Kategorie aus einer deterministischen Liste
|
- Marktart/Kategorie aus einer deterministischen Liste
|
||||||
|
- optionale Website-URL der Veranstaltung
|
||||||
|
|
||||||
Alle übrigen veränderlichen Angaben werden pro Durchführung erfasst. Tages-
|
Alle übrigen veränderlichen Angaben werden pro Durchführung erfasst. Tages-
|
||||||
und Verkaufsdaten werden pro Durchführungstag erfasst.
|
und Verkaufsdaten werden pro Durchführungstag erfasst.
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ function market_management_mcp_tools(): array
|
|||||||
['name' => 'market_management.search_markets', 'description' => 'Märkte suchen', 'inputSchema' => ['type' => 'object']],
|
['name' => 'market_management.search_markets', 'description' => 'Märkte suchen', 'inputSchema' => ['type' => 'object']],
|
||||||
['name' => 'market_management.search_occurrences', 'description' => 'Durchführungen suchen und auflisten', 'inputSchema' => ['type' => 'object']],
|
['name' => 'market_management.search_occurrences', 'description' => 'Durchführungen suchen und auflisten', 'inputSchema' => ['type' => 'object']],
|
||||||
['name' => 'market_management.get_market', 'description' => 'Markt mit Durchführungen lesen', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
['name' => 'market_management.get_market', 'description' => 'Markt mit Durchführungen lesen', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
||||||
['name' => 'market_management.create_market', 'description' => 'Markt mit bestehender Kategorie anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['name', 'category_id']]],
|
['name' => 'market_management.create_market', 'description' => 'Markt mit bestehender Kategorie und optionaler Website-URL anlegen', 'inputSchema' => ['type' => 'object', 'required' => ['name', 'category_id'], 'properties' => ['name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]],
|
||||||
['name' => 'market_management.update_market', 'description' => 'Markt ändern', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
['name' => 'market_management.update_market', 'description' => 'Markt inklusive Website-URL ändern', 'inputSchema' => ['type' => 'object', 'required' => ['market_id'], 'properties' => ['market_id' => ['type' => 'integer'], 'name' => ['type' => 'string'], 'category_id' => ['type' => 'integer'], 'website_url' => ['type' => ['string', 'null'], 'format' => 'uri']]]],
|
||||||
['name' => 'market_management.archive_market', 'description' => 'Markt archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
['name' => 'market_management.archive_market', 'description' => 'Markt archivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
||||||
['name' => 'market_management.reactivate_market', 'description' => 'Markt reaktivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
['name' => 'market_management.reactivate_market', 'description' => 'Markt reaktivieren', 'inputSchema' => ['type' => 'object', 'required' => ['market_id']]],
|
||||||
['name' => 'market_management.list_categories', 'description' => 'Bestehende Kategorien lesen', 'inputSchema' => ['type' => 'object']],
|
['name' => 'market_management.list_categories', 'description' => 'Bestehende Kategorien lesen', 'inputSchema' => ['type' => 'object']],
|
||||||
|
|||||||
@@ -86,6 +86,20 @@ function market_management_optional_integer(array $input, string $field): ?int
|
|||||||
return (int) $value;
|
return (int) $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function market_management_optional_url(array $input, string $field): ?string
|
||||||
|
{
|
||||||
|
$value = market_management_optional_string($input, $field);
|
||||||
|
if ($value === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter_var($value, FILTER_VALIDATE_URL) === false || !preg_match('/^https?:\/\//i', $value)) {
|
||||||
|
throw new InvalidArgumentException($field . ' muss eine gültige HTTP(S)-URL sein.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
function market_management_category_exists(PDO $pdo, int $categoryId): bool
|
function market_management_category_exists(PDO $pdo, int $categoryId): bool
|
||||||
{
|
{
|
||||||
$stmt = $pdo->prepare('SELECT 1 FROM market_category WHERE id = :id AND is_active = TRUE');
|
$stmt = $pdo->prepare('SELECT 1 FROM market_category WHERE id = :id AND is_active = TRUE');
|
||||||
@@ -97,6 +111,7 @@ function market_management_create_market(PDO $pdo, array $input): array
|
|||||||
{
|
{
|
||||||
$name = trim((string) ($input['name'] ?? ''));
|
$name = trim((string) ($input['name'] ?? ''));
|
||||||
$categoryId = market_management_require_positive_id($input['category_id'] ?? null, 'category_id');
|
$categoryId = market_management_require_positive_id($input['category_id'] ?? null, 'category_id');
|
||||||
|
$websiteUrl = market_management_optional_url($input, 'website_url');
|
||||||
|
|
||||||
if ($name === '') {
|
if ($name === '') {
|
||||||
throw new InvalidArgumentException('name ist erforderlich.');
|
throw new InvalidArgumentException('name ist erforderlich.');
|
||||||
@@ -106,11 +121,11 @@ function market_management_create_market(PDO $pdo, array $input): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'INSERT INTO market_definition (name, category_id)
|
'INSERT INTO market_definition (name, category_id, website_url)
|
||||||
VALUES (:name, :category_id)
|
VALUES (:name, :category_id, :website_url)
|
||||||
RETURNING id, name, category_id, archived_at, created_at, updated_at'
|
RETURNING id, name, category_id, website_url, archived_at, created_at, updated_at'
|
||||||
);
|
);
|
||||||
$stmt->execute([':name' => $name, ':category_id' => $categoryId]);
|
$stmt->execute([':name' => $name, ':category_id' => $categoryId, ':website_url' => $websiteUrl]);
|
||||||
return (array) $stmt->fetch();
|
return (array) $stmt->fetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +193,7 @@ function market_management_search_markets(PDO $pdo, array $input): array
|
|||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'SELECT m.id, m.name, m.category_id, c.code AS category_code, c.name AS category_name,
|
'SELECT m.id, m.name, m.category_id, m.website_url, c.code AS category_code, c.name AS category_name,
|
||||||
m.archived_at, m.created_at, m.updated_at,
|
m.archived_at, m.created_at, m.updated_at,
|
||||||
MIN(d.date) AS earliest_date, MAX(d.date) AS latest_date,
|
MIN(d.date) AS earliest_date, MAX(d.date) AS latest_date,
|
||||||
COUNT(DISTINCT o.id) AS occurrence_count
|
COUNT(DISTINCT o.id) AS occurrence_count
|
||||||
@@ -202,7 +217,7 @@ function market_management_get_market(PDO $pdo, int $marketId, bool $includeArch
|
|||||||
{
|
{
|
||||||
$marketArchivePredicate = $includeArchived ? 'TRUE' : 'm.archived_at IS NULL';
|
$marketArchivePredicate = $includeArchived ? 'TRUE' : 'm.archived_at IS NULL';
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'SELECT m.id, m.name, m.category_id, c.code AS category_code, c.name AS category_name,
|
'SELECT m.id, m.name, m.category_id, m.website_url, c.code AS category_code, c.name AS category_name,
|
||||||
m.archived_at, m.created_at, m.updated_at
|
m.archived_at, m.created_at, m.updated_at
|
||||||
FROM market_definition m
|
FROM market_definition m
|
||||||
INNER JOIN market_category c ON c.id = m.category_id
|
INNER JOIN market_category c ON c.id = m.category_id
|
||||||
@@ -331,6 +346,10 @@ function market_management_update_market(PDO $pdo, int $marketId, array $input):
|
|||||||
$sets[] = 'category_id = :category_id';
|
$sets[] = 'category_id = :category_id';
|
||||||
$params[':category_id'] = $categoryId;
|
$params[':category_id'] = $categoryId;
|
||||||
}
|
}
|
||||||
|
if (array_key_exists('website_url', $input)) {
|
||||||
|
$sets[] = 'website_url = :website_url';
|
||||||
|
$params[':website_url'] = market_management_optional_url($input, 'website_url');
|
||||||
|
}
|
||||||
if ($sets === []) {
|
if ($sets === []) {
|
||||||
throw new InvalidArgumentException('Mindestens ein änderbares Feld ist erforderlich.');
|
throw new InvalidArgumentException('Mindestens ein änderbares Feld ist erforderlich.');
|
||||||
}
|
}
|
||||||
@@ -338,7 +357,7 @@ function market_management_update_market(PDO $pdo, int $marketId, array $input):
|
|||||||
$sets[] = 'updated_at = NOW()';
|
$sets[] = 'updated_at = NOW()';
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'UPDATE market_definition SET ' . implode(', ', $sets) . ' WHERE id = :id
|
'UPDATE market_definition SET ' . implode(', ', $sets) . ' WHERE id = :id
|
||||||
RETURNING id, name, category_id, archived_at, created_at, updated_at'
|
RETURNING id, name, category_id, website_url, archived_at, created_at, updated_at'
|
||||||
);
|
);
|
||||||
$stmt->execute($params);
|
$stmt->execute($params);
|
||||||
$market = $stmt->fetch();
|
$market = $stmt->fetch();
|
||||||
@@ -354,7 +373,7 @@ function market_management_set_market_archive(PDO $pdo, int $marketId, bool $arc
|
|||||||
'UPDATE market_definition
|
'UPDATE market_definition
|
||||||
SET archived_at = ' . ($archive ? 'COALESCE(archived_at, NOW())' : 'NULL') . ', updated_at = NOW()
|
SET archived_at = ' . ($archive ? 'COALESCE(archived_at, NOW())' : 'NULL') . ', updated_at = NOW()
|
||||||
WHERE id = :id
|
WHERE id = :id
|
||||||
RETURNING id, name, category_id, archived_at, created_at, updated_at'
|
RETURNING id, name, category_id, website_url, archived_at, created_at, updated_at'
|
||||||
);
|
);
|
||||||
$stmt->execute([':id' => $marketId]);
|
$stmt->execute([':id' => $marketId]);
|
||||||
$market = $stmt->fetch();
|
$market = $stmt->fetch();
|
||||||
|
|||||||
Reference in new issue
Block a user