Skip to content

Modelo de datos

SIVA persiste en SQLite (driver sql.js) mediante TypeORM. Las 31 entidades se declaran en backend/src/entities/ y el esquema se crea con la migración 1718300001000-CreateTables.ts (synchronize:false, migrationsRun:true). Los valores booleanos se almacenan como 0/1 y las fechas como date/datetime de SQLite.

⚠️ Nota: algunas restricciones (uniques compuestos, CHECK, ON DELETE) existen solo en la migración y no están decoradas en las entidades. Se indican en cada tabla.

Diagrama Entidad-Relación

Entidades

Usuarios

User → tabla users

Campo (TS)ColumnaTipoNuloDefaultConstraints
ididuuidNogeneradoPK
namenamevarchar(100)No
emailemailvarchar(255)Nounique
passwordpasswordvarcharNooculto (select:false)
roleroletextNoSUPERVISOR
is_activeis_activebooleanNotrue
is_email_verifiedis_email_verifiedbooleanNofalse
email_verification_tokenemail_verification_tokenvarchar(255)select:false
refresh_tokenrefresh_tokentextselect:false
password_reset_tokenpassword_reset_tokenvarchar(255)select:false
password_reset_expirespassword_reset_expiresdatetime
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP
searchNormalizedsearch_normalizedtextíndice de búsqueda
profile1:1cascade, eager

UserProfile → tabla user_profiles

CampoColumnaTipoNuloConstraints
ididuuidNoPK
avatar_keyavatar_keyvarchar(512)
dnidnivarchar(9)
phonephonevarchar(12)
companycompanyvarchar(255)
notesnotestext
useruser_iduuidNounique (UQ_user_profiles_user_id), FK ON DELETE CASCADE

Catálogos

Vigilante → tabla vigilantes

CampoColumnaTipoNuloDefaultConstraints
ididuuidNogeneradoPK
dnidnivarchar(9)Nounique (UQ_vigilantes_dni)
nombrenombrevarchar(100)No
primer_apellidoprimer_apellidovarchar(100)No
segundo_apellidosegundo_apellidovarchar(100)No(vacío si no se informa)
correo_electronico_corporativoidemvarchar(255)
correo_electronico_personalidemvarchar(255)
telefonotelefonovarchar(20)
bloqueadobloqueadobooleanNofalse
motivo_bloqueo / fecha_bloqueoidemtext/datetime
motivo_desbloqueo / fecha_desbloqueoidemtext/datetime
comentarioscomentariostext
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP
searchNormalizedsearch_normalizedtext

Relaciones: N:M tags (vigilante_tags), 1:N vigilanteEjercicios, 1:N asignaciones.

Tag → tabla tags

CampoColumnaTipoNuloDefaultConstraints
ididuuidNogeneradoPK
nombrenombrevarchar(100)No
system_keysystem_keyvarchar(20)unique (UQ_tags_system_key)
colorcolorvarchar(9)No#6c757d
scopescopevarchar(20)Nogeneral
created_atcreated_atdatetimeNoCURRENT_TIMESTAMP

TipoEjercicio → tabla tipos_ejercicio

CampoColumnaTipoNuloConstraints
ididuuidNoPK
nombrenombrevarchar(100)Nounique
created_atcreated_atdatetimeNo

Ubicaciones: Sede → Edificio → Planta → Aula

Sede → tabla sedes

CampoColumnaTipoNuloDefault
ididuuidNoPK
nombrenombrevarchar(150)No
direcciondireccionvarchar(255)No
municipiomunicipiovarchar(100)
codigoPostalcodigo_postalvarchar(10)
provinciaprovinciavarchar(100)
responsableresponsablevarchar(150)
telefonotelefonovarchar(20)
correoContactocorreo_contactovarchar(255)
isActiveis_activebooleanNotrue
observaciones / comollegarobservaciones / como_llegartext
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: 1:N edificios, 1:N ejercicioSedes.

Edificio → tabla edificios

CampoColumnaTipoNuloDefaultÍndice
ididuuidNoPK
nombrenombrevarchar(100)No
sede_idsede_iduuidNoIDX_edificios_sede_id
direcciondireccionvarchar(255)
estadoestadovarchar(20)Noactivo
observacionesobservacionestext
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: N:1 sede, 1:N aulas.

Planta → tabla plantas

CampoColumnaTipoNuloDefaultConstraints
ididuuidNoPK
nombrenombrevarchar(50)Nounique
ordenordenintegerNo0
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: 1:N edificioPlantas, 1:N aulas.

