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

262 lines
7.3 KiB
Markdown

# 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