diff --git a/development-system/README.md b/development-system/README.md
index 47b0c23..001bba1 100644
--- a/development-system/README.md
+++ b/development-system/README.md
@@ -105,13 +105,12 @@ sowie klar erkennbare Demo-Termine. Die API prüft Kapazitäten innerhalb einer
Transaktion und sperrt den Termin dabei mit `SELECT … FOR UPDATE`; parallele
Anmeldungen können dadurch die Kapazität nicht überschreiten.
-Die Demo speichert eine Anfrage zunächst als `pending_confirmation`. Sie
-erstellt einen zeitlich begrenzten Bestätigungslink, bestätigt danach atomar
-gegen die verfügbare Kapazität und erzeugt eine zweite Bestätigungsnachricht.
-Bestätigungs- und Erinnerungsnachrichten liegen standardmäßig im lokalen
-Mailausgang der Testverwaltung. Mit `BOOKING_MAIL_TRANSPORT=mail` versucht der
-Job den Versand über die PHP-Funktion `mail()`; SMTP-Konfiguration und echter
-Mailbetrieb gehören erst in die Produktiventscheidung.
+Die Demo speichert eine Anfrage zunächst als `pending_confirmation` und
+übergibt die Bestätigungsnachricht direkt an das Server-Sendmail. Der Link ist
+30 Minuten gültig; sein Aufruf bestätigt die Teilnahme atomar und löst die
+zweite Nachricht mit ICS-Anhang aus. Ohne Cronjob werden keine Erinnerungen
+verschickt. Lokal ist der Mailtransport bewusst mit
+`BOOKING_MAIL_TRANSPORT=disabled` deaktiviert.
Der Browser erhält ein CSRF-Token per gleicher Sitzung; die API validiert alle
Pflichtdaten serverseitig und begrenzt Anmeldungen pro Sitzung. Dies ist eine
@@ -174,10 +173,8 @@ Die Testverwaltung läuft unabhängig von Contao unter
- Termin anlegen, bearbeiten sowie aktivieren/deaktivieren,
- Übersicht und Entfernen von Teilnahmen,
-- lokaler Mailausgang mit kopierbarem Bestätigungslink,
- Anzeige bestätigter Teilnahmen nach frei wählbarem Zeitraum,
-- abonnierbaren ICS-Feed je Projekt,
-- manuellen Lauf der Ablauf- und Erinnerungsjobs.
+- abonnierbaren ICS-Feed je Projekt.
Der Verwaltungsbereich hat absichtlich keine Benutzerverwaltung
und darf nicht unverändert außerhalb der Testumgebung bereitgestellt werden.
diff --git a/development-system/database/README.md b/development-system/database/README.md
index 2fa01d9..b20523b 100644
--- a/development-system/database/README.md
+++ b/development-system/database/README.md
@@ -54,9 +54,9 @@ MariaDB-/MySQL-Client ausgeführt. Zugangsdaten gehören dabei in die
Betriebskonfiguration und niemals in die SQL-Datei oder das Repository. Die
erste Migration erstellt `sufw_booking_events` und
`sufw_booking_registrations` sowie neun ungefährliche Demo-Termine für beide
-Instanzen. `002_booking_workflow.sql` ergänzt Bestätigungstoken, lokalen
-Mailausgang und pro Projekt einen beim Import zufällig erzeugten,
-widerrufbaren ICS-Feed-Token. `003_booking_demo_data.sql` legt zusätzlich
+Instanzen. `002_booking_workflow.sql` ergänzt Bestätigungstoken, den später
+entfernten Test-Mailausgang und pro Projekt einen beim Import zufällig
+erzeugten, widerrufbaren ICS-Feed-Token. `003_booking_demo_data.sql` legt zusätzlich
bestätigte Demo-Teilnahmen an und hält Beispieltermine jeweils einen Monat in
der Vergangenheit und Zukunft. Diese letzte Datei ist ausschließlich für die
lokale Entwicklungs- und Testdatenbank bestimmt und darf nicht auf dem
@@ -65,3 +65,6 @@ die Telefonnummer der Ansprechperson und ersetzt die Kontakte der stabilen
Demo-Termine durch Carina Hollederer und Sarah van den Heuvel.
`005_booking_demo_july_august.sql` ergänzt ausschließlich lokal weitere
bestätigte Demo-Termine und -Teilnahmen für Juli und August.
+`006_remove_booking_outbox.sql` entfernt den nicht mehr verwendeten
+Test-Mailausgang; Buchungsnachrichten werden direkt an das Server-Sendmail
+übergeben.
diff --git a/development-system/database/migrations/006_remove_booking_outbox.sql b/development-system/database/migrations/006_remove_booking_outbox.sql
new file mode 100644
index 0000000..e86915f
--- /dev/null
+++ b/development-system/database/migrations/006_remove_booking_outbox.sql
@@ -0,0 +1,6 @@
+-- SUFW Terminbuchung: Der Test-Mailausgang wird durch direkten Sendmail-Versand ersetzt.
+-- Diese Migration entfernt ausschließlich die nicht mehr verwendete Outbox-Tabelle.
+
+DROP TABLE IF EXISTS `sufw_booking_outbox`;
+
+INSERT IGNORE INTO `sufw_booking_schema_migrations` (`version`) VALUES ('006_remove_booking_outbox');
diff --git a/development-system/docker-compose.yml b/development-system/docker-compose.yml
index 59e401f..2d91bbd 100644
--- a/development-system/docker-compose.yml
+++ b/development-system/docker-compose.yml
@@ -10,7 +10,7 @@ services:
CONTAO_ENVIRONMENT: dev
DATABASE_URL: mysql://perspektivwerk:perspektivwerk@db:3306/perspektivwerk?serverVersion=mariadb-10.11.0
BOOKING_BASE_URL: http://localhost:8080/perspektivwerk
- BOOKING_MAIL_TRANSPORT: database
+ BOOKING_MAIL_TRANSPORT: disabled
command:
- sh
- -c
diff --git a/development-system/public/perspektivwerk/booking-admin/index.php b/development-system/public/perspektivwerk/booking-admin/index.php
index 074ede5..c667a2b 100644
--- a/development-system/public/perspektivwerk/booking-admin/index.php
+++ b/development-system/public/perspektivwerk/booking-admin/index.php
@@ -68,10 +68,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$database->prepare("UPDATE sufw_booking_registrations SET status = 'removed', removed_at = UTC_TIMESTAMP() WHERE id = :id AND status IN ('pending_confirmation', 'confirmed')")->execute(['id' => $_POST['id'] ?? '']);
adminBack($project, 'registrations', 'Teilnahme entfernt; die Kapazität ist wieder frei.');
}
- if ($action === 'run_jobs') {
- $result = bookingRunJobs($database);
- adminBack($project, $view, "Jobs ausgeführt: {$result['expired']} abgelaufen, {$result['remindersConsidered']} Erinnerungen geprüft.");
- }
}
$titles = $database->prepare('SELECT DISTINCT title FROM sufw_booking_events WHERE project = :project ORDER BY title');
@@ -101,12 +97,6 @@ if ($view === 'registrations') {
$statement->execute(['project' => $project]);
$registrations = $statement->fetchAll();
}
-$outbox = [];
-if ($view === 'events') {
- $statement = $database->prepare("SELECT o.*, r.name FROM sufw_booking_outbox o JOIN sufw_booking_registrations r ON r.id = o.registration_id JOIN sufw_booking_events e ON e.id = r.event_id WHERE e.project = :project ORDER BY o.created_at DESC LIMIT 20");
- $statement->execute(['project' => $project]);
- $outbox = $statement->fetchAll();
-}
$nextMonth = new DateTimeImmutable('first day of next month');
$defaultFrom = $nextMonth->format('Y-m-01');
$defaultTo = $nextMonth->format('Y-m-t');
@@ -116,7 +106,7 @@ $defaultTo = $nextMonth->format('Y-m-t');