Database Architecture Technical Report

Exhaustive technical specification detailing the relational schema sqls/tablas_mhc_ok.sql. Analyzes all 22 generated tables, conceptual design, foreign keys, integrity constraints, and GDPR compliance architecture.

🗄️
22
Generated Tables
🔗
31
Foreign Key Constraints
🧩
6
Functional Modules
🛡️
GDPR
Ireland & EU Compliance
Modules: All (22) 1. Auth & RBAC (5) 2. Corporate & Onboarding (2) 3. Profiles & Availability (4) 4. Appointments & Clinical Triage (5) 5. Invoicing & Billing (2) 6. Messaging & System (4)

Relational Dependency Map (ERD by Module)

Select or hover over any table to automatically highlight incoming and outgoing Foreign Key relationships.

🔐 1. Auth & Governance
users Central PK: id
roles Parent of users
subroles FK -> roles
subrole_permissions FK -> subroles
consent_log FK -> users
🏢 2. Corporate & Onboarding
companies FK -> users
company_invitations FK -> companies, users
👥 3. Profiles & Schedules
clients FK -> users, providers, companies
providers FK -> users
provider_availability FK -> providers
client_interests FK -> clients
🩺 4. Clinical & Risk Safety
appointments FK -> clients, providers
crisis_assessments FK -> clients
alerts FK -> clients, users
safety_care_plans FK -> clients, providers, appointments
questionnaires_results FK -> clients, providers
🧾 5. Invoicing & Payments
invoices FK -> appointments, providers, clients, companies
payments FK -> invoices
💬 6. Messages & System FAQs
messages FK -> users (sender & receiver)
email_queue Independent Queue
faqs FK -> faq_categories
faq_categories Parent of faqs

users

1. Autenticación & RBAC
ENGINE: InnoDB CHARSET: utf8mb4

Tabla central de identidad de la plataforma. Almacena las credenciales de autenticación (hash bcrypt), tokens de sesión activos, asignación de rol principal (`role_id`) y subrol opcional (`subrole_id`), preferencia de idioma y estado de cuenta.

Column Data Type Nullable Default Key Purpose / Description
idint(11)NOAUTO_INCPRIMARYIdentificador único correlativo del usuario.
emailvarchar(255)NONoneUNIQUECorreo electrónico institucional o personal (login).
password_hashvarchar(255)NONone-Hash seguro de contraseña generado mediante `password_hash()`.
login_tokenvarchar(100)YESNULLUNIQUEToken de autenticación/persistencia de sesión HttpOnly.
role_idint(11)NONoneFKRol principal (1=Admin, 2=Company, 3=Provider, 4=Client).
namevarchar(255)YESNULL-Nombre completo o razón social asociada a la cuenta.
is_activetinyint(1)YES1-Flag de cuenta activa (1=Habilitada, 0=Suspendida/Bloqueada).
lang_prefenum('es','en')YES'es'-Preferencia de idioma de la interfaz del usuario.
created_attimestampNOcurrent_timestamp()-Fecha y hora exacta de registro.
subrole_idint(11)YESNULLFKSubrol fino opcional para permisos especiales (ej. Clinical Lead).
🔗 Foreign Key Constraints
role_id ➔ roles(id) ON DELETE RESTRICT
subrole_id ➔ subroles(id) ON DELETE SET NULL

roles

1. Autenticación & RBAC
ENGINE: InnoDB

Catálogo maestro de roles del sistema. Define los 4 tipos de actores principales: Administrador, Empresa (Company HR), Proveedor (Provider/Therapist) y Paciente (Client).

Column Data Type Nullable Default Key Purpose / Description
idint(11)NOAUTO_INCPRIMARYID único del rol.
namevarchar(50)NONoneUNIQUENombre único del rol (ej: 'admin', 'company', 'provider', 'client').

subroles

1. Autenticación & RBAC
ENGINE: InnoDB

