MELIKA’s persistence layer is a PostgreSQL database whose full schema — tables, indexes, foreign-key constraints, PL/pgSQL functions, and triggers — lives in a single SQL file atDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Imjuanisss/proyecto-melika/llms.txt
Use this file to discover all available pages before exploring further.
server/src/database/melika_db.sql. Applying this file to a fresh database is the only migration step required. This page walks through local setup, explains every table and trigger, and shows how to seed the first admin user so you can log in immediately after deployment.
Prerequisites
PostgreSQL ≥ 14
Install PostgreSQL locally via your OS package manager or use the Railway-managed Postgres service in production. The
psql CLI must be available in your terminal.Node.js ≥ 20
Required to run the admin-creation script in
server/scripts/crearAdmin.js after the schema is applied.Applying the schema
Create the database
Create a new, empty database named If your PostgreSQL user is not the OS user, supply credentials explicitly:
melika_db (or any name you prefer — just update DB_NAME accordingly):Apply the schema
Run the bundled SQL file against the new database. This creates all tables, sequences, constraints, functions, and triggers in the correct dependency order:For remote databases (including Railway), supply the full connection string:
Schema overview
The schema models a complete digital health workflow — from user authentication and invitation management through to appointment booking, clinical history recording, and audit logging.| Table | Description |
|---|---|
usuarios | Platform users (patients, doctors, admins). Stores hashed passwords, email-verification status, and role. |
codigos_verificacion | Short-lived email verification codes sent to users on registration or password reset. |
tokens_invitacion | Single-use invitation tokens that allow a new user to complete registration via a secure link. |
especialidades | Medical specialities catalogue (e.g. Cardiología, Pediatría). Referenced by medicos. |
medicamentos | Medication catalogue used when composing prescriptions inside clinical histories. |
medicos | Doctor profiles linked to a usuarios record; stores specialty, biography, rating, and schedule metadata. |
franjas_horarias | Individual bookable time slots belonging to a doctor, with a disponible flag managed by triggers. |
citas | Appointment records linking a patient, a doctor, and a franja_horaria. Subject to audit triggers. |
historias_clinicas | Clinical history entries attached to a cita; stores diagnosis, treatment, and prescribed medications. |
logs_citas | Immutable audit log populated automatically by the fn_auditar_citas trigger on every change to citas. |
documentos_clinicos | Clinical documents (medical histories, prescriptions, lab orders, external uploads) attached to a patient or clinical history. |
recetas_medicas | Individual prescription lines (medication, dose, frequency, duration) linked to a clinical history. |
ordenes_examenes | Lab and imaging orders issued within a clinical history. |
Database triggers
MELIKA offloads three critical business rules to PostgreSQL triggers, guaranteeing correctness regardless of which application layer (API, admin script, direct SQL) performs the write.fn_auditar_citas — audit trail for appointments
fn_auditar_citas — audit trail for appointments
Fires AFTER INSERT, UPDATE, or DELETE on the
citas table. Every mutation is recorded in logs_citas with the operation type, a timestamp, and a snapshot of the affected row. Because logs_citas is written inside the same transaction, the audit record is guaranteed to exist if and only if the original write succeeded.This table provides the immutable audit trail required for healthcare data compliance. Do not grant DELETE or UPDATE privileges on logs_citas to the application database user.fn_verificar_disponibilidad_critica — concurrency-safe slot booking
fn_verificar_disponibilidad_critica — concurrency-safe slot booking
Fires BEFORE INSERT on
citas. It checks whether the target franja_horaria is still marked disponible = TRUE. If the slot has already been taken, the function raises a custom PostgreSQL exception:45001— the specified time slot does not exist in the records.45002— the slot is already booked (disponible = FALSE).
fn_sincronizar_franja_horaria — automatic slot state management
fn_sincronizar_franja_horaria — automatic slot state management
Fires AFTER INSERT, UPDATE, or DELETE on
citas and keeps the franjas_horarias.disponible flag in sync with actual appointment state:- INSERT — marks the booked slot as
disponible = FALSEimmediately. - UPDATE (state transitions to
'cancelada') — setsdisponible = TRUE, making the time window bookable again without any additional API call. - DELETE — releases the slot by setting
disponible = TRUE.
disponible flag — the source of truth for scheduling — always consistent with actual appointment state, even if a change is performed directly in the database.Creating the first admin user
The database starts empty — there are no users until you run the admin-creation script. This script inserts a fully verified admin account directly into theusuarios table, bypassing the email-verification flow. The admin email and an initial password are hardcoded in the script; you should change the password immediately after the first login.
Set database environment variables
Make sure all five
DB_* variables (DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD) are set in server/.env (local) or in the Railway service environment (production) before running the script.Run the script
From the repository root:The script does not prompt for input — it uses the hardcoded credentials defined inside
crearAdmin.js. If an admin with the same email already exists, the script exits without creating a duplicate. On success it prints the new account’s email, role, and the initial plaintext password to the console.On Railway, run this script using the Railway shell for the server service after the schema has been applied. Open the service in the Railway dashboard, click Shell, and execute
node scripts/crearAdmin.js in the remote environment (the shell opens at the service root directory, /server).Railway PostgreSQL
When you add a PostgreSQL service to your Railway project and link it to the server service, Railway exposes the following individual connection variables, which map directly to whatserver/src/config/db.js expects:
DB_* variable names that MELIKA uses — you must either copy the values from the Railway Postgres service’s Connect tab and add them as DB_HOST, DB_PORT, DB_NAME, DB_USER, and DB_PASSWORD in the server service variables, or use Railway’s variable references to wire them through.
Backup recommendations
Usepg_dump to create a portable backup of the entire database:
For production deployments handling real patient data, schedule daily automated backups and store them in a separate cloud bucket (e.g. AWS S3, Google Cloud Storage). Verify restore procedures periodically — a backup you have never tested is not a backup.