# 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

```mermaid
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

```mermaid
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