Permite crear sub-roles jerárquicos o especializados vinculados a un rol base (por ejemplo, subrol "Clinical Lead" dentro de los administradores).

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del subrol.
role_idint(11)NONoneFKRol primario al que pertenece.
namevarchar(100)NONone-Nombre visible del subrol.
slugvarchar(100)NONoneUNIQUEIdentificador técnico slug único.
descriptiontextYESNULL-Detalle de funciones del subrol.
is_activetinyint(1)YES1-Estado activo/inactivo.
created_attimestampNOcurrent_timestamp()-Fecha de creación.
🔗 Foreign Key Constraints
role_id ➔ roles(id)ON DELETE RESTRICT

subrole_permissions

1. Autenticación & RBAC
ENGINE: InnoDB

Matriz de permisos de grano fino asignados a un subrol específico (ej. `admin.cl_messages.read`, `reports.export`).

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del registro.
subrole_idint(11)NONoneFKSubrol que posee el permiso.
permissionvarchar(150)NONoneUNIQUE_KEYCadena de permiso clave.
🔗 Foreign Key Constraints
subrole_id ➔ subroles(id)ON DELETE CASCADE

companies

2. Corporativo & Invitaciones
ENGINE: InnoDB

Almacena las cuentas de empresas cliente corporativo (Enterprise Clients). Define la asignación de sesiones de salud mental subvencionadas por empleado (`sessions_per_member`), vigencia de contratos corporativos y total de miembros enrolados.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID único de la empresa.
user_idint(11)NONoneUNIQUE / FKCuenta de usuario (login HR).
namevarchar(255)NONone-Nombre/Razón social de la empresa.
contact_namevarchar(255)YESNULL-Nombre del contacto principal HR.
contact_emailvarchar(255)YESNULL-Correo de contacto institucional.
industryvarchar(100)YESNULL-Sector comercial / industria.
countryvarchar(100)YESNULL-País de operación.
sessions_per_memberint(11)YES8-Bolsa de sesiones permitidas por empleado al año.
total_members_enrolledint(11)YES0-Contador de empleados registrados.
contract_startdateYESNULL-Fecha inicio del contrato.
contract_enddateYESNULL-Fecha término del contrato.
is_activetinyint(1)YES1-Estado activo/inactivo del contrato.
🔗 Foreign Key Constraints
user_id ➔ users(id)ON DELETE CASCADE

company_invitations

2. Corporativo & Invitaciones
ENGINE: InnoDB

Tokens únicos y seguros generados por gestores HR o Administradores para permitir el auto-registro anónimo de empleados dentro de la bolsa corporativa de una empresa.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del enlace.
company_idint(11)NONoneFKEmpresa emisora.
tokenvarchar(64)NONoneUNIQUEHash o token seguro de la URL de registro.
is_activetinyint(1)YES1-1=Válido, 0=Revocado.
created_byint(11)NONoneFKUsuario creador del token.
created_attimestampNOcurrent_timestamp()-Timestamp de creación.
🔗 Foreign Key Constraints
company_id ➔ companies(id)ON DELETE CASCADE
created_by ➔ users(id)ON DELETE CASCADE

clients

3. Perfiles & Disponibilidad
ENGINE: InnoDB

Perfil clínico e informativo del paciente (cliente). Vincula la cuenta de usuario con su empresa corporativa, terapeuta asignado (`provider_id`), recuento de sesiones consumidas vs permitidas, estado del emparejamiento (match) y datos de emergencia (Next of Kin y GP médico general).

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID interno del paciente.
user_idint(11)NONoneUNIQUE / FKCuenta de usuario asociada.
provider_idint(11)YESNULLFKTerapeuta asignado (SET NULL si se desasigna).
company_idint(11)NONoneFKEmpresa a la que está afiliado.
namevarchar(255)NONone-Nombre completo del paciente.
service_preferenceenum('coaching','counselling','both')YESNULL-Preferencia de tipo de servicio.
statusenum('new_match','active','engaged','inactive')YES'new_match'-Estado del paciente en la plataforma.
total_sessions_allowedint(11)YES8-Límite total de sesiones.
sessions_usedint(11)YES0-Sesiones ya realizadas.
next_of_kin_namevarchar(255)YESNULL-Contacto de emergencia de familiar cercano.
gp_namevarchar(255)YESNULL-Nombre del Médico General / Cabecera (GP).
intake_completedtinyint(1)YES0-Flag de formulario de admisión completado.
🔗 Foreign Key Constraints
user_id ➔ users(id)ON DELETE CASCADE
provider_id ➔ providers(id)ON DELETE SET NULL
company_id ➔ companies(id)ON DELETE RESTRICT

