# 05 — Modelo de datos *(Entregable E)*

> **Este documento describe entidades, atributos y relaciones. No contiene SQL** — la creación de la base de datos
> ocurre después de la aprobación, en la Fase 0 del plan de desarrollo.

---

## Principios de diseño aplicados

| Principio | Cómo se aplica |
|---|---|
| **Nada se borra** | Ninguna entidad de negocio tiene borrado físico. Se usan estados y banderas de actividad (§48). |
| **Identificador interno inmutable** | Toda entidad tiene una llave técnica que nunca cambia. Las llaves de negocio (documento, código de matrícula) son únicas pero **no** son la llave de relación. |
| **Multi-colegio desde el primer día** | Toda entidad de negocio nace con `institucion_id`, aunque hoy siempre valga 1 (§57). |
| **Precisión numérica exacta** | Las notas y promedios usan tipo decimal exacto, **jamás coma flotante**. Un promedio calculado con flotantes produce empates y desempates erráticos en el puesto (§34). |
| **Fotografía de contexto** | Las entidades académicas guardan el curso y el año del momento, para que un traslado o un cambio de estructura no reescriba la historia. |
| **Auditoría separada** | La auditoría vive en su propia entidad, nunca en columnas dispersas del registro afectado. |

**Convenciones:** codificación `utf8mb4` en toda la base de datos · motor transaccional (InnoDB) · fechas y horas
en zona `America/Bogota` · todo registro lleva `creado_en`, `creado_por`, `actualizado_en`, `actualizado_por`.

---

## Mapa general de entidades

```
                                  ┌──────────────┐
                                  │ INSTITUCION  │  (multi-colegio)
                                  └──────┬───────┘
        ┌────────────────────────────────┼────────────────────────────────┐
        ▼                                ▼                                ▼
 ┌─────────────┐                  ┌─────────────┐                 ┌──────────────┐
 │   PERSONA   │                  │ ANIO_ACADEM │                 │ CONFIG_ACAD  │
 └──────┬──────┘                  └──────┬──────┘                 │ ESCALA_DESEMP│
        │                                │                        └──────────────┘
        ▼                                ▼
 ┌─────────────┐  ┌──────────┐    ┌─────────────┐   ┌────────┐   ┌─────────────┐
 │   USUARIO   │──│ USUARIO_ │    │  PERIODO    │   │ GRADO  │──►│    CURSO    │
 └─────────────┘  │   ROL    │    └─────────────┘   └────────┘   └──────┬──────┘
        │         └────┬─────┘                                          │
        │              ▼                                                │
        │         ┌──────────┐  ┌────────────┐                          │
        │         │   ROL    │──│ ROL_PERMISO│                          │
        │         └──────────┘  └─────┬──────┘                          │
        │                             ▼                                 │
        │                        ┌─────────┐      ┌──────┐  ┌───────────┴──────┐
        │                        │ PERMISO │      │ AREA │─►│   ASIGNATURA     │
        │                        └─────────┘      └──────┘  └────────┬─────────┘
        │                                                            ▼
        ├──► ┌──────────┐                              ┌──────────────────────────┐
        │    │ DOCENTE  │◄─────────────────────────────│  ASIGNACION_DOCENTE      │
        │    └──────────┘                              │ (docente+asig+curso+año) │
        │                                              └──────────────────────────┘
        ├──► ┌────────────┐    ┌──────────────┐    ┌──────────────────────┐
        │    │ ESTUDIANTE │───►│  MATRICULA   │───►│ MATRICULA_MOVIMIENTO │
        │    └─────┬──────┘    └──────┬───────┘    └──────────────────────┘
        │          │                  │
        │          ▼                  ▼
        │    ┌──────────────┐   ┌──────────────┐
        └──► │  ACUDIENTE   │   │ MATRICULA_   │
             │              │◄──│  ACUDIENTE   │
             └──────────────┘   └──────────────┘

  ── NÚCLEO ACADÉMICO ────────────────────────────────────────────────────────
   ┌──────────────┐   ┌────────────────┐   ┌───────────────┐  ┌─────────────┐
   │     NOTA     │──►│  RECUPERACION  │   │  DESEMPENO    │  │ OBSERVACION │
   └──────┬───────┘   └────────────────┘   └───────────────┘  └─────────────┘
          ▼
   ┌──────────────────────┐   ┌──────────────────────┐
   │ CONSOLIDADO_ASIGNAT. │   │ CONSOLIDADO_GENERAL  │  (cálculo materializado)
   └──────────────────────┘   └──────────────────────┘

  ── COMUNICACIÓN Y CONTROL ──────────────────────────────────────────────────
   ┌────────┐  ┌─────────────┐  ┌──────────────────────┐  ┌───────────┐
   │ TAREA  │  │ COMUNICADO  │──│ COMUNICADO_DESTINAT. │  │ AUDITORIA │
   └────────┘  └─────────────┘  └──────────────────────┘  └───────────┘
   ┌───────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐
   │  ARCHIVO  │  │ SESION_LOG   │  │  SECUENCIA   │  │  PARAMETRO   │
   └───────────┘  └──────────────┘  └──────────────┘  └──────────────┘
```

