Esquema de Supabase
Supabase actúa como backend principal de la aplicación. La base de datos subyacente es PostgreSQL. A continuación se describe cada tabla, sus columnas y las relaciones entre ellas.
Tabla: usuarios
Almacena los datos de los usuarios registrados en la aplicación.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único del usuario |
nombre | varchar(100) | NOT NULL | Nombre completo del usuario |
dni | varchar(20) | UNIQUE | Documento Nacional de Identidad. Se usa como identificador de login |
contraseniaHash | varchar(255) | Contraseña almacenada (texto plano en la versión actual) | |
email | varchar(100) | UNIQUE | Correo electrónico. Se usa para la recuperación de contraseña |
telefono | varchar(20) | Número de teléfono de contacto | |
admin | integer | DEFAULT 0 | Indica si el usuario tiene rol de administrador (0 = usuario, 1 = admin) |
premium | boolean | DEFAULT false | Indica si el usuario tiene suscripción Premium activa |
fecha_ini_prem | date | Fecha de inicio de la suscripción Premium | |
fecha_fin_prem | date | Fecha de fin de la suscripción Premium | |
foto | text | Imagen de perfil codificada en Base64 |
La data class correspondiente es models/Usuario.kt.
Tabla: maquinas
Almacena el catálogo de maquinaria del gimnasio.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único de la máquina |
nombre | varchar(100) | NOT NULL | Nombre descriptivo de la máquina |
tipo | varchar(50) | Categoría de ejercicio (Cardio, Espalda, Pierna, Pecho, etc.) | |
estado | integer | DEFAULT 0 | Campo de estado genérico |
descripcion | text | Descripción detallada de la máquina | |
operativa | boolean | DEFAULT true | Indica si la máquina está disponible para reservas |
mantenimiento_desde | varchar | Fecha y hora de inicio del período de mantenimiento (yyyy-MM-dd HH:mm) | |
mantenimiento_hasta | varchar | Fecha y hora de fin del período de mantenimiento (yyyy-MM-dd HH:mm) |
La data class correspondiente es models/Maquina.kt.
Tabla: reservas
Almacena las reservas de maquinaria realizadas por los usuarios.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único de la reserva |
id_usuario | integer | FK → usuarios.id | Usuario que realizó la reserva |
id_maquina | integer | FK → maquinas.id | Máquina reservada |
fecha | date | Fecha de la reserva (yyyy-MM-dd) | |
hora_inicio | time | Hora de inicio de la franja reservada | |
hora_fin | time | Hora de fin de la franja reservada | |
estado | boolean | DEFAULT true | true = activa, false = cancelada |
Las data classes correspondientes son models/Reserva.kt y models/ReservaConDetalles.kt. La segunda incluye los objetos Usuario y Maquina embebidos, obtenidos mediante la sintaxis de relaciones de PostgREST (*, usuarios(*), maquinas(*)).
Tabla: platos
Almacena los platos nutricionales del catálogo.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único del plato |
id_usuario | integer | FK → usuarios.id | Usuario que sugirió el plato (nullable para platos del sistema) |
nombre | varchar(100) | NOT NULL | Nombre del plato |
descripcion | text | Descripción o receta del plato | |
calorias | double precision | Contenido calórico por ración | |
imagen_url | varchar(255) | URL de imagen o cadena Base64 de la imagen del plato | |
fecha_subida | timestamp | Fecha y hora de creación del registro | |
visibilidad | boolean | DEFAULT true | Indica si el plato es visible en el catálogo |
tiempo | varchar | Tiempo de preparación estimado (por ejemplo, "30 minutos") | |
aceptado | boolean | DEFAULT false | Indica si el plato ha sido aprobado por un administrador |
La data class correspondiente es models/Plato.kt.
Tabla: peso_usuario
Almacena el historial de registros de peso de cada usuario.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único del registro |
id_usuario | integer | FK → usuarios.id | Usuario al que pertenece el registro |
peso | double precision | NOT NULL | Peso en kilogramos |
fecha | date | Fecha del registro (yyyy-MM-dd) |
La aplicación impone la restricción de un único registro por día a nivel de UI. La pantalla comprueba si ya existe un registro para la fecha actual antes de permitir añadir uno nuevo.
La data class correspondiente es models/PesoUsuario.kt.
Tabla: pagos
Almacena el historial de transacciones de suscripción Premium.
| Columna | Tipo | Restricciones | Descripción |
|---|---|---|---|
id | integer | PK, auto-increment | Identificador único del pago |
id_usuario | integer | FK → usuarios.id | Usuario que realizó el pago |
monto | double precision | NOT NULL | Importe de la transacción en euros |
fecha_pago | date | Fecha en que se realizó el pago | |
tipo | varchar(50) | Modalidad de suscripción (Mensual, Semestral, Anual) | |
metodo_pago | varchar(25) | Método de pago utilizado (Tarjeta, Bizum) |
La data class correspondiente es models/Pago.kt.
Diagrama de relaciones
usuarios (id)
|
|--< reservas (id_usuario) >-- maquinas (id)
|
|--< peso_usuario (id_usuario)
|
|--< platos (id_usuario)
|
|--< pagos (id_usuario)
Las relaciones son todas de tipo uno a muchos. No se definen claves foráneas explícitas a nivel de Supabase Dashboard; la integridad referencial se gestiona a nivel de aplicación.
Row Level Security
Las políticas de Row Level Security (RLS) de Supabase no están configuradas en esta versión. El acceso a los datos se realiza con la anon key, por lo que cualquier cliente con la clave puede leer y escribir en todas las tablas. En un entorno de producción sería imprescindible definir políticas RLS adecuadas o utilizar la service_role key exclusivamente desde un backend de confianza.
Constantes de base de datos
Los nombres de las tablas y columnas se centralizan en DbConstants.kt mediante los objetos DbTables y DbColumns, evitando el uso de strings literales dispersos por el código:
object DbTables {
const val USUARIOS = "usuarios"
const val MAQUINAS = "maquinas"
const val PLATOS = "platos"
const val PAGOS = "pagos"
const val RESERVAS = "reservas"
const val PESO_USUARIO = "peso_usuario"
}
object DbColumns {
const val ID = "id"
const val DNI = "dni"
const val NOMBRE = "nombre"
// ...
}