providers

3. Perfiles & Disponibilidad
ENGINE: InnoDB

Perfil profesional del terapeuta o coach mental. Guarda sus especialidades clínicas en formato `JSON`, configuración de duración de sesión y tiempo de descanso (buffer time), tope máximo de pacientes activos, zona horaria y enlaces de videollamada (Zoom/Google Meet).

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID único del proveedor.
user_idint(11)NONoneUNIQUE / FKCuenta de usuario.
namevarchar(255)NONone-Nombre profesional y títulos.
specialtieslongtext (JSON)YESNULL-Array JSON validado con especialidades.
session_durationint(11)YES50-Duración estándar de consulta en minutos.
buffer_timeint(11)YES30-Tiempo de descanso/preparación entre citas (min).
max_clientsint(11)YES10-Límite máximo de pacientes activos.
timezonevarchar(100)YES'Europe/Dublin'-Zona horaria de atención (ej. Europe/Dublin).
video_providerenum('zoom','meet','both')YES'zoom'-Proveedor de videoconferencia.
🔗 Foreign Key Constraints
user_id ➔ users(id)ON DELETE CASCADE

provider_availability

3. Perfiles & Disponibilidad
ENGINE: InnoDB

Horarios semanales de atención del terapeuta. Define las ventanas de horas por día de la semana (`day_of_week` 1 a 7) para alimentar el motor de agendamiento automático de citas.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del horario.
provider_idint(11)NONoneFKProveedor al que pertenece.
day_of_weektinyint(4)NONoneUNIQUEDía de la semana (1=Lunes, 7=Domingo).
start_timetimeNO'09:00:00'-Hora de inicio de atención.
end_timetimeNO'17:00:00'-Hora de fin de atención.
activetinyint(1)YES1-Indica si atiende ese día.
🔗 Foreign Key Constraints
provider_id ➔ providers(id)ON DELETE CASCADE

client_interests

3. Perfiles & Disponibilidad
ENGINE: InnoDB

Áreas de interés o temas de salud mental seleccionados por el paciente (ej. Ansiedad, Estrés laboral, Mindfulness) con ponderación (`weight`) para sugerencias de emparejamiento con terapeutas.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del interés.
client_idint(11)NONoneFKPaciente asociado.
topicvarchar(100)NONone-Tópico/Tema de interés.
weightint(11)YES100-Ponderación/Prioridad del interés.
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE

appointments

4. Citas & Triaje Clínico
ENGINE: InnoDB

Citas y sesiones de terapia/coaching agendadas entre un paciente y un proveedor. Registra la fecha programada, tipo de videollamada, estado de la sesión, solicitudes de cambio o cancelación (más/menos de 24h de aviso), asistencia registrada (`attendance`) y las 5 métricas de evaluación de calidad del terapeuta.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID único de la cita.
client_idint(11)NONoneFKPaciente asistente.
provider_idint(11)NONoneFKTerapeuta que atiende.
scheduled_atdatetimeNONoneINDEXFecha y hora programada.
typeenum('therapy','coaching','intake')YES'therapy'-Modalidad de la sesión.
video_linkvarchar(255)YESNULL-URL directa a la videollamada segura.
statusenum('scheduled','completed','cancelled','late_cancel')YES'scheduled'INDEXEstado de la cita.
change_request_typeenum('none','reschedule','cancel')YES'none'-Tipo de cambio solicitado.
attendancetinyint(1)YESNULL-1=Asistió, 0=No asistió (Ausente).
rating_overalltinyint(1)YESNULL-Evaluación global de la sesión (1 a 5).
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE
provider_id ➔ providers(id)ON DELETE CASCADE

crisis_assessments

