Schnittstellen

Manueller Adressimport (CSV)

Einfuehrung

Dieses Dokument beschreibt die manuelle Adressimportschnittstelle. Im Gegensatz zu den kVASy Varianten ist sie nicht auf eine spezifische Quellsystem-Spaltenbelegung festgelegt: die Anwender:innen entscheiden selbst, welche Adressattribute sie pflegen wollen, und liefern eine CSV-Datei deren Spaltenkoepfe zu den unterstuetzten Adressattributen passen.

Die Schnittstelle aktualisiert vorhandene Adressen oder legt neue Adressen an. Die Auswahl wird ueber einen strikt priorisierten Update-Schluessel gesteuert; ein Boolescher Hilfsschluessel _create entscheidet, ob bei nicht gefundenem Update-Schluessel eine neue Adresse erzeugt wird.

Zugriff

Die Import Job Definition wird beim Setup automatisch angelegt:

  1. Navigieren Sie zu Schnittstellen → Import-Job-Definition.
  2. Waehlen Sie den Eintrag "Manueller Adressimport".
  3. Laden Sie eine CSV-Datei hoch und nutzen Sie wahlweise Probelauf (Dry-Run) oder Importieren.

Update-Schluessel

Pro Zeile wird genau einer der folgenden Schluessel verwendet, in dieser Reihenfolge:

  1. id
  2. pit_number
  3. hostsystem_reference
  4. pit_number2

Der erste nicht leere Schluessel der Zeile gewinnt — auch wenn weitere Schluesselspalten gefuellt sind.

Verhalten bei nicht gefundenem Update-Schluessel

_createVerhalten
nicht gesetzt oder falseDie Zeile schlaegt mit dem passenden Fehler fehl: ID_UNKNOWN, PIT_NUMBER_UNKNOWN, HOSTSYSTEM_REFERENCE_UNKNOWN oder PIT_NUMBER2_UNKNOWN.
true und Schluessel ist idDie Zeile schlaegt mit ID_UNKNOWN fehl — eine bestehende Datenbank-id darf vom Import nicht erzwungen werden.
true und Schluessel ist pit_number / hostsystem_reference / pit_number2Eine neue Adresse wird angelegt; der Update-Schlusselwert wird auf das gleichnamige Adressattribut geschrieben.

Fehlt jeder Update-Schluessel in einer Zeile, wird der Fehler NO_UPDATE_KEY gemeldet.

Treffen mehrere Adressen auf den Update-Schluessel zu, wird der Fehler UPDATE_KEY_NOT_UNIQUE gemeldet.

Spaltenliste

Der Spaltenkopf der CSV-Datei steuert die Zuordnung der Werte zu Adressattributen. Spaltenkoepfe ausserhalb der folgenden Allowlist fuehren zu unknown_column und dem Abbruch des gesamten Imports — bevor irgendwelche Aenderungen wirksam werden.

Update-Schluessel und Hilfsfelder

SpalteTypBeschreibung
idIntegerUpdate-Schluessel (hoechste Prioritaet). Niemals als Wert ins Adressattribut geschrieben.
pit_numberTextUpdate-Schluessel und Adressattribut.
hostsystem_referenceTextUpdate-Schluessel und Adressattribut.
pit_number2TextUpdate-Schluessel und Adressattribut.
_createBooleanSteuert das Anlegen bei fehlender Adresse (siehe oben). Wird nicht in die Datenbank geschrieben.

Direkte Adressattribute

SpalteTyp
name, name2, firstname, lastnameText
street, street_ext, street2, zip, postbox, city, districtText
email, phone, mobilephone, fax, webpageText
comment, identText
archivedTimestamp mit Zeitzone (ISO-8601, z. B. 2026-04-28T10:00:00+02:00)
last_drainage_date, drainage_clearance_valid_untilDatum (locale-abhaengig oder ISO yyyy-MM-dd)
socket_availableBoolean
correspondence_typeAufzaehlung: post, email, sms
tags, parcelQuoted, kommagetrennte Liste, z. B. "foo,bar" bzw. "Flur 12/3, Flur 14"
number_of_inhabitants, pit_volume, last_drainage_volume, volume_factor, effective_hose_length, max_drainage_volume, max_cross_vehicle_weight, max_axle_loadDezimalzahl (locale-abhaengig)

