Especificación · S-PLAN

Modelo de datos

Todo S-PLAN vive bajo el prefijo S-PLAN/ de la base Realtime Database del proyecto sigunitropico. Un árbol jerárquico con el plan, varios índices planos que evitan recorrerlo entero, y unos pocos nodos de configuración.

Mapa general

S-PLAN/ ├── ejes/{ejeId}/programas/{progId}/proyectos/{proyId}/metas/{metaId}/acciones/{accionId} │ — el árbol del PDI (fuente estructural) ├── indices_metas/{metaId} — dónde vive cada meta ★ fuente de verdad ├── metas_con_ponderacion/{metaId} — avance efectivo, real y ponderado ├── metas_responsables/{metaId} — { R79: true } ├── metas_contratos/{metaId} — { "0191-2025": true } ├── cumplimiento_meta_paa/{metaId} — cumplimiento del Plan Anual de Acciones ├── evidencias/{ciclo}/{metaId}/{accionId}/{fileKey} ├── contratos/{numeroContrato} ├── cortes/{ciclo} — registro del cierre + stats ├── snapshots/{ciclo} — copia inmutable del plan ├── config/ciclo_carga — ventana de carga vigente ├── alertas_globales/{id} — avisos tipo toast ├── analisis_ia/R_{responsableId} — análisis narrativo generado ├── toast_satisfaccion/{pushId} — encuesta de experiencia ├── PLANES/PDI-2024 — nombre del plan ├── avance_general · inversion · fecha_actualizacion · programacion_general └── fecha_actualizacion_ponderaciones Fuera del prefijo (compartidos con la suite): usuarios/{correoSaneado} — correo, nombre, rol, roles_map responsables/{Rn} — nombre, cargo, área, correo ⚠ datos personales notificaciones/s-plan/global · s-plan/personal/{correoSaneado}

El árbol del PDI

Cinco niveles anidados. Cada nivel guarda su propio avance agregado, que proviene de la carga masiva y no se recalcula al editar una meta suelta.

Eje

CampoTipoDescripción
id_ejestringEJE-01EJE-04.
titulo_ejestringNombre completo del eje estratégico.
descripcion_ejestringTexto de contexto que muestra la portada del eje.
avance_ejenumberAvance agregado (0–1 o 0–100 según la carga).
inversion_ejenumberInversión asociada al eje, en pesos.
url_imgstringImagen de portada, derivada del id: …/{ejeId}.png.

Programa y proyecto

CampoNivelDescripción
id_programa · programaProgramaId PROG-001… y nombre.
avance_programaProgramaAvance agregado del programa.
proyectos_indicesProgramaResumen por proyecto: { codigo, nombre, avance_proyecto, total_metas }. Permite pintar la lista sin bajar al detalle.
id_proyecto · nombre_proyectoProyectoCódigo BPU (BPU-2024023) y nombre.
avance_proyectoProyectoAvance agregado del proyecto.
metas_indicesProyectoArray con los ids de sus metas.

Meta

CampoTipoDescripción
id_metastringE{eje}M{n}, p. ej. E2M14. Obligatorio: su ausencia marca un nodo fantasma.
titulo_metastringEl compromiso. Obligatorio.
ponderacion_metanumber 0–1Peso en el plan completo. Las 120 suman 1.
avance_metanumber 0–1Avance efectivo: el que se publica.
avance_meta_calculado_realnumber 0–1Avance calculado desde las acciones, sin override.
avance_meta_override_temporalobject · nullMetadatos del ajuste manual: valor visual, valor real, motivo, fecha, origen.
proyeccion_anualobject{ año1..año4 } — reparto planeado del cumplimiento.
programacion_avance_anualobject{ año1..año4 } — avance programado ya ponderado por el peso de la meta.
tipo_programacionstringporcentaje · cantidad.
tipo_acumulacionstringacumulado · no acumulado.
valor_metanumberValor de referencia del compromiso, en pesos.
programacion_financieraobject{ año1..año4, total }.
ejecucion_financieraobject{ año1..año4, total }.
inversion_realizadanumberSuma de la inversión reportada en sus acciones.
cantidad_contratosnumberContratos asociados.
resumen_metaobjectNarrativa de avance en HTML enriquecido + trazabilidad (updatedBy, updatedAt).
accionesobjectLas acciones de la meta, indexadas por id.

Acción