4. Citas & Triaje Clínico
ENGINE: InnoDB

Cuestionario de evaluación inmediata de riesgo de crisis de 3 preguntas clave (Intención, Seguridad física y Red de apoyo). Si el resultado determina alto riesgo (`high_risk`), activa automáticamente alertas de crisis en la plataforma.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de la evaluación.
client_idint(11)NONoneFKPaciente evaluado.
q1_intenttinyint(1)NONone-Respuesta Pregunta 1: Intención autodestructiva.
q2_safetytinyint(1)NONone-Respuesta Pregunta 2: Entorno seguro.
q3_supporttinyint(1)NONone-Respuesta Pregunta 3: Contacto de apoyo disponible.
resultenum('safe','high_risk')NONone-Resultado del triaje de riesgo.
created_attimestampNOcurrent_timestamp()-Fecha y hora del test.
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE

alerts

4. Citas & Triaje Clínico
ENGINE: InnoDB

Sistema centralizado de alertas de seguridad del paciente. Registra alertas automáticas por riesgo de crisis (`crisis_risk`) o caída drástica de puntuaciones de bienestar (`screen_wellbeing`). Permite gestionar el flujo de resolución por parte del equipo clínico o administrador.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de la alerta.
client_idint(11)NONoneFKPaciente afectado por la alerta.
typeenum('crisis_risk','screen_wellbeing')NONone-Categoría de la alerta.
severityenum('critical','warning','info')NO'warning'-Nivel de severidad técnica/clínica.
statusenum('active','resolved')NO'active'INDEXEstado de atención (Activa / Resuelta).
resolved_byint(11)YESNULLFKUsuario admin/clínico que resolvió la alerta.
resolved_attimestampYESNULL-Fecha y hora de resolución.
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE
resolved_by ➔ users(id)ON DELETE SET NULL

safety_care_plans

4. Citas & Triaje Clínico
ENGINE: InnoDB

Planes formales de contención de crisis y seguridad médica redactados colaborativamente entre el terapeuta y el paciente en situaciones de alto riesgo. Almacena estrategias de afrontamiento, contactos de red de apoyo y confirmación explícita.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del plan.
client_idint(11)NONoneFKPaciente asociado.
provider_idint(11)NONoneFKTerapeuta responsable.
session_idint(11)YESNULLFKSesión en la que se formuló.
coping_strategiestextYESNULL-Estrategias de afrontamiento.
is_confirmedtinyint(1)YES0-Confirmación explícita por el paciente.
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE
provider_id ➔ providers(id)ON DELETE CASCADE
session_id ➔ appointments(id)ON DELETE SET NULL

questionnaires_results

4. Citas & Triaje Clínico
ENGINE: InnoDB

Resultados de evaluaciones clínicas estandarizadas internacionales (PHQ-9 para depresión, GAD-7 para ansiedad y WHO-5 para bienestar). Almacena las respuestas individuales estructuradas en `answers_json`, puntuación total (`score`) y nivel de riesgo determinado.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del resultado.
client_idint(11)NONoneFKPaciente evaluado.
typeenum('PHQ9','GAD7','WHO5')NONoneINDEXCuestionario aplicado.
scoreint(11)NONone-Puntuación numérica total calculada.
risk_levelenum('minimal','mild','moderate',...)YESNULL-Nivel de severidad clínica inferido.
answers_jsonlongtext (JSON)YESNULL-JSON validado con las respuestas a cada ítem.
administered_byint(11)YESNULLFKProveedor que administró la prueba.
🔗 Foreign Key Constraints
client_id ➔ clients(id)ON DELETE CASCADE
administered_by ➔ providers(id)ON DELETE SET NULL

invoices

5. Facturación & Pagos
ENGINE: InnoDB