Fremdschluessel-Spalten

Fremdschluessel werden ueber den natuerlichen Identifikator des Zielobjekts referenziert. Trifft der Wert keine bzw. mehrere Datensaetze, schlaegt die Zeile mit FK_REFERENCE_UNKNOWN bzw. FK_REFERENCE_NOT_UNIQUE fehl.

SpalteAufgeloest gegenAdressattribut
country_id/alpha2country.alpha_2country_id
country_id/alpha3country.alpha_3country_id
country_id/identcountry.identcountry_id
address_segment/identaddress_segment.identaddress_segment_id
type_of_pit/identtype_of_pit.identtype_of_pit_id
owner_client_id/identclient.identowner_client_id
tour_id/identtour.identtour_id
correspondence_address_id/idaddress.idcorrespondence_address_id
correspondence_address_id/hostsystem_referenceaddress.hostsystem_referencecorrespondence_address_id
billing_address_id/idaddress.idbilling_address_id

Liefern mehrere Spalten der gleichen Gruppe einen Wert (z. B. sowohl country_id/alpha2 als auch country_id/ident), gewinnt die Spalte mit der hoeheren Prioritaet, also die in der Tabelle weiter oben stehende.

Wertinterpretation

Die Interpretation richtet sich nach dem Feld locale der Import-Job-Definition (Default de-DE).

  • Wahrheitswerte sind unabhaengig von Gross-/Kleinschreibung. Akzeptiert werden true/false, yes/no, ja/nein, wahr/falsch, sowie 1 (wahr) und 0 (falsch).
  • Zahlen verwenden das locale-typische Dezimaltrennzeichen — z. B. Komma fuer de-DE. Fuer en-US wird der Punkt erwartet.
  • Datumswerte koennen im locale-typischen Format mit vierstelligem Jahr (z. B. 28.04.2026 fuer de-DE), im locale-typischen Kurzformat mit zweistelligem Jahr (28.04.26 fuer de-DE) oder als ISO yyyy-MM-dd geliefert werden.
  • Zeitstempel mit Zeitzone sind als ISO 8601 mit Offset zu liefern, z. B. 2026-04-28T10:00:00+02:00.
  • Tags und Flurstueck (tags, parcel) kommen als ein einziger CSV-Wert: gewuenschte Eintraege werden mit Komma getrennt, das gesamte Feld wird in Anfuehrungszeichen eingeschlossen, also "foo,bar" bzw. "Flur 12/3, Flur 14". Leere Eintraege werden ignoriert.

Leere Zellen bedeuten „nicht gesetzt": Beim Update wird das vorhandene Datenbankattribut nicht veraendert; beim Anlegen wird das Attribut nicht gesetzt.

Zwei-Phasen-Verarbeitung

Der Import laeuft in zwei Phasen, um Datenbank-Effekte erst bei vollstaendig gueltiger Eingabe wirksam werden zu lassen:

  1. Pruefung (check-data): Es werden alle Zellen aller Zeilen typgerecht geparst und Fremdschluessel aufgeloest. Schon eine einzige fehlerhafte Zelle laesst den Import scheitern.
  2. Verarbeitung (process-data): Erst nachdem Phase 1 vollstaendig erfolgreich war, werden die Update-/Insert-Operationen auf der Datenbank ausgefuehrt.

Der Probelauf ueber /v1/import_job/dry-run/<id> liefert die gleiche normalisierte Datenstruktur, die anschliessend bei einem echten Import verarbeitet werden wuerde — inklusive aufgeloester Fremdschluessel, geparster Datums- und Dezimalwerte sowie der gewaehlten Update-Schluessel pro Zeile. Damit lassen sich Probleme zuverlaessig vor dem eigentlichen Import erkennen.

Fehlercodes

Alle Fehlercodes sind im I18n-Katalog hinterlegt und werden mit Platzhaltern fuer Werte ausgegeben:

