Commit 56bd3ec0885682fb64298e854e965a1d45312607

Authored by Antigravity AI
1 parent 0bafc887

Hito: Pre-Migración a Nomenclatura Alfanumérica (e0505_lotes)

VERSION.txt
@@ -11,3 +11,4 @@ PROYECTO GIS-GEOSERVER - 2026.04.06.13.31.00 ID DOCKER: d983a409769d. Observacià @@ -11,3 +11,4 @@ PROYECTO GIS-GEOSERVER - 2026.04.06.13.31.00 ID DOCKER: d983a409769d. ObservaciÃ
11 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. 11 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.
12 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. 12 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.
13 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. 13 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.
  14 +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).
src/main/java/com/sigem/gis/controller/GisController.java
@@ -27,9 +27,9 @@ public class GisController { @@ -27,9 +27,9 @@ public class GisController {
27 // Consulta a la vista unificada vw_lotes_morosidad_XXX 27 // Consulta a la vista unificada vw_lotes_morosidad_XXX
28 String viewName = "public.vw_lotes_morosidad_" + entidad; 28 String viewName = "public.vw_lotes_morosidad_" + entidad;
29 String sql = "SELECT ccc, inm_ficha, inm_ctacatastral, trb_total_deuda, trb_total_pago, ultimo_pago " + 29 String sql = "SELECT ccc, inm_ficha, inm_ctacatastral, trb_total_deuda, trb_total_pago, ultimo_pago " +
30 - "FROM " + viewName + " WHERE ccc = ? LIMIT 1"; 30 + "FROM " + viewName + " WHERE ccc = ? AND entidad = ? LIMIT 1";
31 31
32 - List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql, ccc); 32 + List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql, ccc, entidad);
33 33
34 if (results.isEmpty()) { 34 if (results.isEmpty()) {
35 // Si no hay datos en la vista (quizás lote sin deuda), buscamos solo datos de lote 35 // Si no hay datos en la vista (quizás lote sin deuda), buscamos solo datos de lote
@@ -45,8 +45,8 @@ public class GisController { @@ -45,8 +45,8 @@ public class GisController {
45 @GetMapping("/entidad/{id}/percentiles") 45 @GetMapping("/entidad/{id}/percentiles")
46 public ResponseEntity<?> getPercentiles(@PathVariable String id) { 46 public ResponseEntity<?> getPercentiles(@PathVariable String id) {
47 try { 47 try {
48 - String sql = "SELECT * FROM public.vw_percentiles_morosidad_" + id + " LIMIT 1";  
49 - List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql); 48 + String sql = "SELECT * FROM public.vw_percentiles_morosidad_" + id + " WHERE entidad = ? LIMIT 1";
  49 + List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql, id);
50 if (results.isEmpty()) return ResponseEntity.notFound().build(); 50 if (results.isEmpty()) return ResponseEntity.notFound().build();
51 return ResponseEntity.ok(results.get(0)); 51 return ResponseEntity.ok(results.get(0));
52 } catch (Exception e) { 52 } catch (Exception e) {
@@ -61,9 +61,9 @@ public class GisController { @@ -61,9 +61,9 @@ public class GisController {
61 String sql = "SELECT " + 61 String sql = "SELECT " +
62 " COUNT(*) as total_lotes, " + 62 " COUNT(*) as total_lotes, " +
63 " COUNT(CASE WHEN trb_total_deuda > 0 THEN 1 END) as lotes_con_deuda " + 63 " COUNT(CASE WHEN trb_total_deuda > 0 THEN 1 END) as lotes_con_deuda " +
64 - "FROM " + viewName; 64 + "FROM " + viewName + " WHERE entidad = ?";
65 65
66 - return ResponseEntity.ok(gisJdbcTemplate.queryForList(sql).get(0)); 66 + return ResponseEntity.ok(gisJdbcTemplate.queryForList(sql, id).get(0));
67 } catch (Exception e) { 67 } catch (Exception e) {
68 return ResponseEntity.status(500).body(Map.of("error", e.getMessage())); 68 return ResponseEntity.status(500).body(Map.of("error", e.getMessage()));
69 } 69 }
@@ -92,8 +92,8 @@ public class GisController { @@ -92,8 +92,8 @@ public class GisController {
92 public ResponseEntity<?> getEstadisticas(@PathVariable String id) { 92 public ResponseEntity<?> getEstadisticas(@PathVariable String id) {
93 try { 93 try {
94 String schemaName = "fdw_" + id; 94 String schemaName = "fdw_" + id;
95 - String sql = "SELECT descripcion, valor FROM " + schemaName + ".estadisticas_datos";  
96 - List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql); 95 + String sql = "SELECT descripcion, valor FROM " + schemaName + ".estadisticas_datos WHERE entidad = ?";
  96 + List<Map<String, Object>> results = gisJdbcTemplate.queryForList(sql, id);
97 97
98 return ResponseEntity.ok(results); 98 return ResponseEntity.ok(results);
99 } catch (Exception e) { 99 } catch (Exception e) {
src/main/java/com/sigem/gis/security/AuthController.java
@@ -70,7 +70,8 @@ public class AuthController { @@ -70,7 +70,8 @@ public class AuthController {
70 System.out.println("Validando usuario vía FDW local para entidad: " + request.getEntidad()); 70 System.out.println("Validando usuario vía FDW local para entidad: " + request.getEntidad());
71 71
72 // 3. Buscar Usuario en el esquema FDW local (en el .123) 72 // 3. Buscar Usuario en el esquema FDW local (en el .123)
73 - 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 " + 73 + String sqlUser = "SELECT usu_nom, usu_ape, activo, entidad, " +
  74 + "pgp_sym_decrypt(usu_clave_a::bytea, '510580', 'compress-algo=0, cipher-algo=aes256')::text as clave_desencriptada " +
74 "FROM " + schemaName + ".usuarios " + 75 "FROM " + schemaName + ".usuarios " +
75 "WHERE usu_alias = ? AND ejer_fisca = date_part('year', now())"; 76 "WHERE usu_alias = ? AND ejer_fisca = date_part('year', now())";
76 77
@@ -83,7 +84,13 @@ public class AuthController { @@ -83,7 +84,13 @@ public class AuthController {
83 84
84 // 4. Validación Final y Generación de Token 85 // 4. Validación Final y Generación de Token
85 if (isActivo && request.getPassword().equals(claveDesencriptada)) { 86 if (isActivo && request.getPassword().equals(claveDesencriptada)) {
86 - String token = jwtUtil.generateToken(request.getUsername(), request.getEntidad()); 87 + // Extraer la Entidad oficial desde el FDW ( character varying 8 )
  88 + String entidadOficial = convertObjectToString(userData.get("entidad"));
  89 + if (entidadOficial == null || entidadOficial.trim().isEmpty()) {
  90 + entidadOficial = request.getEntidad(); // Fallback si el campo está vacío, aunque no debería
  91 + }
  92 +
  93 + String token = jwtUtil.generateToken(request.getUsername(), entidadOficial);
87 String nombreCompleto = convertObjectToString(userData.get("usu_nom")) + " " + convertObjectToString(userData.get("usu_ape")); 94 String nombreCompleto = convertObjectToString(userData.get("usu_nom")) + " " + convertObjectToString(userData.get("usu_ape"));
88 95
89 // Metadatos georreferenciados de la entidad 96 // Metadatos georreferenciados de la entidad
@@ -98,7 +105,7 @@ public class AuthController { @@ -98,7 +105,7 @@ public class AuthController {
98 105
99 return ResponseEntity.ok(new AuthResponse(token, nombreCompleto, "Login Exitoso", 106 return ResponseEntity.ok(new AuthResponse(token, nombreCompleto, "Login Exitoso",
100 lat, lng, zoom, minZoom, maxZoom, mapaBase, bounds, 107 lat, lng, zoom, minZoom, maxZoom, mapaBase, bounds,
101 - nombreEntidad, eslogan, logo, responsable)); 108 + nombreEntidad, eslogan, logo, responsable, entidadOficial));
102 } 109 }
103 } 110 }
104 111
src/main/java/com/sigem/gis/service/FdwService.java
@@ -55,10 +55,18 @@ public class FdwService { @@ -55,10 +55,18 @@ public class FdwService {
55 try { 55 try {
56 // ... (verificación de infraestructura fdw igual hasta la creación de vistas) 56 // ... (verificación de infraestructura fdw igual hasta la creación de vistas)
57 // ... 57 // ...
58 - String checkSql = "SELECT count(*) FROM information_schema.tables WHERE table_schema = ? AND table_name = 'usuarios'"; 58 + // Regla Multi-Tenant: Verificar presencia de las 5 tablas críticas
  59 + String checkSql = "SELECT count(*) FROM information_schema.tables " +
  60 + "WHERE table_schema = ? AND table_name IN " +
  61 + "('usuarios', 'estadisticas_datos', 'v_liq_entidad_percentiles', 'v_liq_entidad_totalxobjeto', 'ventanas_usuario')";
  62 +
59 Integer count = (forceUpdate) ? 0 : gisJdbcTemplate.queryForObject(checkSql, Integer.class, schemaName); 63 Integer count = (forceUpdate) ? 0 : gisJdbcTemplate.queryForObject(checkSql, Integer.class, schemaName);
60 64
61 - if (forceUpdate || count == null || count == 0) { 65 + // Si falta alguna de las 5 tablas o se solicita actualización forzada
  66 + if (forceUpdate || count == null || count < 5) {
  67 + if (count != null && count > 0 && count < 5) {
  68 + System.out.println("Infraestructura incompleta para " + entidadId + " (" + count + "/5 tablas). Forzando recreación...");
  69 + }
62 // (creación de server, user mapping y esquema igual) 70 // (creación de server, user mapping y esquema igual)
63 gisJdbcTemplate.execute("DROP SERVER IF EXISTS " + serverName + " CASCADE"); 71 gisJdbcTemplate.execute("DROP SERVER IF EXISTS " + serverName + " CASCADE");
64 gisJdbcTemplate.execute(String.format( 72 gisJdbcTemplate.execute(String.format(
@@ -79,13 +87,19 @@ public class FdwService { @@ -79,13 +87,19 @@ public class FdwService {
79 // Vista de Auditoría (MVT) - LIBERADA (Sin LIMIT) 87 // Vista de Auditoría (MVT) - LIBERADA (Sin LIMIT)
80 String viewLotesName = "vw_lotes_morosidad_" + entidadId; 88 String viewLotesName = "vw_lotes_morosidad_" + entidadId;
81 gisJdbcTemplate.execute(String.format( 89 gisJdbcTemplate.execute(String.format(
82 - "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", 90 + "CREATE OR REPLACE VIEW public.%s AS " +
  91 + "SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago " +
  92 + "FROM %s l " +
  93 + "LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral AND l.entidad::text = m.entidad::text",
83 viewLotesName, tableLotes, schemaName)); 94 viewLotesName, tableLotes, schemaName));
84 95
85 // Vista PNG FULL (WMS) - SIN LIMIT 96 // Vista PNG FULL (WMS) - SIN LIMIT
86 String viewWmsName = "vw_lotes_wms_" + entidadId; 97 String viewWmsName = "vw_lotes_wms_" + entidadId;
87 gisJdbcTemplate.execute(String.format( 98 gisJdbcTemplate.execute(String.format(
88 - "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", 99 + "CREATE OR REPLACE VIEW public.%s AS " +
  100 + "SELECT l.*, m.inm_ficha, m.inm_ctacatastral, m.trb_total_deuda, m.trb_total_pago, m.ultimo_pago " +
  101 + "FROM %s l " +
  102 + "LEFT JOIN %s.v_liq_entidad_totalxobjeto m ON l.ccc = m.inm_ctacatastral AND l.entidad::text = m.entidad::text",
89 viewWmsName, tableLotes, schemaName)); 103 viewWmsName, tableLotes, schemaName));
90 104
91 // 4. Sincronización con GeoServer 105 // 4. Sincronización con GeoServer
GitLab Appliance - Powered by TurnKey Linux