Registros contables de facturación por servicios de terapia/coaching prestados. Relaciona la sesión realizada con el proveedor emisor, el paciente receptor y la empresa corporativa financiadora.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de factura.
session_idint(11)YESNULLFKCita asociada.
provider_idint(11)YESNULLFKProveedor de la atención.
amountdecimal(10,2)NONone-Monto bruto cobrado.
currencyvarchar(10)YES'EUR'-Moneda (predeterminado EUR para IE/UK).
statusenum('pending','submitted','paid')YES'pending'INDEXEstado del ciclo de cobro.
pdf_pathvarchar(255)YESNULL-Ruta al archivo PDF generado.
🔗 Foreign Key Constraints
session_id ➔ appointments(id)ON DELETE SET NULL
provider_id ➔ providers(id)ON DELETE SET NULL
client_id ➔ clients(id)ON DELETE SET NULL
company_id ➔ companies(id)ON DELETE SET NULL

payments

5. Facturación & Pagos
ENGINE: InnoDB

Registros de transacciones y conciliaciones de pago asociadas a las facturas emitidas (vía transferencia bancaria o registro manual). Almacena el número de comprobante o ID de transacción externa.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del pago.
invoice_idint(11)NONoneFKFactura pagada.
methodenum('transfer','manual')NO'transfer'-Método de liquidación.
transaction_idvarchar(255)YESNULL-ID o código de transferencia bancaria.
receipt_pathvarchar(255)YESNULL-Comprobante adjunto.
🔗 Foreign Key Constraints
invoice_id ➔ invoices(id)ON DELETE CASCADE

messages

6. Mensajería & Sistema
ENGINE: InnoDB

Sistema de mensajería interna peer-to-peer (ej. Paciente ↔ Terapeuta o Terapeuta ↔ Admin). Implementa mecanismo de borrado suave dual (`deleted_by_sender` y `deleted_by_receiver`) para permitir ocultar chats individualmente sin perder trazabilidad legal.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID del mensaje.
sender_idint(11)NONoneFKUsuario remitente.
receiver_idint(11)NONoneFKUsuario destinatario.
contenttextNONone-Cuerpo cifrado/texto del mensaje.
is_readtinyint(1)YES0INDEX1=Leído, 0=Pendiente.
deleted_by_sendertinyint(1)NO0-Flag de borrado por emisor.
deleted_by_receivertinyint(1)NO0-Flag de borrado por receptor.
🔗 Foreign Key Constraints
sender_id ➔ users(id)ON DELETE CASCADE
receiver_id ➔ users(id)ON DELETE CASCADE

email_queue

6. Mensajería & Sistema
ENGINE: InnoDB

Cola asíncrona de envío de correos electrónicos transaccionales (confirmaciones de cita, alertas de crisis, invitaciones corporativas). Evita bloqueos en peticiones HTTP mediante procesamiento desacoplado en background.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de la cola.
to_emailvarchar(255)NONone-Email del destinatario.
subjectvarchar(500)NONone-Asunto del correo.
statusenum('pending','sent','failed')YES'pending'INDEXEstado del envío.
attemptstinyint(4)YES0-Número de reintentos acumulados.
metadatalongtext (JSON)YESNULL-Metadatos adicionales en formato JSON validado.

faqs

6. Mensajería & Sistema
ENGINE: InnoDB

Base de conocimiento y Preguntas Frecuentes. Permite segmentar el contenido según el rol del usuario objetivo (`target_role`: cliente, proveedor, empresa, admin o todos).

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de la pregunta.
category_idint(11)NONoneFKCategoría de la FAQ.
target_roleenum('all','client','provider',...)NO'all'INDEXRol objetivo para filtrar respuestas.
questionvarchar(500)NONone-Pregunta formulada.
answertextNONone-Respuesta detallada.
🔗 Foreign Key Constraints
category_id ➔ faq_categories(id)ON DELETE CASCADE

faq_categories

6. Mensajería & Sistema
ENGINE: InnoDB

Categorías para organizar las FAQs (ej: Facturación, Uso de Plataforma, Primeros Pasos) con icono emoji y ordenamiento visual.

ColumnData TypeNullableDefaultKeyDescription
idint(11)NOAUTO_INCPRIMARYID de categoría.
slugvarchar(50)NONoneUNIQUESlug amigable para URLs.
labelvarchar(100)NONone-Nombre visible de la categoría.
iconvarchar(20)YES'❓'-Icono o emoji asociativo.