CodeBedeutung
unknown_columnSpaltenkopf liegt nicht in der Allowlist (siehe Spaltenliste).
NO_UPDATE_KEYZeile enthaelt keinen Update-Schluessel.
UPDATE_KEY_NOT_UNIQUEUpdate-Schluessel verweist auf mehrere Adressen.
ID_UNKNOWNAdresse mit der angegebenen id existiert nicht.
PIT_NUMBER_UNKNOWNAdresse mit dem angegebenen pit_number existiert nicht und _create ist false.
HOSTSYSTEM_REFERENCE_UNKNOWNAdresse mit dem angegebenen hostsystem_reference existiert nicht und _create ist false.
PIT_NUMBER2_UNKNOWNAdresse mit dem angegebenen pit_number2 existiert nicht und _create ist false.
FK_REFERENCE_UNKNOWNFremdschluesselwert konnte nicht aufgeloest werden.
FK_REFERENCE_NOT_UNIQUEFremdschluesselwert ist nicht eindeutig (mehrere Treffer).
CELL_PARSE_FAILEDWert konnte nicht in den erwarteten Datentyp umgewandelt werden.
STANDING_ORDER_DEFINITION_INCOMPLETEDauerauftrag kann nicht angelegt werden: standing_order_definition/job_type_id/ident und standing_order_definition/cycle_weeks muessen beide angegeben werden.
RECURRING_DRAINAGE_DEFINITION_INCOMPLETERegelentsorgung kann nicht angelegt werden: recurring_drainage_definition/job_type_id/ident und recurring_drainage_definition/cycle_months muessen beide angegeben werden.

Regelentsorgung (recurring_drainage_definition)

Zusaetzlich zu den Adressspalten unterstuetzt der Import fuenf ephemere Spalten, die pro Zeile eine Regelentsorgung (recurring_drainage_definition) fuer die betroffene Adresse anlegen oder aktualisieren. Diese Spalten werden nie auf address persistiert und funktionieren auch, wenn die Adresse selbst in derselben Zeile per _create=true neu angelegt wird.

SpalteTypBedeutung
recurring_drainage_definition/job_type_id/identFremdschluesselAuftragsart, aufgeloest ueber job_type.ident
recurring_drainage_definition/cycle_monthsGanzzahlZyklus in Monaten
recurring_drainage_definition/active_monthsEnum-ListeKomma-separierte Monate, z. B. "MAR, JUN, SEP, DEC" – gueltige Werte: JAN … DEC
recurring_drainage_definition/activeBooleanAktiv-Flag (Standard bei Neuanlage: true, wenn nicht gesetzt)
recurring_drainage_definition/waste_material_id/identFremdschluesselAbfallart / Artikel, aufgeloest ueber article.ident

Verhalten bei vorhandener Regelentsorgung: Existiert fuer die Adresse bereits ein recurring_drainage_definition mit demselben job_type_id (Unique-Schluessel (address_id, job_type_id)), wird dieser Datensatz mit den nicht leeren ephemeren Feldern dieser Zeile aktualisiert; leere Zellen ueberschreiben nichts. job_type_id/ident identifiziert den Datensatz und kann nicht auf einen anderen Auftragstyp umgehaengt werden.

Verhalten ohne vorhandene Regelentsorgung: Eine neue, aktive Regelentsorgung wird nur angelegt, wenn in der Zeile sowohl recurring_drainage_definition/job_type_id/ident als auch recurring_drainage_definition/cycle_months nicht leer sind. Fehlt eines der beiden, meldet der Import RECURRING_DRAINAGE_DEFINITION_INCOMPLETE:

  • Bei einer per _create=true neu angelegten Adresse schlaegt der gesamte Importjob fehl, bevor irgendein Datensatz geschrieben wird.
  • Bei einer bestehenden Adresse ohne passende Regelentsorgung schlaegt nur diese Zeile fehl; etwaige andere Adressaenderungen dieser Zeile bleiben dabei bestehen (kein Zeilen-Rollback). Ein erneuter Import mit korrigierten Werten ist gefahrlos moeglich.

Ein unbekannter job_type_id/ident- oder waste_material_id/ident-Wert meldet FK_REFERENCE_UNKNOWN bzw. FK_REFERENCE_NOT_UNIQUE; ein ungueltiger active_months-Wert meldet CELL_PARSE_FAILED.

