# Manual del Programador · DH Inspección V2 **Baseline documental:** F6.1 **API:** 0.29.0-1 **WEB:** 0.23.0-1 **Android:** 0.15.0 Este manual describe la arquitectura, las reglas que no deben romperse y el procedimiento seguro para modificar DH Inspección V2. No reemplaza los tests ni las restricciones de base de datos: los tres forman juntos el contrato del sistema. --- ## 1. Estructura del repositorio - `api-v3/`: API NestJS + TypeORM + PostgreSQL/PostGIS. - `web-v2/`: aplicación WEB React/Vite. - `android-app/`: aplicación Android Kotlin/Compose. - `scripts/`: despliegue, preflight y utilidades operativas. - `docs/`: documentación funcional y técnica viva. - `.github/workflows/`: CI de API/WEB/Docker y build/test de Android. El backend expone `/api/v3`. Los cambios de dominio deben resolverse primero en API/base de datos; WEB y Android consumen ese contrato y no deben inventar reglas paralelas. --- ## 2. Invariantes de dominio ### 2.1 Inventario físico La jerarquía canónica es: **Departamento → Área → Yacimiento → Instalación → Subinstalación** `parent_id` expresa exclusivamente esa jerarquía. No agregue Empresa dentro de este árbol. ### 2.2 Empresa y Operadora `Empresa` es un maestro independiente. La relación operativa vigente se modela en `area_company_relations`: - Área ↔ Empresa. - `relation_role = 'OPERATOR'` para la Operadora. - `valid_from` / `valid_until` para vigencia. Esta tabla es la fuente temporal de verdad. `assets.operator_company_id` es una fotografía de compatibilidad; nunca debe usarse como sustituto del historial. Cambiar Operadora no mueve Yacimientos, Instalaciones ni Subinstalaciones. ### 2.3 Clasificación técnica - Departamento: sin familia. - Área: sin familia. - Yacimiento: sin familia. - Instalación: requiere familia `INSTALLATION`. - Subinstalación: requiere familia `SUBINSTALLATION` compatible con la Instalación padre. La compatibilidad está protegida por PostgreSQL, no sólo por la UI. ### 2.4 Hallazgos Un Hallazgo directo sólo puede asignarse a: - Yacimiento. - Instalación. - Subinstalación. Departamento y Área no reciben Hallazgos directos. `OTROS / Agregar otro` debe permanecer disponible siempre. En Yacimiento no se exige familia técnica. En Instalación/Subinstalación sí. Si un elemento fue creado en campo, antes de admitir un Hallazgo debe tener GPS de creación y al menos una fotografía; Instalación/Subinstalación además deben quedar clasificadas. ### 2.5 Inspecciones Lifecycle operativo: `DRAFT → PLANNED → IN_PROGRESS → CLOSED` La planificación requiere: - Área. - Operadora vigente del Área. - Inspector responsable habilitado. - fecha/hora prevista de inicio. - checklist generado. La APK puede abrir una Inspección, pero no posee un lifecycle alternativo: el endpoint móvil crea la visita y utiliza los mismos servicios `plan()` y `start()` que el resto del sistema. ### 2.6 Actas Una Inspección puede tener **múltiples Actas**. Reglas críticas: - sólo puede existir un `DRAFT` simultáneo por Inspección; - un Acta en `DRAFT` es editable; - al finalizar se bloquea y queda inmutable; - el sellado conserva integridad y firmas; - no existe reapertura normal de un Acta bloqueada a borrador; - para cerrar la Inspección todas las Actas no canceladas deben estar `SEALED`; - el Informe pertenece al Acta, no a la Inspección completa. La unicidad del borrador está protegida por el índice parcial `uq_inspection_acts_one_draft_per_visit`. ### 2.7 Informe, GEDO y vencimientos Flujo conceptual: **Acta → INF → oficialización GEDO/IF** GEDO oficializa el Informe, pero **no equivale por sí solo a la notificación administrativa que inicia el plazo No urgente**. Existe una compatibilidad histórica importante: el valor físico `GEDO_DATE` se conserva en el enum/base, mientras el significado funcional vigente es `NOTIFICATION_DATE`. No cambie el valor persistido en una refactorización sin una migración explícita y pruebas de compatibilidad. --- ## 3. Modelo de Inventarios La referencia completa es [`F6_INVENTORY_MODEL.md`](./F6_INVENTORY_MODEL.md). Puntos técnicos centrales: - `assets.parent_id`: pertenencia física. - `assets.operational_area_id`: contexto transversal de Área. - `area_company_relations`: historia de Operadora. - `inventory_families`: clasificaciones técnicas. - `inventory_family_parent_rules`: compatibilidad Subinstalación ↔ Instalación. - `inventory_family_attribute_definitions`: campos técnicos por familia. - `asset_inventory_attribute_values`: valores técnicos por objeto. - `asset_context_history` y versiones: trazabilidad contextual/histórica. No se debe rediseñar el esquema para coincidir con una planilla importada. Los archivos externos se normalizan al modelo canónico. --- ## 4. Migraciones ### Regla principal **Nunca modifique una migración ya aplicada.** Si cambia esquema, constraints, seeds o reglas persistentes: 1. cree una migración nueva; 2. haga `up()` determinista; 3. agregue verificación al final cuando la regla sea crítica; 4. implemente `down()` cuando la operación sea razonablemente reversible; 5. agregue/actualice tests de contrato; 6. pruebe la cadena completa sobre PostGIS limpio. ### F5.1 es una excepción histórica `F51CleanManualInventory1790087400000` fue un corte destructivo intencional para reiniciar los datos de dominio. Su `down()` no intenta reconstruir información eliminada: el rollback depende del backup PRE. No repita este patrón para una migración normal sin una decisión explícita, backup validado y procedimiento de restauración. ### Guards importantes de base de datos PostgreSQL protege, entre otras cosas: - jerarquía Departamento → Área → Yacimiento → Instalación → Subinstalación; - familia correcta según el nivel físico; - compatibilidad de familia de Subinstalación con su Instalación padre; - un solo Acta `DRAFT` por Inspección. Las validaciones de API mejoran la experiencia, pero no reemplazan estos guards. --- ## 5. API ### Principios - Reutilice servicios canónicos; no duplique lifecycle en controllers móviles. - Las mutaciones relevantes deben producir auditoría. - Los errores de dominio deben tener `code` estable y mensaje legible. - Los estados históricos/inmutables no deben reabrirse por conveniencia de UI. - Para relaciones temporales, valide la vigencia en la fecha correspondiente, no sólo `valid_until IS NULL` cuando el caso exige reconstrucción histórica. ### Áreas a revisar antes de tocar un flujo - Inventario: `src/asset-master/`. - Inspecciones: `src/inspection-visits/`. - Actas: `src/inspection-acts/`, `src/inspection-closing/`, `src/act-administration/`. - Hallazgos: `src/inspection-findings/` y gate móvil en `src/inspection-visits/field-findings.service.ts`. - Informes/GEDO: `src/inspection-reports/`. - Verificaciones: `src/inspection-verifications/`. - Entidades/migraciones: `src/database/`. --- ## 6. WEB La WEB es el frente principal de administración, planificación y seguimiento. Las rutas protegidas se declaran en `web-v2/src/app/App.tsx` y usan permisos para controlar acceso. Módulos principales: - Dashboard. - Mapa. - Inventarios y dossier. - Revisión de Inventario nacido en campo. - Inspecciones y preparación de campo. - Actas. - Hallazgos y planificación de verificaciones. - Seguimiento de Actas. - Informes. - Historial y consulta temporal. - Administración de usuarios, roles, auditoría, tipos y catálogo. No esconda una regla sólo en la WEB: toda restricción de integridad debe existir también en API/DB. --- ## 7. Android La APK está orientada a ejecución en campo. Reglas que deben mantenerse: - sólo un usuario con capacidad de ejecución puede iniciar/operar una Inspección; - `Abrir inspección` selecciona Área y Operadora vigente; - la nueva visita queda autoasignada al inspector actual; - se genera checklist antes de iniciar; - el backend recorre DRAFT → PLANNED → IN_PROGRESS con el lifecycle canónico; - Inventario nuevo en campo captura evidencia mínima antes de Hallazgos; - Hallazgos respetan los mismos niveles y catálogo que la API. Al cambiar contratos móviles, actualice tanto Kotlin como los tests de contrato montados por el preflight de API. --- ## 8. Permisos y seguridad El sistema utiliza permisos finos; las pantallas no deben asumir permisos por nombre visual del rol. La fuente efectiva es la matriz rol-permiso de base de datos. Buenas prácticas: - proteja controllers con permisos explícitos; - no confíe en que una ruta esté oculta en la WEB; - preserve la política especial del inspector móvil; - mantenga auditadas las mutaciones administrativas; - no exponga secretos ni credenciales en repositorio, logs o documentación. --- ## 9. Tests y CI La barrera principal está en `.github/workflows/ci.yml`. ### API Ejecuta: ```bash npm ci npm run typecheck npm test npm run build ``` ### WEB Ejecuta: ```bash npm ci npm run typecheck bash ../scripts/check-f3-1-web-contract.sh npm run build ``` ### Docker / contratos Valida: - sintaxis de scripts shell; - paridad del preflight de deploy; - `docker compose config`; - cadena de migraciones sobre PostGIS limpio; - estado limpio F5.1 y preservación de maestros técnicos; - segunda ejecución sin migraciones pendientes; - preflight API aislado equivalente al VPS; - build de imágenes productivas. ### Android El workflow específico de Android debe completar: - `assembleDebug`; - unit tests; - publicación del artefacto APK. ### Contrato transversal F6.1 `api-v3/test/unit/f6-1-project-invariants.test.ts` fija las reglas que más fácilmente podrían degradarse por refactors: jerarquía, contexto Área+Operadora, multi-Acta, Hallazgos, apertura móvil y separación GEDO/vencimiento. --- ## 10. Versionado Cuando una entrega cambia versión, revise como mínimo: - `api-v3/package.json`; - `api-v3/src/version.ts`; - `web-v2/package.json`; - `android-app/app/build.gradle.kts` si cambia APK; - tests que fijen metadata de versión; - metadata raíz de `package-lock.json` regenerándola con npm cuando corresponda. Los lockfiles son archivos generados: no los edite manualmente en forma parcial. Use npm para reconciliarlos. --- ## 11. Flujo Git y despliegue Secuencia recomendada: 1. crear rama desde `main` estable; 2. implementar código + migración + tests + documentación; 3. abrir PR; 4. exigir API + WEB + Docker/migraciones + Android verdes cuando aplique; 5. mergear a `main`; 6. exigir nuevamente CI verde sobre el SHA de `main`; 7. recién entonces promover el SHA exacto a `deploy`; 8. esperar el watcher/deploy; 9. comprobar SHA objetivo, health, versiones y backup generado. Nunca despliegue un SHA distinto al que pasó la barrera. Nunca use `deploy` para “probar” una rama incompleta. Si una migración es de una sola vía, el rollback operativo es el backup PRE validado, no un `migration:revert` improvisado. --- ## 12. Checklist antes de aprobar un cambio - ¿Respeta la jerarquía canónica? - ¿Empresa sigue fuera del árbol físico? - ¿Una modificación de Operadora conserva historia temporal? - ¿La regla importante está protegida también en API/DB? - ¿Hallazgos siguen limitados a Yacimiento/Instalación/Subinstalación? - ¿OTROS sigue disponible? - ¿Una Inspección puede tener varias Actas y sólo un DRAFT simultáneo? - ¿Actas finalizadas siguen inmutables? - ¿Informe sigue perteneciendo al Acta? - ¿GEDO sigue separado del inicio automático del plazo No urgente? - ¿WEB y Android consumen el mismo contrato? - ¿Se agregó un test para la nueva regla o regresión? - ¿CI completa está verde? - ¿Documentación viva quedó actualizada? --- ## 13. Terminología canónica Use consistentemente: - **Inventario**, no “Activo” en la interfaz de usuario cuando se refiere al módulo funcional. - **Departamento**. - **Área**. - **Yacimiento**. - **Instalación**. - **Subinstalación**. - **Empresa / Operadora** como maestro/rol operativo, no como padre físico. - **Inspección** para la visita operativa. - **Acta** para el documento de campo; una Inspección puede contener varias. - **Hallazgo** para la observación fiscalizable asociada a Inventario. - **Informe / INF** por Acta. - **GEDO / IF** para la oficialización documental, separada de la notificación administrativa cuando corresponda. Si una etiqueta histórica contradice estos términos, corrija la etiqueta; no cambie el modelo para conservar una denominación obsoleta.