UC-Kunden – Vorentscheide (vor Spezifikation)¶
Status: Vorentscheide gesammelt — fliessen in UC-Kunden-Spezifikation ein
Stand: April 2026 | Version: 0.2 (Schema-Vorbereitung V1 ergänzt)
Autor: David
V1 – Datenmodell-Entscheide¶
KE1: Kunde = Person (Szenario A)¶
- In V1 ist ein Kunde immer eine einzelne natürliche Person
- Keine Organisationsstruktur in V1
- Passt zum primären Anwendungsfall: Eigentümer von Tauchgeräten (Flaschen, Regler)
KE2: V2-Vorbereitung — Kunde optional einer Organisation zuordnen (Szenario C)¶
- Das
customers-Schema in V1 enthält bereits ein nullableorganization_id-Feld (FK →organizations) - In V1 bleibt dieses Feld immer NULL — kein UI, keine Logik
- In V2 wird die
organizations-Tabelle hinzugefügt und das Feld befüllt - Kein Breaking Change, keine Migration bestehender Daten erforderlich
KE3: Aufträge gehören immer zur Person¶
orders.customer_idzeigt immer auf die Person (nie direkt auf eine Organisation)- Bestehende Aufträge bleiben bei Zuordnung einer Person zu einer Organisation unverändert
- Die Organisation ist technisch nur ein Gruppierungsmerkmal
KE4: Rechnungsstellung flexibel auf Auftragsebene (V2)¶
- Neues Feld
orders.bill_tomit Wertencustomer|organization - Standard bei neuem Auftrag:
customer(Rechnungsstellung an Person) - Wenn Person einer Organisation zugeordnet ist: wählbar → Person oder Organisation
- Anwendungsfall: Firmenmitarbeiter lässt Flasche prüfen, Rechnung geht an Firma
Offene Fragen für UC-Kunden-Spezifikation¶
| ID | Frage | Priorität |
|---|---|---|
| KOF1 | Welche Pflichtfelder hat ein Kunde in V1? (Name, E-Mail, Telefon, Adresse?) | Hoch |
| KOF2 | Kann ein Kunde mehrere Geräte besitzen? (1:n Kunde → Ausrüstung) | Hoch |
| KOF3 | Wie wird ein Kunde mit einem Auftrag verknüpft? | Hoch |
| KOF4 | Gibt es eine Kundennummer / externe Referenz? | Mittel |
| KOF5 | Mitarbeiter-Einladungsmodell: Mitarbeiter werden via Einladungslink hinzugefügt (analog UC00 Modell C1) — in UC-Mitarbeiter definieren | Mittel |
Hinweis Mitarbeiter-Einladungsmodell¶
Entscheid aus UC00-Diskussion (April 2026):
Mitarbeiter werden via Einladungslink hinzugefügt — analog UC00 Modell C1.
Sie registrieren sich selbst, setzen ihr Passwort und richten 2FA ein.
Danach sind sie aktive Systembenutzer mit Login.
→ Details in UC-Mitarbeiter-Spezifikation festhalten.
Schema-Vorbereitung V1¶
Das
organization_id-Feld muss beim Anlegen dercustomers-Tabelle
(Schritt 3 – Datenmodell UC-Kunden) von Anfang an enthalten sein.
Dieorganizations-Tabelle selbst wird erst in V2 erstellt.
SQL-Snippet (verbindliche Vorgabe für schema-final.sql)¶
-- ── CUSTOMERS ──────────────────────────────────────────────────────────────
-- V1: Kunde = Person. organization_id ist nullable (V2-Vorbereitung).
-- Die organizations-Tabelle existiert in V1 noch nicht — der FK-Constraint
-- wird daher erst in V2 aktiviert. In V1 bleibt das Feld immer NULL.
CREATE TABLE customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
name TEXT NOT NULL,
email TEXT,
phone_landline TEXT,
phone_mobile TEXT,
address_street TEXT,
address_zip TEXT,
address_city TEXT,
address_country CHAR(2), -- ISO 3166-1 alpha-2
organization_id UUID, -- nullable, V2: FK → organizations(id)
notes TEXT,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT chk_customers_phone
CHECK (phone_landline IS NOT NULL OR phone_mobile IS NOT NULL)
-- mind. eine Telefonnummer Pflicht (analog Schulprofil)
-- → in V1 als NOT ENFORCED vorbereiten, Pflicht via App-Logik
);
-- Index für Tenant-Isolation (RLS-Unterstützung)
CREATE INDEX idx_customers_tenant_id ON customers(tenant_id);
-- Index für spätere Organization-Zuordnung (V2)
CREATE INDEX idx_customers_organization_id ON customers(organization_id);
Prisma-Schema-Snippet (verbindliche Vorgabe)¶
model Customer {
id String @id @default(uuid()) @db.Uuid
tenantId String @map("tenant_id") @db.Uuid
name String
email String?
phoneLandline String? @map("phone_landline")
phoneMobile String? @map("phone_mobile")
addressStreet String? @map("address_street")
addressZip String? @map("address_zip")
addressCity String? @map("address_city")
addressCountry String? @map("address_country") @db.Char(2)
organizationId String? @map("organization_id") @db.Uuid // V2-Vorbereitung
notes String?
isActive Boolean @default(true) @map("is_active")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
tenant Tenant @relation(fields: [tenantId], references: [id])
// organization Organization? @relation(...) // V2: einkommentieren
@@index([tenantId])
@@index([organizationId])
@@map("customers")
}
Was in V2 hinzukommt (zur Erinnerung)¶
-- V2: organizations-Tabelle anlegen
CREATE TABLE organizations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
name TEXT NOT NULL,
...
);
-- V2: FK-Constraint nachträglich aktivieren
ALTER TABLE customers
ADD CONSTRAINT fk_customers_organization
FOREIGN KEY (organization_id) REFERENCES organizations(id);