CampoTipoDescripción
id_accion · titulo_accionstringA-001… y la descripción de la tarea.
ponderacion_accionnumber 0–1Peso dentro de su meta. Las acciones de una meta suman 1. Alias heredado: importancia_accion.
cronograma_anualobject{ año1: { "12": true } } — meses programados por año.
avance_accion_anualobject{ "AAAA-MM-DD": { año1..año4 } } — historial por corte. Solo cuenta el más reciente.
avance_accionobjectHistorial simple por fecha, heredado.
inversion_realizadanumberInversión reportada para esta acción.
responsablestringCódigo de responsable (R79). Puede llegar con espacios o saltos de línea de la carga por Excel.
evidenciastringDescripción del soporte esperado (texto del formato original).
Las acciones se renderizan por orden de clave. La ficha de meta itera el objeto con for…in, así que los ids deben ser secuenciales y limpios (A-031A-037) para que aparezcan en el orden esperado.

Índices auxiliares

El árbol pesa demasiado para consultarlo en cada pantalla. Estos índices planos son los que realmente alimentan dashboards, informes y buscadores.

NodoFormaPara qué
indices_metas/{meta}{ eje, programa, proyecto, createdAt, updatedAt } Fuente de verdad de la ubicación de una meta. Toda escritura debe resolver aquí la ruta antes de guardar.
metas_con_ponderacion/{meta}{ avance_meta_efectivo, avance_meta_real_calculado, avance_ponderado, idEje, idPrograma, idProyecto, override_temporal_activo, titulo_meta } Cálculo del avance institucional sin recorrer el árbol. Se reescribe al guardar la meta.
metas_responsables/{meta}{ R32: true } Asignación meta ↔ responsable. Alimenta el tablero por responsable y los informes por dependencia.
metas_contratos/{meta}{ "0191-2025": true } Índice inverso de contratos.
cumplimiento_meta_paa/{meta}por año Cumplimiento del Plan Anual de Acciones de la vigencia.
La regla que evita los peores incidentes: nunca deduzcas la ruta de una meta a partir de su código. E1M1 no implica EJE-01/PROG-001/BPU-2024023 — implica lo que diga indices_metas/E1M1. Escribir en la ruta adivinada crea un nodo fantasma que después hay que limpiar a mano.

Nodos globales

NodoTipoDescripción
avance_generalnumber 0–1El avance del PDI: suma de avance_ponderado de las 120 metas.
inversionnumberInversión reportada total del plan.
programacion_generalobject{ anio1, anio2, … } — avance programado institucional por año. Nótese la clave anioN (sin ñ), distinta de la añoN de metas y acciones.
fecha_actualizacionnumberTimestamp de la última carga masiva del plan.
fecha_actualizacion_ponderacionesnumberTimestamp de la última carga de ponderaciones.
PLANES/PDI-2024/nombrestringNombre del plan vigente.

Responsables y datos personales

El árbol del PDI nunca guarda nombres ni correos: guarda códigos (R79). El directorio está fuera del prefijo, en responsables/{Rn}, y sí contiene datos personales:

responsables/R79 = {
  id:              "R79",
  nombre_completo: "…",
  cargo:           "…",
  area:            "Oficina de Aseguramiento a la Calidad y Acreditación",
  correo:          "…@unitropico.edu.co",
  correo_personal: "…",
  documento:       12345678
}
Trátalo como dato personal. Este nodo no debe exponerse en integraciones, exportaciones abiertas ni documentación. La API que alimenta estas páginas publica únicamente el conteo de responsables por meta, nunca su identidad. Ver Permisos.

Convenciones que hay que conocer

0–1 o 0–100

Los porcentajes conviven en ambas escalas. La regla universal del código es si v ≤ 1 → v × 100.

añoN vs. ciclo

añoN es el año del plan (base 2024); el ciclo es AAAA_S. Las evidencias se particionan por ciclo; el avance, por año.

Historial por fecha

Los avances no se sobrescriben: se agrega una clave AAAA-MM-DD. El orden alfabético es cronológico.

Texto sucio heredado

Campos venidos de Excel pueden traer espacios y saltos de línea ("R79\r\n"). Normaliza siempre antes de comparar.

Antes de escribir en la base

  1. Haz respaldo del subárbol que vas a tocar.
  2. Resuelve la ruta de cada meta con indices_metas; no la deduzcas.
  3. Nunca escribas undefined: la escritura completa se rechaza.
  4. Respeta la escala del campo (0–1 frente a 0–100) y el tipo (número, no cadena).
  5. Si tocas avance_meta, actualiza también metas_con_ponderacion — si no, los dashboards seguirán mostrando el valor anterior.
  6. Recuerda que un override en el código de la ficha de meta puede revertir tu escritura al abrir la meta. Ver Overrides.