Jürgen MummertandClaude Fable 5.1 8aebfcd28d Housekeeping from the code review
Adds wk-sync:purge to remove old files under var/wk-sync (purge() was
never reachable), makes stored file names unique within a second,
excludes widgets from service autowiring, removes unused repository
methods, and adds a planner test covering re-imports with and without
member groups.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-26 18:56:59 +02:00
2026-09-26 18:56:59 +02:00
2026-09-26 18:56:59 +02:00
2026-09-26 18:56:59 +02:00
2026-09-26 18:56:59 +02:00

W&K-Sync Bundle

Verbindet Contao 5.7 mit der Seminarverwaltung W&K (Windows-Software ohne Schnittstelle) über CSV-Dateien:

  1. Import: Die Redaktion exportiert in W&K die Seminarliste als CSV und lädt sie im Contao-Backend hoch. Vor dem Schreiben zeigt eine Vorschau, was sich ändert (neu, geändert, storniert, unverändert, übersprungen, Warnungen). Erst nach Bestätigung werden die Veranstaltungen im Kalender angelegt bzw. aktualisiert.
  2. Online-Anmeldung: Besucher melden sich über ein Formular des Formulargenerators zu einer Veranstaltung an. Das Bundle blendet je nach Veranstaltung Felder ein und aus, prüft Plätze und Anmeldeschluss, speichert die Anmeldung, verschickt die passende Benachrichtigung (Notification Center 2) und leitet auf die Bestätigungsseite weiter.
  3. Posteingang: Anmeldungen und Kontaktanfragen werden in Ordnern bearbeitet (Neu, Download-Liste, Bereits bearbeitet, Ignoriert/Spam, Exportiert).
  4. Export: Die Download-Liste wird als CSV für den W&K-Import erzeugt (ISO-8859-1, Semikolon, feste Spalten), die Datensätze werden als exportiert markiert und die freien Plätze der Veranstaltungen reduziert.
  • Contao 5.7, PHP 8.5, Doctrine DBAL 4, MySQL 8 oder MariaDB
  • Keine Abhängigkeiten außer dem Contao-Core und dem Kalender-Bundle
  • Notification Center 2 wird für Benachrichtigungen empfohlen (Typ „W&K-Anmeldung“), ist aber nicht erforderlich
  • Newsletter-Anmeldung (Double-Opt-in) mit dem Newsletter-Bundle, optional

Installation

composer require mummert/wk-sync-bundle

Das Paket liegt nicht auf Packagist; das Repository in der composer.json des Projekts eintragen:

"repositories": [
    { "type": "vcs", "url": "ssh://git@git.mummert.media:3245/mummert/wk-sync-bundle.git" }
]

Danach die Datenbank aktualisieren:

vendor/bin/contao-console contao:migrate

