Skip to content

ADR-0039: Field cardinality and required

  • Status: accepted
  • Datum: 2026-09-01
  • Phase: Web Schema-CMS
  • Bezug: ADR-0025, ADR-0037

Kontext

Jedes Feld hat einen Typ; Pflicht (required) lag schon in field_definitions, war in der UI aber unsichtbar und beim Anlegen fest false. Kardinalität fehlte. Nutzer brauchen beides immer — wie Typ und Scope an der Entität. Unbounded n reicht nicht: Fachmodelle setzen oft eine feste Obergrenze (wenige Werte, nie unbegrenzt).

Entscheidung

  1. Jedes Feld hat Kardinalität n (unbegrenzt) oder 1–99 und Pflicht (Ja / Nein). Beide sind Pflichtangaben. Default 1 und nicht Pflicht.
  2. UI: ein Feld mit Eingabe (n oder 1–99) und Pfeil-Auswahl derselben Werte. list-Typen werden auf n gesetzt, bleiben aber auf 1–99 änderbar.
  3. Spalten auf field_definitions (nicht nur config JSON). Legacy one / many wird beim Schreiben auf 1 / n normalisiert.
  4. Validierung: alles außer 1 erwartet ein Array des Feldtyps; eine Zahl begrenzt die Länge; Pflicht lehnt [] ab. field_type=list bleibt das verschachtelte Listen-Modell (Item-Typ/Gruppe), die Kardinalität begrenzt die Item-Anzahl.
  5. Create/Edit-Dialog und Feldliste zeigen Kardinalität und Pflicht immer.
Gate Recommendation Why it fits here Rejected alternative and why
Modell cardinality (n | 199) + required getrennt Entspricht XSD maxOccurs vs minOccurs; Cap 99 hält die Auswahl endlich Ein 4-Wege-Enum 0..1 / 1 / 0..* / 1..* — vermischt Pflicht und Anzahl
Speicher eigene Text-Spalte Immer gesetzt, API/QGIS lesen ohne JSON-Pfad; n bleibt das unbegrenzte Zeichen Nur Integer + Sentinel, oder nur config
list-Typ behalten, Default n Seed-Felder und Nested-Groups bleiben list streichen — Bruch ohne Gewinn

Begründung (für dieses Setup)

GIS-Fachmodelle (INSPIRE/XPlanung) trennen Multiplizität und Pflicht. n deckt unbegrenzte Listen ab; 1–99 ist die feste maxOccurs ohne offenes Integer-Feld. JSONB-attrs speichern alles außer 1 als Array; QGIS liest weiter die Felddefs.

Verworfene Alternativen

Alternative Warum verworfen
Nur Pflicht, Kardinalität implizit über list list ist ein Typ (verschachtelte Gruppe), keine Anzahl
Nur one / many Keine feste Obergrenze (2…99)
Unbegrenztes Integer max_occurs UI und Check ohne Bedarf über 99
Pflicht aus Kardinalität ableiten (1 = Pflicht) Nutzer wollen beide Schalter getrennt

Folgen

  • Alembic 0016_field_cardinality plus 0018_cardinality_n_or_count (Tenant 0004 / 0006).
  • API FieldDefinitionIn/Out.cardinality: n oder "1""99" (schreibt auch legacy one / many).
  • Plugin bleibt apply-only; Formulare lesen die neuen Attribute.
  • Enum/Liste und Auswahllisten: ADR-0042.