From 56bd3ec0885682fb64298e854e965a1d45312607 Mon Sep 17 00:00:00 2001 From: Antigravity AI Date: Wed, 8 Apr 2026 06:38:23 -0300 Subject: [PATCH] Hito: Pre-Migración a Nomenclatura Alfanumérica (e0505_lotes) --- VERSION.txt | 1 + src/main/java/com/sigem/gis/controller/GisController.java | 16 ++++++++-------- src/main/java/com/sigem/gis/security/AuthController.java | 13 ++++++++++--- src/main/java/com/sigem/gis/service/FdwService.java | 22 ++++++++++++++++++---- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index e6a0684..3ef6012 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -11,3 +11,4 @@ PROYECTO GIS-GEOSERVER - 2026.04.06.13.31.00 ID DOCKER: d983a409769d. Observacià PROYECTO GIS-GEOSERVER - 2026.04.07.08.18.07 ID DOCKER: d983a409769d. Observación: Optimización visual de interfaz completada: unificación de anchos al 100%, limpieza de barra superior, traslado de controles al sidebar y registro legal SIGEM-MIC/DINAPI. PROYECTO GIS-GEOSERVER - 2026.04.07.20.37.47 ID DOCKER: d983a409769d. Observación: Modernización definitiva del Dashboard completada: Replicación de bloque de bienvenida legado, integración de mapa embebido en modo limpio y reestructuración de la fila inferior de gestión al 100% de ancho. Versión estable validada.Version SIG (Abril 2026) - 2026.04.07.22.30.00 ID DOCKER: d983a409769d. Observación: Éxito en implementación de Login Dinámico (SaaS), integración de logos binarios, eslóganes y responsables desde el servidor .254. Version SIG (Abril 2026) - 2026.04.07.23.35.00 ID DOCKER: cb7329596324. Observación: Éxito en la implementación de Estadísticas Reales (formato vertical fdw_X.estadisticas_datos) y actualización forzada de FDW desde el menú Administración. +Version SIG (Abril 2026) - 2026.04.08.06.45.00 ID DOCKER: cb7329596324. Observación: Inicio de migración a Nomenclatura Alfanumérica Multi-Tenant (e0505_lotes). diff --git a/src/main/java/com/sigem/gis/controller/GisController.java b/src/main/java/com/sigem/gis/controller/GisController.java index e9bb16a..e29b365 100644 --- a/src/main/java/com/sigem/gis/controller/GisController.java +++ b/src/main/java/com/sigem/gis/controller/GisController.java @@ -27,9 +27,9 @@ public class GisController { // Consulta a la vista unificada vw_lotes_morosidad_XXX String viewName = "public.vw_lotes_morosidad_" + entidad; String sql = "SELECT ccc, inm_ficha, inm_ctacatastral, trb_total_deuda, trb_total_pago, ultimo_pago " + - "FROM " + viewName + " WHERE ccc = ? LIMIT 1"; + "FROM " + viewName + " WHERE ccc = ? AND entidad = ? LIMIT 1"; - List> results = gisJdbcTemplate.queryForList(sql, ccc); + List> results = gisJdbcTemplate.queryForList(sql, ccc, entidad); if (results.isEmpty()) { // Si no hay datos en la vista (quizás lote sin deuda), buscamos solo datos de lote @@ -45,8 +45,8 @@ public class GisController { @GetMapping("/entidad/{id}/percentiles") public ResponseEntity getPercentiles(@PathVariable String id) { try { - String sql = "SELECT * FROM public.vw_percentiles_morosidad_" + id + " LIMIT 1"; - List> results = gisJdbcTemplate.queryForList(sql); + String sql = "SELECT * FROM public.vw_percentiles_morosidad_" + id + " WHERE entidad = ? LIMIT 1"; + List> results = gisJdbcTemplate.queryForList(sql, id); if (results.isEmpty()) return ResponseEntity.notFound().build(); return ResponseEntity.ok(results.get(0)); } catch (Exception e) { @@ -61,9 +61,9 @@ public class GisController { String sql = "SELECT " + " COUNT(*) as total_lotes, " + " COUNT(CASE WHEN trb_total_deuda > 0 THEN 1 END) as lotes_con_deuda " + - "FROM " + viewName; + "FROM " + viewName + " WHERE entidad = ?"; - return ResponseEntity.ok(gisJdbcTemplate.queryForList(sql).get(0)); + return ResponseEntity.ok(gisJdbcTemplate.queryForList(sql, id).get(0)); } catch (Exception e) { return ResponseEntity.status(500).body(Map.of("error", e.getMessage())); } @@ -92,8 +92,8 @@ public class GisController { public ResponseEntity getEstadisticas(@PathVariable String id) { try { String schemaName = "fdw_" + id; - String sql = "SELECT descripcion, valor FROM " + schemaName + ".estadisticas_datos"; - List> results = gisJdbcTemplate.queryForList(sql); + String sql = "SELECT descripcion, valor FROM " + schemaName + ".estadisticas_datos WHERE entidad = ?"; + List> results = gisJdbcTemplate.queryForList(sql, id); return ResponseEntity.ok(results); } catch (Exception e) { diff --git a/src/main/java/com/sigem/gis/security/AuthController.java b/src/main/java/com/sigem/gis/security/AuthController.java index ad288f0..2768948 100644 --- a/src/main/java/com/sigem/gis/security/AuthController.java +++ b/src/main/java/com/sigem/gis/security/AuthController.java @@ -70,7 +70,8 @@ public class AuthController { System.out.println("Validando usuario vía FDW local para entidad: " + request.getEntidad()); // 3. Buscar Usuario en el esquema FDW local (en el .123) - String sqlUser = "SELECT usu_nom, usu_ape, activo, pgp_sym_decrypt(usu_clave_a::bytea, '510580', 'compress-algo=0, cipher-algo=aes256')::text as clave_desencriptada " + + String sqlUser = "SELECT usu_nom, usu_ape, activo, entidad, " + + "pgp_sym_decrypt(usu_clave_a::bytea, '510580', 'compress-algo=0, cipher-algo=aes256')::text as clave_desencriptada " + "FROM " + schemaName + ".usuarios " + "WHERE usu_alias = ? AND ejer_fisca = date_part('year', now())"; @@ -83,7 +84,13 @@ public class AuthController { // 4. Validación Final y Generación de Token if (isActivo && request.getPassword().equals(claveDesencriptada)) { - String token = jwtUtil.generateToken(request.getUsername(), request.getEntidad()); + // Extraer la Entidad oficial desde el FDW ( character varying 8 ) + String entidadOficial = convertObjectToString(userData.get("entidad")); + if (entidadOficial == null || entidadOficial.trim().isEmpty()) { + entidadOficial = request.getEntidad(); // Fallback si el campo está vacío, aunque no debería + } + + String token = jwtUtil.generateToken(request.getUsername(), entidadOficial); String nombreCompleto = convertObjectToString(userData.get("usu_nom")) + " " + convertObjectToString(userData.get("usu_ape")); // Metadatos georreferenciados de la entidad @@ -98,7 +105,7 @@ public class AuthController { return ResponseEntity.ok(new AuthResponse(token, nombreCompleto, "Login Exitoso", lat, lng, zoom, minZoom, maxZoom, mapaBase, bounds, - nombreEntidad, eslogan, logo, responsable)); + nombreEntidad, eslogan, logo, responsable, entidadOficial)); } } diff --git a/src/main/java/com/sigem/gis/service/FdwService.java b/src/main/java/com/sigem/gis/service/FdwService.java index 51658bf..db62d97 100644 --- a/src/main/java/com/sigem/gis/service/FdwService.java +++ b/src/main/java/com/sigem/gis/service/FdwService.java @@ -55,10 +55,18 @@ public class FdwService { try { // ... (verificación de infraestructura fdw igual hasta la creación de vistas) // ... - String checkSql = "SELECT count(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = 'usuarios'"; + // Regla Multi-Tenant: Verificar presencia de las 5 tablas críticas + String checkSql = "SELECT count(*) FROM information_schema.tables " + + "WHERE table_schema = ? AND table_name IN " + + "('usuarios', 'estadisticas_datos', 'v_liq_entidad_percentiles', 'v_liq_entidad_totalxobjeto', 'ventanas_usuario')"; + Integer count = (forceUpdate) ? 0 : gisJdbcTemplate.queryForObject(checkSql, Integer.class, schemaName); - if (forceUpdate || count == null || count == 0) { + // Si falta alguna de las 5 tablas o se solicita actualización forzada + if (forceUpdate || count == null || count < 5) { + if (count != null && count > 0 && count < 5) { + System.out.println("Infraestructura incompleta para " + entidadId + " (" + count + "/5 tablas). Forzando recreación..."); + } // (creación de server, user mapping y esquema igual) gisJdbcTemplate.execute("DROP SERVER IF EXISTS " + serverName + " CASCADE"); gisJdbcTemplate.execute(String.format( @@ -79,13 +87,19 @@ public class FdwService { // Vista de Auditoría (MVT) - LIBERADA (Sin LIMIT) String viewLotesName = "vw_lotes_morosidad_" + entidadId; gisJdbcTemplate.execute(String.format( - "CREATE OR REPLACE VIEW public.%s AS SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago FROM %s l LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral", + "CREATE OR REPLACE VIEW public.%s AS " + + "SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago " + + "FROM %s l " + + "LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral AND l.entidad::text = m.entidad::text", viewLotesName, tableLotes, schemaName)); // Vista PNG FULL (WMS) - SIN LIMIT String viewWmsName = "vw_lotes_wms_" + entidadId; gisJdbcTemplate.execute(String.format( - "CREATE OR REPLACE VIEW public.%s AS SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago FROM %s l LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral", + "CREATE OR REPLACE VIEW public.%s AS " + + "SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago " + + "FROM %s l " + + "LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral AND l.entidad::text = m.entidad::text", viewWmsName, tableLotes, schemaName)); // 4. Sincronización con GeoServer -- libgit2 0.22.2