Einrichtung

  1. Kategorien anlegen – Backend „W&K-Tools → Kategorien“ oder die Standardkategorien des TPI Moritzburg per Befehl:

    vendor/bin/contao-console wk-sync:categories:seed
    

    Jede Kategorie hat eine Art (Schule, Evangelische Schulen, Elementarbereich, Gemeinde, Gottesdienst mit Kindern, Tagungen, Ausbildung, Mentoring, Sonstiges) und die W&K-Bezeichnungen (Werte des Felds kbsgebiet, eine pro Zeile). Beim Import zählen genaue Treffer zuerst (alle Kategorien mit dieser Bezeichnung, z. B. „Alle Schularten“ für Grundschule und weiterführende Schule), sonst der erste Teilstring-Treffer in Sortierreihenfolge. Die erste zugeordnete Kategorie wird Hauptkategorie und steuert die Formularregeln und die Benachrichtigung.

  2. Anmeldeformular anlegen – im Formulargenerator, am einfachsten per Befehl (legt alle Felder mit passenden Namen, Optionen und CSS-Klassen an und trägt es im Kalender ein):

    vendor/bin/contao-console wk-sync:form:create --calendar=1
    

    Die Feldnamen entsprechen den Spalten von tl_wk_booking (gender, firstname, lastname, street, postal, city, email, phone, position, birthday, teacherPosition, schoolName, schoolCity, vegetarian, overnightStay, addDifferentInvoiceAddress, invoice…, addNotes, notes, newsletter, privacyAccepted, agbAccepted). Spamschutz über das ALTCHA-Feld des Contao-Kerns. Das Formular braucht keine Weiterleitungsseite und kein „Daten in Tabelle speichern“ – beides übernimmt das Bundle.

    Der Befehl legt bei jedem Aufruf ein neues Formular an (Alias wk-anmeldung, bei Bedarf nummeriert); bei der Installation passiert nichts automatisch. Ein von Hand gebautes Formular funktioniert genauso, solange die Feldnamen stimmen – welches Formular gilt, entscheidet allein die Auswahl „Anmeldeformular“ in den Einstellungen.

  3. Einstellungen anlegen – Backend „W&K-Tools → Einstellungen → Neu“, ein Eintrag je Kalender:

    • Kalender, in den importiert wird und dessen Veranstaltungen buchbar sind
    • Anmeldeformular, Seite mit dem Anmeldeformular, Bestätigungsseite, Seite mit dem Anfrageformular
    • Anmeldeschluss (Tage vor Beginn, Standard 1) und angezeigter Anmeldeschluss (Standard 31)
    • Eigene Veranstaltungsorte (Standard „TPI Moritzburg“; Orte, die so beginnen, gelten als „im eigenen Haus“)
    • Autor importierter Veranstaltungen, Mitgliedergruppen für Kursleitung und Referenten (leer = keine Mitglieder anlegen, die Namen aus W&K bleiben dann unberücksichtigt)
    • Newsletter-Verteiler und Aktivierungsseite (optional)
    • Benachrichtigungen: Standard sowie je Bedingung 1–12 (siehe unten); die Auswahl zeigt den Titel mit ID. Das Formular erklärt die Bedingungen mit einer Matrix (Art × ein-/mehrtägig); solange keine Benachrichtigung vom Typ „W&K-Anmeldung“ existiert, steht dort ein Hinweis mit Link zum Notification Center.

    wk-sync:form:create --calendar=1 legt den Eintrag bei Bedarf mit an. Am Kalender selbst wird nichts konfiguriert.

    Beim Bearbeiten zeigt die Legende Prüfung der Einrichtung oben im Formular, ob die Verkettung stimmt: Feldnamen des Anmeldeformulars (fehlen Vorname, Nachname oder E-Mail, ist das ein Fehler), Modul „W&K-Anmeldeformular“ auf der Anmeldeseite, Bestätigungsseite, Anfrageformular mit Zieltabelle tl_wk_inquiry, Modul „W&K-Anmeldestatus“ auf der Weiterleitungsseite des Kalenders und mindestens eine zugeordnete Benachrichtigung. Grün, wenn alles passt, rot mit konkreten Hinweisen sonst.

  4. Seiten und Module

    • Seite Kurs (kurs): Modul Event-Reader des Kerns plus Modul W&K-Anmeldestatus (freie Plätze, Anmeldeschluss, Link „Jetzt anmelden“, Hinweis bei externer Anmeldung, geschlossenem Teilnehmerkreis usw.)
    • Seite Anmeldung (kurs/anmeldung): Modul W&K-Anmeldeformular – wird wie der Event-Reader mit dem Alias der Veranstaltung aufgerufen (/kurs/anmeldung/<alias>)
    • Seite Anmeldung eingegangen: Text; der Link enthält ?booking=<Token>, damit Folgeformulare (z. B. Workshop-Auswahl) die Anmeldung kennen (siehe unten)
    • Seite Anfrage: Formular des Formulargenerators mit „Daten in Tabelle speichern“ → tl_wk_inquiry (Feldnamen gender, academicTitle, firstname, lastname, street, postal, city, email, phone, subject, notes, newsletter, privacy). Der Link vom Anmeldestatus hängt ?event=<ID> an; das Bundle trägt die Veranstaltung automatisch ein.
    • Kalender-Module des Kerns (Eventliste, Kalender, Eventmenü) erhalten das Feld W&K-Kategorien, um nur Veranstaltungen bestimmter Kategorien zu zeigen.
  5. Benachrichtigungen (Notification Center 2): Benachrichtigungen vom Typ W&K-Anmeldung anlegen (System → Benachrichtigungen) und unter W&K-Tools → Einstellungen den Bedingungen zuordnen. Ohne zugeordnete Benachrichtigung wird die Anmeldung gespeichert, aber keine Mail verschickt (Warnung im Systemprotokoll). Tokens: ##recipient_email##, ##subscription_*## (alle Felder der Anmeldung, Auswahlfelder zusätzlich als ##subscription_gender_label## usw., Ja/Nein-Felder als ##subscription_vegetarian_label##), ##event_*## (alle Felder der Veranstaltung, Datumsfelder formatiert), ##event_datetime##, ##event_link##, ##event_categories##, ##event_speakers##, ##subscription_event_wk_id##, ##subscription_confirmation_page_url##, ##calendar_*##, ##admin_email##. Die bisherigen Token-Namen event_organizerCity und event_internalEventNumber bleiben erhalten.

  6. Benutzergruppen: Zugriff auf die Module des Bereichs „W&K-Tools“ (Import, Posteingang, Anmeldungen, Kontaktanfragen, Exporte, Kategorien, Einstellungen, Protokoll) freigeben. Anmeldungen werden ausschließlich dort bearbeitet, nicht am Event im Kalender.


