Un solo conjunto residencial por instancia. Todas las tablas usan id como llave primaria; en los diagramas solo aparecen las llaves foráneas. Los atributos de negocio se omiten a propósito.
condominio_id. Los datos del conjunto (nombre, NIT, logo) van en ConfiguracionConjunto, una tabla de una sola fila. El portal multi-conjunto vive fuera, en otra app.codigo fijo. El código del backend compara contra codigo, nunca contra el id.deleted_at y deleted_by en las tablas de negocio. No aplica a tablas de registro que solo crecen: Auditoria, Notificacion, RegistroAcceso, TicketHistorial, Voto y PagoCargo.entidad_tipo + entidad_id, sin FK física hacia cada tabla.Las tablas principales de cada módulo y cómo se conectan, sin catálogos. Usuario y Propiedad son el centro: casi todo cuelga de una de las dos.
erDiagram
Usuario ||--o{ PropiedadPersona : "vive o es dueño"
Propiedad ||--o{ PropiedadPersona : "tiene"
Propiedad ||--o{ Adicional : "tiene asignado"
Propiedad ||--o{ Ticket : "reporta"
Propiedad ||--o{ Cargo : "debe"
Propiedad ||--o{ Pago : "paga"
Pago ||--o{ PagoCargo : "se aplica en"
Cargo ||--o{ PagoCargo : "se cubre con"
Amenidad ||--o{ ReservaAmenidad : "se reserva en"
Propiedad ||--o{ ReservaAmenidad : "reserva"
ReservaAmenidad |o--o| Cargo : "genera"
Sesion ||--o{ AsistenciaSesion : "registra"
Sesion ||--o| Acta : "produce"
Sesion |o--o{ Votacion : "incluye"
Votacion ||--o{ Voto : "recibe"
Propiedad ||--o{ Voto : "emite"
Propiedad ||--o{ AutorizacionVisita : "autoriza"
AutorizacionVisita |o--o{ RegistroAcceso : "genera entradas"
Propiedad ||--o{ Trasteo : "solicita"
Adicional ||--o{ ReservaParqueadero : "se reserva en"
Usuario ||--o{ Notificacion : "recibe"
Usuario ||--o{ Auditoria : "realiza"
erDiagram
Rol ||--o{ Usuario : "define permisos"
TipoDocumento ||--o{ Usuario : "clasifica"
Usuario ||--o{ TokenRecuperacion : "solicita"
Usuario {
int rol_id FK
int tipo_documento_id FK
}
TokenRecuperacion {
int usuario_id FK
}
ConfiguracionConjunto {
string nota "una sola fila, sin FKs"
}
erDiagram
Torre ||--o{ Propiedad : "agrupa"
TipoPropiedad ||--o{ Propiedad : "clasifica"
Propiedad |o--o{ Adicional : "tiene asignado"
TipoAdicional ||--o{ Adicional : "clasifica"
Propiedad ||--o{ Vehiculo : "registra"
Propiedad ||--o{ PropiedadPersona : "tiene"
Usuario ||--o{ PropiedadPersona : "pertenece a"
TipoRelacion ||--o{ PropiedadPersona : "define"
Propiedad {
int torre_id FK
int tipo_propiedad_id FK
}
Adicional {
int propiedad_id FK "nullable"
int tipo_adicional_id FK
}
Vehiculo {
int propiedad_id FK
}
PropiedadPersona {
int propiedad_id FK
int usuario_id FK
int tipo_relacion_id FK
}
erDiagram
Propiedad |o--o{ Ticket : "reporta"
Usuario ||--o{ Ticket : "solicita"
Usuario |o--o{ Ticket : "atiende"
CategoriaTicket ||--o{ Ticket : "clasifica"
PrioridadTicket ||--o{ Ticket : "prioriza"
EstadoTicket ||--o{ Ticket : "estado actual"
Ticket ||--o{ TicketHistorial : "registra cambios"
Usuario ||--o{ TicketHistorial : "hace el cambio"
Ticket ||--o{ TicketAdjunto : "adjunta"
Ticket {
int propiedad_id FK "nullable, zona común"
int solicitante_id FK "Usuario"
int asignado_a_id FK "Usuario, nullable"
int categoria_ticket_id FK
int prioridad_ticket_id FK
int estado_ticket_id FK
}
TicketHistorial {
int ticket_id FK
int usuario_id FK
int estado_anterior_id FK "EstadoTicket"
int estado_nuevo_id FK "EstadoTicket"
}
TicketAdjunto {
int ticket_id FK
}
erDiagram
Propiedad ||--o{ Cargo : "debe"
ConceptoCobro ||--o{ Cargo : "clasifica"
EstadoCargo ||--o{ Cargo : "estado"
Propiedad ||--o{ Pago : "paga"
Usuario ||--o{ Pago : "registra pago"
Usuario |o--o{ Pago : "aprueba"
MetodoPago ||--o{ Pago : "medio"
EstadoPago ||--o{ Pago : "estado"
Pago ||--o{ PagoCargo : "se aplica en"
Cargo ||--o{ PagoCargo : "se cubre con"
Cargo {
int propiedad_id FK
int concepto_cobro_id FK
int estado_cargo_id FK
}
Pago {
int propiedad_id FK
int pagador_id FK "Usuario"
int aprobado_por_id FK "Usuario, nullable"
int metodo_pago_id FK
int estado_pago_id FK
}
PagoCargo {
int pago_id FK
int cargo_id FK
}
erDiagram
Amenidad ||--o{ HorarioAmenidad : "disponible en"
Amenidad ||--o{ BloqueoAmenidad : "cerrada en"
Amenidad ||--o{ ReservaAmenidad : "se reserva en"
Propiedad ||--o{ ReservaAmenidad : "reserva"
Usuario ||--o{ ReservaAmenidad : "solicita"
EstadoReserva ||--o{ ReservaAmenidad : "estado"
ReservaAmenidad |o--o| Cargo : "genera cobro"
HorarioAmenidad {
int amenidad_id FK
}
BloqueoAmenidad {
int amenidad_id FK
}
ReservaAmenidad {
int amenidad_id FK
int propiedad_id FK
int usuario_id FK
int estado_reserva_id FK
int cargo_id FK "nullable, único"
}
erDiagram
TipoSesion ||--o{ Sesion : "clasifica"
EstadoSesion ||--o{ Sesion : "estado"
Usuario ||--o{ Sesion : "crea"
Sesion ||--o{ AsistenciaSesion : "registra"
Propiedad ||--o{ AsistenciaSesion : "asiste"
Usuario ||--o{ AsistenciaSesion : "representa"
Sesion ||--o| Acta : "produce"
Usuario ||--o{ Acta : "redacta"
Sesion |o--o{ Votacion : "incluye"
EstadoVotacion ||--o{ Votacion : "estado"
Votacion ||--o{ OpcionVotacion : "ofrece"
Votacion ||--o{ Voto : "recibe"
OpcionVotacion ||--o{ Voto : "elegida en"
Propiedad ||--o{ Voto : "emite"
Usuario ||--o{ Voto : "vota"
Sesion {
int tipo_sesion_id FK
int estado_sesion_id FK
int creado_por_id FK "Usuario"
}
AsistenciaSesion {
int sesion_id FK
int propiedad_id FK
int usuario_id FK
}
Acta {
int sesion_id FK "único"
int redactada_por_id FK "Usuario"
}
Votacion {
int sesion_id FK "nullable"
int estado_votacion_id FK
int creado_por_id FK "Usuario"
}
OpcionVotacion {
int votacion_id FK
}
Voto {
int votacion_id FK
int opcion_votacion_id FK
int propiedad_id FK
int usuario_id FK
}
deleted_at de Sesion.
erDiagram
TipoDocumento ||--o{ Visitante : "clasifica"
Visitante ||--o{ AutorizacionVisita : "es autorizado"
Propiedad ||--o{ AutorizacionVisita : "autoriza"
Usuario ||--o{ AutorizacionVisita : "firma"
TipoVisita ||--o{ AutorizacionVisita : "esporádica o recurrente"
AutorizacionVisita |o--o{ RegistroAcceso : "genera entradas"
Visitante ||--o{ RegistroAcceso : "entra"
Propiedad ||--o{ RegistroAcceso : "recibe"
Usuario ||--o{ RegistroAcceso : "registra en portería"
Propiedad ||--o{ Trasteo : "solicita"
Usuario ||--o{ Trasteo : "solicita o aprueba"
TipoTrasteo ||--o{ Trasteo : "ingreso o salida"
EstadoReserva ||--o{ Trasteo : "estado"
Trasteo |o--o| Cargo : "genera depósito"
Adicional ||--o{ ReservaParqueadero : "se reserva en"
Propiedad ||--o{ ReservaParqueadero : "reserva"
AutorizacionVisita |o--o| ReservaParqueadero : "acompaña"
EstadoReserva ||--o{ ReservaParqueadero : "estado"
Visitante {
int tipo_documento_id FK
}
AutorizacionVisita {
int propiedad_id FK
int visitante_id FK
int autorizado_por_id FK "Usuario"
int tipo_visita_id FK
}
RegistroAcceso {
int autorizacion_visita_id FK "nullable"
int visitante_id FK
int propiedad_id FK
int registrado_por_id FK "Usuario vigilante"
}
Trasteo {
int propiedad_id FK
int solicitado_por_id FK "Usuario"
int aprobado_por_id FK "Usuario, nullable"
int tipo_trasteo_id FK
int estado_reserva_id FK
int cargo_id FK "nullable"
}
ReservaParqueadero {
int adicional_id FK "parqueadero de visitantes"
int propiedad_id FK
int autorizacion_visita_id FK "nullable"
int estado_reserva_id FK
}
erDiagram
Usuario ||--o{ Notificacion : "recibe"
TipoNotificacion ||--o{ Notificacion : "clasifica"
Usuario |o--o{ Auditoria : "realiza"
Notificacion {
int usuario_id FK "destinatario"
int tipo_notificacion_id FK
string entidad_tipo "ej. Ticket"
int entidad_id "id del registro"
}
Auditoria {
int usuario_id FK "nullable, procesos del sistema"
string tabla "ej. Pago"
int registro_id "id del registro"
}
leida_en. Con entidad_tipo y entidad_id el frontend sabe a qué pantalla llevar al usuario al tocarla.Todos los catálogos comparten la misma forma: id, codigo (único y fijo, el que usa el backend), nombre (el que ve el usuario), orden y activo. Los valores de abajo son el codigo sugerido para el seed.
| Catálogo | Lo usa | Valores de ejemplo |
|---|---|---|
| Usuarios y propiedades | ||
| Rol | Usuario | ADMINPROPIETARIORESIDENTEVIGILANTECONSEJO |
| TipoDocumento | Usuario, Visitante | CCCETIPASAPORTENIT |
| TipoPropiedad | Propiedad | APARTAMENTOCASALOCALOFICINA |
| TipoAdicional | Adicional | PARQUEADEROBODEGATERRAZA |
| TipoRelacion | PropiedadPersona | PROPIETARIOARRENDATARIORESIDENTEFAMILIAR |
| Mantenimiento | ||
| CategoriaTicket | Ticket | PLOMERIAELECTRICOHUMEDADCERRAJERIAZONAS_COMUNESASCENSOR |
| PrioridadTicket | Ticket | BAJAMEDIAALTAURGENTE |
| EstadoTicket | Ticket, TicketHistorial | PENDIENTEAPROBADOEN_PROGRESOCOMPLETADOCANCELADO |
| Pagos | ||
| ConceptoCobro | Cargo | CUOTA_ADMINCUOTA_EXTRAORDINARIAMULTAINTERES_MORARESERVA_AMENIDADDEPOSITO_TRASTEO |
| EstadoCargo | Cargo | PENDIENTEPARCIALPAGADOVENCIDOANULADO |
| MetodoPago | Pago | TRANSFERENCIAPSECONSIGNACIONEFECTIVOTARJETA |
| EstadoPago | Pago | PENDIENTE_APROBACIONAPROBADORECHAZADO |
| Reservas y acceso | ||
| EstadoReserva | ReservaAmenidad, Trasteo, ReservaParqueadero | SOLICITADAAPROBADARECHAZADACANCELADAREALIZADA |
| TipoVisita | AutorizacionVisita | ESPORADICARECURRENTE |
| TipoTrasteo | Trasteo | INGRESOSALIDA |
| Comunales y notificaciones | ||
| TipoSesion | Sesion | ASAMBLEA_ORDINARIAASAMBLEA_EXTRAORDINARIAREUNION_CONSEJO |
| EstadoSesion | Sesion | PROGRAMADAEN_CURSOFINALIZADACANCELADA |
| EstadoVotacion | Votacion | BORRADORABIERTACERRADA |
| TipoNotificacion | Notificacion | PAGO_APROBADOPAGO_RECHAZADOCARGO_POR_VENCERTICKET_ACTUALIZADORESERVA_APROBADAVISITA_EN_PORTERIANUEVA_VOTACION |