EdificioPlanta → tabla edificio_plantas (puente N:M)

CampoColumnaTipoNuloFK
ididuuidNoPK
edificioedificio_iduuidNoON DELETE CASCADE
plantaplanta_iduuidNoON DELETE CASCADE

⚠️ No tiene unique compuesto: se permiten pares repetidos.

Aula → tabla aulas

CampoColumnaTipoNuloDefaultÍndice
ididuuidNoPK
nombrenombrevarchar(100)No
planta_idplanta_iduuidFK ON DELETE SET NULL
capacidadcapacidadintegerNo
tipotipovarchar(20)Nogeneral
equipamientoequipamientotext
estadoestadovarchar(20)Nodisponible
observacionesobservacionestext
edificio_idedificio_iduuidNoIDX_aulas_edificio_id
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: N:1 planta, N:1 edificio, N:M tags (aula_tags), 1:N ejercicioSedeAulas.

Convocatoria y ejercicio

Convocatoria → tabla convocatorias

CampoColumnaTipoNuloDefault
ididuuidNoPK
nombrenombrevarchar(200)No
anioaniointegerNo2025
observacionesobservacionestext
estadoestadotextNoABIERTA
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: 1:N ejercicios, 1:N miembros.

TribunalMiembro → tabla tribunal_miembros

CampoColumnaTipoNuloDefault
ididuuidNoPK
convocatoria_ididemuuidNo
tipotipotextNoTITULAR
nombrenombrevarchar(200)No
cargocargotextNoVOCAL
correo_electronicoidemvarchar(255)
telefonotelefonovarchar(20)
renunciarenunciabooleanNofalse
motivo_renuncia / fecha_renunciaidemtext/datetime
motivo_reincorporacion / fecha_reincorporacionidemtext/datetime
comentarioscomentariostext
searchNormalizedsearch_normalizedtext
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relación: N:1 convocatoria.

Ejercicio → tabla ejercicios

CampoColumnaTipoNuloDefault
ididuuidNoPK
nombrenombrevarchar(200)No
fechafechadate
hora_vigilantes_aula_tribunalidemtext
hora_comienzo_ejercicioidemtext
duracion_acceso_libreideminteger
duracion_promocion_internaideminteger
observacionesobservacionestext
tipotipotextNo
convocatoria_ididemuuidNo
estadoestadotextNoABIERTA
fecha_cierreidemdatetime
cerrado_poridemuuid— (sin FK)
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Relaciones: N:1 convocatoria, 1:N ejercicioSedes, 1:N vigilanteEjercicios, 1:N llamamientos.

EjercicioGrupo → tabla ejercicio_grupos

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_ididemuuidNoFK ON DELETE CASCADE
nombrenombrevarchar(200)No
ordenordenintegerNo0
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

VigilanteEjercicio → tabla vigilante_ejercicios (puente N:M con datos)

CampoColumnaTipoNuloConstraints
ididuuidNoPK
vigilante_ididemuuidNoIDX_vigilante_ejercicios_vigilante_id
ejercicio_ididemuuidNoIDX_vigilante_ejercicios_ejercicio_id
grupo_ididemuuidFK ON DELETE SET NULL
ordenordeninteger
fecha_seleccionidemdatetimeNo
created_at/updated_atidemdatetimeNo

Constraints: unique (vigilante_id, ejercicio_id).

EjercicioSede → tabla ejercicio_sedes

CampoColumnaTipoNulo
ididuuidNo
ejercicio_ididemuuidNo
sede_ididemuuidNo

Constraints: unique (ejercicio_id, sede_id). Relación 1:N ejercicioSedeEdificios.

EjercicioSedeEdificio → tabla ejercicio_sede_edificios

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_sede_ididemuuidNoFK ON DELETE CASCADE
edificio_ididemuuidNo
modomodovarchar(20)Nocalcular_aulas
vigilantes_manualideminteger

Constraints: unique (ejercicio_sede_id, edificio_id).

EjercicioSedeAula → tabla ejercicio_sede_aulas

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_sede_edificio_ididemuuidNoFK ON DELETE CASCADE
aula_idaula_iduuidNo
modo_asignacionidemtextNoratio
ratio_denominadorideminteger
vigilantes_fijosideminteger

Constraints: unique (ejercicio_sede_edificio_id, aula_id).

Llamamientos

Llamamiento → tabla llamamientos

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_ididemuuidNoFK ON DELETE CASCADE
numeronumerointegerNo
fecha_exportacionidemdatetimeNo
fecha_limite_respuestaidemdatetime
estadoestadotextNoactivo
fecha_anulacion / motivo_anulacionidemdatetime/text
created_byidemuuidFK ON DELETE SET NULL
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Constraints: unique (ejercicio_id, numero) (solo en migración).

