3.2 KiB
Executable File
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
nicknameals 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
emailundphonenicht aufUNIQUE(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.
- Warum: Die Felder variieren stark je nach Land (Ausgestellt in, Gültig bis, Behörde). Ein JSONB-Objekt
- 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
Addressund verknüpfen die Person(en) per ID damit. Das spart immense Redundanz.
- Warum: Eine Adresse (Straße, Stadt, Land) kann von 5 Familienmitgliedern oder einer Firma geteilt werden. Wir bauen eine Tabelle
- 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
}