Overview
OdontologyApp uses MySQL as its primary database with a well-structured relational schema. The database is accessed through a connection pool and primarily uses stored procedures for data operations.Database Connection
Connection Pool (src/lib/server/db.js:1-13):Configuration
- Connection limit: 10 concurrent connections
- Queue limit: Unlimited (0 = no limit)
- Wait for connections: true (requests wait for available connection)
- Promise-based: Uses mysql2/promise for async/await support
Environment Variables
Required in.env:
Core Tables
Branches (Sucursales)
Stores clinic branch/location information:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| name | VARCHAR(100) | NOT NULL | Branch name |
| address | VARCHAR(255) | Physical address | |
| icon | VARCHAR(50) | Icon/emoji for UI | |
| status | ENUM | ’active’, ‘inactive’ | Branch status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Creation timestamp |
Users
System users (administrators, doctors, secretaries):| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| name | VARCHAR(100) | NOT NULL | Full name |
| username | VARCHAR(50) | UNIQUE, NOT NULL | Login username |
| VARCHAR(100) | UNIQUE | Email address | |
| password | VARCHAR(255) | NOT NULL | Bcrypt hashed password |
| role | ENUM | ’admin’, ‘doctor’, ‘secretary’ | User role |
| initials | VARCHAR(5) | User initials for UI | |
| branch_id | INT | FOREIGN KEY → branches(id) | Assigned branch |
| status | ENUM | ’active’, ‘inactive’ | Account status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Creation timestamp |
Doctors
Extended information for medical staff:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| user_id | INT | UNIQUE, NOT NULL, FOREIGN KEY → users(id) | Associated user account |
| specialty | VARCHAR(100) | Medical specialty | |
| license_number | VARCHAR(50) | Professional license number |
Doctor_Branches
Many-to-many relationship between doctors and branches:| Column | Type | Constraints | Description |
|---|---|---|---|
| doctor_id | INT | PRIMARY KEY, FOREIGN KEY → doctors(id) | Doctor reference |
| branch_id | INT | PRIMARY KEY, FOREIGN KEY → branches(id) | Branch reference |
Patients
Patient records:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| medrecno | INT | NOT NULL | Medical record number |
| first_name | VARCHAR(100) | NOT NULL | First name |
| last_name | VARCHAR(100) | NOT NULL | Last name |
| cedula | VARCHAR(20) | UNIQUE | National ID number |
| birth_date | DATE | Date of birth | |
| phone | VARCHAR(20) | Contact phone | |
| VARCHAR(100) | Email address | ||
| sex | ENUM | ’masculino’, ‘femenino’, ‘otro’ | Gender |
| blood_group | VARCHAR(5) | Blood type | |
| allergies | TEXT | Known allergies | |
| branch_id | INT | FOREIGN KEY → branches(id) | Primary branch |
| status | ENUM | ’active’, ‘inactive’, ‘on_hold’ | Patient status |
| uuid | CHAR(36) | UNIQUE | UUID for public URLs |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Creation timestamp |
Appointments (Citas)
Appointment scheduling:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| patient_id | INT | NOT NULL, FOREIGN KEY → patients(id) | Patient reference |
| doctor_id | INT | NOT NULL, FOREIGN KEY → doctors(id) | Doctor reference |
| branch_id | INT | NOT NULL, FOREIGN KEY → branches(id) | Branch location |
| appointment_date | DATE | NOT NULL | Appointment date |
| appointment_time | TIME | NOT NULL | Appointment time |
| duration_minutes | INT | DEFAULT 30 | Duration in minutes |
| status | ENUM | ’scheduled’, ‘confirmed’, ‘waiting’, ‘completed’, ‘cancelled’ | Appointment status |
| notes | TEXT | Additional notes | |
| uuid | CHAR(36) | UNIQUE | UUID for reminders |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Creation timestamp |
Medical_Records
Clinical history and consultations:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| patient_id | INT | NOT NULL, FOREIGN KEY → patients(id) | Patient reference |
| doctor_id | INT | NOT NULL, FOREIGN KEY → doctors(id) | Attending doctor |
| record_date | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Consultation date |
| motif | TEXT | Chief complaint | |
| diagnosis | TEXT | Medical diagnosis | |
| treatment | TEXT | Treatment provided | |
| future_plan | TEXT | Future treatment plan | |
| next_visit | DATE | Next appointment date | |
| observations | TEXT | Additional observations |
Indications
Medical prescriptions and instructions:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| patient_id | INT | NOT NULL, FOREIGN KEY → patients(id) | Patient reference |
| doctor_id | INT | NOT NULL, FOREIGN KEY → doctors(id) | Prescribing doctor |
| indication_date | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Date prescribed |
| description | TEXT | NOT NULL | Prescription details |
Odontograms
Dental chart/diagram data:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| patient_id | INT | NOT NULL, FOREIGN KEY → patients(id) | Patient reference |
| tooth_number | INT | NOT NULL | Tooth number (FDI notation) |
| state | ENUM | ’healthy’, ‘caries’, ‘restored’, ‘extracted’, ‘crown’, ‘treatment’ | Tooth condition |
| notes | TEXT | Additional notes | |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | Last update |
Patient_Files
File attachments (X-rays, documents, etc.):| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| patient_id | INT | NOT NULL, FOREIGN KEY → patients(id) | Patient reference |
| name | VARCHAR(255) | NOT NULL | File name |
| file_type | VARCHAR(50) | MIME type | |
| file_size | INT | Size in bytes | |
| file_url | VARCHAR(255) | NOT NULL | Storage URL/path |
| upload_date | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Upload timestamp |
Logs
System audit trail:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| user_id | INT | FOREIGN KEY → users(id) | User who performed action |
| action | VARCHAR(50) | NOT NULL | Action type |
| module | VARCHAR(50) | NOT NULL | Module/feature |
| description | TEXT | Detailed description | |
| ip_address | VARCHAR(45) | User IP address | |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Action timestamp |
Permission System Tables
Permissions
Catalog of all system permissions:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| code | VARCHAR(60) | UNIQUE, NOT NULL | Permission code (e.g., VIEW_PATIENTS) |
| label | VARCHAR(100) | NOT NULL | Human-readable name |
| module | VARCHAR(60) | NOT NULL | Module grouping |
| description | TEXT | Detailed description | |
| sort_order | INT | DEFAULT 0 | Display order |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Creation timestamp |
User_Permissions
Individual permission assignments:| Column | Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| user_id | INT | NOT NULL, FOREIGN KEY → users(id) | User reference |
| permission_id | INT | NOT NULL, FOREIGN KEY → permissions(id) | Permission reference |
| granted | TINYINT(1) | DEFAULT 1 | 1 = granted, 0 = revoked |
| granted_by | INT | FOREIGN KEY → users(id) | Admin who granted permission |
| granted_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Grant timestamp |
Stored Procedures
Patient Procedures
Defined in database.sql and referenced in API endpoints: sp_list_patients(search_query)- Lists patients with optional search filter
- Usage:
CALL sp_list_patients('')orCALL sp_list_patients('John')
- Creates new patient record
- Returns: patient_id
- Usage in API: (src/routes/api/patients/+server.js:69)
- Soft delete or archive patient
- Logs action in audit trail
Finance Procedures
Defined in sp_finance.sql: sp_get_patient_finance(patient_id)- Returns multiple result sets:
- Budgets with doctor names
- Budget items with service names
- Payment history
- Creates budget with line items
- Uses JSON parameter for items
- Transactional (rollback on error)
- Returns: budget_id
- Records payment transaction
- Returns: payment_id
- Updates budget status (draft, approved, rejected)
Permission Procedures
Defined in migration_phase6_permissions.sql: sp_check_single_permission(user_id, permission_code)- Checks if user has specific permission
- Returns: granted (0 or 1)
- Used in: (src/lib/server/checkPermission.js:25)
- Returns array of permission codes for user
- Used for frontend permission checks
- Returns complete permission catalog
- Used for admin permission management
- Assigns or revokes permission
- Idempotent (insert or update)
Database Relationships
Query Patterns
Using the Connection Pool
Prepared Statements
All queries use prepared statements to prevent SQL injection:Database Initialization
- Create database:
CREATE DATABASE IF NOT EXISTS ontology_db; - Run schema:
mysql -u user -p ontology_db < database.sql - Run migrations:
mysql -u user -p ontology_db < migration_phase6_permissions.sql - Run stored procedures:
mysql -u user -p ontology_db < sp_finance.sql
