Skip to content

Database Schema ​

CareLog uses a JSON-based database stored in data/data.json. This document describes the data structure and relationships.

Database Structure ​

The database is a single JSON file with collections as top-level keys:

json
{
  "users": {},
  "healthLogs": {},
  "appointments": {},
  "medicalRecords": {},
  "diagnoses": {},
  "prescriptions": {},
  "emergencyCalls": {},
  "notifications": {},
  "visitRequests": {},
  "auditLogs": {},
  "feedback": {}
}

Collections ​

users ​

Stores all user accounts across all roles.

Structure:

json
{
  "user_id": {
    "id": "string",
    "name": "string",
    "firstName": "string",
    "lastName": "string",
    "email": "string (unique)",
    "password": "string (hashed)",
    "role": "patient|doctor|nurse|hospitaladmin|family",
    "isDisabled": "boolean",
    "deletionRequested": "boolean",
    "linkedPatients": ["array of patient IDs (for family role)"]
  }
}

Relationships:

  • linkedPatients: References users collection (patient role IDs)

Indexes:

  • Primary Key: id
  • Unique: email
  • Index: role

healthLogs ​

Daily health status logs created by patients.

Structure:

json
{
  "log_id": {
    "logID": "string",
    "patientID": "string",
    "timestamp": "ISO 8601 datetime",
    "physicalStatus": "array or string",
    "emotionalStatus": "array or string",
    "symptoms": "string",
    "isSensitive": "boolean"
  }
}

Relationships:

  • patientID: References users.id (role: patient)

Indexes:

  • Primary Key: logID
  • Foreign Key: patientID
  • Index: timestamp, isSensitive

appointments ​

Medical appointment requests and schedules.

Structure:

json
{
  "appointment_id": {
    "appointmentID": "string",
    "patientID": "string",
    "doctorID": "string (optional)",
    "reason": "string",
    "requestedDate": "ISO 8601 datetime",
    "scheduledDate": "ISO 8601 datetime (optional)",
    "status": "Pending|Scheduled|Completed|Cancelled",
    "notes": "string (optional)",
    "createdAt": "ISO 8601 datetime"
  }
}

Relationships:

  • patientID: References users.id (role: patient)
  • doctorID: References users.id (role: doctor)

Indexes:

  • Primary Key: appointmentID
  • Foreign Keys: patientID, doctorID
  • Index: status, scheduledDate

medicalRecords ​

Comprehensive medical records for each patient.

Structure:

json
{
  "record_id": {
    "recordID": "string",
    "patientID": "string",
    "diagnoses": ["array of diagnosis IDs"],
    "prescriptions": ["array of prescription IDs"],
    "appointments": ["array of appointment IDs"],
    "healthLogs": ["array of health log IDs"],
    "lastUpdated": "ISO 8601 datetime"
  }
}

Relationships:

  • patientID: References users.id (role: patient)
  • diagnoses[]: References diagnoses.diagnosisID
  • prescriptions[]: References prescriptions.prescriptionID
  • appointments[]: References appointments.appointmentID
  • healthLogs[]: References healthLogs.logID

Indexes:

  • Primary Key: recordID
  • Foreign Key: patientID
  • Unique: One record per patient

diagnoses ​

Medical diagnoses made by doctors.

Structure:

json
{
  "diagnosis_id": {
    "diagnosisID": "string",
    "doctorID": "string",
    "patientID": "string",
    "condition": "string",
    "notes": "string",
    "dateDiagnosed": "ISO 8601 date",
    "treatmentPlan": "string (optional)",
    "followUp": "string (optional)"
  }
}

Relationships:

  • doctorID: References users.id (role: doctor)
  • patientID: References users.id (role: patient)

Indexes:

  • Primary Key: diagnosisID
  • Foreign Keys: doctorID, patientID
  • Index: dateDiagnosed

prescriptions ​

Medication prescriptions written by doctors.

Structure:

json
{
  "prescription_id": {
    "prescriptionID": "string",
    "doctorID": "string",
    "patientID": "string",
    "medication": "string",
    "dosage": "string",
    "instruction": "string",
    "datePrescribed": "ISO 8601 date",
    "duration": "string (optional)",
    "warnings": "string (optional)",
    "isActive": "boolean (optional)"
  }
}