Import aus W&K

Backend → W&K-Tools → Import → Datei hochladen. Erwartet wird der Seminarexport aus W&K (Semikolon, Anführungszeichen, Windows-1252 oder UTF-8, mehrzeilige Felder). Wichtig: in W&K das größtmögliche Zeitintervall exportieren – Seminare, die nicht in der Datei stehen, werden storniert und ausgeblendet (nur Veranstaltungen des Kalenders, die eine W&K-Nummer tragen; manuell angelegte Veranstaltungen ohne W&K-Nummer bleiben unberührt).

Regeln beim Import:

W&K Contao Bemerkung
kbnr wkId Muss mit einer führenden Null beginnen, sonst wird der Datensatz übersprungen
kbvsnr wkInternalEventNumber Leer = nicht veröffentlichen (übersprungen); „keine“ wird zu leer
kbtitel, kbutitel, kbrtitel title, wkSubTitle, wkSubTitleAdditional Titel ist Pflicht
kbanreise, kbabreise, kbuanreise, kbuabreise startDate, endDate, startTime, endTime, addTime Datum TT.MM.JJJJ, Uhrzeit HH.MM; wie im Contao-Kern (ganztägig bis 23:59:59)
kbstatus1 wkState 1–5; 5 (Storno) blendet aus. Manuelles Ausblenden bleibt erhalten, bis sich der W&K-Status ändert
kbsgebiet wkCategoryText, wkCategories, wkCategoryPrimary Keine Zuordnung möglich → Storno + Hinweis
kbpmemo, kbzusatz teaser, wkTopics Text wird HTML-sicher in Absätze bzw. Listen (- ) umgewandelt
kbwmemo wkTags Kommagetrennt, dedupliziert
kbkln1, kbmref wkInstructor, wkSpeakers Mitglieder nach Nachname; werden nur angelegt, wenn in den Einstellungen Mitgliedergruppen gesetzt sind (die Vorschau kündigt das an). „N.N.“ wird ignoriert
kbanzmax, kbanztat wkMaxPlaces, wkPlacesLeft Freie Plätze = max − belegt
kbkp1–kbkp6, kbktxp1–kbktxp6 wkPrice1–6, wkPriceType1–6 Dezimalzahlen
kbkd* wkOrganizer* Straße und Landeskennzahl richtig zugeordnet (war vertauscht)
kbkdemail wkOrganizerEmail E-Mail oder URL (Veranstaltungsart 3: Anmeldung beim Veranstalter)
kbvort, kbgruppe, kbvsart, kbztermin location, wkAudience, wkEventType, wkAdditionalDates „geschlossener Teilnehmerkreis“ verhindert die Online-Anmeldung

Das Euro-Zeichen, das W&K als „Ç“ exportiert, wird im Umfeld von Zahlen korrigiert. Aliase werden nur beim Anlegen erzeugt und bleiben danach stabil. Ein erneuter Import derselben Datei meldet alle Seminare als unverändert. Jeder Import wird protokolliert (W&K-Tools → Protokoll); die Datei liegt unter var/wk-sync/imports/. Alte Import- und Exportdateien räumt vendor/bin/contao-console wk-sync:purge --days=90 auf (z. B. per Cronjob); die Protokolleinträge bleiben erhalten.

Auf der Konsole:

vendor/bin/contao-console wk-sync:import files/Import/stva.csv 1            # Vorschau
vendor/bin/contao-console wk-sync:import files/Import/stva.csv 1 --apply    # anwenden

Formularregeln

