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 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 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 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 27 // Consulta a la vista unificada vw_lotes_morosidad_XXX
28 28 String viewName = "public.vw_lotes_morosidad_" + entidad;
29 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 34 if (results.isEmpty()) {
35 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 45 @GetMapping("/entidad/{id}/percentiles")
46 46 public ResponseEntity<?> getPercentiles(@PathVariable String id) {
47 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 50 if (results.isEmpty()) return ResponseEntity.notFound().build();
51 51 return ResponseEntity.ok(results.get(0));
52 52 } catch (Exception e) {
... ... @@ -61,9 +61,9 @@ public class GisController {
61 61 String sql = "SELECT " +
62 62 " COUNT(*) as total_lotes, " +
63 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 67 } catch (Exception e) {
68 68 return ResponseEntity.status(500).body(Map.of("error", e.getMessage()));
69 69 }
... ... @@ -92,8 +92,8 @@ public class GisController {
92 92 public ResponseEntity<?> getEstadisticas(@PathVariable String id) {
93 93 try {
94 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 98 return ResponseEntity.ok(results);
99 99 } catch (Exception e) {
... ...
src/main/java/com/sigem/gis/security/AuthController.java
... ... @@ -70,7 +70,8 @@ public class AuthController {
70 70 System.out.println("Validando usuario vía FDW local para entidad: " + request.getEntidad());
71 71  
72 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 75 "FROM " + schemaName + ".usuarios " +
75 76 "WHERE usu_alias = ? AND ejer_fisca = date_part('year', now())";
76 77  
... ... @@ -83,7 +84,13 @@ public class AuthController {
83 84  
84 85 // 4. Validación Final y Generación de Token
85 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 94 String nombreCompleto = convertObjectToString(userData.get("usu_nom")) + " " + convertObjectToString(userData.get("usu_ape"));
88 95  
89 96 // Metadatos georreferenciados de la entidad
... ... @@ -98,7 +105,7 @@ public class AuthController {
98 105  
99 106 return ResponseEntity.ok(new AuthResponse(token, nombreCompleto, "Login Exitoso",
100 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 55 try {
56 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 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 70 // (creación de server, user mapping y esquema igual)
63 71 gisJdbcTemplate.execute("DROP SERVER IF EXISTS " + serverName + " CASCADE");
64 72 gisJdbcTemplate.execute(String.format(
... ... @@ -79,13 +87,19 @@ public class FdwService {
79 87 // Vista de Auditoría (MVT) - LIBERADA (Sin LIMIT)
80 88 String viewLotesName = "vw_lotes_morosidad_" + entidadId;
81 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 94 viewLotesName, tableLotes, schemaName));
84 95  
85 96 // Vista PNG FULL (WMS) - SIN LIMIT
86 97 String viewWmsName = "vw_lotes_wms_" + entidadId;
87 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 103 viewWmsName, tableLotes, schemaName));
90 104  
91 105 // 4. Sincronización con GeoServer
... ...
GitLab Appliance - Powered by TurnKey Linux