---

# Bloque 1 — Institución y configuración

## INSTITUCION
Los datos del colegio (§12). **Una fila hoy; varias en el futuro [FF].**

| Atributo | Tipo | Notas |
|---|---|---|
| `id` | entero | Llave primaria |
| `nombre_oficial` | texto 200 | **Único campo obligatorio** |
| `nit`, `digito_verificacion` | texto | Opcional |
| `codigo_dane` | texto 20 | Opcional, índice |
| `direccion`, `municipio`, `departamento` | texto | Opcional |
| `telefono`, `correo`, `sitio_web` | texto | Opcional |
| `rector_nombre`, `rector_documento`, `rector_cargo` | texto | Para firmas del boletín |
| `jornada`, `naturaleza`, `calendario` | catálogo | Opcional |
| `resolucion_aprobacion`, `secretaria_educacion` | texto | Opcional |
| `logo_archivo_id`, `escudo_archivo_id` | referencia a ARCHIVO | Opcional |
| `texto_encabezado_boletin`, `texto_pie_boletin` | texto largo | Opcional |
| `activo` | booleano | |

> Las firmas del boletín se modelan como una entidad hija **INSTITUCION_FIRMA** (`cargo`, `nombre`, `orden`,
> `imagen_archivo_id`), porque un boletín suele llevar dos o tres firmas y el número varía por colegio. **[RT]**

## SEDE [RT]
Sedes de una misma institución. No está en la especificación, pero añadirla ahora cuesta una entidad y añadirla
después obliga a migrar cursos y matrículas.

`id` · `institucion_id` · `nombre` · `codigo_dane_sede` · `direccion` · `es_principal` · `activo`

## ANIO_ACADEMICO
| Atributo | Tipo | Notas |
|---|---|---|
| `id`, `institucion_id` | | |
| `anio` | entero | Único por institución (2026) |
| `fecha_inicio`, `fecha_fin` | fecha | |
| `numero_periodos` | entero | 1 a 8. Solo Superadmin (§7) |
| `estado` | catálogo | `EN_CONFIGURACION` / `ACTIVO` / `CERRADO` |
| `es_predeterminado` | booleano | Máximo uno en `verdadero` por institución |
| `fecha_cierre`, `cerrado_por` | | Registro del cierre (§47) |

## PERIODO
| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `anio_academico_id` | |
| `numero`, `nombre` | 1, "Primer periodo" |
| `fecha_inicio`, `fecha_fin` | |
| `estado` | `ABIERTO` / `CERRADO` |
| `es_predeterminado` | Máximo uno por año |
| `fue_reabierto`, `veces_reabierto` | Trazabilidad de reaperturas (§46) |
| `fecha_cierre`, `cerrado_por`, `fecha_limite_reapertura` | |