VigilanteLlamamiento → tabla vigilante_llamamientos (puente N:M con datos)

CampoColumnaTipoNuloDefault
ididuuidNoPK
llamamiento_ididemuuidNoFK ON DELETE CASCADE
vigilante_ididemuuidNoIDX_vigilante_llamamientos_vigilante_id
grupo_nombreidemtext
fecha_envioidemdatetimeNo
estado_respuestaidemtextNopendiente
sede_idsede_iduuidFK ON DELETE SET NULL
fecha_respuestaidemdatetime
origen_confirmacionidemtext
correo_enviadoidembooleanNofalse
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Constraints: unique (llamamiento_id, vigilante_id).

Asignaciones

Asignacion → tabla asignaciones

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_sede_aula_ididemuuidFK ON DELETE CASCADE
ejercicio_sede_edificio_ididemuuidFK ON DELETE CASCADE
vigilante_ididemuuidNoIDX_asignaciones_vigilante_id
es_responsable_aulaidembooleanNofalse
estado_asistenciaidemtextNopendiente
anuladoanuladobooleanNofalse
motivo_anulacionidemtext
fecha_anulacion_asistenciaidemdatetime
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Constraints:

  • unique (ejercicio_sede_aula_id, vigilante_id).
  • unique (ejercicio_sede_edificio_id, vigilante_id).
  • CHECK CHK_asignaciones_destino: exactamente uno de los dos destinos no nulo.
  • CHECK CHK_asignaciones_estado_asistencia: pendiente | asistio | no_asistio.

Notificaciones y documentos

Notificacion → tabla notificaciones

CampoColumnaTipoNuloDefault
ididuuidNoPK
ejercicio_ididemuuidNoFK ON DELETE CASCADE
numeronumerointegerNo
tipotipotextNollamamiento
asuntoasuntotextNo
cuerpocuerpotextNo
fecha_envioidemdatetimeNo
estadoestadotextNoactivo
fecha_anulacion / motivo_anulacionidemdatetime/text
created_byidemuuidFK ON DELETE SET NULL
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Constraints: unique (ejercicio_id, tipo, numero) (solo en migración). Relaciones 1:N notificacionVigilantes, 1:N documentos.

NotificacionVigilante → tabla notificacion_vigilantes

CampoColumnaTipoNuloDefault
ididuuidNoPK
notificacion_ididemuuidNoFK ON DELETE CASCADE
vigilante_ididemuuidNoIDX_notificacion_vigilantes_vigilante_id
asignacion_ididemuuidFK ON DELETE SET NULL
fecha_envioidemdatetimeNo
snapshotsnapshottext
correo_enviadoidembooleanNofalse
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Constraints: unique (notificacion_id, vigilante_id).

NotificacionDocumento → tabla notificacion_documentos

CampoColumnaTipoNulo
ididuuidNo
notificacion_ididemuuidNo (FK ON DELETE CASCADE)
nombre_originalidemtextNo
nombre_almacenadoidemtextNo
mime_typeidemtextNo
tamañotamanointegerNo
created_atcreated_atdatetimeNo

EjercicioDocumento → tabla ejercicio_documentos

Misma estructura que NotificacionDocumento, con ejercicio_id en lugar de notificacion_id (FK ON DELETE CASCADE).

Penalizaciones

Penalizacion → tabla penalizaciones

CampoColumnaTipoNuloDefault
ididuuidNoPK
vigilante_ididemuuidNoIDX_penalizaciones_vigilante_id
asignacion_ididemuuidFK ON DELETE SET NULL
ejercicio_ididemuuidFK ON DELETE SET NULL
motivomotivotext
duracion_diasidemintegerNo
fecha_inicioidemdatetimeNo
fecha_finidemdatetimeNo
estadoestadotextNoactiva
fecha_levantada / motivo_levantamientoidemdatetime/text
created_byidemuuidFK ON DELETE SET NULL (solo migración)
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

Plantillas y configuración

EmailTemplate → tabla email_templates

CampoColumnaTipoNuloDefault
ididuuidNoPK
nombrenombrevarchar(150)No
descriptiondescriptiontext
tipotipotextNo
asuntoasuntovarchar(300)No
cuerpocuerpotextNo
is_activeis_activebooleanNofalse
is_systemis_systembooleanNofalse
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

La migración añade search_normalized, no declarada en la entidad.

DocumentTemplate → tabla document_templates

