Files
appointment-booking-software/docs/entity-relationship-diagram.md
T

7.3 KiB

Entity-Relationship Diagram

Appointment Booking Platform Data Structure

Please note that this is currently the unencrypted data model. Appointments, Notes, Attachments and Answers of course have to be encrypted before being stored in the database.

Central database

erDiagram
    ADMIN {
        uuid id PK
        string email
        string name
        timestamp created_at
        timestamp updated_at
        timestamp last_login_at
        boolean is_active
        boolean confirmed
        string token "Email confirmation token"
        timestamp token_valid_until
    }

    ADMIN_PASSKEY {
        string id PK "WebAuthn credential ID"
        uuid admin_id FK
        string public_key "Base64 encoded"
        int counter
        string device_name "MacBook Pro, YubiKey 5, etc."
        timestamp created_at
        timestamp updated_at
        timestamp last_used_at
    }

    TENANT {
        uuid id PK
        string short_name "Used as subdomain"
        string long_name
        text description "Optional"
        bytea logo "PNG, JPEG, GIF, or WEBP"
        string database_url "Connection string for tenant DB"
        timestamp created_at
        timestamp updated_at
    }

    TENANT_CONFIG {
        uuid id PK
        uuid tenant_id FK
        string name "Configuration key"
        enum type "BOOLEAN, NUMBER, STRING"
        string value "Configuration value as text"
        timestamp created_at
        timestamp updated_at
    }


    ADMIN ||--o{ ADMIN_PASSKEY : "has"
    TENANT ||--o{ TENANT_CONFIG : "has"

Tenant-specific database

erDiagram

    AGENT {
        uuid id PK
        string name
        string description "Optional"
        blob image "PNG, JPEG, GIF, or WEBP"
    }

    CHANNEL {
        uuid id PK
        string name
        string color
        string description "Optional"
        string language
        boolean public "A channel may be only bookable with Code or internally if this is false"
        boolean require_confirmation "Must appointments be explicitly confirmed"
    }

    SLOT_TEMPLATE {
        uuid id PK
        string name "Slot template name"
        from time "Start time"
        to time "End time"
        duration integer "Slot length in minutes"
        weekdays integer "7-bit representation of the selected weekdays"
    }

    CLIENT {
        uuid id PK
        string hash_key "Generated from email"
        string public_key
        string private_key_share
        string email "Optional"
        string language
    }

    STAFF {
        uuid id PK
        uuid role_id "Role of staff member (e.g. 'tenant-admin', 'staff')"
        string hash_key "Generated from login name"
        string public_key
        string name "Optional"
        string email
        string language
    }

    SLOT {
        uuid id PK
        uuid channel_id FK
        datetime start
        int length
        uuid appointment_id FK "Optional, set when in use"
    }

    APPOINTMENT {
        uuid id PK
        uuid client_id FK
        uuid channel_id FK
        uuid team_id FK
        uuid slot_id FK
        date appointment_date
        date expiry_date
        string title
        string description
        enum status "NEW, CONFIRMED, HELD, REJECTED, NO_SHOW"
    }

    NOTE {
        uuid id PK
        uuid appointment_id FK
        string title
        text content
        timestamp created_at
    }

    ATTACHMENT {
        uuid id PK
        uuid appointment_id FK
        string title
        blob file_data
        string mime_type
        timestamp created_at
    }

    QUESTIONNAIRE {
        uuid id PK
        uuid channel_id FK
        string title
        string description "Optional"
        boolean is_active
    }

    QUESTION {
        uuid id PK
        string text
        enum type "FREETEXT, SINGLE_CHOICE, MULTIPLE_CHOICE"
        json options "For choice questions"
        boolean is_required
    }

    QUESTIONNAIRE_QUESTION {
        uuid questionnaire_id FK
        uuid question_id FK
        int order_index
    }

    QUESTIONNAIRE_ANSWER {
        uuid id PK
        uuid appointment_id FK
        uuid questionnaire_id FK
        uuid question_id FK
        text answer
        timestamp created_at
    }

    CLIENT ||--o{ APPOINTMENT : "has"
    CHANNEL ||--o{ APPOINTMENT : "assigned_to"
    CHANNEL ||--o{ QUESTIONNAIRE : "has"
    CHANNEL }o--o{ AGENT : "associated"
    APPOINTMENT ||--o{ NOTE : "contains"
    APPOINTMENT ||--o{ ATTACHMENT : "contains"
    QUESTIONNAIRE ||--o{ QUESTIONNAIRE_QUESTION : "contains"
    QUESTION ||--o{ QUESTIONNAIRE_QUESTION : "used_in"
    APPOINTMENT ||--o{ QUESTIONNAIRE_ANSWER : "answered"
    QUESTIONNAIRE ||--o{ QUESTIONNAIRE_ANSWER : "answered_for"
    QUESTION ||--o{ QUESTIONNAIRE_ANSWER : "answer_to"

Database Architecture Notes

  • Multi-tenancy: Each tenant operates with a separate database instance
  • Central vs. Tenant Databases:
    • Central database contains: ADMIN, ADMIN_PASSKEY, TENANT, TENANT_CONFIG
    • Tenant-specific databases contain: CLIENT, STAFF, CHANNEL, APPOINTMENT, etc.
  • No explicit tenant references: Since each tenant has its own database, foreign key relationships don't need to reference the tenant
  • Encryption: The system uses end-to-end encryption with public/private key pairs for clients and staff
  • Hash-based identification: Both clients and staff are identified by hash keys derived from their credentials
  • WebAuthn Authentication: Admins use WebAuthn passkeys for secure authentication
  • Flexible appointments: Appointments support multiple notes and attachments for comprehensive record keeping

Entity Descriptions

ADMIN (Central Database)

System administrators who manage the platform and tenants. Uses WebAuthn for secure authentication.

ADMIN_PASSKEY (Central Database)

WebAuthn credentials for admin authentication. Each admin can have multiple passkeys (different devices).

TENANT (Central Database)

Central configuration entity for each tenant organization. Contains database connection information for tenant isolation.

TENANT_CONFIG (Central Database)

Flexible configuration system for tenant-specific settings. Each tenant can have multiple typed configuration entries.

CLIENT (Tenant Database)

End-to-end encrypted client records with optional email for notifications

STAFF (Tenant Database)

Practice staff members with minimal required information for privacy

CHANNEL (Tenant Database)

Represents bookable resources such as rooms, machines, or personnel that appointments can be scheduled for

APPOINTMENT (Tenant Database)

Core booking entity with flexible status management and expiry handling, now linked to specific channels

NOTE (Tenant Database)

Text-based annotations attached to appointments

ATTACHMENT (Tenant Database)

File attachments (documents, images, etc.) associated with appointments

QUESTIONNAIRE (Tenant Database)

Collection of questions associated with a specific channel, can be activated/deactivated

QUESTION (Tenant Database)

Individual questions that can be reused across multiple questionnaires, supporting different answer types

QUESTIONNAIRE_QUESTION (Tenant Database)

Junction table linking questionnaires to questions with ordering information

QUESTIONNAIRE_ANSWER (Tenant Database)

Stores answers provided by clients for specific appointments and questionnaires