## CONFIGURACION_ACADEMICA
Un registro por institución y año — permite que la escala cambie de un año a otro sin alterar el histórico.

`nota_minima` (0.0) · `nota_maxima` (5.0) · `decimales_visualizacion` (1) · `decimales_calculo` (4) ·
`nota_minima_aprobatoria` (3.0) · `politica_recuperacion` (`REEMPLAZO` / `MAXIMO` / `MAXIMO_CON_TOPE`) ·
`tope_recuperacion` (opcional) · `maximo_asignaturas_en_bajo` (sugerencia de promoción) ·
`mostrar_promedio_numerico_a_familias` · `mostrar_puesto_a_familias` · `granularidad_indicador_familias` ·
`bloquear_cierre_con_notas_pendientes` · `permitir_cambio_password_familias`

## ESCALA_DESEMPENO
Bandas configurables (§35). Ligada a institución **y año**.

| Atributo | Notas |
|---|---|
| `nombre` | "Superior", "Alto", "Básico", "Bajo" |
| `valor_minimo`, `valor_maximo` | Decimal exacto. Intervalos **semiabiertos** `[min, max)` |
| `color`, `orden`, `es_aprobatorio`, `activo` | |

> Al guardar, el sistema **valida que las bandas cubran 0.00 a la nota máxima sin huecos ni solapamientos** — ver
> [AMB-02](00-hallazgos-y-decisiones.md#amb-02--la-escala-de-desempeño-tiene-huecos-numéricos).

---

# Bloque 2 — Identidad y seguridad

## PERSONA
**La entidad que resuelve el problema de identidad.** Representa a un ser humano, una sola vez, sin importar
cuántos roles tenga en el colegio — ver [AMB-09](00-hallazgos-y-decisiones.md#amb-09--una-misma-persona-con-varios-roles).

| Atributo | Notas |
|---|---|
| `id`, `institucion_id` | |
| `tipo_documento_id` | Catálogo: RC, TI, CC, CE, PEP, PPT, NUIP, NES, PASAPORTE… |
| `numero_documento` | **Único por (institución, tipo)** |
| `primer_nombre`, `segundo_nombre`, `primer_apellido`, `segundo_apellido` | Normalizados a mayúsculas, conservando `ÑÁÉÍÓÚÜ` |
| `fecha_nacimiento`, `sexo`, `nacionalidad` | |
| `celular`, `celular_es_internacional`, `correo`, `direccion` | Correo y celular **no** son únicos: padre y madre pueden compartirlos (§22) |
| `activo` | |

## USUARIO
| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `persona_id` | |
| `nombre_usuario` | = número de documento (§10). Único por institución. Modificable **solo por Superadmin** con auditoría — ver [AMB-08](00-hallazgos-y-decisiones.md#amb-08--el-documento-es-el-usuario-pero-los-documentos-cambian) |
| `password_hash` | Hash moderno con sal automática. **Nunca texto plano** (§11) |
| `estado` | `ACTIVO` / `BLOQUEADO` / `INACTIVO` |
| `debe_cambiar_password` | Para uso futuro |
| `intentos_fallidos`, `bloqueado_hasta` | Bloqueo progresivo — [DP-08](00-hallazgos-y-decisiones.md#dp-08--la-política-de-contraseñas-tiene-un-riesgo-de-seguridad-real) |
| `ultimo_acceso`, `ultima_ip` | Bitácora |
| `password_actualizado_en`, `password_actualizado_por` | |

## ROL, PERMISO, ROL_PERMISO, USUARIO_ROL
- **ROL:** `codigo` (`SUPERADMIN`, `COORDINADOR`, `DOCENTE`, `ACUDIENTE`, `ESTUDIANTE`), `nombre`,
  `nivel_jerarquico` (entero — impide que un rol restablezca contraseñas de niveles iguales o superiores,
  ver [AMB-10](00-hallazgos-y-decisiones.md#amb-10--el-coordinador-puede-restablecer-contraseñas--de-quién)).
- **PERMISO:** `codigo` (`notas.editar`, `anio.crear`…), `modulo`, `descripcion`.
- **ROL_PERMISO:** la matriz del documento 03, en datos, no en código.
- **USUARIO_ROL:** un usuario puede tener varios roles simultáneos.

## USUARIO_DOCUMENTO_HISTORICO [RT]
Registra los cambios de número de documento (TI → CC, correcciones), con valor anterior, nuevo, motivo, fecha y
usuario. Permite encontrar a una persona por su documento antiguo.

## SESION_LOG
Bitácora de acceso: `usuario_id`, `fecha_hora`, `ip`, `agente_usuario`, `resultado` (`EXITO` /
`PASSWORD_INCORRECTO` / `USUARIO_BLOQUEADO`). Alimenta la detección de intentos de fuerza bruta.

---

# Bloque 3 — Estructura académica

## GRADO  *(clave — ver [DP-09](00-hallazgos-y-decisiones.md#dp-09--el-modelo-confunde-grado-con-curso--y-eso-rompe-la-promoción))*

| Atributo | Notas |
|---|---|
| `id`, `institucion_id` | |
| `nombre`, `nombre_corto` | "Sexto", "6°" |
| `orden` | Entero: −1 Prejardín … 0 Transición, 1..11. **Hace posible la sugerencia de promoción** |
| `nivel` | `PREESCOLAR` / `PRIMARIA` / `SECUNDARIA` / `MEDIA` |
| `es_terminal` | Verdadero en 11° → sugerencia "Graduado" |
| `activo` | |

## CURSO
| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `anio_academico_id`, `grado_id`, `sede_id` | |
| `grupo` | "A", "B", "01" |
| `nombre_visible` | Compuesto: "6°A". Se calcula, se guarda para reportes |
| `jornada` | `MANANA` / `TARDE` / `UNICA` / `NOCTURNA` |
| `director_docente_id` | Opcional. Origen del sub-rol "director de curso" |
| `cupo_maximo` | Opcional, informativo |
| `activo` | |

**Unicidad:** (institución, año, grado, grupo, jornada).

## AREA
`id` · `institucion_id` · `nombre` · `nombre_corto` · `orden` · `activo` — sin borrado físico (§15).

## ASIGNATURA
`id` · `institucion_id` · `area_id` · `nombre` · `nombre_corto` · `orden` · `activo`.
Catálogo institucional; qué curso la dicta se define en la siguiente entidad.

## CURSO_ASIGNATURA
La oferta real: qué asignaturas se dictan en cada curso de cada año.

`id` · `curso_id` · `asignatura_id` · `intensidad_horaria` (opcional, informativa — ver
[DP-05](00-hallazgos-y-decisiones.md#dp-05--el-boletín-se-organiza-por-área-o-por-asignatura)) ·
`orden_boletin` · `activo`. **Unicidad:** (curso, asignatura).

## DOCENTE
`id` · `institucion_id` · `persona_id` (uno a uno) · `profesion` · `titulo` · `informacion_adicional` ·
`fecha_vinculacion` · `activo`.

## ASIGNACION_DOCENTE
**La relación que gobierna todos los permisos del docente (§8).**

| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `anio_academico_id` | |
| `docente_id`, `curso_asignatura_id` | |
| `fecha_inicio`, `fecha_fin` | Permite el relevo de docente a mitad de año conservando la historia |
| `activo` | |

**Regla:** una `curso_asignatura` tiene **un solo** docente titular activo a la vez. Un docente tiene tantas
asignaciones como necesite (§19).

---

# Bloque 4 — Población escolar

## ESTUDIANTE
Datos del estudiante (§21). El estudiante existe con independencia de estar matriculado.

| Grupo | Atributos | Obligatoriedad |
|---|---|---|
| **Identidad** *(en PERSONA)* | tipo y número de documento, nombres, apellidos, fecha de nacimiento, sexo | **Obligatorio** |
| **Origen** | `lugar_nacimiento_municipio`, `lugar_nacimiento_pais`, `nacionalidad` | Opcional |
| **Residencia** | `direccion`, `barrio`, `municipio_residencia`, `departamento_residencia`, `zona` (urbana/rural), `estrato` | Opcional |
| **Salud** ⚠ sensible | `eps`, `rh`, `discapacidad`, `observaciones_medicas` | Opcional — acceso restringido y auditado ([RG-02](00-hallazgos-y-decisiones.md#rg-02--datos-sensibles-de-menores--ley-1581-de-2012)) |
| **Complementarios** | `sisben`, `grupo_etnico`, `victima_conflicto`, `institucion_procedencia`, `observaciones` | Opcional |
| **Sistema** | `codigo_estudiante`, `foto_archivo_id`, `activo` | |
| **Protección de datos** | `autoriza_tratamiento_datos`, `fecha_autorizacion`, `autorizacion_registrada_por` | **Obligatorio en la matrícula** [RT] |

> **Campos condicionales:** si `nacionalidad ≠ Colombia` → se exige país de nacimiento y se relajan las
> validaciones de documento y celular. Si `discapacidad = sí` → se habilita el detalle.

## ACUDIENTE
`id` · `institucion_id` · `persona_id` (uno a uno) · `ocupacion` · `lugar_trabajo` · `telefono_trabajo` · `activo`.
Los datos personales viven en PERSONA, así el mismo acudiente sirve a varios estudiantes sin duplicarse (§22).

## ESTUDIANTE_ACUDIENTE
Relación muchos a muchos con atributos (§9, §22):

`estudiante_id` · `acudiente_id` · `parentesco` (padre/madre/abuelo/tío/otro) · `es_principal` ·
`es_responsable_financiero` · `convive_con_estudiante` · `activo`.

**Regla:** máximo un acudiente principal activo por estudiante.

## MATRICULA
Registro histórico e inmutable en su esencia (§23, §24).

| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `anio_academico_id`, `estudiante_id`, `curso_id` | `curso_id` es el curso **actual**; los traslados quedan en el movimiento |
| `codigo_matricula` | `MAT-2026-000123`, único, generado con secuencia bajo bloqueo ([AMB-13](00-hallazgos-y-decisiones.md#amb-13--el-código-de-matrícula-tiene-una-condición-de-carrera)) |
| `fecha_matricula` | |
| `estado` | `ACTIVA` / `RETIRADO` / `TRASLADADO` / `PROMOVIDO` / `NO_PROMOVIDO` / `GRADUADO` / `ANULADA` |
| `es_repitente`, `procedencia` | |
| `observaciones` | |
| `fecha_estado`, `motivo_estado`, `usuario_estado` | Quién cambió el estado y por qué |

**Regla:** un estudiante tiene **como máximo una** matrícula `ACTIVA` por año. Puede tener varias filas históricas
del mismo año si hubo anulación y rematrícula.

## MATRICULA_MOVIMIENTO
Cada traslado o cambio de estado (§25):

`matricula_id` · `tipo` (`TRASLADO_CURSO` / `CAMBIO_ESTADO` / `REINGRESO`) · `curso_origen_id` ·
`curso_destino_id` · `estado_anterior` · `estado_nuevo` · `fecha` · `motivo` · `usuario_id`.

**El histórico jamás se pierde** — es el requisito explícito de §25 y §48.

---

# Bloque 5 — Núcleo académico

## NOTA — *la decisión de anclaje más importante del modelo*

| Atributo | Notas |
|---|---|
| `id`, `institucion_id`, `anio_academico_id`, `periodo_id` | |
| `estudiante_id` | **Ancla al estudiante, no a la matrícula** |
| `asignatura_id` | **Ancla a la asignatura, no a curso_asignatura** |
| `curso_id` | **Fotografía de contexto**: el curso donde estaba al calificar. Para reportes, no para la llave |
| `nota_original` | Decimal exacto. La que digitó el docente |
| `nota_definitiva` | Decimal exacto. La que usan promedios y boletín |
| `tiene_recuperacion` | Bandera de acceso rápido |
| `docente_id` | Quién la registró |
| `fecha_registro`, `fecha_ultima_modificacion`, `usuario_ultima_modificacion` | |

**Unicidad:** (estudiante, año, asignatura, periodo).

> **Por qué así:** si la nota dependiera del curso, un traslado de 6°A a 6°B dejaría huérfanas las notas del
> periodo 1. Con este anclaje, **el traslado conserva las notas sin ninguna operación adicional** — ver
> [AMB-01](00-hallazgos-y-decisiones.md#amb-01--qué-pasa-con-las-notas-cuando-un-estudiante-se-traslada-de-curso).
>
> **Puerta abierta [RT]:** si en el futuro se adoptan notas parciales
> ([DP-03](00-hallazgos-y-decisiones.md#dp-03--una-sola-nota-por-asignatura-y-periodo-o-notas-parciales)), se
> agrega una entidad `ACTIVIDAD_EVALUATIVA` que alimente `nota_original`. Esta entidad **no cambia**.

## RECUPERACION
`id` · `nota_id` · `nota_recuperacion` · `nota_definitiva_resultante` · `politica_aplicada` · `fecha` ·
`observacion` · `docente_id` · `usuario_registro`.

Se conservan **todos** los intentos; la nota original nunca se sobrescribe (§30).

## DESEMPENO
Banco de logros a nivel de grupo (§27).

`id` · `institucion_id` · `anio_academico_id` · `curso_asignatura_id` · `periodo_id` (nulo = banco sin asignar) ·
`descripcion` (texto largo) · `tipo` (`COGNITIVO` / `PROCEDIMENTAL` / `ACTITUDINAL`, opcional) · `orden` ·
`docente_id` · `activo`.

> **Preparado para [FF]:** una futura entidad `DESEMPENO_ESTUDIANTE` (estudiante, desempeño, estado alcanzado)
> habilita el marcado individual sin tocar nada de lo anterior —
> [DP-07](00-hallazgos-y-decisiones.md#dp-07--los-desempeños-del-boletín-iguales-para-todo-el-curso-o-marcados-por-estudiante).

## OBSERVACION_BOLETIN
Dos niveles, según [AMB-06](00-hallazgos-y-decisiones.md#amb-06--quién-escribe-la-observación-del-boletín):

`id` · `estudiante_id` · `anio_academico_id` · `periodo_id` · `asignatura_id` (**nulo = observación general**) ·
`texto` · `docente_id` · `fecha` · `activo`.

---

# Bloque 6 — Cálculo materializado

> Estas entidades **no contienen información nueva**: contienen resultados derivados de NOTA. Existen por
> rendimiento — ver [RG-04](00-hallazgos-y-decisiones.md#rg-04--cálculo-de-puestos-y-promedios-en-cada-carga-de-pantalla).
> Se recalculan al cambiar una nota del curso, al cerrar un periodo, o bajo demanda. **Nunca se editan a mano.**

## CONSOLIDADO_ASIGNATURA
Por estudiante, año, asignatura y periodo:

`nota_periodo` · `promedio_acumulado` (media de los periodos calificados hasta ese momento) ·
`nivel_desempeno_id` · `periodos_calificados`.

## CONSOLIDADO_GENERAL
Por estudiante, año y periodo:

`promedio_periodo` · `promedio_acumulado` · `nivel_desempeno_id` · `puesto_periodo` · `puesto_acumulado` ·
`total_estudiantes_curso` · `asignaturas_calificadas` · `asignaturas_en_bajo` · `curso_id` ·
`calculado_en` · `esta_desactualizado`.

**Precisión:** los promedios se guardan con **4 decimales** aunque se muestren con 1. El puesto se ordena por el
valor de 4 decimales, cumpliendo §34 (4.126 / 4.125 / 4.124 son tres puestos distintos, no un empate).

**Empates:** ranking competitivo — mismo puesto, el siguiente salta
([AMB-04](00-hallazgos-y-decisiones.md#amb-04--reglas-de-empate-en-el-puesto)).

---

# Bloque 7 — Comunicación

## TAREA
`id` · `institucion_id` · `anio_academico_id` · `periodo_id` · `curso_asignatura_id` · `docente_id` ·
`titulo` · `descripcion` · `fecha_asignacion` (del sistema, **no editable**, §36) · `fecha_entrega` ·
`prioridad` · `archivo_id` · `enlace` · `activo`.

El estado (Próxima / Próxima a vencer / Vencida) **se calcula**, no se almacena — así nunca queda desactualizado.

## COMUNICADO y COMUNICADO_DESTINATARIO
- **COMUNICADO:** `titulo` · `contenido` · `fecha_publicacion` (automática) · `fecha_vencimiento` ·
  `emisor_usuario_id` · `archivo_id` · `estado` · `activo`.
- **COMUNICADO_DESTINATARIO:** `comunicado_id` · `tipo_destinatario` (`INSTITUCION` / `GRADO` / `CURSO` / `ROL` /
  `USUARIO`) · `referencia_id`.

Modelar los destinatarios como **filas** (y no como un campo único) es lo que permite el "varios cursos" que §37
plantea como condicional. Con esta estructura, no es condicional: funciona desde el primer día.

## ARCHIVO
Punto único de control de adjuntos (§50):

`id` · `institucion_id` · `nombre_original` · `nombre_almacenado` (aleatorio) · `ruta` (**fuera de la raíz web**) ·
`mime_type` · `extension` · `tamano_bytes` · `hash` · `modulo_origen` · `subido_por` · `activo`.

La descarga **siempre** pasa por un controlador que verifica permisos. Nunca hay enlaces directos a archivos.

---

# Bloque 8 — Control

## AUDITORIA
| Atributo | Notas |
|---|---|
| `id`, `institucion_id` | |
| `usuario_id`, `rol_codigo`, `nombre_usuario_snapshot` | Se guarda el nombre por si el usuario se elimina o renombra |
| `fecha_hora`, `ip`, `agente_usuario` | |
| `modulo`, `accion` | `NOTAS` / `MODIFICAR` |
| `entidad`, `entidad_id` | Qué registro se afectó |
| `descripcion` | Texto legible: *"Modificación de nota de JUAN GÓMEZ en Matemáticas, Periodo 2"* |
| `valor_anterior`, `valor_nuevo` | Estructurados, solo de los campos que cambiaron |
| `resultado` | `EXITO` / `FALLIDO` / `RECHAZADO_POR_PERMISOS` |
| `anio_academico_id`, `periodo_id` | Contexto, para filtrar la auditoría por año |

**Índices imprescindibles:** (institución, fecha_hora), (usuario, fecha_hora), (entidad, entidad_id), (módulo, acción).
Sin ellos la consulta de auditoría se vuelve inusable en el segundo año de operación.

## SECUENCIA
`institucion_id` · `tipo` (`MATRICULA`) · `anio` · `ultimo_valor`.
Se lee y se incrementa **con bloqueo de fila dentro de la transacción**, nunca con un conteo previo.

## PARAMETRO
Configuración clave–valor tipada por institución, para ajustes que no merecen columna propia.

---

# Catálogos

Tablas pequeñas y estables que evitan cadenas libres inconsistentes:

`TIPO_DOCUMENTO` (RC, TI, CC, CE, PEP, PPT, NUIP, NES, PASAPORTE, VISA) · `PARENTESCO` · `DEPARTAMENTO` ·
`MUNICIPIO` (con su departamento) · `EPS` · `GRUPO_SANGUINEO` · `ESTRATO` · `JORNADA` · `ZONA` ·
`NIVEL_EDUCATIVO` · `GRUPO_ETNICO`.

> **[RT]** Cargar el catálogo oficial de departamentos y municipios (DANE) en la instalación. Cuesta muy poco y
> elimina de raíz el problema de tener "Bogotá", "BOGOTA D.C." y "bogota" como tres municipios distintos en los
> reportes.

---

# Índices y rendimiento

| Entidad | Índice recomendado | Consulta que acelera |
|---|---|---|
| NOTA | (año, periodo, asignatura, estudiante) | Digitación y consulta de notas de un curso |
| NOTA | (estudiante, año) | Boletín e histórico del estudiante |
| MATRICULA | (año, curso, estado) | Listado de estudiantes de un curso |
| MATRICULA | (estudiante, año) | Verificación de matrícula activa |
| ASIGNACION_DOCENTE | (docente, año, activo) | "Mis cursos" del docente |
| CONSOLIDADO_GENERAL | (año, periodo, curso, promedio) | Cálculo y consulta de puestos |
| AUDITORIA | (institución, fecha_hora) | Panel de auditoría |
| PERSONA | (institución, tipo_documento, numero_documento) | Búsqueda por documento en matrícula |
| TAREA | (curso_asignatura, fecha_entrega, activo) | Tareas próximas del dashboard |

**Volumen esperado** (colegio de 800 estudiantes, 5 años de operación):
notas ≈ 800 × 12 asignaturas × 4 periodos × 5 años ≈ **192 000 filas**; auditoría ≈ 500 000 filas.
Son volúmenes pequeños para MariaDB **siempre que los índices existan**; sin ellos, el boletín de un curso se
degrada notablemente ya en el segundo año.

---

# Integridad referencial

| Regla | Aplicación |
|---|---|
| **Restringir el borrado** | Es la regla por defecto. Ninguna entidad de negocio permite borrado en cascada. |
| **Cascada solo en dependientes puros** | COMUNICADO_DESTINATARIO al borrar un comunicado en estado borrador. Nada más. |
| **Validación de rango** | Notas dentro de mínimo y máximo configurados; bandas de escala sin solapamiento. |
| **Unicidad de negocio** | Documento por institución · código de matrícula · (estudiante, año, asignatura, periodo) en NOTA · (año, grado, grupo, jornada) en CURSO. |
| **Coherencia de año** | Un periodo, un curso y una matrícula referidos en la misma operación deben pertenecer al mismo año. Se valida en la capa de servicio, donde el mensaje de error puede ser comprensible. |

---

# Preparación multi-colegio — cómo se materializa

| Decisión | Implementación |
|---|---|
| **Estrategia** | Base de datos única, esquema compartido, discriminador `institucion_id` |
| **Por qué no una BD por colegio** | Multiplica el costo de migraciones y respaldos por el número de colegios, y complica los reportes agregados |
| **Alcance de la columna** | Todas las entidades de negocio. Los catálogos globales (departamentos, municipios, tipos de documento) no la llevan |
| **Unicidad** | Toda llave de negocio incluye `institucion_id`: el mismo documento puede existir en dos colegios distintos |
| **Protección real** | El filtro **no se escribe a mano**: lo inyecta la capa de repositorio, siempre — ver [RG-05](00-hallazgos-y-decisiones.md#rg-05--multi-colegio-el-riesgo-no-es-la-columna-es-el-olvido) y [13 — Arquitectura técnica](13-arquitectura-tecnica.md) |
| **Qué falta para activarlo [FF]** | Un selector de institución en el login, la administración de instituciones, y un rol de superadministrador global. **Ningún cambio en el modelo de datos.** |