CampoColumnaTipoNuloDefault
ididuuidNoPK
nombrenombrevarchar(150)No
descripcionidemtext
tipotipotextNo
htmlhtmltext
is_activeis_activebooleanNofalse
is_systemis_systembooleanNofalse
created_at/updated_atidemdatetimeNoCURRENT_TIMESTAMP

ParametroSistema → tabla parametros_sistema

CampoColumnaTipoNuloConstraints
ididuuidNoPK
claveclavevarchar(100)Nounique
valorvalortextNo
descripciondescripciontext
created_at/updated_atidemdatetimeNo

Importación masiva

ImportBatch → tabla import_batches

CampoColumnaTipoNuloDefault
ididuuidNoPK
user_iduser_iduuidNoFK ON DELETE CASCADE
archivo_nombreidemvarchar(255)
etiquetas_aplicadasidemtext
total_nuevosidemintegerNo0
total_actualizadosidemintegerNo0
total_solo_etiquetaidemintegerNo0
total_sin_cambiosidemintegerNo0
total_omitidosidemintegerNo0
total_erroresidemintegerNo0
created_atcreated_atdatetimeNoCURRENT_TIMESTAMP

ImportBatchRow → tabla import_batch_rows

CampoColumnaTipoNuloÍndice
ididuuidNoPK
import_batch_ididemuuidNoIDX_import_batch_rows_import_batch_id, FK ON DELETE CASCADE
dnidnivarchar(20)
resultadoresultadovarchar(20)No
detalledetalletext
created_atcreated_atdatetimeNo

Enumerados

EnumValores
UserRoleSUPERADMIN, ADMIN, SUPERVISOR
ConvocatoriaEstadoABIERTA, CERRADA
EjercicioEstadoABIERTA, CERRADA
EstadoAsistenciapendiente, asistio, no_asistio
LlamamientoEstadoactivo, anulado, cerrado
RespuestaEstadopendiente, confirmado, rechazado, sin_respuesta
OrigenConfirmacionmanual, excel
NotificacionEstadoactivo, anulado
NotificacionTipocitacion, llamamiento, anulacion, restauracion
PenalizacionEstadoactiva, finalizada, levantada
EmailTemplateTipoPASSWORD_RESET, VERIFICATION_EMAIL, CONVOCATORIA_LLAMAMIENTO, NOTIFICACION_ASIGNACION, NOTIFICACION_REASIGNACION, NOTIFICACION_CANCELACION, ANULACION_ASISTENCIA, NOTIFICACION_RESTAURACION
DocumentTemplateTipoCONTROL_ASISTENCIA
TribunalTipoTITULAR, SUPLENTE
TribunalMiembroCargoPRESIDENTE, VOCAL, SECRETARIO
EjercicioSedeEdificio.modocalcular_aulas, manual
EjercicioSedeAula.modo_asignacionratio, fijo

Índices y constraints destacados

  • users.email único; users.search_normalized para búsquedas sin acentos.
  • vigilantes.dni único.
  • user_profiles.user_id único (1:1 con users).
  • tags.system_key único.
  • plantas.nombre único; tipos_ejercicio.nombre único; parametros_sistema.clave único.
  • Claves foráneas con ON DELETE CASCADE: user_profiles, ejercicio_grupos, ejercicio_sede_edificios, ejercicio_sede_aulas, asignaciones (ambos destinos), llamamientos, vigilante_llamamientos, notificaciones, notificacion_vigilantes, notificacion_documentos, ejercicio_documentos, import_batches, import_batch_rows, edificio_plantas y los puentes vigilante_tags/aula_tags (lado etiqueta).
  • Claves foráneas con ON DELETE SET NULL: aulas.planta_id, vigilante_ejercicios.grupo_id, vigilante_llamamientos.sede_id, notificacion_vigilantes.asignacion_id, penalizaciones.ejercicio_id, penalizaciones.asignacion_id, penalizaciones.created_by, llamamientos.created_by, notificaciones.created_by.

Datos iniciales

Las migraciones de datos crean:

  • Usuarios: superadministrador (SUPERADMIN) siempre, y dos cuentas de desarrollo (ADMIN Laura y SUPERVISOR) — ver DEUDA_TECNICA.md para la salvedad de que se crean también en producción.
  • Plantillas de email por defecto, etiquetas por defecto, tipos de ejercicio, plantas, parámetros de configuración y datos de demo (vigilantes, sedes, edificios, aulas, convocatorias, tribunales y ejercicios).

SIVA — Sistema Integral de Vigilantes de Aulas