Especificación · UniProy

Modelo de datos

Todo UniProy vive bajo el prefijo uniproy/ de la base Realtime Database del proyecto sigunitropico. La unidad es el proyecto: un nodo que acumula sus fases, su flujo, su expediente documental y su historia.

Mapa general

uniproy/ ├── projects/{projectId} │ ├── meta — identidad, etapa, estado, dueño, fechas │ ├── access — quién puede ver o editar │ ├── workflow — paso actual, bloqueo, transiciones │ ├── progress/{fase} — completitud por fase │ ├── sections/ │ │ ├── alistamiento[_structured|_catalog] — Fase 01 │ │ ├── identificacion_programacion[_structured]— Fase 02 │ │ └── viabilidad[_radicar] — Fase 03 │ ├── gestion_documental/documents/{formato} — Fase 04 │ ├── decision — aprobación con su firma │ ├── observaciones/{pushId} — comentarios del Banco de Proyectos │ ├── historial/{pushId} — bitácora de transiciones │ └── seguimiento/reports/{id}— Fase 05: informes y su análisis ├── admin_queue/{pushId} — cola de radicados para el Banco de Proyectos ├── slugs/{slug} — URL legible → projectId └── catalogs/ — catálogos auxiliares Fuera del prefijo (compartidos con la suite): usuarios/{correoSaneado} — perfil y roles_map notificaciones/{pushId} — feed unificado, app: "uniproy" S-PLAN/ — origen de la cadena estratégica de la Fase 01

meta — la identidad del proyecto

CampoDescripción
projectIdIdentificador interno. No cambia nunca, ni siquiera al asignar el BPU.
titleNombre del proyecto.
codigo_bpuCódigo del banco de proyectos. Se asigna o corrige desde la vista de decisión; se escribe también en la Fase 01.
slugFragmento legible para la URL pública. Se resuelve por el índice uniproy/slugs.
currentStageLa fase actual: alistamiento, identificacion_programacion, viabilidad, decision, seguimiento.
nextStageLa siguiente fase esperada.
statusQué le ocurrió por última vez. Ver Las cinco fases.
ownerEmail · ownerName · ownerUidQuién formula. Dato personal: no se publica en integraciones.
createdAt · updatedAt · lastSavedAtMarcas de creación, última modificación y último guardado automático.
submittedAtFecha de radicación. Su presencia marca el proyecto como radicado.
returnedAtFecha de devolución. Se compara con submittedAt para saber cuál es más reciente.
sourceOrigen: el asistente de formulación, una importación o un registro directo en seguimiento.
versionNumber · versionLabelVersión del proyecto.
Estado devuelto frente a radicado. Un proyecto devuelto y vuelto a radicar tiene las dos marcas. El estado se decide por recencia: solo se considera devuelto si su fecha de devolución es posterior a la de radicación. Comparar solo por presencia deja proyectos re-radicados mostrándose como devueltos.

sections — una rama por fase

NodoFaseContenido
alistamiento01Campos planos del formulario: descripción, objetivos, valores del AIU, códigos de la cadena estratégica.
alistamiento_structured01Lo que tiene estructura: objetivos específicos, metas, actividades y secciones de actividad con sus tasas.
alistamiento_catalog01Copia de los catálogos usados, para que la ficha siga leyéndose aunque el catálogo cambie.
identificacion_programacion02Campos planos del encabezado: instancia, fechas, duración, estado, supervisor.
identificacion_programacion_structured02Las matrices: clasificación de actividades, reparto por fuente, cronograma y flujos.
viabilidad03Las respuestas de titularidad y de los 64 requisitos.
viabilidad_radicar03Las declaraciones firmadas al radicar.
Por qué plano y estructurado conviven. Los campos planos alimentan los formularios y las plantillas de documento; los estructurados alimentan tablas y cálculos. Al escribir en la base hay que mantener los dos coherentes: tocar solo uno deja la ficha y el documento contradiciéndose.

workflow y progress

workflow = {
  currentStep, nextStep,
  isLocked: true,                 // radicado → nadie edita, tampoco el administrador
  lastAction, lastActionAt,
  requiredRoles: ["formulador-uniproy", "admin-uniproy"],
  transitions: [ { to, at, by, note } ]
}

progress/{fase} = {
  completionPct: 100,             // completitud del formulario, NO avance de obra
  filled, total,                  // campos diligenciados sobre exigidos
  reason: "autosave" | "pre-radicacion",
  at
}

isLocked es la pieza central del modelo de permisos: mientras esté activo, los asistentes muestran un aviso y deshabilitan los campos, conservando la navegación para poder consultar.

gestion_documental

gestion_documental/documents/{formato} = {
  status: "pending" | "generated" | "uploaded",
  generatedAt, uploadedAt, uploadedBy,
  path,                            // ruta del archivo en el almacenamiento
  url                              // descarga; nunca se publica fuera de la aplicación
}

Las claves son los siete formatos del sistema de gestión. Ver Formalización.

seguimiento

seguimiento/reports/{reportId} = {
  formato_pet_0902: { … },        // campos extraídos del informe oficial
  ai_analysis: {
    resumen_ejecutivo, score_cumplimiento,
    indicadores_clave: [ { label, value, trend } ],
    riesgos: [ … ], alertas_cumplimiento: [ … ], recomendaciones: [ … ]
  },
  pdf, fotos, decision, createdAt, createdBy
}

Otros nodos

NodoPara qué
observaciones/{pushId}Comentarios del Banco de Proyectos. El formulador los ve en un aviso al abrir cualquier fase.
historial/{pushId}Bitácora de transiciones: qué pasó, cuándo y por quién.
decisionResultado de la aprobación, con su constancia de verificación.
uniproy/admin_queue/{pushId}Cola de avisos para el Banco de Proyectos; alimenta su campana.
uniproy/slugs/{slug}Índice de URL legible a identificador, para la vitrina pública.

Índices de la base

Dos nodos que se consultan ordenados necesitan su índice declarado en las reglas: at en la cola de administración y timestamp en las notificaciones. Sin ellos, la consulta ordenada falla. Como salvaguarda, el servidor lee los nodos completos y ordena en memoria, así que la aplicación no depende de que el índice esté desplegado —pero conviene declararlo—.

Convenciones

El id no cambia

Asignar o corregir el BPU no altera el identificador del proyecto ni sus rutas internas.

El bloqueo es del dato

isLocked vive en el proyecto, no en la sesión: aplica a cualquiera que lo abra.

Avance ≠ ejecución

progress mide qué tan lleno está el formulario, no cuánto se ha construido.

HTML conservado

Los campos narrativos guardan su formato tal cual, para que el documento oficial salga igual que en pantalla.

Antes de escribir en la base

  1. Respalda el nodo del proyecto completo.
  2. Nunca escribas valores indefinidos: la escritura entera se rechaza.
  3. Mantén coherentes la rama plana y la estructurada de la misma fase.
  4. Si el proyecto está bloqueado, plantéate primero si la corrección debe ir por una devolución formal.
  5. Al mover una fase, actualiza meta.currentStage, workflow y progress juntos.
  6. Deja rastro en historial: un cambio sin bitácora es indistinguible de un error.