Welche Felder das Anmeldeformular zeigt, hängt von der Hauptkategorie (Art), dem Veranstaltungsort und der Veranstaltungsnummer ab:

  • Lehrertätigkeit (teacherPosition, schoolName, schoolCity): nur bei den Arten Schule und Evangelische Schulen.
  • Abweichende Rechnungsanschrift: bei Schulkursen nur, wenn „Ich unterrichte an einer Schule in sonstiger Trägerschaft“ gewählt ist; sonst immer.
  • Übernachtung: nur bei mehrtägigen Veranstaltungen. Bei EXTP-Kursen und Elementarkursen im eigenen Haus erscheint stattdessen der Hinweis, dass Übernachtung und Verpflegung direkt im Gästehaus gebucht werden (Erklärungsfeld mit CSS-Klasse wk-slot-no-overnight-stay). Ausnahme: Lehrerkurse außer Haus zeigen das Feld.
  • Vegetarisch: nicht bei Online-Kursen und nicht bei mehrtägigen EXTP-Kursen oder Elementarkursen (außer Tagungen); Lehrerkurse außer Haus zeigen das Feld.
  • Abhängige Felder (Schule, Rechnungsanschrift, Nachricht) werden serverseitig nur validiert und gespeichert, wenn ihr steuerndes Feld sichtbar ist und den passenden Wert hat; ein kleines Skript (bundles/contaowksync/wk-sync.js) blendet sie im Browser ein und aus.

Zusätzlich prüft das Bundle vor dem Anzeigen und noch einmal beim Absenden: veröffentlicht, nicht storniert, kein geschlossener Teilnehmerkreis, keine externe Anmeldung (Veranstaltungsart 3 mit E-Mail/URL), Anmeldeschluss, freie Plätze (W&K-Stand minus offene Anmeldungen, zusätzlich maximale Plätze).

Benachrichtigungs-Bedingungen

Vorrang: Benachrichtigung an der Veranstaltung (Legende „Anmeldung“) → erste erfüllte Bedingung in den Einstellungen → Standard-Benachrichtigung der Einstellungen. Eine zutreffende Bedingung ohne Zuordnung wird übersprungen.

Nr. Bedingung
1 Online-Kurs (Veranstaltungsort „Online“)
2 / 5 Tages- / Mehrtagesveranstaltung, Art Schule, Nummer beginnt mit EXTP
3 / 7 Tages- / Mehrtagesveranstaltung, Art Gemeinde, Gottesdienst mit Kindern oder Tagungen
4 / 6 Tages- / Mehrtagesveranstaltung, Art Elementarbereich
8 / 9 Tages- / Mehrtagesveranstaltung, Art Evangelische Schulen
10 / 11 Tages- / Mehrtagesveranstaltung, Art Mentoring
12 Mehrtägige Ausbildung
– Alles andere (Schule ohne EXTP-Nummer, eintägige Ausbildung, Sonstiges wie AusZEIT) → Standard-Benachrichtigung

Die Bedingungen sind bewusst fest im Code hinterlegt (NotificationRouter), weil sie kundenspezifisch sind; die Einstellungen zeigen sie als Matrix mit Erklärungen an jedem Auswahlfeld. Ohne Notification Center werden Anmeldungen gespeichert, aber keine Mails verschickt (Warnung im Systemprotokoll).

Folgeformulare (z. B. Workshop-Auswahl)

Die Bestätigungsseite wird mit ?booking=<Token> aufgerufen. Formulare des Formulargenerators auf dieser Seite erhalten beim Absenden automatisch die Felder subscription (ID der Anmeldung), subscription_email, subscription_firstname, subscription_lastname, event, event_title und event_wk_id – in Benachrichtigungen als ##form_subscription_email## usw. verwendbar. Eine eigene Bestätigungsseite lässt sich je Veranstaltung hinterlegen.

Posteingang und Export

W&K-Tools → Posteingang. Neue Anmeldungen und Kontaktanfragen werden gesichtet und einzeln oder gesammelt verschoben. Doppelte Anmeldungen (gleiche E-Mail-Adresse, gleiche Veranstaltung) werden markiert. „Bearbeiten“ öffnet den Datensatz unter W&K-Tools → Anmeldungen bzw. W&K-Tools → Kontaktanfragen; dort lassen sich alle Angaben korrigieren (Liste mit Filter nach Veranstaltung und Ordner, Suche nach Name/E-Mail; der Geburtstag wird wie im Formular als TT.MM.JJJJ gespeichert, so wie W&K es erwartet). Beim Löschen einer Veranstaltung werden ihre Anmeldungen mitgelöscht.