Relationships:

  • doctorID: References users.id (role: doctor)
  • patientID: References users.id (role: patient)

Indexes:

  • Primary Key: prescriptionID
  • Foreign Keys: doctorID, patientID
  • Index: datePrescribed, isActive

emergencyCalls ​

Urgent care requests from patients.

Structure:

json
{
  "call_id": {
    "callID": "string",
    "patientID": "string",
    "timestamp": "ISO 8601 datetime",
    "urgencyLevel": "CRITICAL|HIGH|MEDIUM",
    "description": "string (optional)",
    "isResolved": "boolean",
    "isEscalated": "boolean",
    "respondedBy": "string (optional, nurse/doctor ID)",
    "responseTime": "ISO 8601 datetime (optional)",
    "notes": "string (optional)"
  }
}

Relationships:

  • patientID: References users.id (role: patient)
  • respondedBy: References users.id (role: nurse or doctor)

Indexes:

  • Primary Key: callID
  • Foreign Keys: patientID, respondedBy
  • Index: isResolved, urgencyLevel, timestamp

notifications ​

System notifications for users.

Structure:

json
{
  "notification_id": {
    "notificationID": "string",
    "userID": "string",
    "message": "string",
    "timestamp": "ISO 8601 datetime",
    "isRead": "boolean",
    "type": "string (optional)",
    "relatedID": "string (optional)"
  }
}

Relationships:

  • userID: References users.id
  • relatedID: May reference any entity depending on type

Indexes:

  • Primary Key: notificationID
  • Foreign Key: userID
  • Index: isRead, timestamp

visitRequests ​

Family visit requests to patients.

Structure:

json
{
  "request_id": {
    "requestID": "string",
    "patientID": "string",
    "familyMemberID": "string",
    "requestedDate": "ISO 8601 datetime",
    "status": "Submitted|Approved|Denied|Completed",
    "purpose": "string (optional)",
    "createdAt": "ISO 8601 datetime",
    "approvedAt": "ISO 8601 datetime (optional)"
  }
}

Relationships:

  • patientID: References users.id (role: patient)
  • familyMemberID: References users.id (role: family)

Indexes:

  • Primary Key: requestID
  • Foreign Keys: patientID, familyMemberID
  • Index: status, requestedDate

auditLogs ​

System-wide audit trail for compliance.

Structure:

json
{
  "log_id": {
    "logID": "string",
    "userID": "string",
    "action": "string",
    "timestamp": "ISO 8601 datetime",
    "details": "string",
    "ipAddress": "string (optional)",
    "resourceType": "string (optional)",
    "resourceID": "string (optional)"
  }
}

Relationships:

  • userID: References users.id
  • resourceID: May reference any entity depending on resourceType

Indexes:

  • Primary Key: logID
  • Foreign Key: userID
  • Index: timestamp, action

Note: Audit logs are immutable and cannot be deleted.


feedback ​

User feedback submissions.

Structure:

json
{
  "feedback_id": {
    "feedbackID": "string",
    "userID": "string",
    "category": "string",
    "message": "string",
    "timestamp": "ISO 8601 datetime",
    "status": "Pending|Reviewed|Resolved (optional)",
    "response": "string (optional)"
  }
}

Relationships:

  • userID: References users.id

Indexes:

  • Primary Key: feedbackID
  • Foreign Key: userID
  • Index: timestamp, category

Data Relationships ​

Entity Relationship Diagram (Conceptual) ​

User (Patient) ──┬─── HealthLog (1:N)
                 ├─── Appointment (1:N)
                 ├─── MedicalRecord (1:1)
                 ├─── EmergencyCall (1:N)
                 ├─── VisitRequest (1:N, as patient)
                 └─── Notification (1:N)

User (Doctor) ───┬─── Appointment (1:N)
                 ├─── Diagnosis (1:N)
                 └─── Prescription (1:N)

User (Nurse) ────└─── EmergencyCall (N:1, respondedBy)

User (Family) ───└─── VisitRequest (1:N, as family member)
                      └──> Linked to User (Patient) (N:N)

