Partieller Import
Dieses Dokument erklärt die partielle Importfunktionalität zur Manipulation von Veranstaltungen. Da diese recht mächtig ist und somit auch das Potential besitzt Dinge kaputt zu machen, sollte sie erst benutzt werden, nachdem diese Seite komplett verstanden wurde.
Grundlegende Funktionsweise
Als Orga wünscht man sich manchmal, dass die Datenbank doch Aufgabe X übernehmen könnte (bspw. Management der Warteliste), es aber für diese durchaus programmierbare Arbeit keine Implementation gibt. Für genau diesen Fall gibt es den partiellen Import. Dieser erlaubt es die Datenmanipulation mit einem eigenen Skript durchzuführen und die Änderungen dann in die Datenbank zu importieren.
Der prinzipielle Ablauf ist wie folgt.
Auf der Downloads-Seite lädt man einen partiellen Export herunter, der den aktuellen Stand der Veranstaltung bereitstellt.
Mit einem eigenen Skript erstellt man nun eine JSON Datei, die die gewünschten Änderungen codiert.
Diese wird dann schlussendlich über die Seite “partieller Import” wieder in die Datenbank zurückgespielt. Dies ist ein zweistufiger Prozess, bei dem zuerst die durch den Import verursachten Änderungen ermittelt und zur Überprüfung angezeigt werden und erst im zweiten Schritt nach einer Bestätigung durchgeführt werden.
Dabei können mit dem partiellen Import genau Anmeldungen, Kurse und Unterkünfte manipuliert werden. Dementsprechend können die fundamentalen Attribute einer Veranstaltung wie Anmeldungsbeginn, Veranstaltungsteile, Kursschienen, Datenfelder und Fragebogen nicht bearbeitet werden.
Die Import-Datei
Bei der Import-Datei handelt es sich um eine JSON-Datei, die im gleichen Format ist wie der partielle Export minus einige unveränderliche Felder. Im Wesentlichen enthält der Export die folgenden Elemente:
{
"EVENT_SCHEMA_VERSION": [<numeric id>, <numeric id>],
"id": <numeric event id>,
"kind": "partial",
"timestamp": <ISO 8601 encoded timestamp>,
"summary": <String summarizing your changes>,
"courses": {<numeric course id stringified>:
<dict with course properties>},
"event": {<event attribute>: <associated value>},
"lodgement_groups": {<numeric lodgement group id stringified>:
<dict with lodgement group properties>},
"lodgements": {<numeric lodgement id stringified>:
<dict with lodgement properties>},
"registrations": {<numeric registration id stringified>:
<dict with registration properties>},
}
Dabei gibt EVENT_SCHEMA_VERSION
das verwendete Format an um
Inkonsistenzen zu vermeiden, diese muss mit der aktuellen Version kompatibel
sein (siehe Versionierung) und kann dem
Export entnommen werden. Ebenso wird für das restliche Schema auf den Export
verwiesen.
Der Schlüssel event
, sowie der Schlüssel persona
der in jeder
Anmeldung vorhanden ist, dürfen beim Import nicht vorkommen. Sie stellen
Informationen zur Verfügung, die durch den partiellen Import nicht verändert
werden können.
Prinzipiell sind alle Elemente außer EVENT_SCHEMA_VERSION
, id
kind
und timestamp
optional, können also weggelassen werden. Es ist
sogar explizit empfehlenswert nur die für die gewünschte Änderung nötigen
Informationen einzutragen um nicht in Konflikt mit möglicherweise
gleichzeitig stattfindenden manuellen Änderungen anderer Orgas zu
kommen. Das einzige was sich nicht granular ändern lässt sind die
Kurswünsche, hier ersetzt die übermittelte Liste immer die kompletten
Kurswünsche.
Die Angabe einer summary
ist optional, wird jedoch empfohlen. Sie wird
im Log als Anmerkung zum Logeintrag des Partiellen Imports hinterlegt.
Darüber hinaus erhalten Anmeldungen, die durch den Partiellen Import
bearbeitet wurden, automatisch diese Lognachricht.
Die möglichen Operationen sind wie folgt.
Aktualisierungen: Um einen Wert zu ändern, schreibt man an die gewünschte Stelle den neuen Wert.
Erstellung: Um einen neuen Eintrag anzulegen (bspw. eine neue Unterkunft) wird diese mit einer negativen ID hinzugefügt.
Löschen: Um einen Eintrag zu löschen wird der entsprechenden ID der Wert
null
zugewiesen.
Ein Beispiel mit allen möglichen Operationen findet sich am Ende Beispiel.
Note
Eine Reihe von vorgefertigten Templates existiert im Import-Daten-Repo. Mit diesen ist es bspw. möglich alle Höfe in Kirchheim anzulegen.
Hinweise
Ein server-seitig nur schwer abzufangender Fehler ist, wenn eine Import-Datei, die die Erstellung von Einträgen enthält, mehrfach hochgeladen wird. Dies wird versucht zu detektieren, kann aber nicht mit Sicherheit abgefangen werden.
In allen anderen Fällen sollte das mehrmalige Hochladen weitestgehend harmlos sein.
Die für die Erstellung von Einträgen angegebenen negativen IDs können als Referenzen benutzt werden, z.B. um neu erstellte Unterkünfte direkt mit Bewohnern zu versehen.
Bei der Erstellung von Einträgen müssen die meisten Attribute angegeben werden. Da es hier auch kein Konfliktpotential mit gleichzeitigen Änderungen gibt, empfiehlt es sich einfach alle anzugeben (möglicherweise mit Ausnahme der benutzerdefinierten Felder, da diese immer optional sind).
Außerdem ist es bei der Erstellung einer Anmeldungen erforderlich die zugehörige Person mit dem Attribut
persona_id
anzugeben.Sowohl Export als auch Import verwenden für einige Felder wie das Geschlecht der Teilnehmer oder den Teilnahmestatus Ganzzahlen, um verschiedene Werte darzustellen. Wie diese Ganzzahlen auf die entsprechenden Werte abbilden, ist unter Constants zu finden.
Versionierung
Der Schlüssel EVENT_SCHEMA_VERSION
ist ein Tupel aus zwei
Integern. Diese werden lexikographisch geordnet, es gilt also:
(6, 17) < (7, 14) < (7, 19) < (8, 12) < (13, 5)
wobei größere Tupel für neuere Schemaversionen stehen. Die zweite Komponente wird erhöht, falls eine Änderung vorwärtskompatibel bezüglich des partiellen Exports und Imports ist. Genauer gesagt können dabei die folgenden Schemaveränderungen passieren.
Hinzufügen einer optionalen Spalte (entweder nullbar oder mit Standardwert)
Hinzufügen einer neuen Tabelle
Wesentlicher Fall ist ein externes Werkzeug, das mit Schemaversion (x, y) arbeitet, wobei die DB auf Schemaversion (x, y+z) aktualisiert hat. In diesem Fall kann das Werkzeug einen Export der Version (x, y+z) lesen indem es die neuen Objekte ignoriert. Außerdem wird die DB einen partiellen Import mit Schemaversion (x, y) akzeptieren, da die enthaltenen Änderungen weiterhin gültig sind.
Beispiel
Das folgende Beispiel bearbeitet, löscht und erschafft jeweils einen Eintrag aus jeder der Kategorien Kurs, Unterkunft und Anmeldung. Außerdem wird eine neue Unterkunftsgruppe angelegt. Die verwendeten nutzerdefinierten Felder müssen vorher definiert sein.
{
"kind": "partial",
"summary": "Sehr wichtiger Import",
"courses": {
"1": {
"segments": {
"1": false,
"2": true
},
"instructors": "Die Buddenbroks",
"title": "Ganz Kurzer Kurs",
"min_size": 10,
"fields": {
"room": "Seminarraum 111"
},
"max_size": 20,
"notes": "Planaenderung!",
"shortname": "DieserKurznameIstNunAberWirklichNichtGanzKurz",
"nr": "\u03b2",
"description": "mit extrem hoher Leistung."
},
"3": null,
"2": {
"instructors": "Adams und Heinlein"
},
"5": {
"segments": {
"1": false,
"3": true
}
},
"4": {
"segments": {
"1": null
}
},
"-1": {
"segments": {
"1": false,
"3": true
},
"instructors": "The Flash",
"title": "Blitzkurs",
"min_size": null,
"fields": {
"room": "Wintergarten"
},
"max_size": null,
"notes": null,
"shortname": "Blitz",
"nr": "\u03b6",
"description": "Ein Lichtstrahl traf uns",
"is_visible": true
}
},
"timestamp": "2018-10-21T20:18:43.414427+00:00",
"id": 1,
"lodgement_groups": {
"-1": {
"title": "Geheime Etage"
}
},
"lodgements": {
"3": null,
"2": {
"camping_mat_capacity": 5,
"regular_capacity": 8,
"fields": {
"contamination": "medium"
},
"title": "K\u00fchle Kammer",
"notes": "mit Frischluft (also im Vergleich zum Rest)."
},
"1": {
"fields": {
"contamination": "medium"
}
},
"4": {
"notes": "Wirklich eng.",
"group_id": -1
},
"-1": {
"camping_mat_capacity": 2,
"regular_capacity": 12,
"fields": {
"contamination": "none"
},
"title": "Geheimkabinett",
"notes": "Einfach den unsichtbaren Schildern folgen.",
"group_id": -1
},
"-2": {
"camping_mat_capacity": 0,
"regular_capacity": 42,
"fields": {
"contamination": "low"
},
"title": "Handtuchraum",
"notes": "Hier gibt es Handtücher für jeden.",
"group_id": 2
}
},
"registrations": {
"3": {
"fields": {
"transportation": "pedes"
},
"personalized_fees": {
"10": "-45"
},
"mixed_lodging": false,
"orga_notes": "Wir wurden hinters Licht gefuehrt, alles ist anders",
"parts": {
"3": {
"lodgement_id": 1,
"status": 2,
"is_camping_mat": true
},
"2": {
"lodgement_id": null,
"status": 3,
"is_camping_mat": false
},
"1": {
"lodgement_id": 2,
"status": 2,
"is_camping_mat": false
}
},
"list_consent": false,
"notes": "Reingelegt",
"parental_agreement": true,
"tracks": {
"3": {
"course_id": -1,
"course_instructor": null,
"choices": [
4,
-1,
5
]
},
"2": {
"course_id": null,
"course_instructor": 1,
"choices": [
5,
4
]
},
"1": {
"course_id": 4,
"course_instructor": 4,
"choices": [
5,
1
]
}
}
},
"2": {
"fields": {
"brings_balls": false
},
"parts": {
"3": {
"lodgement_id": 1
},
"2": {
"status": 2
}
},
"tracks": {
"3": {
"course_id": 5
},
"2": {
"choices": [
4,
5
]
}
}
},
"1": {
"orga_notes": "Neueste Geruechte hier einfuegen",
"tracks": {
"1": {
"choices": [
1,
2
]
}
}
},
"5": null,
"6": {
"checkin_periods": [
{
"checkin_time": "2022-02-22T17:00:00+00:00",
"checkout_time": "2022-02-23T09:00:00+00:00"
},
{
"checkin_time": "2022-02-23T09:00:01+00:00",
"checkout_time": "2022-02-23T09:00:02+00:00"
}
]
},
"-1": {
"checkin_periods": [
{
"checkin_time": "2022-02-22T17:00:00+00:00",
"checkout_time": "2022-02-23T09:00:00+00:00"
}
],
"fields": {
"lodge": "egal"
},
"mixed_lodging": true,
"orga_notes": null,
"parts": {
"3": {
"lodgement_id": 1,
"status": 2,
"is_camping_mat": false
},
"2": {
"lodgement_id": -1,
"status": 1,
"is_camping_mat": false
},
"1": {
"lodgement_id": null,
"status": -1,
"is_camping_mat": false
}
},
"list_consent": true,
"persona_id": 3,
"notes": null,
"parental_agreement": true,
"tracks": {
"3": {
"course_id": -1,
"course_instructor": -1,
"choices": [
1,
4,
5,
-1
]
},
"2": {
"course_id": null,
"course_instructor": null,
"choices": [
5,
4
]
},
"1": {
"course_id": null,
"course_instructor": null,
"choices": [
1
]
}
}
}
},
"EVENT_SCHEMA_VERSION": [
19,
0
]
}
Changelog
Hier sind die Änderungen gelistet, die in den jeweiligen Inkrementierungen der Export-Version neu eingeführt wurden. Für jede Version ist angegeben, ob die Version für den partiellen Import strikt abwärtskompatibel sind oder nicht.
Version (19, 0): Ersatz des Checkin-Zeitpunkts durch eine Liste von Checkins und Checkouts
Version (18, 0): Umstellung des Namensmodells von Personen
Version (17, 2): Personalisierte Teilnahmebeiträge sind nun im Export enthalten. Mit dem partiellen Import können personalisierten Beiträge für einzelne Anmeldungen gesetzt werden.
Version (17, 1): Für jede Anmeldung wird nun gespeichert und exportiert, ob der Benutzer zum Zeitpunkt der Anmeldung CdE-Mitglied war.
Version (17, 0): Der bereits bezahlte Betrag und das Zahlungsdatum können jetzt nicht mehr durch den partiellen Import geändert werden, sind aber weiterhin im Export vorhanden.
Version (16, 2): Gespeicherte Suchabfragen verwenden nun ein anderes Schema zur Angabe ihrer Sortierungsschlüssel.
Version (16, 1): Das Isomattenfeld wird jetzt pro Veranstaltungsteil, der Kursraum pro Kursschiene erfasst.
Version (16, 0): Einführung von Conditional Event Fees.
Version (15, 7): Kursschienengruppen sind nun im vollen und partiellen Export enthalten. Beide werden nun beim vollen Import übernommen.
Version (15, 6): Keine Änderungen am partiellen Export.
Version (15, 5): Veranstaltungsteilgruppen sind nun im vollen und im partiellen Export enthalten. Sie können derzeit __nicht__ importiert werden und werden, falls vorhanden, beim Import ignoriert.
Version (15, 4): Der gesamte Fragebogen ist jetzt unter
questionnaire
im partiellen Export enthalten.Version (15, 3): Hinzufügen von
fee_modifiers
pro Part. Alte Versionsnummer entfernt.Version (15, 2): Hinzufügen des Feldes
participant_info
für die Teilnehmer-Infos.Version (15, 1): Umbenennung von
courses_in_participant_list
zuis_course_assignment_visible
.Version (14, 1): Umbenennung von
moniker
. Infolge dessen wurden zwei Spalten desevent
-Schemas umbenannt.Version (13, 2): Hinzufügen einer Feldreferenz pro Part, in dem ein Datenfeld zum Verwalten einer Warteliste hinterlegt werden kann.
Version (13, 1): Umstellung von CDEDB_EXPORT_EVENT_VERSION auf EVENT_SCHEMA_VERSION.
Version 12: Umbenennen von
reserve
zucamping_mat
. Infolge dessen wurden drei Spalten desevent
Schemas umbenannt.Version 11: Für Anmeldungen wird gespeichert, wie viel ein Teilnehmer bezahlen soll. Der Fragebogen wurde aufgeteilt in einen Anmeldungs-Teil, der direkt bei der eigentlichen Anmeldung abgefragt wird und einen zusätzlichen Teil, der dem bisherigen Fragebogen entspricht. Für Veranstaltungsteile können nun Beitragsmodifikatoren angelegt werden.
Version 10 (abwärtskompatibel): Es wird ein Flag
is_cancelled
je Event eingeführt, mit dem die Absage von Veranstaltungen gekennzeichnet werden kann.Version 9 (abwärtskompatibel): Es wird eine Dezimalzahl
additional_external_fee
je Event eingeführt, die den Zusatzbeitrag für Externe ergänzt.Version 8: Es wird eine Dezimalzahl
amount_paid
eingeführt, die dokumentiert, wie groß der bereits bezahlte Beitrag ist.Version 7: Die Semantik der Kursgrößen wird dahingehend angepasst, dass die Kursleiter nicht mehr in die Kursgrößen mit einbezogen werden.
Version 6: …