Zum Inhalt

Domänenmodell

Das folgende Entity-Relationship-Diagramm ist die Landkarte der TxRide-Daten. Im Kern stehen drei Konzepte:

  • RideOffer – eine angebotene Fahrt einer Fahrerin oder eines Fahrers, mit Richtung (OUTBOUND / RETURN), Abfahrtszeit und freien Plätzen.
  • RideRequest – ein Fahrtgesuch einer mitfahrenden Person, definiert über früheste/späteste Zeit am Zentrum statt über eine Abfahrtszeit.
  • Match – die Verbindung zwischen Angebot und Gesuch; durchläuft die Zustände von PROPOSED bis COMPLETED.

Hin- und Rückfahrten werden über die Selbstbezüge linkedOffer bzw. linkedRequest miteinander verknüpft.

Notifications (Phase 6)

  • Notification – kanonische Inbox-Zeile: messageKey + JSON-params (nie gerenderter Chat-Text), Kategorie, Deep-Link, readAt/seenAt, optional dedupeKey.
  • NotificationPreference – pro User/Kategorie/Kanal (INBOX immer an, EMAIL/PUSH default aus) mit Consent-Zeitstempel und optionalem graceMinutes.
  • PushSubscription – Browser-Push-Abonnement (Endpoint + Keys); Versand folgt in einem eigenen Issue.
  • User.locale / User.lastInboxOpenedAt – serverseitige Locale für E-Mails und Escalation-Grace-Fenster.

Automatisch generiert

Dieses Diagramm wird bei bun run db:generate über den prisma-erd-generator direkt aus packages/db/prisma/schema.prisma erzeugt. Pflege es nicht von Hand – das Prisma-Schema bleibt die Quelle der Wahrheit.

erDiagram

        RideOfferStatus {
            OPEN OPEN
MATCHED MATCHED
CANCELLED CANCELLED
COMPLETED COMPLETED
        }



        RideRequestStatus {
            OPEN OPEN
MATCHED MATCHED
CANCELLED CANCELLED
FULFILLED FULFILLED
        }



        MatchStatus {
            PROPOSED PROPOSED
ACCEPTED ACCEPTED
DECLINED DECLINED
CANCELLED CANCELLED
COMPLETED COMPLETED
        }



        RideDirection {
            OUTBOUND OUTBOUND
RETURN RETURN
        }



        NotificationCategory {
            BOOKING BOOKING
RIDE RIDE
CHAT CHAT
SYSTEM SYSTEM
        }



        NotificationChannel {
            INBOX INBOX
EMAIL EMAIL
PUSH PUSH
        }

  "Item" {
    String id "PK"
    String name 
    DateTime createdAt 
    }


  "User" {
    String id "PK"
    String keycloakSub 
    String email 
    String displayName 
    String matrixUserId "nullable"
    String locale "nullable"
    DateTime lastInboxOpenedAt "nullable"
    DateTime createdAt 
    DateTime updatedAt 
    }


  "ActivationCode" {
    String id "PK"
    String code 
    DateTime expiresAt "nullable"
    DateTime redeemedAt "nullable"
    String redeemedSub "nullable"
    String redeemedEmail "nullable"
    DateTime createdAt 
    }


  "Address" {
    String id "PK"
    String street 
    String houseNumber "nullable"
    String postalCode 
    String city 
    String country 
    Float latitude "nullable"
    Float longitude "nullable"
    DateTime createdAt 
    }


  "TransplantationCenter" {
    String id "PK"
    String name 
    DateTime createdAt 
    }


  "RideOffer" {
    String id "PK"
    RideDirection direction 
    DateTime departureAt 
    Int seatsTotal 
    Int seatsAvailable 
    RideOfferStatus status 
    String notes "nullable"
    String specialties "nullable"
    DateTime createdAt 
    DateTime updatedAt 
    }


  "RideRequest" {
    String id "PK"
    RideDirection direction 
    DateTime earliestAt "nullable"
    DateTime latestAt "nullable"
    Int seats 
    RideRequestStatus status 
    String notes "nullable"
    DateTime createdAt 
    DateTime updatedAt 
    }


  "Match" {
    String id "PK"
    MatchStatus status 
    String matrixRoomId "nullable"
    DateTime driverChatReadyAt "nullable"
    DateTime passengerChatReadyAt "nullable"
    DateTime createdAt 
    DateTime updatedAt 
    }


  "ChatMessage" {
    String id "PK"
    String senderId 
    String body 
    DateTime createdAt 
    DateTime readAt "nullable"
    }


  "Notification" {
    String id "PK"
    NotificationCategory category 
    String messageKey 
    Json params 
    String deepLink 
    DateTime createdAt 
    DateTime readAt "nullable"
    DateTime seenAt "nullable"
    DateTime deletedAt "nullable"
    String dedupeKey "nullable"
    }


  "NotificationPreference" {
    String id "PK"
    NotificationCategory category 
    NotificationChannel channel 
    Boolean enabled 
    DateTime consentAt "nullable"
    DateTime revokedAt "nullable"
    Int graceMinutes "nullable"
    DateTime createdAt 
    DateTime updatedAt 
    }


  "PushSubscription" {
    String id "PK"
    String endpoint 
    String p256dh 
    String auth 
    String userAgent "nullable"
    DateTime createdAt 
    DateTime lastSeenAt 
    }

    "User" |o--|o "Address" : "homeAddress"
    "ActivationCode" |o--|o "User" : "redeemedBy"
    "TransplantationCenter" |o--|| "Address" : "address"
    "RideOffer" |o--|| "RideDirection" : "enum:direction"
    "RideOffer" |o--|| "RideOfferStatus" : "enum:status"
    "RideOffer" }o--|| "User" : "driver"
    "RideOffer" }o--|| "Address" : "startAddress"
    "RideOffer" }o--|| "TransplantationCenter" : "destinationCenter"
    "RideOffer" |o--|o "RideOffer" : "linkedOffer"
    "RideRequest" |o--|| "RideDirection" : "enum:direction"
    "RideRequest" |o--|| "RideRequestStatus" : "enum:status"
    "RideRequest" }o--|| "User" : "passenger"
    "RideRequest" }o--|| "Address" : "startAddress"
    "RideRequest" }o--|| "TransplantationCenter" : "destinationCenter"
    "RideRequest" |o--|o "RideRequest" : "linkedRequest"
    "Match" |o--|| "MatchStatus" : "enum:status"
    "Match" }o--|| "RideOffer" : "offer"
    "Match" }o--|| "RideRequest" : "request"
    "ChatMessage" }o--|| "Match" : "match"
    "Notification" |o--|| "NotificationCategory" : "enum:category"
    "Notification" }o--|| "User" : "user"
    "Notification" }o--|o "Match" : "match"
    "Notification" }o--|o "RideOffer" : "rideOffer"
    "Notification" }o--|o "RideRequest" : "rideRequest"
    "NotificationPreference" |o--|| "NotificationCategory" : "enum:category"
    "NotificationPreference" |o--|| "NotificationChannel" : "enum:channel"
    "NotificationPreference" }o--|| "User" : "user"
    "PushSubscription" }o--|| "User" : "user"