Export: In der Download-Liste erzeugt „Download-Liste für W&K exportieren“ die Datei JJJJ-MM-TT_website_kontaktanfragen_wk.csv mit den Spalten KBNR;KNKDAN;KNKDTITEL;KNKDN2;KNKDN1;KNKDSTR;KNKDPLZ;KNKDORT;KNGEBDAT;KDEMAIL;KDTEL1;KDFREI01;KDFREI02;KDFREI03;KDFREI04;KNUKAT;KNVEG;schoolName;schoolCity. Kontaktanfragen stehen ohne Kursnummer in der Datei. Die Datensätze werden als „Exportiert“ markiert, die freien Plätze der Veranstaltungen um die Zahl der Anmeldungen reduziert (bis zum nächsten W&K-Import), und die Datei bleibt unter W&K-Tools → Exporte zum erneuten Download (mehrere Exporte am selben Tag tragen den gleichen Dateinamen, liegen auf dem Server aber mit Zeitstempel getrennt unter var/wk-sync/exports/).

Berechtigungen

Alle Unterpunkte von „W&K-Tools“ sind normale Contao-Backend-Module und werden je Benutzergruppe unter Benutzergruppen → Erlaubte Module freigeschaltet oder ausgeblendet (Gruppe „W&K-Tools“: Import, Posteingang, Anmeldungen, Kontaktanfragen, Exporte, Kategorien, Einstellungen, Protokoll). Was nicht freigeschaltet ist, erscheint nicht in der linken Spalte und ist auch per URL nicht aufrufbar. Wie bei den Tabellen des Contao-Kerns gilt darüber hinaus: Unter Tabellenrechte (Spalten „Anlegen“, „Bearbeiten“, „Löschen“) legt die Gruppe fest, ob sie Datensätze der Tabellen tl_wk_booking, tl_wk_inquiry, tl_wk_category und tl_wk_config anlegen, bearbeiten und löschen darf, und unter Erlaubte Felder sind alle Felder dieser Tabellen sowie die W&K-Felder der Veranstaltungen einzeln freigebbar. Zum Bearbeiten von Anmeldungen braucht eine Gruppe also das Modul „Anmeldungen“, unter Tabellenrechte „Bearbeiten“ für tl_wk_booking und die gewünschten Felder; ein Zugriff auf den Kalender ist nicht nötig (die Anmeldungen hängen bewusst nicht als Untertabelle an den Veranstaltungen). Eine typische Redaktionsgruppe erhält Posteingang, Anmeldungen, Kontaktanfragen und Exporte plus die Felder von tl_wk_booking und tl_wk_inquiry; Import, Kategorien und Einstellungen bleiben der Leitung bzw. Administratoren vorbehalten.

Eigene Templates

  • Frontend-Module: frontend_module/wk_booking_form.html.twig und frontend_module/wk_booking_status.html.twig (Blöcke booking_header, booking_status, booking_form bzw. status, inquiry).
  • Twig-Funktionen für eigene Event-Templates: wk_booking_info(event.id) (Verfügbarkeit, freie Plätze, Anmeldeschluss, Links), wk_event_categories(event) (Kategorien), wk_event_people(event) (Kursleitung, Referenten).

Sicherheit und Robustheit

  • Alle schreibenden Backend-Aktionen laufen über POST mit Request-Token; Ausgaben sind escaped.
  • Upload nur .csv/.txt, Dateien liegen außerhalb des Web-Roots (var/wk-sync/).
  • Import in einer Transaktion; fehlerhafte Zeilen brechen den Import nicht ab, sondern werden gemeldet.
  • Verfügbarkeit wird beim Absenden erneut geprüft (Wettlauf um den letzten Platz).
  • Anmeldungen und Anfragen werden nur mit bekannten Spalten gespeichert.

Entwicklung

composer install
vendor/bin/phpunit

Die Tests decken CSV-Parsing, Zeilen-Zuordnung, Kategorie-Auflösung, Formularregeln, Benachrichtigungs-Routing, Textaufbereitung und den W&K-Export ab.

Backend-Bausteine, die sich auch anderswo nutzen lassen:

  • Widget wk_explanation (inputType) für Erklärtexte in DCA-Formularen; Text aus eval.text oder der Sprachdatei des Feldes, Box über eval.boxClass (tl_info, tl_confirm, tl_error). Contaos eigener Typ explanation existiert nur im Frontend-Formulargenerator.
  • BackendMenuListener hängt das Icon der Navigationsgruppe ein und nimmt die doppelte Escapierung zurück, mit der der Contao-Kern Modulbeschreibungen mit & in Tooltips ausgibt.
S
Description
No description provided
Readme
494 KiB
0 Stars 1 Watchers 0 Forks
Languages
PHP 92.3%
Twig 5.6%
CSS 1.3%
JavaScript 0.8%