Beispiele

Die folgenden Beispiele entstammen dem ausfuehrbaren Beispielsatz im Repo werner unter integration-tests/userdata/address/. Die dortige README.md katalogisiert alle Faelle inklusive Fehlerpfaden und schlaegt eine manuelle Testreihenfolge vor.

Minimaler Insert

Kleinste sinnvolle Eingabe: zwei neue Adressen, identifiziert ueber pit_number. Spalten, die nicht im Header stehen, werden bei einem spaeteren Update nicht angefasst -- sie bleiben in der Datenbank erhalten.

Quelle: integration-tests/userdata/address/01_minimal_create.csv.

_create,pit_number,name,city
true,DEMO-MIN-001,Mustermann GmbH,Berlin
true,DEMO-MIN-002,Musterfrau OHG,Hamburg

Vollstaendiger Insert mit deutscher Locale

Demonstriert das volle Spektrum der Wertinterpretation: Dezimalzahlen mit Komma muessen wegen des CSV-Trenners in Anfuehrungszeichen stehen ("12,5"), tags und parcel werden als ein in Anfuehrungszeichen eingeschlossener Wert mit kommagetrennten Eintraegen geliefert ("vip,abrechnung-q2" bzw. "Flur 12/3, Flur 14"), socket_available akzeptiert 1/0, correspondence_type ist eine Aufzaehlung, und country_id/alpha2 loest gegen country.alpha_2 auf.

Quelle: integration-tests/userdata/address/02_full_create_de_locale.csv.

_create,pit_number,name,name2,firstname,lastname,street,street_ext,zip,city,email,phone,number_of_inhabitants,pit_volume,volume_factor,socket_available,last_drainage_date,correspondence_type,tags,parcel,country_id/alpha2
true,DEMO-FULL-001,Beispiel KG,Zentrale,Erika,Mustermann,Musterstraße 12,WHG 4,10115,Berlin,[email protected],+49 30 1234567,4,"12,5","2,5",1,2026-04-15,email,"vip,abrechnung-q2","Flur 12/3, Flur 14",DE
true,DEMO-FULL-002,Beispiel AG,,Max,Mustermann,Hauptstraße 7,,20095,Hamburg,[email protected],+49 40 7654321,2,"8,1","1,0",0,2026-03-30,post,"intern",,DE

Reines Update ueber pit_number

_create=false zwingt den Import in den Aktualisierungspfad: Treffer per pit_number werden aktualisiert, fehlt der Eintrag in der Datenbank, faellt die Zeile mit PIT_NUMBER_UNKNOWN durch.

Quelle: integration-tests/userdata/address/03_update_by_pit_number.csv.

_create,pit_number,phone,email
false,DEMO-MIN-001,+49 30 9999999,[email protected]
false,DEMO-MIN-002,+49 40 8888888,[email protected]

Fehlerpfad: unbekannter Update-Schluessel ohne _create

Kanonischer Fall fuer das Fehler-Detail-Reporting: _create=false und ein pit_number, den es in der Datenbank nicht gibt. Der Import erzeugt fuer diese Zeile einen Eintrag in error_details mit error-code = PIT_NUMBER_UNKNOWN; alle anderen, gueltigen Zeilen des selben Imports werden trotzdem ausgefuehrt.

Quelle: integration-tests/userdata/address/06_unknown_pit_no_create.csv.

_create,pit_number,name
false,DEMO-NICHT-VORHANDEN-001,Sollte PIT_NUMBER_UNKNOWN ausloesen

Vollstaendiger Beispielsatz

Der vollstaendige, ausfuehrbare Beispielsatz inklusive der weiteren Faelle -- unknown_column, FK_REFERENCE_UNKNOWN, NO_UPDATE_KEY, locale-Varianten fuer Booleans und Dezimalzahlen, partielles Update und Update-Schluessel-Prioritaet (id vor hostsystem_reference) -- liegt zusammen mit einer ausfuehrlichen README.md unter integration-tests/userdata/address/ im Repo werner.

Previous
Import Adressen aus kVASy Tourenplanung V2