Files
RoggioApp/Brainstorm/260426/13_Personen_Feld_Analyse.md
T
2026-04-26 19:42:42 +02:00

3.2 KiB
Executable File

RoggioApp - Analyse: Die Person-Entität (Hard vs. Flexible)

Die Herausforderung

Was gehört zwingend als harte, durchsuchbare SQL-Spalte in die Tabelle Person, und was lagern wir als flexible Eigenschaft (Trait) in das JSONB-Feld oder in Relationen aus?

Sevs Entwurf & Claras Analyse

1. Originär (Die Person selbst)

  • Vorname & Nachname: Absolut notwendig. Harte SQL-Spalten. (Ggf. um nickname als Spalte erweitern).
  • Geburtsdatum: Harte Spalte (für Altersberechnungen, Kurtaxe, Meldescheine extrem wichtig).
  • Mobile-Nr & Private E-Mail: ⚠️ Diskussion: Sind die eindeutig?
    • Realität: Oft buchen Ehepaare oder Familien mit nur einer gemeinsamen Mailadresse oder Handynummer.
    • Lösung: Wir dürfen email und phone nicht auf UNIQUE (Einzigartig) in der Datenbank setzen! Sie bleiben harte SQL-Spalten für die schnelle Suche, aber Doppelungen sind erlaubt.

2. Relational / Flexibel (Die Eigenschaften)

  • Anrede (Pronouns / Title): -> JSONB (traits). (Ändert sich gesellschaftlich, JSONB ist hier flexibler als ein harter SQL-Enum).
  • Identity-Dokument (Perso/Passport): -> JSONB (traits).
    • Warum: Die Felder variieren stark je nach Land (Ausgestellt in, Gültig bis, Behörde). Ein JSONB-Objekt identity_document: { type: "passport", number: "...", valid_until: "..." } ist hier perfekt.
  • Geburtsort: -> JSONB (traits).
  • Adresse (Wohnort): -> ⚠️ Eigene Tabelle!
    • Warum: Eine Adresse (Straße, Stadt, Land) kann von 5 Familienmitgliedern oder einer Firma geteilt werden. Wir bauen eine Tabelle Address und verknüpfen die Person(en) per ID damit. Das spart immense Redundanz.
  • Finanz-Infos (IBAN etc.): -> JSONB (traits).

3. Logisch durch den Graphen gelöst (Architektur-Bonus)

  • Buchungsverlauf: Wird nicht in der Person gespeichert. Ergibt sich zu 100% aus den Event-Knoten, die mit der Person (oder ihrer Gruppe) verknüpft sind.
  • Loginrights: Werden nicht gespeichert. Das übernimmt die Nextcloud (SSO). Wir speichern nur die ssoId.
  • Type (Kollektiv / Client / Personal): Wird nicht als hartes Feld gespeichert! Ergibt sich aus den GroupMembership-Verknüpfungen (z.B. wenn Person A Mitglied in der Operator-Gruppe ist, ist sie Personal).
  • Groups & Groupfunction: Wird 1:1 durch unsere Pivot-Tabelle GroupMembership (inkl. role) abgebildet.

Claras Vorschlag für die finale Prisma-Tabelle Person

model Person {
  id          String    @id @default(uuid())
  firstName   String    @db.VarChar(100)
  lastName    String    @db.VarChar(100)
  nickname    String?   @db.VarChar(100)
  birthDate   DateTime? @db.Date
  
  // Kontaktdaten (NICHT UNIQUE!)
  email       String?   @db.VarChar(255)
  phone       String?   @db.VarChar(50)

  // Verknüpfung zur Authentifizierung
  ssoId       String?   @unique @db.VarChar(255)

  // Die Wohnadresse (Relational)
  addressId   String?
  address     Address?  @relation(fields: [addressId], references: [id])

  // Alles andere (Pass, Finanzen, Anrede, Geburtsort, Allergien)
  traits      Json      @default("{}")

  groupMemberships GroupMembership[]

  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
}