MedicalRecord ───┬─── Diagnosis (1:N)
                 ├─── Prescription (1:N)
                 ├─── Appointment (1:N)
                 └─── HealthLog (1:N)

AuditLog ────────└─── User (N:1)
Feedback ────────└─── User (N:1)

Data Integrity Rules ​

Referential Integrity ​

  • Users: Cannot delete if referenced by other entities
  • Patients: Cannot delete if have active appointments or medical records
  • Doctors: Cannot delete if have active appointments
  • Family Members: Remove patient links before deletion

Business Rules ​

  1. Health Logs

    • Must have valid patientID
    • Timestamp auto-generated if not provided
    • Sensitive flag defaults to False
  2. Appointments

    • Must have valid patientID
    • doctorID optional until assigned
    • Status transitions: Pending → Scheduled → Completed/Cancelled
  3. Medical Records

    • One record per patient (1:1 relationship)
    • Auto-created when patient created
    • References must exist in respective collections
  4. Diagnoses & Prescriptions

    • Must have valid doctorID and patientID
    • Date cannot be in the future
    • Automatically added to patient's medical record
  5. Emergency Calls

    • Must have valid patientID
    • urgencyLevel required
    • Cannot be deleted, only resolved
    • Escalation creates audit log entry
  6. Visit Requests

    • Must have valid patientID and familyMemberID
    • Family member must be linked to patient
    • Status transitions: Submitted → Approved/Denied → Completed
  7. Audit Logs

    • Immutable (no updates or deletes)
    • Automatically created for sensitive operations
    • Timestamp auto-generated
  8. Notifications

    • Must have valid userID
    • Auto-generated for significant events
    • isRead defaults to False

Data Access Patterns ​

Common Queries ​

  1. Get user by email (login)

    Filter users where email = ?
  2. Get patient health logs

    Filter healthLogs where patientID = ?
    Order by timestamp DESC
  3. Get non-sensitive health logs (for family)

    Filter healthLogs where patientID = ? AND isSensitive = false
    Order by timestamp DESC
  4. Get pending appointments

    Filter appointments where status = "Pending"
    Order by requestedDate ASC
  5. Get unresolved emergencies

    Filter emergencyCalls where isResolved = false
    Order by urgencyLevel DESC, timestamp ASC
  6. Get patient medical record

    Filter medicalRecords where patientID = ?
    Then fetch all related diagnoses, prescriptions, appointments
  7. Get user notifications

    Filter notifications where userID = ?
    Order by timestamp DESC
  8. Get audit logs by user

    Filter auditLogs where userID = ?
    Order by timestamp DESC

ID Generation ​

All IDs are generated using UUID or a combination of:

  • Entity prefix (e.g., "user", "appt", "diag")
  • Timestamp
  • Random suffix

Example: user_20251026_abc123

Data Migration ​

When schema changes are needed:

  1. Create backup
  2. Write migration script
  3. Test on copy of database
  4. Apply migration
  5. Verify data integrity
  6. Update application code

Performance Considerations ​

Indexing Strategy ​

While JSON doesn't have traditional indexes, access patterns should:

  • Use ID lookups when possible (O(1))
  • Cache frequently accessed data
  • Minimize full collection scans
  • Consider pagination for large datasets

Optimization Tips ​

  1. Lazy Loading: Load related entities only when needed
  2. Caching: Cache user sessions and frequently accessed records
  3. Batch Operations: Group multiple updates
  4. Pagination: Limit results for large collections

Backup and Recovery ​

Backup Strategy ​

  • Automatic daily backups
  • Manual backup before major changes
  • Stored in data/backups/
  • Named with timestamp: backup_YYYYMMDD_HHMMSS.json

Recovery ​

python
from core.services.database_service import DatabaseService

db = DatabaseService()
db.restore_from_backup("data/backups/backup_20251026_120000.json")

Security Considerations ​

  1. Passwords: Always hashed using Argon2
  2. Sensitive Data: Marked with isSensitive flag
  3. Access Control: Enforced at service layer
  4. Audit Trail: All sensitive operations logged
  5. Data Export: Restrict to authorized roles

Next Steps ​