Commit 99c89404686599b814a59e27a3e6066706437a38

Authored by Antigravity AI
0 parents

Observación: Reestructuracion pura de BaseMap y soporte Google auto-escalado satelital.

Showing 113 changed files with 9393 additions and 0 deletions

Too many changes.

To preserve performance only 50 of 113 files are displayed.

GIS-GEOSERVER/.mvn/wrapper/maven-wrapper.properties 0 → 100644
  1 +++ a/GIS-GEOSERVER/.mvn/wrapper/maven-wrapper.properties
  1 +wrapperVersion=3.3.4
  2 +distributionType=only-script
  3 +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.14/apache-maven-3.9.14-bin.zip
GIS-GEOSERVER/0 0 → 100644
1 Binary files /dev/null and a/GIS-GEOSERVER/0 differ 1 Binary files /dev/null and a/GIS-GEOSERVER/0 differ
GIS-GEOSERVER/Dockerfile 0 → 100644
  1 +++ a/GIS-GEOSERVER/Dockerfile
  1 +FROM eclipse-temurin:21-jdk-alpine
  2 +VOLUME /tmp
  3 +ARG JAR_FILE=gis-geoserver-0.0.1-SNAPSHOT.jar
  4 +COPY ${JAR_FILE} app.jar
  5 +EXPOSE 8081
  6 +ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
GIS-GEOSERVER/FdwService.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/FdwService.java
  1 +package com.sigem.gis.service;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.beans.factory.annotation.Qualifier;
  5 +import org.springframework.jdbc.core.JdbcTemplate;
  6 +import org.springframework.stereotype.Service;
  7 +import java.util.List;
  8 +import java.util.Map;
  9 +
  10 +@Service
  11 +public class FdwService {
  12 +
  13 + @Autowired
  14 + private GeoServerService geoServerService;
  15 +
  16 + @Autowired
  17 + @Qualifier("masterJdbcTemplate")
  18 + private JdbcTemplate masterJdbcTemplate;
  19 +
  20 + @Autowired
  21 + @Qualifier("gisJdbcTemplate")
  22 + private JdbcTemplate gisJdbcTemplate;
  23 +
  24 + public void setupFdw(String entidadId) {
  25 + String sqlEntidad = "SELECT sigem_site, sigem_dbname, boundno, boundse, latlong, zoom, maxzoom, minzoom FROM public.entidades WHERE entidad = ?";
  26 + List<Map<String, Object>> entidades = masterJdbcTemplate.queryForList(sqlEntidad, Integer.parseInt(entidadId));
  27 +
  28 + if (entidades.isEmpty()) throw new RuntimeException("Entidad " + entidadId + " no encontrada.");
  29 +
  30 + Map<String, Object> data = entidades.get(0);
  31 + String sigemSite = (String) data.get("sigem_site");
  32 + String sigemDbname = (String) data.get("sigem_dbname");
  33 + String boundNo = (String) data.get("boundno");
  34 + String boundSe = (String) data.get("boundse");
  35 +
  36 + String host = extractParam(sigemSite, "host", "127.0.0.1");
  37 + String port = extractParam(sigemSite, "port", "5432");
  38 + String user = extractParam(sigemSite, "user", "postgres");
  39 + String pass = extractParam(sigemSite, "password", "x25yvaga2017");
  40 +
  41 + String serverName = "srv_mun_" + entidadId;
  42 + String schemaName = "fdw_" + entidadId;
  43 +
  44 + try {
  45 + gisJdbcTemplate.execute("CREATE EXTENSION IF NOT EXISTS postgres_fdw");
  46 + gisJdbcTemplate.execute("DROP SERVER IF EXISTS " + serverName + " CASCADE");
  47 + gisJdbcTemplate.execute(String.format("CREATE SERVER %s FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host '%s', port '%s', dbname '%s')", serverName, host, port, sigemDbname));
  48 + gisJdbcTemplate.execute(String.format("CREATE USER MAPPING FOR sigem_user SERVER %s OPTIONS (user '%s', password '%s')", serverName, user, pass));
  49 + gisJdbcTemplate.execute("CREATE SCHEMA IF NOT EXISTS " + schemaName);
  50 + gisJdbcTemplate.execute(String.format("IMPORT FOREIGN SCHEMA public LIMIT TO (v_liq_entidad_totalxobjeto, v_liq_entidad_percentiles, usuarios, ventanas_usuario) FROM SERVER %s INTO %s", serverName, schemaName));
  51 +
  52 + // REGLA 23 ACTUALIZADA: Join OBLIGATORIO por CCC = INM_CTACATASTRAL
  53 + String tableLotes = "public.e" + entidadId + "_lotes_conccc";
  54 + String viewName = "vw_lotes_morosidad_" + entidadId;
  55 + String viewWms = "vw_lotes_wms_" + entidadId;
  56 + String sqlJoin = 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", viewName, tableLotes, schemaName);
  57 +
  58 + gisJdbcTemplate.execute(sqlJoin);
  59 + gisJdbcTemplate.execute(sqlJoin.replace(viewName, viewWms));
  60 +
  61 + try {
  62 + geoServerService.publishLayer(viewName, viewName, null, boundNo, boundSe);
  63 + enableMvt(viewName);
  64 + geoServerService.truncateCache(viewName);
  65 + geoServerService.publishLayer(viewWms, viewWms, "morosidad_style_wms", boundNo, boundSe);
  66 + geoServerService.truncateCache(viewWms);
  67 + } catch (Exception e) { System.err.println("Advertencia GS: " + e.getMessage()); }
  68 +
  69 + } catch (Exception e) { throw new RuntimeException("Error FDW: " + e.getMessage(), e); }
  70 + }
  71 +
  72 + private String extractParam(String siteParam, String key, String defaultValue) {
  73 + if (siteParam != null && siteParam.contains(key + "=")) {
  74 + String[] parts = siteParam.split(key + "=");
  75 + if (parts.length > 1) return parts[1].split(" ")[0].trim();
  76 + }
  77 + return defaultValue;
  78 + }
  79 +
  80 + public void enableMvt(String layerName) {
  81 + // Hablar con host interno proyecto-geoserver-1
  82 + String geoserverUrl = "http://proyecto-geoserver-1:8080/geoserver/gwc/rest/layers/sigem:" + layerName + ".xml";
  83 + String auth = "admin:geoserver";
  84 + String encodedAuth = java.util.Base64.getEncoder().encodeToString(auth.getBytes());
  85 + String xmlBody = "<GeoServerLayer><enabled>true</enabled><mimeFormats><string>application/x-protobuf</string></mimeFormats></GeoServerLayer>";
  86 + try {
  87 + java.net.URL url = new java.net.URL(geoserverUrl);
  88 + java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();
  89 + conn.setRequestMethod("POST");
  90 + conn.setRequestProperty("Authorization", "Basic " + encodedAuth);
  91 + conn.setRequestProperty("Content-Type", "text/xml");
  92 + conn.setDoOutput(true);
  93 + conn.setConnectTimeout(2000);
  94 + try (java.io.OutputStream os = conn.getOutputStream()) { os.write(xmlBody.getBytes()); }
  95 + conn.getResponseCode();
  96 + } catch (Exception e) { System.err.println("Error MVT: " + e.getMessage()); }
  97 + }
  98 +}
GIS-GEOSERVER/GeoServerService.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/GeoServerService.java
  1 +package com.sigem.gis.service;
  2 +
  3 +import org.springframework.http.*;
  4 +import org.springframework.stereotype.Service;
  5 +import org.springframework.web.client.RestTemplate;
  6 +
  7 +@Service
  8 +public class GeoServerService {
  9 +
  10 + private final String GS_URL = "http://proyecto-geoserver-1:8080/geoserver/rest";
  11 + private final String GS_USER = "admin";
  12 + private final String GS_PASS = "geoserver";
  13 +
  14 + private final RestTemplate restTemplate;
  15 +
  16 + public GeoServerService() {
  17 + org.springframework.http.client.SimpleClientHttpRequestFactory factory = new org.springframework.http.client.SimpleClientHttpRequestFactory();
  18 + factory.setConnectTimeout(2000);
  19 + factory.setReadTimeout(2000);
  20 + this.restTemplate = new RestTemplate(factory);
  21 + }
  22 +
  23 + public void ensureStyleExists(String styleName) {
  24 + String url = GS_URL + "/styles/" + styleName;
  25 + try {
  26 + restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(createHeaders()), String.class);
  27 + } catch (Exception e) {
  28 + String sldBody = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
  29 + "<StyledLayerDescriptor version=\"1.0.0\" xmlns=\"http://www.opengis.net/sld\">" +
  30 + "<NamedLayer><Name>morosidad_style_wms</Name><UserStyle><FeatureTypeStyle>" +
  31 + "<Rule><Title>Verde</Title><ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\"><ogc:PropertyIsEqualTo><ogc:PropertyName>ultimo_pago</ogc:PropertyName><ogc:Literal>2026</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Filter><PolygonSymbolizer><Fill><CssParameter name=\"fill\">#71de75</CssParameter></Fill><Stroke><CssParameter name=\"stroke\">#000000</CssParameter><CssParameter name=\"stroke-width\">0.2</CssParameter></Stroke></PolygonSymbolizer></Rule>" +
  32 + "<Rule><Title>Ambar</Title><ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\"><ogc:PropertyIsGreaterThanOrEqualTo><ogc:PropertyName>ultimo_pago</ogc:PropertyName><ogc:Literal>2024</ogc:Literal></ogc:PropertyIsGreaterThanOrEqualTo></ogc:Filter><PolygonSymbolizer><Fill><CssParameter name=\"fill\">#ffaa00</CssParameter></Fill><Stroke><CssParameter name=\"stroke\">#000000</CssParameter><CssParameter name=\"stroke-width\">0.2</CssParameter></Stroke></PolygonSymbolizer></Rule>" +
  33 + "<Rule><Title>Rojo</Title><ogc:Filter xmlns:ogc=\"http://www.opengis.net/ogc\"><ogc:PropertyIsLessThanOrEqualTo><ogc:PropertyName>ultimo_pago</ogc:PropertyName><ogc:Literal>2023</ogc:Literal></ogc:PropertyIsLessThanOrEqualTo></ogc:Filter><PolygonSymbolizer><Fill><CssParameter name=\"fill\">#f87171</CssParameter></Fill><Stroke><CssParameter name=\"stroke\">#000000</CssParameter><CssParameter name=\"stroke-width\">0.2</CssParameter></Stroke></PolygonSymbolizer></Rule>" +
  34 + "<Rule><ElseFilter/><PolygonSymbolizer><Fill><CssParameter name=\"fill\">#94a3b8</CssParameter><CssParameter name=\"fill-opacity\">0.4</CssParameter></Fill></PolygonSymbolizer></Rule>" +
  35 + "</FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";
  36 +
  37 + try {
  38 + // Crear el estilo
  39 + String createJson = String.format("{\"style\": {\"name\": \"%s\", \"filename\": \"%s.sld\"}}", styleName, styleName);
  40 + HttpHeaders h = createHeaders();
  41 + h.setContentType(MediaType.APPLICATION_JSON);
  42 + restTemplate.postForEntity(GS_URL + "/styles", new HttpEntity<>(createJson, h), String.class);
  43 +
  44 + // Subir el SLD
  45 + HttpHeaders sldHeaders = createHeaders();
  46 + sldHeaders.setContentType(MediaType.parseMediaType("application/vnd.ogc.sld+xml"));
  47 + restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(sldBody, sldHeaders), String.class);
  48 + } catch (Exception ex) {
  49 + System.err.println("Error creando estilo: " + ex.getMessage());
  50 + }
  51 + }
  52 + }
  53 +
  54 + public void publishLayer(String layerName, String viewName, String styleName, String boundNo, String boundSe) {
  55 + ensureInfrastructureExists();
  56 + if (styleName != null) ensureStyleExists(styleName);
  57 +
  58 + String workspace = "sigem";
  59 + String datastore = "sigem_db";
  60 + String url = String.format("%s/workspaces/%s/datastores/%s/featuretypes/%s", GS_URL, workspace, datastore, layerName);
  61 +
  62 + String jsonBody = String.format("{\"featureType\": {\"name\": \"%s\", \"nativeName\": \"%s\", \"srs\": \"EPSG:4326\"}}", layerName, viewName);
  63 + HttpHeaders headers = createHeaders();
  64 + headers.setContentType(MediaType.APPLICATION_JSON);
  65 +
  66 + try {
  67 + restTemplate.exchange(url, HttpMethod.PUT, new HttpEntity<>(jsonBody, headers), String.class);
  68 + } catch (Exception e) {
  69 + String postUrl = String.format("%s/workspaces/%s/datastores/%s/featuretypes", GS_URL, workspace, datastore);
  70 + try { restTemplate.postForEntity(postUrl, new HttpEntity<>(jsonBody, headers), String.class); } catch (Exception ex) {}
  71 + }
  72 +
  73 + if (styleName != null) {
  74 + String layerUrl = String.format("%s/layers/sigem:%s", GS_URL, layerName);
  75 + String layerJson = String.format("{\"layer\": {\"defaultStyle\": {\"name\": \"%s\"}}}", styleName);
  76 + try { restTemplate.exchange(layerUrl, HttpMethod.PUT, new HttpEntity<>(layerJson, headers), String.class); } catch (Exception e) {}
  77 + }
  78 + }
  79 +
  80 + private void ensureInfrastructureExists() {
  81 + String workspace = "sigem";
  82 + String datastore = "sigem_db";
  83 + try {
  84 + restTemplate.exchange(GS_URL + "/workspaces/" + workspace, HttpMethod.GET, new HttpEntity<>(createHeaders()), String.class);
  85 + } catch (Exception e) {
  86 + String wsJson = String.format("{\"workspace\": {\"name\": \"%s\"}}", workspace);
  87 + HttpHeaders h = createHeaders(); h.setContentType(MediaType.APPLICATION_JSON);
  88 + try { restTemplate.postForEntity(GS_URL + "/workspaces", new HttpEntity<>(wsJson, h), String.class); } catch (Exception ex) {}
  89 + }
  90 +
  91 + try {
  92 + restTemplate.exchange(GS_URL + "/workspaces/" + workspace + "/datastores/" + datastore, HttpMethod.GET, new HttpEntity<>(createHeaders()), String.class);
  93 + } catch (Exception e) {
  94 + String dsJson = String.format("{\"dataStore\": {\"name\": \"%s\", \"connectionParameters\": {\"host\": \"proyecto-postgres-1\", \"port\": \"5432\", \"database\": \"sigem\", \"user\": \"sigem_user\", \"passwd\": \"sigem_pass\", \"dbtype\": \"postgis\"}}}", datastore);
  95 + HttpHeaders h = createHeaders(); h.setContentType(MediaType.APPLICATION_JSON);
  96 + try { restTemplate.postForEntity(GS_URL + "/workspaces/" + workspace + "/datastores", new HttpEntity<>(dsJson, h), String.class); } catch (Exception ex) {}
  97 + }
  98 + }
  99 +
  100 + public void truncateCache(String layerName) {
  101 + String url = "http://proyecto-geoserver-1:8080/geoserver/gwc/rest/masstruncate";
  102 + String xmlBody = String.format("<truncateLayer><layerName>sigem:%s</layerName></truncateLayer>", layerName);
  103 + HttpHeaders h = createHeaders(); h.setContentType(MediaType.TEXT_XML);
  104 + try { restTemplate.postForEntity(url, new HttpEntity<>(xmlBody, h), String.class); } catch (Exception e) {}
  105 + }
  106 +
  107 + private HttpHeaders createHeaders() {
  108 + HttpHeaders headers = new HttpHeaders();
  109 + headers.setBasicAuth(GS_USER, GS_PASS);
  110 + return headers;
  111 + }
  112 +}
GIS-GEOSERVER/Jenkinsfile 0 → 100644
  1 +++ a/GIS-GEOSERVER/Jenkinsfile
  1 +pipeline {
  2 + agent any
  3 +
  4 + tools {
  5 + // Asegurar que Jenkins tenga configurado el JDK 21 y Maven 3
  6 + jdk 'Java 21'
  7 + maven 'Maven 3'
  8 + }
  9 +
  10 + environment {
  11 + // Variables del Contenedor de Producción (GeoServer)
  12 + SERVER_IP = '192.168.1.123'
  13 + // NOTA: Reemplazar por la Credencial SSH configurada en Jenkins para apuntar a root@192.168.1.123
  14 + SSH_CREDENTIAL_ID = 'sigem-server-123'
  15 + IMAGE_NAME = 'sigem/gis-geoserver-app:latest'
  16 + TAR_FILE = 'gis-backend.tar'
  17 + }
  18 +
  19 + stages {
  20 + stage('Clonar Repositorio (Checkout)') {
  21 + steps {
  22 + checkout scm
  23 + echo "Código Fuente clonado y listo para validación."
  24 + }
  25 + }
  26 +
  27 + stage('Compilación Java (Build & Test)') {
  28 + steps {
  29 + echo "Empaquetando microservicio con Maven..."
  30 + sh 'mvn clean package -DskipTests'
  31 + echo "Archivo .jar generado con éxito."
  32 + }
  33 + }
  34 +
  35 + stage('Construcción de Imagen Docker') {
  36 + steps {
  37 + echo "Construyendo imagen Docker usando Temurin JDK 21..."
  38 + sh "docker build -t ${IMAGE_NAME} ."
  39 + }
  40 + }
  41 +
  42 + stage('Exportación y Despliegue Secuencial') {
  43 + steps {
  44 + sshagent([SSH_CREDENTIAL_ID]) {
  45 + echo "Exportando contenedor a archivo tar. Esto toma unos segundos..."
  46 + sh "docker save ${IMAGE_NAME} > ${TAR_FILE}"
  47 +
  48 + echo "Transfiriendo archivos vía SCP hacia 192.168.1.123..."
  49 + sh "scp -o StrictHostKeyChecking=no ${TAR_FILE} root@${SERVER_IP}:/tmp/${TAR_FILE}"
  50 + sh "ssh -o StrictHostKeyChecking=no root@${SERVER_IP} 'mkdir -p /opt/gis-backend/'"
  51 + sh "scp -o StrictHostKeyChecking=no docker-compose.yml root@${SERVER_IP}:/opt/gis-backend/"
  52 +
  53 + echo "Levantando el Sistema Remotamente en el Nodo PostGIS..."
  54 + sh '''
  55 + ssh -o StrictHostKeyChecking=no root@${SERVER_IP} "
  56 + cd /opt/gis-backend/
  57 + docker load < /tmp/${TAR_FILE}
  58 + docker compose down
  59 + docker compose up -d
  60 + rm -f /tmp/${TAR_FILE}
  61 + echo 'Microservicio Reiniciado sin caída de datos.'
  62 + "
  63 + '''
  64 + }
  65 + }
  66 + }
  67 + }
  68 +
  69 + post {
  70 + success {
  71 + echo "Despliegue del Módulo GIS completado de forma impecable. Disponible en el puerto 8081."
  72 + }
  73 + failure {
  74 + echo "La compilación o el despliegue del mapa ha fallado. Revisa los logs de SSH."
  75 + }
  76 + }
  77 +}
GIS-GEOSERVER/ProxyController.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/ProxyController.java
  1 +package com.sigem.gis.controller;
  2 +
  3 +import jakarta.servlet.http.HttpServletRequest;
  4 +import org.springframework.http.*;
  5 +import org.springframework.web.bind.annotation.*;
  6 +import org.springframework.web.client.RestTemplate;
  7 +import org.springframework.util.StreamUtils;
  8 +import java.net.URI;
  9 +import java.net.URISyntaxException;
  10 +import java.util.Enumeration;
  11 +
  12 +@RestController
  13 +public class ProxyController {
  14 +
  15 + private final RestTemplate restTemplate;
  16 + private final String geoserverInternalBase = "http://proyecto-geoserver-1:8080";
  17 +
  18 + public ProxyController(RestTemplate restTemplate) {
  19 + this.restTemplate = restTemplate;
  20 + }
  21 +
  22 + @RequestMapping(value = {"/geoserver/**", "/gwc/**"}, method = {RequestMethod.GET, RequestMethod.POST})
  23 + @ResponseBody
  24 + public ResponseEntity<byte[]> proxy(HttpServletRequest request) throws URISyntaxException {
  25 + String path = request.getRequestURI();
  26 + // Eliminamos el prefijo del contexto de la aplicación
  27 + if (path.startsWith("/gis-geoserver")) {
  28 + path = path.substring("/gis-geoserver".length());
  29 + }
  30 +
  31 + // Si la petición viene por /gwc/, GeoServer la espera en /geoserver/gwc/
  32 + if (path.startsWith("/gwc")) {
  33 + path = "/geoserver" + path;
  34 + }
  35 +
  36 + String query = request.getQueryString();
  37 + String fullUrl = geoserverInternalBase + path + (query != null ? "?" + query : "");
  38 + URI uri = new URI(fullUrl);
  39 +
  40 + HttpHeaders headers = new HttpHeaders();
  41 + Enumeration<String> headerNames = request.getHeaderNames();
  42 + while (headerNames.hasMoreElements()) {
  43 + String hName = headerNames.nextElement();
  44 + // Evitamos pasar el Host original para que GeoServer no intente redirecciones externas
  45 + if (!hName.equalsIgnoreCase("host")) {
  46 + headers.add(hName, request.getHeader(hName));
  47 + }
  48 + }
  49 +
  50 + return restTemplate.execute(uri, HttpMethod.valueOf(request.getMethod()), (req) -> {
  51 + req.getHeaders().putAll(headers);
  52 + if (request.getContentLength() > 0) StreamUtils.copy(request.getInputStream(), req.getBody());
  53 + }, (res) -> {
  54 + byte[] body = StreamUtils.copyToByteArray(res.getBody());
  55 + HttpHeaders responseHeaders = new HttpHeaders();
  56 + responseHeaders.putAll(res.getHeaders());
  57 + // Sobrescribimos el content type si es necesario para asegurar la entrega de imágenes/PBF
  58 + return new ResponseEntity<>(body, responseHeaders, res.getStatusCode());
  59 + });
  60 + }
  61 +}
GIS-GEOSERVER/RestTemplateConfig.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/RestTemplateConfig.java
  1 +package com.sigem.gis.config;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.web.client.RestTemplate;
  6 +
  7 +@Configuration
  8 +public class RestTemplateConfig {
  9 + @Bean
  10 + public RestTemplate restTemplate() {
  11 + return new RestTemplate();
  12 + }
  13 +}
GIS-GEOSERVER/SecurityConfig.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/SecurityConfig.java
  1 +package com.sigem.gis.security;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  7 +import org.springframework.security.config.http.SessionCreationPolicy;
  8 +import org.springframework.security.web.SecurityFilterChain;
  9 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  10 +
  11 +@Configuration
  12 +@EnableWebSecurity
  13 +public class SecurityConfig {
  14 +
  15 + private final JwtAuthenticationFilter jwtAuthFilter;
  16 +
  17 + public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter) {
  18 + this.jwtAuthFilter = jwtAuthFilter;
  19 + }
  20 +
  21 + @Bean
  22 + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  23 + http
  24 + .csrf(csrf -> csrf.disable())
  25 + .cors(cors -> cors.disable())
  26 + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  27 + .authorizeHttpRequests(authz -> authz
  28 + .requestMatchers("/api/auth/**").permitAll()
  29 + .requestMatchers("/api/admin/**").permitAll()
  30 + .requestMatchers("/login.html", "/", "/mapas", "/login", "/error").permitAll()
  31 + .requestMatchers("/css/**", "/js/**", "/img/**").permitAll()
  32 +
  33 + // Permitimos el tráfico hacia el puente interno de GeoServer (Solución C)
  34 + .requestMatchers("/gwc/**").permitAll()
  35 + .requestMatchers("/geoserver/**").permitAll()
  36 +
  37 + .requestMatchers("/api/**").authenticated()
  38 + .anyRequest().permitAll()
  39 + )
  40 + .httpBasic(basic -> basic.disable())
  41 + .formLogin(form -> form.disable())
  42 + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
  43 +
  44 + return http.build();
  45 + }
  46 +}
GIS-GEOSERVER/SecurityConfig_master.java 0 → 100644
  1 +++ a/GIS-GEOSERVER/SecurityConfig_master.java
  1 +package com.sigem.gis.security;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  7 +import org.springframework.security.config.http.SessionCreationPolicy;
  8 +import org.springframework.security.web.SecurityFilterChain;
  9 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  10 +
  11 +@Configuration
  12 +@EnableWebSecurity
  13 +public class SecurityConfig {
  14 +
  15 + private final JwtAuthenticationFilter jwtAuthFilter;
  16 +
  17 + public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter) {
  18 + this.jwtAuthFilter = jwtAuthFilter;
  19 + }
  20 +
  21 + @Bean
  22 + public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
  23 + http
  24 + .csrf(csrf -> csrf.disable()) // Deshabilitado para APIs REST (Stateless con JWT)
  25 + .cors(cors -> cors.disable()) // Modificable luego para permitir conexiones cruzadas
  26 + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
  27 + .authorizeHttpRequests(authz -> authz
  28 + // Accesos no autenticados permitidos (Puerta de Entrada Prototipo)
  29 + .requestMatchers("/api/auth/**").permitAll()
  30 + .requestMatchers("/api/admin/**").permitAll()
  31 + .requestMatchers("/login_prototipo.html", "/login.html", "/", "/mapas", "/login", "/error").permitAll()
  32 + .requestMatchers("/css/**", "/js/**", "/img/**").permitAll()
  33 + .requestMatchers("/gwc/**").permitAll()
  34 +
  35 + // Todas las demás llamadas API estarán protegidas mediante JWT
  36 + .requestMatchers("/api/**").authenticated()
  37 + .anyRequest().permitAll()
  38 + )
  39 + .httpBasic(basic -> basic.disable())
  40 + .formLogin(form -> form.disable())
  41 + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
  42 +
  43 + return http.build();
  44 + }
  45 +}
GIS-GEOSERVER/VERSION.txt 0 → 100644
  1 +++ a/GIS-GEOSERVER/VERSION.txt
  1 +Version de Estabilizacion SIG (Abril 2026) - 2026.04.02.13.00.00
  2 +Version de Estabilizacion SIG (Abril 2026) - 2026.04.03.11.58.33
  3 +V e r s i o n d e E s t a b i l i z a c i o n S I G ( A b r i l 2 0 2 6 ) - 2 0 2 6 . 0 4 . 0 3 . 1 6 . 1 0 . 0 0
  4 +
  5 + Version de Estabilizacion SIG (Abril 2026) - 2026.04.04.20.43.27 ID DOCKER: 932819b9d2da
  6 +
  7 +Version de Estabilizacion SIG (Abril 2026) - 2026.04.05.01.49.29 ID DOCKER: c68e229b6d94
  8 +Mapa Coloreado
  9 +Version de Estabilizacion SIG (Abril 2026) - 2026.04.05.04.28.49 ID DOCKER: c68e229b6d94. Observación: Fix de las contraseñas WMS y polígonos a full color.
  10 +Versión de Estabilización SIG (Abril 2026) - 2026.04.05.06.31.00 ID DOCKER: c68e229b6d94. Observación: Reestructuracion pura de BaseMap y soporte Google auto-escalado satelital.
0 \ No newline at end of file 11 \ No newline at end of file
GIS-GEOSERVER/apache_ssl_update.conf 0 → 100644
  1 +++ a/GIS-GEOSERVER/apache_ssl_update.conf
  1 +<IfModule mod_ssl.c>
  2 +<VirtualHost *:443>
  3 + ServerName sigemtest.yvaga.com.py
  4 + ServerAdmin cbareiro@yvaga.com.py
  5 +
  6 + ProxyPass /api/portalciudadano/backend/ http://192.168.1.162:9003/api/sigemweb-portal-backend/ timeout=1200
  7 + ProxyPassReverse /api/portalciudadano/backend/ http://192.168.1.162:9003/api/sigemweb-portal-backend/ timeout=1200
  8 + ProxyPreserveHost On
  9 +
  10 + ProxyPass /portalciudadano/ http://192.168.1.162:9004/portalciudadano/ timeout=1200
  11 + ProxyPassReverse /portalciudadano/ http://192.168.1.162:9004/portalciudadano/ timeout=1200
  12 + ProxyPreserveHost On
  13 +
  14 + ProxyPass /sigemweb/ http://192.168.1.162:9002/sigemweb/ timeout=1200
  15 + ProxyPassReverse /sigemweb/ http://192.168.1.162:9002/sigemweb/ timeout=1200
  16 + ProxyPreserveHost On
  17 +
  18 + ProxyPass /api/ http://192.168.1.162:9001/api/ timeout=1200
  19 + ProxyPassReverse /api/ http://192.168.1.162:9001/api/ timeout=1200
  20 + ProxyPreserveHost On
  21 +
  22 + ProxyPass /sigemweb http://192.168.1.162:9002/sigemweb/ timeout=1200
  23 + ProxyPassReverse /sigemweb/ http://192.168.1.162:9002/sigemweb/ timeout=1200
  24 + ProxyPreserveHost On
  25 +
  26 + # --- INICIO BLOQUE GIS GEOSERVER (.123) ---
  27 + # Rutas Web Frontend (Spring Boot en Puerto 8081)
  28 + ProxyPass /mapas http://192.168.1.123:8081/mapas timeout=1200
  29 + ProxyPassReverse /mapas http://192.168.1.123:8081/mapas timeout=1200
  30 + ProxyPass /login http://192.168.1.123:8081/login timeout=1200
  31 + ProxyPassReverse /login http://192.168.1.123:8081/login timeout=1200
  32 +
  33 + # Ruta Diferenciada de API GIS para no chocar con el /api/ de la .162 principal
  34 + ProxyPass /gis-api/ http://192.168.1.123:8081/api/ timeout=1200
  35 + ProxyPassReverse /gis-api/ http://192.168.1.123:8081/api/ timeout=1200
  36 +
  37 + # Ruta Nativa del Servidor espacial para consumo WMS Seguro por HTTPS
  38 + ProxyPass /geoserver/ http://192.168.1.123:8080/geoserver/ timeout=1200
  39 + ProxyPassReverse /geoserver/ http://192.168.1.123:8080/geoserver/ timeout=1200
  40 + # --- FIN BLOQUE GIS ---
  41 +
  42 + ProxyPass / http://192.168.1.20/ timeout=1200
  43 + ProxyPassReverse / http://192.168.1.20/ timeout=1200
  44 + ProxyPreserveHost On
  45 +
  46 + ErrorLog /var/log/httpd/sigemtest-error.log
  47 + SSLCertificateFile /etc/letsencrypt/live/sigemtest.yvaga.com.py/cert.pem
  48 + SSLCertificateKeyFile /etc/letsencrypt/live/sigemtest.yvaga.com.py/privkey.pem
  49 + Include /etc/letsencrypt/options-ssl-apache.conf
  50 + SSLCertificateChainFile /etc/letsencrypt/live/sigemtest.yvaga.com.py/chain.pem
  51 +</VirtualHost>
  52 +</IfModule>
GIS-GEOSERVER/application_master.properties 0 → 100644
  1 +++ a/GIS-GEOSERVER/application_master.properties
  1 +server.port=8081
  2 +server.servlet.context-path=/gis-geoserver
  3 +
  4 +# Configuración de Recursos Estáticos para Prototipado en Vivo (Carga desde Disco)
  5 +# Esto permite modificar login_prototipo.html y ver cambios al instante sin rebuild
  6 +spring.web.resources.static-locations=classpath:/static/,file:/yvyape/proyectos/sigem-gis/src/main/resources/static/
  7 +
  8 +# Configuración JPA
  9 +spring.jpa.hibernate.ddl-auto=none
  10 +spring.jpa.show-sql=true
  11 +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
  12 +spring.application.name=gis-geoserver
  13 +
  14 +# JPA Config - Master (SigemWeb)
  15 +spring.datasource.master.url=jdbc:postgresql://192.168.1.254:5432/sigemweb
  16 +spring.datasource.master.username=postgres
  17 +spring.datasource.master.password=x25yvaga2017
  18 +
  19 +# JPA Config - GIS (PostGIS Local .123)
  20 +spring.datasource.gis.url=jdbc:postgresql://proyecto-postgres-1:5432/sigem
  21 +spring.datasource.gis.username=sigem_user
  22 +spring.datasource.gis.password=sigem_pass
GIS-GEOSERVER/check_geom.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/check_geom.sql
  1 +SELECT
  2 + 'vw_lotes_morosidad_505' as view_name,
  3 + count(*) as total_records,
  4 + ST_GeometryType(geom) as geom_type,
  5 + ST_SRID(geom) as srid,
  6 + sum(case when ST_IsValid(geom) then 1 else 0 end) as valid_geometries,
  7 + sum(case when geom IS NULL then 1 else 0 end) as null_geometries
  8 +FROM public.vw_lotes_morosidad_505
  9 +GROUP BY 1, 3, 4;
GIS-GEOSERVER/check_rule5.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/check_rule5.sql
  1 +SELECT sigem_site, sigem_dbname, latlong, lng, lat, zoom, mapa_base, boundno, boundse, maxzoom, minzoom
  2 +FROM public.entidades
  3 +WHERE entidad=505;
GIS-GEOSERVER/control_gestion.php 0 → 100644
  1 +++ a/GIS-GEOSERVER/control_gestion.php
  1 +<!-- MENU DE CONTROL DE GESTION -->
  2 +<li class="treeview">
  3 + <a href="#">
  4 + <i class="fa fa-tasks"></i> <span>CONTROL DE GESTION</span>
  5 + <span class="pull-right-container">
  6 + <i class="fa fa-angle-left pull-right"></i>
  7 + </span>
  8 + </a>
  9 + <ul class="treeview-menu">
  10 + <li class="treeview">
  11 + <a href="#"><i class="fa fa-globe"></i> MAPAS
  12 + <span class="pull-right-container">
  13 + <i class="fa fa-angle-left pull-right"></i>
  14 + </span>
  15 + </a>
  16 + <ul class="treeview-menu">
  17 + <li class="treeview">
  18 + <a href="#"><i class="fa fa-tasks"></i> TRIBUTARIOS
  19 + <span class="pull-right-container">
  20 + <i class="fa fa-angle-left pull-right"></i>
  21 + </span>
  22 + </a>
  23 + <ul class="treeview-menu">
  24 + <li><a href="liq_por_tipo.php"><i class="fa fa-money"> </i>MAPA MOROSIDAD/PAGO</a></li>
  25 + <li><a href="liq_por_zona.php"><i class="fa fa-location-arrow"> </i>MAPA ZONAS TRIBUTARIAS</a></li>
  26 + <li><a href="liq_por_frente.php"><i class="fa fa-street-view"> </i>MAPA TIPO PAVIMENTO</a></li>
  27 + <li><a href="estado_notificacion.php"><i class="fa fa-flag"> </i>MAPA NOTIFICACIONES</a></li>
  28 + <li><a href="liq_baldios.php"><i class="fa fa-map-marker"> </i>LOTES BALDIOS</a></li>
  29 + </ul>
  30 + </li>
  31 + <li class="treeview">
  32 + <a href="#"><i class="fa fa-search"></i> SEGUIMIENTO
  33 + <span class="pull-right-container">
  34 + <i class="fa fa-angle-left pull-right"></i>
  35 + </span>
  36 + </a>
  37 + <ul class="treeview-menu">
  38 + <li><a href="estado_sigem.php"><i class="fa fa-exclamation-triangle"> </i>LOTES SIN FICHAS</a></li>
  39 + </ul>
  40 + <ul class="treeview-menu">
  41 + <li><a href="estado_migracion.php"><i class="fa fa-flag"> </i>ACTUALIZACIONES</a></li>
  42 + </ul>
  43 + <ul class="treeview-menu">
  44 + <li><a href="estado_lotes.php"><i class="fa fa-check"> </i>ESTADO DE LOTES</a></li>
  45 + </ul>
  46 + <ul class="treeview-menu">
  47 + <li><a href="estado_mejoras.php"><i class="fa fa-check-circle"> </i>ESTADO DE MEJORAS</a></li>
  48 + </ul>
  49 + <!-- COMPARATIVOS -->
  50 + <ul class="treeview-menu">
  51 + <li class="treeview">
  52 + <a href="#"><i class="fa fa-globe"></i> COMPARATIVO
  53 + <span class="pull-right-container">
  54 + <i class="fa fa-angle-left pull-right"></i>
  55 + </span>
  56 + </a>
  57 + <ul class="treeview-menu">
  58 + <!--li><a href="comp_por_tipo.php"><i class="fa fa-money"> </i>MOROSIDAD/PAGO</a></li-->
  59 + <!--li><a href="#"><i class="fa fa-money"> </i>MOROSIDAD/PAGO</a></li-->
  60 + <li><a href="comp_por_zona.php"><i class="fa fa-location-arrow"> </i>ZONAS TRIBUTARIAS</a></li>
  61 + <li><a href="comp_por_frente.php"><i class="fa fa-street-view"> </i>TIPO PAVIMENTO</a></li>
  62 + <li><a href="comp_baldios.php"><i class="fa fa-map-marker"> </i>BALDIOS</a></li>
  63 + </ul>
  64 + </li>
  65 + </ul>
  66 + <!-- /COMPARATIVOS -->
  67 + </li>
  68 + <li class="treeview">
  69 + <a href="#"><i class="fa fa-globe"></i> MONITOREO
  70 + <span class="pull-right-container">
  71 + <i class="fa fa-angle-left pull-right"></i>
  72 + </span>
  73 + </a>
  74 + <ul class="treeview-menu">
  75 + <li><a href="fiscalizacion_obras.php"><i class="fa fa-map-marker"> </i>FISCALIZACION DE OBRAS</a></li>
  76 + </ul>
  77 + <?php if ($_SESSION['entidad'] == 9999 || $_SESSION['entidad'] == 507) { ?>
  78 + <ul class="treeview-menu">
  79 + <li><a href="liq_recoleccion.php"><i class="fa fa-truck"> </i>RECOLECCION DE BASURA</a></li>
  80 + </ul>
  81 + <ul class="treeview-menu">
  82 + <li><a href="baches.php"><i class="fa fa-car"> </i>BACHES</a></li>
  83 + </ul>
  84 + <?php } ?>
  85 + </li>
  86 + </ul>
  87 + </li>
  88 + <li class="treeview">
  89 + <a href="#"><i class="fa fa-tasks"></i> INFORMES
  90 + <span class="pull-right-container">
  91 + <i class="fa fa-angle-left pull-right"></i>
  92 + </span>
  93 + </a>
  94 + <ul class="treeview-menu">
  95 + <li class="treeview">
  96 + <a href="#"><i class="fa fa-money"></i> INGRESOS
  97 + <span class="pull-right-container">
  98 + <i class="fa fa-angle-left pull-right"></i>
  99 + </span>
  100 + </a>
  101 + <ul class="treeview-menu">
  102 + <li><a href="informe_ingresos_diarios.php"><i class="fa fa-money"> </i>INGRESOS POR DIA</a></li>
  103 + <li><a href="#"><i class="fa fa-location-arrow"> </i>INGRESOS POR MES</a></li>
  104 + <li><a href="informe_ingresos_periodo.php"><i class="fa fa-street-view"> </i>INGRESOS POR PERIODO</a></li>
  105 + </ul>
  106 + </li>
  107 + <li class="treeview">
  108 + <a href="#"><i class="fa fa-tasks"></i> EGRESOS
  109 + <span class="pull-right-container">
  110 + <i class="fa fa-angle-left pull-right"></i>
  111 + </span>
  112 + </a>
  113 + <ul class="treeview-menu">
  114 + <li><a href="#"><i class="fa fa-money"> </i>REPORTE DIARIO</a></li>
  115 + </ul>
  116 + </li>
  117 + </ul>
  118 + </li>
  119 +
  120 + <!-- -->
  121 + <?php if ($_SESSION['entidad'] == 9999 || $_SESSION['entidad'] == 507) { ?>
  122 + <li class="treeview">
  123 + <a href="expediente.php"><i class="fa fa-tasks"></i> EXPEDIENTES
  124 + </a>
  125 + </li>
  126 + <?php } ?>
  127 + </ul>
  128 +</li>
0 \ No newline at end of file 129 \ No newline at end of file
GIS-GEOSERVER/dbconf.php 0 → 100644
  1 +++ a/GIS-GEOSERVER/dbconf.php
  1 +<?php
  2 +//DATABASE CONNECTION VARIABLES
  3 +//$host = "host.docker.internal"; // Host name
  4 +$host = "192.168.1.90"; // Host name
  5 +$username = "postgres"; // Mysql username
  6 +$password = "x25yvaga2018"; // Mysql password
  7 +$db_name = "cartodb_user_17b59d48-0892-47a7-a206-e1b3bb6fb6f8_db"; // Database name
  8 +$db_port = "5432";
  9 +
  10 +//DO NOT CHANGE BELOW THIS LINE UNLESS YOU CHANGE THE NAMES OF THE MEMBERS AND LOGINATTEMPTS TABLES
  11 +
  12 +$tbl_prefix = ""; //***PLANNED FEATURE, LEAVE VALUE BLANK FOR NOW*** Prefix for all database tables
  13 +$tbl_members = $tbl_prefix."public.entidades";
  14 +$tbl_attempts = $tbl_prefix."public.loginattempts";
GIS-GEOSERVER/debug_db.sh 0 → 100644
  1 +++ a/GIS-GEOSERVER/debug_db.sh
  1 +#!/bin/bash
  2 +echo "=== INSPECCION DE CONTENEDOR ==="
  3 +docker inspect proyecto-postgres-1 --format '
  4 +Imagen: {{.Config.Image}}
  5 +Puertos: {{.NetworkSettings.Ports}}
  6 +Montajes: {{range .Mounts}}{{.Source}} -> {{.Destination}}{{end}}
  7 +Env: {{range .Config.Env}}{{.}} {{end}}
  8 +'
  9 +echo "=== BUSQUEDA DE DEFINICION ==="
  10 +grep -r "proyecto-postgres-1" /yvyape/proyectos/sigem-gis --exclude-dir=geoserver-data --exclude-dir=target
GIS-GEOSERVER/detect_locks.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/detect_locks.sql
  1 +SELECT
  2 + a.pid AS blocking_pid, a.usename AS blocking_user, a.client_addr AS blocking_ip,
  3 + b.pid AS blocked_pid, b.usename AS blocked_user, b.query AS blocked_statement,
  4 + age(now(), a.query_start) AS age_of_lock
  5 +FROM pg_stat_activity a
  6 +JOIN pg_stat_activity b ON a.datid = b.datid AND a.pid != b.pid
  7 +JOIN pg_locks l1 ON a.pid = l1.pid
  8 +JOIN pg_locks l2 ON b.pid = l2.pid AND l1.relation = l2.relation
  9 +WHERE NOT l2.granted AND l1.granted;
GIS-GEOSERVER/diag_db.sh 0 → 100644
  1 +++ a/GIS-GEOSERVER/diag_db.sh
  1 +sudo -u postgres psql -d sigem_gis -c "\dv public.vw_lotes_morosidad_505"
  2 +sudo -u postgres psql -d sigem_gis -c "\d public.lotes_nomenclatura"
GIS-GEOSERVER/diag_db_docker.sh 0 → 100644
  1 +++ a/GIS-GEOSERVER/diag_db_docker.sh
  1 +docker inspect proyecto-postgres-1 | grep -iE "POSTGRES_USER|POSTGRES_DB"
  2 +docker exec proyecto-postgres-1 psql -U postgres -d sigem_gis -c "\dv" || docker exec proyecto-postgres-1 psql -U sigem_user -d sigem_gis -c "\dv" || true
GIS-GEOSERVER/diag_fdw.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/diag_fdw.sql
  1 +-- Diagnóstico de Integridad FDW Entidad 505
  2 +SELECT '--- TABLAS IMPORTADAS EN fdw_505 ---' as reporte;
  3 +SELECT table_name FROM information_schema.tables WHERE table_schema = 'fdw_505' ORDER BY table_name;
  4 +
  5 +SELECT '--- COLUMNAS DE fdw_505.usuarios ---' as reporte;
  6 +SELECT column_name, data_type FROM information_schema.columns
  7 +WHERE table_schema = 'fdw_505' AND table_name = 'usuarios'
  8 +ORDER BY ordinal_position;
  9 +
  10 +SELECT '--- PRUEBA DE ACCESO (SIN DESENCRIPTAR) ---' as reporte;
  11 +SELECT usu_alias, ejer_fisca FROM fdw_505.usuarios WHERE usu_alias = 'operador' LIMIT 1;
GIS-GEOSERVER/diag_schema_505.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/diag_schema_505.sql
  1 +-- Diagnóstico detallado de esquemas para la Entidad 505
  2 +\echo '--- ESTRUCTURA DE LOTES ---'
  3 +\d public.e505_lotes_conccc
  4 +
  5 +\echo '--- ESTRUCTURA DE MEJORAS ---'
  6 +\d public.e505_mejoras
  7 +
  8 +\echo '--- ESTRUCTURA DE MOROSIDAD (FDW) ---'
  9 +\d fdw_505.v_liq_entidad_totalxobjeto
  10 +
  11 +\echo '--- LISTADO DE TABLAS EN EL ESQUEMA PUBLIC ---'
  12 +SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name LIKE 'e505_%';
GIS-GEOSERVER/diag_v28.sh 0 → 100644
No preview for this file type
GIS-GEOSERVER/docker-compose-v33.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose-v33.yml
  1 +version: '3.8'
  2 +services:
  3 + gis-geoserver-backend:
  4 + image: sigem/gis-geoserver-app:latest
  5 + container_name: sigem-gis-backend
  6 + restart: unless-stopped
  7 + ports:
  8 + - "8081:8081"
  9 + environment:
  10 + - TZ=America/Asuncion
  11 + - GIS_DB_HOST=proyecto-postgres-1
  12 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  13 + networks:
  14 + - sigem-net
  15 + - proyecto_sigem_network
  16 +
  17 +networks:
  18 + sigem-net:
  19 + driver: bridge
  20 + proyecto_sigem_network:
  21 + external: true
GIS-GEOSERVER/docker-compose.integrated.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose.integrated.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + container_name: proyecto-geoserver-1
  5 + environment:
  6 + - GEOSERVER_ADMIN_PASSWORD=admin
  7 + - GEOSERVER_CORS_ENABLED=true
  8 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  9 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  10 + volumes:
  11 + - ./geoserver-data:/opt/geoserver/data_dir
  12 + ports:
  13 + - "8080:8080"
  14 + networks:
  15 + - proyecto_sigem_network
  16 + restart: always
  17 +
  18 + backend-java:
  19 + image: eclipse-temurin:21-jre
  20 + container_name: proyecto-backend-java-1
  21 + environment:
  22 + - SERVER_PORT=8081
  23 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  24 + # Configuración Maestra Directa (Reglas 2/5)
  25 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  26 + - SPRING_DATASOURCE_MASTER_USERNAME=postgres
  27 + - SPRING_DATASOURCE_MASTER_PASSWORD=x25yvaga2017
  28 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  29 + # Configuración Local (Regla 1) - PostgreSQL 18
  30 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://postgres:5432/sigem
  31 + - SPRING_DATASOURCE_GIS_USERNAME=sigem_user
  32 + - SPRING_DATASOURCE_GIS_PASSWORD=sigem_pass
  33 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  34 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  35 + volumes:
  36 + - ../backend-java/gis-geoserver.jar:/app.jar
  37 + ports:
  38 + - "8081:8081"
  39 + command: ["java", "-jar", "/app.jar"]
  40 + networks:
  41 + - proyecto_sigem_network
  42 + restart: always
  43 +
  44 + postgres:
  45 + image: postgis/postgis:18-3.6
  46 + container_name: proyecto-postgres-1
  47 + environment:
  48 + - POSTGRES_USER=sigem_user
  49 + - POSTGRES_PASSWORD=sigem_pass
  50 + - POSTGRES_DB=sigem
  51 + volumes:
  52 + - pg_data:/var/lib/postgresql
  53 + ports:
  54 + - "5432:5432"
  55 + networks:
  56 + - proyecto_sigem_network
  57 + restart: always
  58 +
  59 +networks:
  60 + proyecto_sigem_network:
  61 + external: true
  62 +
  63 +volumes:
  64 + pg_data:
  65 + external: true
  66 + name: proyecto_proyecto_postgres_data
GIS-GEOSERVER/docker-compose.v18.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose.v18.yml
  1 +version: '3.8'
  2 +services:
  3 + postgres:
  4 + image: postgis/postgis:18-3.6
  5 + container_name: proyecto-postgres-1
  6 + ports:
  7 + - "5432:5432"
  8 + environment:
  9 + - POSTGRES_USER=sigem_user
  10 + - POSTGRES_PASSWORD=sigem_pass
  11 + - POSTGRES_DB=sigem_gis
  12 + volumes:
  13 + # Ajuste para PostgreSQL 18+: Montaje en la raíz del directorio de datos
  14 + - proyecto_postgres_data:/var/lib/postgresql
  15 + networks:
  16 + - sigem-net
  17 + restart: always
  18 +
  19 +networks:
  20 + sigem-net:
  21 + driver: bridge
  22 +
  23 +volumes:
  24 + proyecto_postgres_data:
  25 + driver: local
  26 + # No definimos external: true para que docker-compose gestione el ciclo de vida del volumen limpio
GIS-GEOSERVER/docker-compose.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + container_name: proyecto-geoserver-1
  5 + environment:
  6 + - GEOSERVER_ADMIN_PASSWORD=geoserver
  7 + - GEOSERVER_CORS_ENABLED=true
  8 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  9 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  10 + volumes:
  11 + - ./geoserver-data:/opt/geoserver/data_dir
  12 + ports:
  13 + - "8080:8080"
  14 + networks:
  15 + - proyecto_sigem_network
  16 + restart: always
  17 +
  18 + backend-java:
  19 + image: eclipse-temurin:21-jre
  20 + container_name: proyecto-backend-java-1
  21 + environment:
  22 + - SERVER_PORT=8081
  23 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  24 + # Configuración Maestra Directa (Reglas 2/5)
  25 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  26 + - SPRING_DATASOURCE_MASTER_USERNAME=postgres
  27 + - SPRING_DATASOURCE_MASTER_PASSWORD=x25yvaga2017
  28 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  29 + # Configuración Local (Regla 1) - PostgreSQL 18
  30 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://postgres:5432/sigem
  31 + - SPRING_DATASOURCE_GIS_USERNAME=sigem_user
  32 + - SPRING_DATASOURCE_GIS_PASSWORD=sigem_pass
  33 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  34 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  35 + volumes:
  36 + - ./target/gis-geoserver-0.0.1-SNAPSHOT.jar:/app.jar
  37 + ports:
  38 + - "8081:8081"
  39 + command: ["java", "-jar", "/app.jar"]
  40 + networks:
  41 + - proyecto_sigem_network
  42 + restart: always
  43 +
  44 + postgres:
  45 + image: postgis/postgis:18-3.6
  46 + container_name: proyecto-postgres-1
  47 + environment:
  48 + - POSTGRES_USER=sigem_user
  49 + - POSTGRES_PASSWORD=sigem_pass
  50 + - POSTGRES_DB=sigem
  51 + volumes:
  52 + - pg_data:/var/lib/postgresql
  53 + ports:
  54 + - "5432:5432"
  55 + networks:
  56 + - proyecto_sigem_network
  57 + restart: always
  58 +
  59 +networks:
  60 + proyecto_sigem_network:
  61 + external: true
  62 +
  63 +volumes:
  64 + pg_data:
  65 + external: true
  66 + name: proyecto_proyecto_postgres_data
GIS-GEOSERVER/docker-compose.yml.remote.tmp 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose.yml.remote.tmp
  1 +version: '3.8'
  2 +services:
  3 + gis-geoserver-backend:
  4 + image: sigem/gis-geoserver-app:latest
  5 + container_name: sigem-gis-backend
  6 + restart: unless-stopped
  7 + ports:
  8 + - "8081:8081"
  9 + volumes:
  10 + - /home/cbareiro/sigem-gis/gis-geoserver.jar:/app.jar
  11 + environment:
  12 + - TZ=America/Asuncion
  13 + - GIS_DB_HOST=proyecto-postgres-1
  14 + networks:
  15 + - sigem-net
  16 + - proyecto_sigem_network
  17 +
  18 +networks:
  19 + sigem-net:
  20 + driver: bridge
  21 + proyecto_sigem_network:
  22 + external: true
GIS-GEOSERVER/docker-compose_v20.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose_v20.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + environment:
  5 + - GEOSERVER_ADMIN_PASSWORD=admin
  6 + - GEOSERVER_CORS_ENABLED=true
  7 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  8 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  9 + volumes:
  10 + - ./geoserver-data:/opt/geoserver/data_dir
  11 + ports:
  12 + - "8080:8080"
  13 + restart: always
  14 +
  15 + backend-java:
  16 + image: eclipse-temurin:21-jre
  17 + environment:
  18 + - SERVER_PORT=8081
  19 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  20 + - APP_DB_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  21 + - APP_DB_MASTER_USERNAME=sigemweb
  22 + - APP_DB_MASTER_PASSWORD=sigemweb
  23 + - APP_DB_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  24 + - APP_DB_GIS_URL=jdbc:postgresql://192.168.1.123:5432/sigem_gis
  25 + - APP_DB_GIS_USERNAME=cbareiro
  26 + - APP_DB_GIS_PASSWORD=x25yvaga2023
  27 + - APP_DB_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  28 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  29 + volumes:
  30 + - ../backend-java/gis-geoserver.jar:/app.jar
  31 + ports:
  32 + - "8081:8081"
  33 + command: ["java", "-jar", "/app.jar"]
  34 + restart: always
GIS-GEOSERVER/docker-compose_v22.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose_v22.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + environment:
  5 + - GEOSERVER_ADMIN_PASSWORD=admin
  6 + - GEOSERVER_CORS_ENABLED=true
  7 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  8 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  9 + volumes:
  10 + - ./geoserver-data:/opt/geoserver/data_dir
  11 + ports:
  12 + - "8080:8080"
  13 + restart: always
  14 +
  15 + backend-java:
  16 + image: eclipse-temurin:21-jre
  17 + environment:
  18 + - SERVER_PORT=8081
  19 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  20 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  21 + - SPRING_DATASOURCE_MASTER_USERNAME=sigemweb
  22 + - SPRING_DATASOURCE_MASTER_PASSWORD=sigemweb
  23 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  24 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://192.168.1.123:5432/sigem_gis
  25 + - SPRING_DATASOURCE_GIS_USERNAME=cbareiro
  26 + - SPRING_DATASOURCE_GIS_PASSWORD=x25yvaga2023
  27 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  28 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  29 + volumes:
  30 + - ../backend-java/gis-geoserver.jar:/app.jar
  31 + ports:
  32 + - "8081:8081"
  33 + command: ["java", "-jar", "/app.jar"]
  34 + restart: always
GIS-GEOSERVER/docker-compose_v24.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose_v24.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + environment:
  5 + - GEOSERVER_ADMIN_PASSWORD=admin
  6 + - GEOSERVER_CORS_ENABLED=true
  7 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  8 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  9 + volumes:
  10 + - ./geoserver-data:/opt/geoserver/data_dir
  11 + ports:
  12 + - "8080:8080"
  13 + restart: always
  14 +
  15 + backend-java:
  16 + image: eclipse-temurin:21-jre
  17 + environment:
  18 + - SERVER_PORT=8081
  19 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  20 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  21 + - SPRING_DATASOURCE_MASTER_USERNAME=postgres
  22 + - SPRING_DATASOURCE_MASTER_PASSWORD=x25yvaga2017
  23 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  24 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://192.168.1.123:5432/sigem_gis
  25 + - SPRING_DATASOURCE_GIS_USERNAME=cbareiro
  26 + - SPRING_DATASOURCE_GIS_PASSWORD=x25yvaga2017
  27 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  28 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  29 + volumes:
  30 + - ../backend-java/gis-geoserver.jar:/app.jar
  31 + ports:
  32 + - "8081:8081"
  33 + command: ["java", "-jar", "/app.jar"]
  34 + restart: always
GIS-GEOSERVER/docker-compose_v25.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose_v25.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + environment:
  5 + - GEOSERVER_ADMIN_PASSWORD=admin
  6 + - GEOSERVER_CORS_ENABLED=true
  7 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  8 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  9 + volumes:
  10 + - ./geoserver-data:/opt/geoserver/data_dir
  11 + ports:
  12 + - "8080:8080"
  13 + restart: always
  14 +
  15 + backend-java:
  16 + image: eclipse-temurin:21-jre
  17 + environment:
  18 + - SERVER_PORT=8081
  19 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  20 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.90:5432/cartodb_user_17b59d48-0892-47a7-a206-e1b3bb6fb6f8_db
  21 + - SPRING_DATASOURCE_MASTER_USERNAME=postgres
  22 + - SPRING_DATASOURCE_MASTER_PASSWORD=x25yvaga2018
  23 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  24 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://192.168.1.123:5432/sigem_gis
  25 + - SPRING_DATASOURCE_GIS_USERNAME=cbareiro
  26 + - SPRING_DATASOURCE_GIS_PASSWORD=x25yvaga2023
  27 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  28 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  29 + volumes:
  30 + - ../backend-java/gis-geoserver.jar:/app.jar
  31 + ports:
  32 + - "8081:8081"
  33 + command: ["java", "-jar", "/app.jar"]
  34 + restart: always
GIS-GEOSERVER/docker-compose_v26.yml 0 → 100644
  1 +++ a/GIS-GEOSERVER/docker-compose_v26.yml
  1 +services:
  2 + geoserver:
  3 + image: kartoza/geoserver:2.24.1
  4 + environment:
  5 + - GEOSERVER_ADMIN_PASSWORD=admin
  6 + - GEOSERVER_CORS_ENABLED=true
  7 + - GEOSERVER_CORS_ALLOWED_ORIGINS=*
  8 + - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/data_dir/gwc
  9 + volumes:
  10 + - ./geoserver-data:/opt/geoserver/data_dir
  11 + ports:
  12 + - "8080:8080"
  13 + restart: always
  14 +
  15 + backend-java:
  16 + image: eclipse-temurin:21-jre
  17 + environment:
  18 + - SERVER_PORT=8081
  19 + - SERVER_SERVLET_CONTEXT_PATH=/gis-geoserver
  20 + - SPRING_DATASOURCE_MASTER_URL=jdbc:postgresql://192.168.1.254:5432/sigemweb
  21 + - SPRING_DATASOURCE_MASTER_USERNAME=postgres
  22 + - SPRING_DATASOURCE_MASTER_PASSWORD=x25yvaga2017
  23 + - SPRING_DATASOURCE_MASTER_DRIVER_CLASS_NAME=org.postgresql.Driver
  24 + - SPRING_DATASOURCE_GIS_URL=jdbc:postgresql://192.168.1.123:5432/sigem_gis
  25 + - SPRING_DATASOURCE_GIS_USERNAME=cbareiro
  26 + - SPRING_DATASOURCE_GIS_PASSWORD=x25yvaga2017
  27 + - SPRING_DATASOURCE_GIS_DRIVER_CLASS_NAME=org.postgresql.Driver
  28 + - JWT_SECRET=sigem_gis_secret_key_2024_v1
  29 + volumes:
  30 + - ../backend-java/gis-geoserver.jar:/app.jar
  31 + ports:
  32 + - "8081:8081"
  33 + command: ["java", "-jar", "/app.jar"]
  34 + restart: always
GIS-GEOSERVER/extensions.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/extensions.sql
  1 +-- Instalación de Extensiones Necesarias en DB sigem
  2 +CREATE EXTENSION IF NOT EXISTS dblink SCHEMA public;
  3 +CREATE EXTENSION IF NOT EXISTS pg_trgm SCHEMA public;
  4 +CREATE EXTENSION IF NOT EXISTS pgcrypto SCHEMA public;
  5 +CREATE EXTENSION IF NOT EXISTS postgres_fdw SCHEMA public;
  6 +-- plpgsql suele venir por defecto en el catálogo, nos aseguramos:
  7 +CREATE EXTENSION IF NOT EXISTS plpgsql SCHEMA pg_catalog;
GIS-GEOSERVER/extract_carto.sh 0 → 100644
  1 +++ a/GIS-GEOSERVER/extract_carto.sh
  1 +#!/bin/bash
  2 +echo "Verificando ogr2ogr..."
  3 +if ! command -v ogr2ogr &> /dev/null
  4 +then
  5 + echo "ogr2ogr no se encuentra. Intentando instalar gdal-bin..."
  6 + echo "x25yvaga2023" | sudo -S DEBIAN_FRONTEND=noninteractive apt-get update
  7 + echo "x25yvaga2023" | sudo -S DEBIAN_FRONTEND=noninteractive apt-get install -y gdal-bin
  8 +fi
  9 +
  10 +echo "Iniciando Extraccion de PostGIS a GPKG (Carto Sanity Pass)..."
  11 +cd /home/cbareiro
  12 +rm -f sigem_export.gpkg
  13 +ogr2ogr -f "GPKG" sigem_export.gpkg PG:"dbname=cartodb_user_17b59d48-0892-47a7-a206-e1b3bb6fb6f8_db host=127.0.0.1 user=postgres password=x25yvaga2017" "e505_barloc" "e505_calles" "e505_distrito" "e505_lotes" "e505_lotes_conccc" "e505_lotes_sinccc" "e505_manzanas" "e505_medidores" "e505_mejoras" "e505_zonas_tributarias"
  14 +
  15 +echo "Verificando exportacion final:"
  16 +ls -lh sigem_export.gpkg
  17 +echo "Extraccion Exitosa."
GIS-GEOSERVER/fix_fdw_direct.sql 0 → 100644
  1 +++ a/GIS-GEOSERVER/fix_fdw_direct.sql
  1 +-- REPARACIÓN DEFINITIVA DE FDW USUARIOS (v42.1)
  2 +DROP SCHEMA IF EXISTS fdw_505 CASCADE;
  3 +DROP SERVER IF EXISTS srv_mun_505 CASCADE;
  4 +
  5 +-- Crear servidor con los parámetros dinámicos de la Entidad 505 (Host: 10.0.25.1 Port: 5414 DB: sigem0505)
  6 +CREATE SERVER srv_mun_505 FOREIGN DATA WRAPPER postgres_fdw
  7 +OPTIONS (host '10.0.25.1', port '5414', dbname 'sigem0505');
  8 +
  9 +-- Mapeo de usuario con contraseña de la tabla ENTIDADES para 505 (postgres / x25yvaga2018)
  10 +CREATE USER MAPPING FOR sigem_user SERVER srv_mun_505
  11 +OPTIONS (user 'postgres', password 'x25yvaga2018');
  12 +
  13 +CREATE SCHEMA fdw_505;
  14 +
  15 +-- Importación explícita incluyendo pgcrypto local
  16 +IMPORT FOREIGN SCHEMA public LIMIT TO (v_liq_entidad_totalxobjeto, v_liq_entidad_percentiles, usuarios, ventanas_usuario)
  17 +FROM SERVER srv_mun_505 INTO fdw_505;
  18 +
  19 +-- Verificación de columnas de usuarios
  20 +SELECT column_name, data_type FROM information_schema.columns
  21 +WHERE table_schema = 'fdw_505' AND table_name = 'usuarios';
GIS-GEOSERVER/gwc_lotes.xml 0 → 100644
  1 +++ a/GIS-GEOSERVER/gwc_lotes.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<GeoServerLayer>
  3 + <enabled>true</enabled>
  4 + <name>sigem:vw_lotes_morosidad_505</name>
  5 + <mimeFormats>
  6 + <string>image/png</string>
  7 + <string>image/jpeg</string>
  8 + <string>application/x-protobuf</string>
  9 + </mimeFormats>
  10 + <gridSubsets>
  11 + <gridSubset>
  12 + <gridSetName>EPSG:900913</gridSetName>
  13 + </gridSubset>
  14 + <gridSubset>
  15 + <gridSetName>EPSG:4326</gridSetName>
  16 + </gridSubset>
  17 + </gridSubsets>
  18 +</GeoServerLayer>
GIS-GEOSERVER/gwc_mejoras.xml 0 → 100644
  1 +++ a/GIS-GEOSERVER/gwc_mejoras.xml
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<GeoServerLayer>
  3 + <enabled>true</enabled>
  4 + <name>sigem:e505_mejoras</name>
  5 + <mimeFormats>
  6 + <string>image/png</string>
  7 + <string>image/jpeg</string>
  8 + <string>application/x-protobuf</string>
  9 + </mimeFormats>
  10 + <gridSubsets>
  11 + <gridSubset>
  12 + <gridSetName>EPSG:900913</gridSetName>
  13 + </gridSubset>
  14 + <gridSubset>
  15 + <gridSetName>EPSG:4326</gridSetName>
  16 + </gridSubset>
  17 + </gridSubsets>
  18 +</GeoServerLayer>
GIS-GEOSERVER/inject_gis.sh 0 → 100644
  1 +++ a/GIS-GEOSERVER/inject_gis.sh
  1 +#!/bin/bash
  2 +echo "1. Asegurando extension PostGIS en BD 'sigem'..."
  3 +docker exec proyecto-postgres-1 psql -U sigem_user -d sigem -c "CREATE EXTENSION IF NOT EXISTS postgis;" || echo "BD no lista o error"
  4 +
  5 +echo "2. Copiando paquete GeoPackage al interior del contenedor..."
  6 +docker cp /yvyape/proyectos/sigem-gis/sigem_export.gpkg proyecto-postgres-1:/tmp/sigem_export.gpkg
  7 +
  8 +echo "3. Ejecutando inyeccion masiva ogr2ogr a PostgreSQL (sigem)..."
  9 +docker exec proyecto-postgres-1 sh -c "ogr2ogr -f PostgreSQL PG:'dbname=sigem host=127.0.0.1 user=sigem_user password=sigem_pass' /tmp/sigem_export.gpkg -nlt PROMOTE_TO_MULTI -skipfailures"
  10 +echo "Validando inyeccion:"
  11 +docker exec proyecto-postgres-1 psql -U sigem_user -d sigem -c "\dt e505_*"
  12 +echo "Inyeccion completada!"
GIS-GEOSERVER/liq_por_tipo.php 0 → 100644
  1 +++ a/GIS-GEOSERVER/liq_por_tipo.php
  1 +<?php require_once 'dist/template/mapa_template.php'; ?>
  2 +
  3 +
  4 + <div id="map"></div>
  5 +
  6 + <div id="box">
  7 + <b>Ultimo año pagado: </b><p id="ultimo">AÑO</p>
  8 + <b>Cuenta Catastral: </b><p id="ccc">CCCC</p>
  9 + </div>
  10 +
  11 + <div id="box2" hidden>
  12 + <div id="toggle_resumen"></div>
  13 + <div id="resumen"></div>
  14 + </div>
  15 +
  16 + <?php require_once 'dist/template/mapa_footer.php' ?>
  17 +
  18 + <!-- CARGA DE VARIABLES GLOBALES-->
  19 + <script type='text/javascript'>
  20 + var mapa = 'morosidad';
  21 + var periodo = <?= date('Y') ?>;
  22 + var periodo1 = periodo - 1;
  23 + var periodo2 = periodo -2;
  24 + var periodo3 = periodo -3;
  25 + var periodo4 = periodo -4;
  26 + var periodo5 = periodo -5;
  27 + var periodo6 = periodo -6;
  28 + </script>
  29 + <!-- Estilos -->
  30 + <script src="dist/js/mapa_mapStyles.js"></script>
  31 + <!-- Parametros -->
  32 + <script src="dist/js/mapa_parametros.js"></script>
  33 + <script src="dist/js/mapa_main.js"></script>
  34 + </body>
  35 +</html>
GIS-GEOSERVER/login.html 0 → 100644
  1 +++ a/GIS-GEOSERVER/login.html
  1 +<!DOCTYPE html>
  2 +<html lang="es">
  3 +<head>
  4 + <meta charset="utf-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1">
  6 + <title>SIGEM-GIS | Acceso Institucional AdminLTE 3</title>
  7 +
  8 + <!-- Google Font: Inter -->
  9 + <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap">
  10 + <!-- Font Awesome -->
  11 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  12 + <!-- AdminLTE 3.2 Modernized -->
  13 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/css/adminlte.min.css">
  14 +
  15 + <style>
  16 + body.login-page {
  17 + background: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 50, 100, 0.8)),
  18 + url('https://images.unsplash.com/photo-1524661135-423995f22d0b?auto=format&fit=crop&q=80&w=1920') no-repeat center center fixed;
  19 + background-size: cover;
  20 + font-family: 'Inter', sans-serif;
  21 + height: 100vh;
  22 + }
  23 + .login-box { width: 480px !important; }
  24 + .card-primary.card-outline { border-top: 4px solid #17a2b8; background: rgba(255, 255, 255, 0.95); backdrop-filter: blur(10px); }
  25 + .login-logo a { color: #fff; font-weight: 700; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); }
  26 +
  27 + #entidad {
  28 + border: 1px solid #dee2e6;
  29 + border-radius: 8px;
  30 + padding: 8px;
  31 + width: 100%;
  32 + height: 140px !important;
  33 + background: #f8f9fa;
  34 + }
  35 + #entidad option { padding: 10px; border-bottom: 1px solid #eee; }
  36 + #entidad option:checked { background-color: #17a2b8 !important; color: white; }
  37 +
  38 + .input-group-text { background-color: #f4f6f9; border-left: 0; }
  39 + .form-control:focus { border-color: #17a2b8; box-shadow: none; }
  40 +
  41 + .btn-modern {
  42 + background: #17a2b8;
  43 + border: none;
  44 + border-radius: 8px;
  45 + padding: 12px;
  46 + font-weight: 600;
  47 + letter-spacing: 1px;
  48 + transition: all 0.3s;
  49 + }
  50 + .btn-modern:hover { background: #138496; transform: translateY(-2px); }
  51 +
  52 + .institutional-banner {
  53 + background: #343a40;
  54 + color: #ffc107;
  55 + padding: 5px;
  56 + border-radius: 4px;
  57 + font-size: 0.75rem;
  58 + font-weight: bold;
  59 + display: inline-block;
  60 + margin-bottom: 15px;
  61 + }
  62 + </style>
  63 +</head>
  64 +<body class="hold-transition login-page">
  65 +<div class="login-box">
  66 + <div class="login-logo mb-4">
  67 + <a href="#">SIGEM<span class="text-info">GIS</span> 2026</a>
  68 + </div>
  69 +
  70 + <div class="card card-primary card-outline shadow-lg border-0">
  71 + <div class="card-body login-card-body rounded">
  72 + <div class="text-center">
  73 + <span class="institutional-banner uppercase">SISTEMA DE GESTIÓN CATASTRAL</span>
  74 + <h4 class="mb-3 font-weight-bold text-dark">Portal de Acceso</h4>
  75 + <p class="text-muted text-sm mb-4">Seleccione su institución y valide sus credenciales</p>
  76 + </div>
  77 +
  78 + <form id="loginForm">
  79 + <!-- Filtro de Entidad -->
  80 + <div class="form-group mb-3">
  81 + <label class="text-xs text-info font-weight-bold">BÚSQUEDA DE MUNICIPIO</label>
  82 + <div class="input-group">
  83 + <input type="text" id="municipioSearch" class="form-control" placeholder="Nombre o código entidad..." autocomplete="off">
  84 + <div class="input-group-append">
  85 + <div class="input-group-text"><i class="fas fa-search text-info"></i></div>
  86 + </div>
  87 + </div>
  88 + </div>
  89 +
  90 + <div class="form-group mb-4">
  91 + <select id="entidad" required size="4" class="form-control custom-scroll">
  92 + <option value="505" selected>505 - MUNICIPALIDAD DE REPATRIACIÓN</option>
  93 + <option value="800">800 - ENTIDAD DE PRUEBAS SIGEM</option>
  94 + <option value="900">900 - LABORATORIO DE DESARROLLO</option>
  95 + </select>
  96 + </div>
  97 +
  98 + <div class="row">
  99 + <div class="col-6">
  100 + <div class="form-group mb-3">
  101 + <label class="text-xs text-secondary font-weight-bold">USUARIO</label>
  102 + <div class="input-group">
  103 + <input type="text" id="username" class="form-control" placeholder="operador" required>
  104 + <div class="input-group-append">
  105 + <div class="input-group-text"><i class="fas fa-user-shield"></i></div>
  106 + </div>
  107 + </div>
  108 + </div>
  109 + </div>
  110 + <div class="col-6">
  111 + <div class="form-group mb-3">
  112 + <label class="text-xs text-secondary font-weight-bold">CONTRASEÑA</label>
  113 + <div class="input-group">
  114 + <input type="password" id="password" class="form-control" placeholder="••••••••" required>
  115 + <div class="input-group-append">
  116 + <div class="input-group-text"><i class="fas fa-key"></i></div>
  117 + </div>
  118 + </div>
  119 + </div>
  120 + </div>
  121 + </div>
  122 +
  123 + <div class="mt-4">
  124 + <button type="submit" id="btn-login" class="btn btn-info btn-block btn-modern shadow">
  125 + <span id="btn-text">ACCEDER AL ECOSISTEMA</span>
  126 + <div class="spinner-border spinner-border-sm text-light d-none" id="spinner" role="status"></div>
  127 + </button>
  128 + </div>
  129 +
  130 + <div id="error-msg" class="alert alert-danger mt-3 text-sm d-none animate__animated animate__shakeX"></div>
  131 + </form>
  132 + </div>
  133 +
  134 + <div class="card-footer bg-light text-center border-0 py-3">
  135 + <p class="mb-0 text-xs text-muted">Infraestructura Geográfica Digital &copy; 2026 <b>YVAGA</b></p>
  136 + </div>
  137 + </div>
  138 +</div>
  139 +
  140 +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  141 +<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
  142 +<script src="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/js/adminlte.min.js"></script>
  143 +
  144 +<script>
  145 + // --- LÓGICA INSTITUCIONAL RECUPERADA (03 DE ABRIL) ---
  146 + const searchInput = $('#municipioSearch');
  147 + const selectEntidad = $('#entidad');
  148 + const originalOptions = selectEntidad.find('option').clone();
  149 +
  150 + searchInput.on('input', function() {
  151 + const text = $(this).val().toLowerCase();
  152 + selectEntidad.empty();
  153 + originalOptions.each(function() {
  154 + const opt = $(this);
  155 + if (opt.text().toLowerCase().includes(text) || opt.val().includes(text)) {
  156 + selectEntidad.append(opt.clone());
  157 + }
  158 + });
  159 + if (selectEntidad.find('option').length > 0) {
  160 + selectEntidad.find('option').first().prop('selected', true);
  161 + bksp20();
  162 + }
  163 + });
  164 +
  165 + selectEntidad.on('change', bksp20);
  166 +
  167 + // TÉCNICA BKSP 20: El corazón del borrado seguro de ayer
  168 + function bksp20() {
  169 + $('#username').val('');
  170 + $('#password').val('');
  171 + for(let i=0; i<20; i++) {
  172 + const e = jQuery.Event('keydown', { keyCode: 8, which: 8 });
  173 + $('#username').trigger(e);
  174 + $('#password').trigger(e);
  175 + }
  176 + $('#error-msg').addClass('d-none');
  177 + }
  178 +
  179 + // --- PROCESO DE AUTENTICACIÓN DOCKER-INTEGRATED ---
  180 + $('#loginForm').on('submit', function(e) {
  181 + e.preventDefault();
  182 +
  183 + const username = $('#username').val();
  184 + const password = $('#password').val();
  185 + const entidad = $('#entidad').val();
  186 + const errorMsg = $('#error-msg');
  187 + const spinner = $('#spinner');
  188 + const btnLogin = $('#btn-login');
  189 + const btnText = $('#btn-text');
  190 +
  191 + errorMsg.addClass('d-none').text("");
  192 + spinner.removeClass('d-none');
  193 + btnText.text("AUTENTICANDO...");
  194 + btnLogin.prop('disabled', true);
  195 +
  196 + fetch('/gis-geoserver/api/auth/login', {
  197 + method: 'POST',
  198 + headers: { 'Content-Type': 'application/json' },
  199 + body: JSON.stringify({ username, password, entidad })
  200 + })
  201 + .then(response => {
  202 + if (!response.ok) return response.json().then(e => { throw new Error(e.message || "Error de acceso"); });
  203 + return response.json();
  204 + })
  205 + .then(data => {
  206 + // Persistencia de Sesión
  207 + localStorage.setItem('jwt', data.token);
  208 + localStorage.setItem('entidad', entidad);
  209 + localStorage.setItem('map_lat', data.lat);
  210 + localStorage.setItem('map_lng', data.lng);
  211 + localStorage.setItem('map_zoom', data.zoom);
  212 +
  213 + // Redirección al Visor Dual Institucional
  214 + window.location.href = "/gis-geoserver/mapas_institucional.html";
  215 + })
  216 + .catch(error => {
  217 + errorMsg.text(error.message).removeClass('d-none');
  218 + spinner.addClass('d-none');
  219 + btnText.text("ACCEDER AL ECOSISTEMA");
  220 + btnLogin.prop('disabled', false);
  221 + });
  222 + });
  223 +</script>
  224 +</body>
  225 +</html>
GIS-GEOSERVER/login_institucional_bksp.html 0 → 100644
  1 +++ a/GIS-GEOSERVER/login_institucional_bksp.html
  1 +<!DOCTYPE html>
  2 +<html lang="es">
  3 +<head>
  4 + <meta charset="utf-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1">
  6 + <title>SIGEMWEB | LOGIN - PROTOTIPO ADN CARTO</title>
  7 +
  8 + <!-- Google Font: Source Sans Pro -->
  9 + <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
  10 + <!-- Font Awesome -->
  11 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  12 + <!-- AdminLTE 3.2 (Bootstrap 4/5 integration) -->
  13 + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/css/adminlte.min.css">
  14 +
  15 + <style>
  16 + body.login-page { background-color: #f4f6f9; }
  17 + .login-box { width: 450px !important; }
  18 + .login-logo b { color: #007bff; }
  19 + .card-primary.card-outline { border-top: 3px solid #007bff; }
  20 + .btn-primary { background-color: #007bff; border-color: #007bff; }
  21 + .btn-primary:hover { background-color: #0069d9; border-color: #0062cc; }
  22 +
  23 + #entidad {
  24 + border: 1px solid #ced4da;
  25 + border-radius: .25rem;
  26 + padding: .375rem .75rem;
  27 + width: 100%;
  28 + height: 120px !important;
  29 + }
  30 +
  31 + .loader-spinner {
  32 + display: none;
  33 + width: 1.5rem;
  34 + height: 1.5rem;
  35 + border-width: 0.2em;
  36 + }
  37 + </style>
  38 +</head>
  39 +<body class="hold-transition login-page">
  40 +<div class="login-box">
  41 + <div class="login-logo">
  42 + <a href="#"><b>SIGEM</b>WEB</a>
  43 + </div>
  44 +
  45 + <div class="card card-primary card-outline shadow-sm">
  46 + <div class="card-header text-center">
  47 + <h3 class="h3 mb-0"><b>Visor</b>GIS</h3>
  48 + <p class="text-xs text-secondary mt-1">Ecosistema Georreferenciado Multi-Tenant</p>
  49 + </div>
  50 + <div class="card-body">
  51 + <p class="login-box-msg text-muted">Inicie sesión para acceder a su municipio</p>
  52 +
  53 + <form id="loginForm">
  54 + <!-- Filtro de Entidad -->
  55 + <div class="form-group mb-3">
  56 + <label for="municipioSearch" class="text-xs text-uppercase font-weight-bold text-secondary">Municipalidad (Entidad)</label>
  57 + <div class="input-group">
  58 + <input type="text" id="municipioSearch" class="form-control" placeholder="Buscar entidad (ej: 505)" autocomplete="off">
  59 + <div class="input-group-append">
  60 + <div class="input-group-text">
  61 + <span class="fas fa-university"></span>
  62 + </div>
  63 + </div>
  64 + </div>
  65 + </div>
  66 +
  67 + <div class="form-group mb-3">
  68 + <select id="entidad" required size="4" class="form-control">
  69 + <option value="505" selected>Entidad 505 (Piloto GIS)</option>
  70 + <option value="800">Entidad 800 (Pruebas)</option>
  71 + <option value="900">Entidad 900 (Desarrollo)</option>
  72 + </select>
  73 + </div>
  74 +
  75 + <hr class="my-4">
  76 +
  77 + <!-- Usuario -->
  78 + <div class="form-group mb-3">
  79 + <label for="username" class="text-xs text-uppercase font-weight-bold text-secondary">Usuario</label>
  80 + <div class="input-group">
  81 + <input type="text" id="username" class="form-control" placeholder="Nombre de usuario" required autocomplete="username">
  82 + <div class="input-group-append">
  83 + <div class="input-group-text">
  84 + <span class="fas fa-user"></span>
  85 + </div>
  86 + </div>
  87 + </div>
  88 + </div>
  89 +
  90 + <!-- Contraseña -->
  91 + <div class="form-group mb-3">
  92 + <label for="password" class="text-xs text-uppercase font-weight-bold text-secondary">Contraseña</label>
  93 + <div class="input-group">
  94 + <input type="password" id="password" class="form-control" placeholder="Clave de acceso" required autocomplete="current-password">
  95 + <div class="input-group-append">
  96 + <div class="input-group-text">
  97 + <span class="fas fa-lock"></span>
  98 + </div>
  99 + </div>
  100 + </div>
  101 + </div>
  102 +
  103 + <div class="row mt-4">
  104 + <div class="col-12">
  105 + <button type="submit" id="btn-login" class="btn btn-primary btn-block btn-flat py-2 font-weight-bold shadow-sm">
  106 + <span id="btn-text" class="text-uppercase">INGRESAR AL SISTEMA</span>
  107 + <div class="spinner-border spinner-border-sm text-light loader-spinner ml-2" id="spinner" role="status"></div>
  108 + </button>
  109 + </div>
  110 + </div>
  111 +
  112 + <div id="error-msg" class="alert alert-danger mt-3 text-sm" style="display: none;"></div>
  113 + </form>
  114 + </div>
  115 +
  116 + <div class="card-footer bg-white text-center py-3">
  117 + <small class="text-muted">© 2026 <b>YVAGA</b>. Todos los derechos reservados.</small>
  118 + </div>
  119 + </div>
  120 +</div>
  121 +
  122 +<!-- jQuery (necesario para AdminLTE) -->
  123 +<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  124 +<!-- Bootstrap 4 (necesario para AdminLTE 3.2) -->
  125 +<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js"></script>
  126 +<!-- AdminLTE App -->
  127 +<script src="https://cdn.jsdelivr.net/npm/admin-lte@3.2/dist/js/adminlte.min.js"></script>
  128 +
  129 +<script>
  130 + // Filtro interactivo de municipios (adn SIGEM)
  131 + const searchInput = $('#municipioSearch');
  132 + const selectEntidad = $('#entidad');
  133 + const originalOptions = selectEntidad.find('option').clone();
  134 +
  135 + searchInput.on('input', function() {
  136 + const text = $(this).val().toLowerCase();
  137 + selectEntidad.empty();
  138 + originalOptions.each(function() {
  139 + const opt = $(this);
  140 + if (opt.text().toLowerCase().includes(text) || opt.value.includes(text)) {
  141 + selectEntidad.append(opt.clone());
  142 + }
  143 + });
  144 + if (selectEntidad.find('option').length > 0) {
  145 + selectEntidad.find('option').first().prop('selected', true);
  146 + bksp20(); // Rueda recuperada de ayer (03 de Abril)
  147 + }
  148 + });
  149 +
  150 + selectEntidad.on('change', bksp20);
  151 +
  152 + function bksp20() {
  153 + $('#username').val('');
  154 + $('#password').val('');
  155 + for(let i=0; i<20; i++) {
  156 + const e = jQuery.Event('keydown', { keyCode: 8, which: 8 });
  157 + $('#username').trigger(e);
  158 + $('#password').trigger(e);
  159 + }
  160 + $('#error-msg').hide();
  161 + }
  162 +
  163 + // Lógica de Login (adn SIGEM-GIS)
  164 + $('#loginForm').on('submit', function(e) {
  165 + e.preventDefault();
  166 +
  167 + const username = $('#username').val();
  168 + const password = $('#password').val();
  169 + const entidad = $('#entidad').val();
  170 + const errorMsg = $('#error-msg');
  171 + const btnText = $('#btn-text');
  172 + const spinner = $('#spinner');
  173 + const btnLogin = $('#btn-login');
  174 +
  175 + // Bloquear UI
  176 + errorMsg.hide().text("");
  177 + spinner.css('display', 'inline-block');
  178 + btnLogin.prop('disabled', true);
  179 +
  180 + const payload = {
  181 + username: username,
  182 + password: password,
  183 + entidad: entidad
  184 + };
  185 +
  186 + fetch('/gis-geoserver/api/auth/login', {
  187 + method: 'POST',
  188 + headers: { 'Content-Type': 'application/json' },
  189 + body: JSON.stringify(payload)
  190 + })
  191 + .then(response => {
  192 + if (!response.ok) {
  193 + return response.json().then(errData => {
  194 + throw new Error(errData.message || "Credenciales incorrectas.");
  195 + });
  196 + }
  197 + return response.json();
  198 + })
  199 + .then(data => {
  200 + // ÉXITO: Persistencia de Sesión
  201 + localStorage.setItem('jwt', data.token);
  202 + localStorage.setItem('user_name', data.nombre);
  203 + localStorage.setItem('entidad', entidad);
  204 +
  205 + // Metadatos del Mapa (Regla 5)
  206 + localStorage.setItem('map_lat', data.lat);
  207 + localStorage.setItem('map_lng', data.lng);
  208 + localStorage.setItem('map_zoom', data.zoom);
  209 + localStorage.setItem('map_min_zoom', data.minZoom);
  210 + localStorage.setItem('map_max_zoom', data.maxZoom);
  211 + localStorage.setItem('mapa_base_id', data.mapaBase);
  212 + localStorage.setItem('map_bounds', data.bounds);
  213 +
  214 + // Redirección al Visor Modernizado
  215 + window.location.href = "/gis-geoserver/mapas_institucional.html";
  216 + })
  217 + .catch(error => {
  218 + // ERROR: Feedback visual robusto
  219 + errorMsg.text(error.message).fadeIn();
  220 + spinner.hide();
  221 + btnLogin.prop('disabled', false);
  222 + });
  223 + });
  224 +</script>
  225 +</body>
  226 +</html>
GIS-GEOSERVER/loginform.php 0 → 100644
  1 +++ a/GIS-GEOSERVER/loginform.php
  1 +<?php
  2 +class LoginForm extends DbConn
  3 +{
  4 + public function checkLogin($myusername, $mypassword, $myentidad)
  5 + {
  6 + $conf = new GlobalConf;
  7 + $ip_address = $conf->ip_address;
  8 + $login_timeout = $conf->login_timeout;
  9 + $max_attempts = $conf->max_attempts;
  10 + $timeout_minutes = $conf->timeout_minutes;
  11 + $attcheck = checkAttempts($myusername);
  12 + $curr_attempts = $attcheck['attempts'];
  13 + $datetimeNow = date("Y-m-d H:i:s");
  14 + $oldTime = strtotime($attcheck['lastlogin']);
  15 + $newTime = strtotime($datetimeNow);
  16 + $timeDiff = $newTime - $oldTime;
  17 +
  18 + // QUERY
  19 + try {
  20 + $db = new DbConn;
  21 + $tbl_members = $db->tbl_members;
  22 + $err = '';
  23 + } catch (PDOException $e) {
  24 + $err = "Error: " . $e->getMessage();
  25 + }
  26 +
  27 + //Se setea el search_path al esquema correspondiente..
  28 + $stentidad = $db->conn->prepare("SET search_path TO sigem".$myentidad);
  29 + $stentidad->execute();
  30 + $anio = date('Y');
  31 +
  32 + // ***********************************************************************
  33 + // Muestra del código el nuevo login de usuarios
  34 + // Los datos de la entidad se encuentran en la BD entidades del taperekaha
  35 + // ***********************************************************************
  36 +
  37 + /*
  38 +
  39 + // Conexión al taperekaha para traer los parámetros de conexión a la base de datos de la Municipalidad
  40 + sql_conexion := 'dbname=sigemweb host=192.168.1.254 port=5432 user=postgres password=x25yvaga2017' ;
  41 + sql_consulta := 'SELECT consulta.sigem_site, consulta.sigem_dbname FROM entidades AS consulta WHERE consulta.activo = TRUE AND consulta.entidad = ' || $myentidad || ' ;' ;
  42 + // Traer los parámetros de conexión a la base de datos de la Municipalidad
  43 + SELECT t1.sigem_site, t1.sigem_dbname
  44 + FROM public.dblink(
  45 + CAST( sql_conexion AS text ),CAST( sql_consulta AS TEXT )
  46 + )
  47 + AS t1 (
  48 + sigem_site text,
  49 + sigem_dbname text
  50 + ) INTO val_sigem_site, val_sigem_dbname ;
  51 +
  52 + // Hacer la consulta para validar credenciales del usuario
  53 + consulta_sql_conexion := ('dbname=' || val_sigem_dbname || ' ' || val_sigem_site) ;
  54 +
  55 + consulta_sql_caso1 := ' SELECT caso1.ejer_fisca AS ejer_fisca, caso1.usu_alias AS usu_alias, ' ;
  56 + consulta_sql_caso1 := consulta_sql_caso1 || ' '|| '''LOGIN''' || ' AS tipo_dato ,' ;
  57 + consulta_sql_caso1 := consulta_sql_caso1 || ' caso1.usu_numero AS cod_dato, ' ;
  58 + consulta_sql_caso1 := consulta_sql_caso1 || ' CONCAT(' || val || ',' || '''-USUARIO EXISTE''' || ' ) AS descripcion_dato ';
  59 + consulta_sql_caso1 := consulta_sql_caso1 || ' FROM ( SELECT count(usua.usu_numero) AS cant_usuario, usua.ejer_fisca, usua.usu_alias, usua.usu_numero FROM usuarios usua WHERE ' ;
  60 + consulta_sql_caso1 := consulta_sql_caso1 || ' usua.activo = TRUE ';
  61 + consulta_sql_caso1 := consulta_sql_caso1 || ' AND usua.ejer_fisca = ' || val_ejer || ' AND usua.usu_alias = ' || val_alias ;
  62 + consulta_sql_caso1 := consulta_sql_caso1 || ' AND pgp_sym_decrypt(usua.usu_clave_a,' || '''510580''' || ', ' || '''compress-algo=0, cipher-algo=aes256''' || ' ) = ' || val_clave ;
  63 + consulta_sql_caso1 := consulta_sql_caso1 || ' GROUP BY usua.ejer_fisca, usua.usu_alias, usua.usu_numero ) AS caso1 ';
  64 +
  65 + RETURN QUERY SELECT t1.tipo_dato as tipo_dato, t1.cod_dato AS cod_dato, t1.descripcion_dato AS descripcion_dato FROM
  66 + public.dblink(CAST(consulta_sql_conexion AS text),
  67 + format( 'SELECT consulta.ejer_fisca, consulta.usu_alias, consulta.tipo_dato, consulta.cod_dato, consulta.descripcion_dato FROM (' || consulta_sql || ') AS consulta WHERE consulta.ejer_fisca = %L and consulta.usu_alias = %L GROUP BY consulta.ejer_fisca, consulta.usu_alias, consulta.tipo_dato, consulta.cod_dato, consulta.descripcion_dato ORDER BY consulta.ejer_fisca, consulta.usu_alias, consulta.tipo_dato, consulta.cod_dato, consulta.descripcion_dato ;',usu_ejer_fisca, usu_usu_alias ))
  68 + AS t1(
  69 + ejer_fisca numeric(18,0),
  70 + usu_alias text,
  71 + tipo_dato text,
  72 + cod_dato numeric(18,0),
  73 + descripcion_dato text)
  74 + ORDER BY t1.tipo_dato, t1.cod_dato, t1.descripcion_dato
  75 +
  76 + */
  77 + // ***********************************************************************
  78 +
  79 + //SI ENTIDAD es CDE, corre query de password encriptado
  80 + //if ($myentidad == 505) {
  81 + //Se corre el query directamente sin usar PDO ya que la funcion pgp_sym_decrypt no puede ser escapada desde PDO y no reconoce la funcion
  82 + $dbconn = pg_connect("host=$db->host dbname=$db->db_name user=$db->username password=$db->password") or die('Could not connect: ' . pg_last_error());
  83 +
  84 + $query = "SELECT entidad, ejer_fisca, usu_numero, usu_nom, usu_ape, usu_nivel, usu_alias, activo,
  85 + pgp_sym_decrypt(usu_clave_a::bytea,'510580')::text as usu_clave
  86 + FROM sigem".$myentidad.".usuarios WHERE usu_alias ilike '%".$myusername."%' and ejer_fisca = date_part('year', now())";
  87 + $datos = pg_query($query) or die('Error message: ' . pg_last_error());
  88 +
  89 + // Se traen los datos de la tabla usuario
  90 + $result = pg_fetch_assoc($datos);
  91 +
  92 + pg_close($dbconn);
  93 + /*} else {
  94 + // query normal via PDO
  95 + $stmt = $db->conn->prepare("SET search_path TO sigem".$myentidad);
  96 + $stmt = $db->conn->prepare("SELECT * FROM sigem".$myentidad.".usuarios WHERE usu_alias = :myusername and ejer_fisca = date_part('year', now())");
  97 + $stmt->bindParam(':myusername', $myusername);
  98 + $stmt->execute();
  99 +
  100 + // Se traen los datos de la tabla usuario
  101 + $result = $stmt->fetch(PDO::FETCH_ASSOC);
  102 + }*/
  103 +
  104 + if ($curr_attempts >= $max_attempts && $timeDiff < $login_timeout) {
  105 + //Demasiados intentos fallidos
  106 + $success = "<div class=\"alert alert-danger alert-dismissable\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>Numero maximo de reintentos excedido... por favor espere ".$timeout_minutes." minutos e intente nuevamente</div>";
  107 + } else {
  108 + //Si no se excede el maximo de intentos fallidos, continua....
  109 +
  110 + // TODO: AGREGAR validacion contra hash no password en plano -.-
  111 + //La funcion password_verify solo funciona con versiones de php 5.5++, como centos 7 solo llega
  112 + //a 5.4 se obvia por de pronto
  113 + //if (password_verify($mypassword, $result['usu_clave']) && $result['activo'] == true) {
  114 +
  115 + //Se agrego validacion de credenciales contra la tabla usuarios del esquema correspondiente a la institucion
  116 + //donde mypassword sea igual a usu_clave y activo == true
  117 +
  118 + if (($mypassword == $result['usu_clave']) && $result['activo'] == true) {
  119 + //if ( $result['activo'] == true) {
  120 + //Inicio de Sesion Exitoso
  121 + $success = 'true';
  122 + session_start();
  123 +
  124 + //Variables tabla sigemxxx.usuarios
  125 + $_SESSION['username'] = $myusername;
  126 + $_SESSION['entidad'] = $myentidad; //id_entidad
  127 + $_SESSION['usu_nom'] = $result['usu_nom'];
  128 + $_SESSION['usu_ape'] = $result['usu_ape'];
  129 +
  130 + //Variables tabla public.entidades
  131 + try {
  132 + $datos = new DbConn;
  133 + $err = '';
  134 + } catch (PDOException $e) {$err = "Error: " . $e->getMessage();}
  135 +
  136 + // Query
  137 + $dtent = $datos->conn->prepare("SELECT * FROM public.entidades WHERE entidad = ".$myentidad);
  138 + $dtent->execute();
  139 + $datosent = $dtent->fetch(PDO::FETCH_ASSOC);
  140 +
  141 + //TODO: HACER FUNCIONAR EN CASA, asi establecer año fiscal y parametros de version directo de BD
  142 + //Variables tabla sigemxxx.parametros
  143 + /*try {
  144 + $param = new DbConn;
  145 + $err = '';
  146 + } catch (PDOException $e) {$err = "Error: " . $e->getMessage();}
  147 +
  148 + // Query
  149 + $pent = $param->conn->prepare("SELECT * FROM parametros WHERE entidad ilike '".$myentidad."'");
  150 + $pent->execute();
  151 + $parament = $pent->fetch(PDO::FETCH_ASSOC);
  152 + error_log('PARAMETROS ENTIDAD: '.$parament);
  153 + error_log('Resultado: '.print_r($parament, true));*/
  154 +
  155 + //DATOS public.entidades
  156 + $_SESSION['n_entidad'] = $datosent['nombre'];
  157 + $_SESSION['niv_entidad'] = $datosent['niv_entidad'];
  158 + $_SESSION['sig_entidad'] = $datosent['sig_entidad'];
  159 + $_SESSION['sigem_site'] = $datosent['sigem_site'];
  160 + $_SESSION['sigem_dbname'] = $datosent['sigem_dbname'];
  161 + $_SESSION['direccion'] = $datosent['direccion'];
  162 + $_SESSION['telefono'] = $datosent['telefono'];
  163 + $_SESSION['fax'] = $datosent['fax'];
  164 + $_SESSION['responsable'] = $datosent['responsable'];
  165 + $_SESSION['eslogan'] = $datosent['eslogan'];
  166 + $_SESSION['imagen'] = $datosent['imagen'];
  167 + $_SESSION['site_url'] = $datosent['site_url'];
  168 + $_SESSION['latlong'] = $datosent['latlong'];
  169 + $_SESSION['lng'] = $datosent['lng'];
  170 + $_SESSION['lat'] = $datosent['lat'];
  171 + $_SESSION['zoom'] = $datosent['zoom'];
  172 + $_SESSION['maxzoom'] = $datosent['maxzoom'];
  173 + $_SESSION['minzoom'] = $datosent['minzoom'];
  174 + $_SESSION['mapa_base'] = $datosent['mapa_base'];
  175 + $_SESSION['boundno'] = $datosent['boundno'];
  176 + $_SESSION['boundse'] = $datosent['boundse'];
  177 +
  178 + //} elseif (password_verify($mypassword, $result['usu_clave']) && $result['activo'] == true) {
  179 + // TODO: AGREGAR validacion contra hash no password en plano -.-
  180 + } elseif (($mypassword == $result['usu_clave']) && $result['activo'] == true) {
  181 + //Cuenta sin verificar
  182 + $success = "<div class=\"alert alert-danger alert-dismissable\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>La cuenta ha sido creada, pero no puedes iniciar sesion hasta que sea verificada</div>";
  183 + } else {
  184 + //Usuario o password invalido
  185 + $success = "<div class=\"alert alert-danger alert-dismissable\"><button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">&times;</button>Usuario o Contraseña Incorrecto/s</div>";
  186 + }
  187 +
  188 +
  189 + return $success;
  190 + }
  191 + }
  192 +
  193 + public function insertAttempt($username)
  194 + {
  195 + try {
  196 + $db = new DbConn;
  197 + $conf = new GlobalConf;
  198 + $tbl_attempts = $db->tbl_attempts;
  199 + $ip_address = $conf->ip_address;
  200 + $login_timeout = $conf->login_timeout;
  201 + $max_attempts = $conf->max_attempts;
  202 +
  203 + $datetimeNow = date("Y-m-d H:i:s");
  204 + $attcheck = checkAttempts($username);
  205 + $curr_attempts = $attcheck['attempts'];
  206 +
  207 + $stmt = $db->conn->prepare("INSERT INTO ".$tbl_attempts." (ip, attempts, lastlogin, username) values(:ip, 1, :lastlogin, :username)");
  208 + $stmt->bindParam(':ip', $ip_address);
  209 + $stmt->bindParam(':lastlogin', $datetimeNow);
  210 + $stmt->bindParam(':username', $username);
  211 + $stmt->execute();
  212 + $curr_attempts++;
  213 + $err = '';
  214 +
  215 + } catch (PDOException $e) {
  216 +
  217 + $err = "Error: " . $e->getMessage();
  218 +
  219 + }
  220 +
  221 + //Determines returned value ('true' or error code)
  222 + $resp = ($err == '') ? 'true' : $err;
  223 +
  224 + return $resp;
  225 +
  226 + }
  227 +
  228 +
  229 + public function updateAttempts($username)
  230 + {
  231 + try {
  232 + $db = new DbConn;
  233 + $conf = new GlobalConf;
  234 + $tbl_attempts = $db->tbl_attempts;
  235 + $ip_address = $conf->ip_address;
  236 + $login_timeout = $conf->login_timeout;
  237 + $max_attempts = $conf->max_attempts;
  238 + $timeout_minutes = $conf->timeout_minutes;
  239 +
  240 + $att = new LoginForm;
  241 + $attcheck = checkAttempts($username);
  242 + $curr_attempts = $attcheck['attempts'];
  243 +
  244 + $datetimeNow = date("Y-m-d H:i:s");
  245 + $oldTime = strtotime($attcheck['lastlogin']);
  246 + $newTime = strtotime($datetimeNow);
  247 + $timeDiff = $newTime - $oldTime;
  248 +
  249 + $err = '';
  250 + $sql = '';
  251 +
  252 + if ($curr_attempts >= $max_attempts && $timeDiff < $login_timeout) {
  253 +
  254 + if ($timeDiff >= $login_timeout) {
  255 +
  256 + $sql = "UPDATE ".$tbl_attempts." SET attempts = :attempts, lastlogin = :lastlogin where ip = :ip and username = :username";
  257 + $curr_attempts = 1;
  258 +
  259 + }
  260 +
  261 + } else {
  262 +
  263 + if ($timeDiff < $login_timeout) {
  264 +
  265 + $sql = "UPDATE ".$tbl_attempts." SET attempts = :attempts, lastlogin = :lastlogin where ip = :ip and username = :username";
  266 + $curr_attempts++;
  267 +
  268 + } elseif ($timeDiff >= $login_timeout) {
  269 +
  270 + $sql = "UPDATE ".$tbl_attempts." SET attempts = :attempts, lastlogin = :lastlogin where ip = :ip and username = :username";
  271 + $curr_attempts = 1;
  272 +
  273 + }
  274 +
  275 + $stmt2 = $db->conn->prepare($sql);
  276 + $stmt2->bindParam(':attempts', $curr_attempts);
  277 + $stmt2->bindParam(':ip', $ip_address);
  278 + $stmt2->bindParam(':lastlogin', $datetimeNow);
  279 + $stmt2->bindParam(':username', $username);
  280 + $stmt2->execute();
  281 +
  282 + }
  283 +
  284 + } catch (PDOException $e) {
  285 +
  286 + $err = "Error: " . $e->getMessage();
  287 +
  288 + }
  289 +
  290 + //Determines returned value ('true' or error code) (ternary)
  291 + $resp = ($err == '') ? 'true' : $err;
  292 +
  293 + return $resp;
  294 +
  295 + }
  296 +}
0 \ No newline at end of file 297 \ No newline at end of file
GIS-GEOSERVER/main_login.php 0 → 100644
  1 +++ a/GIS-GEOSERVER/main_login.php
  1 +<?php
  2 +require 'includes/functions.php';
  3 +session_start();
  4 +if (isset($_SESSION['username'])) {
  5 + header("location:../index.php");
  6 +}
  7 +?>
  8 +<!DOCTYPE html>
  9 +<html lang="es">
  10 + <head>
  11 + <meta charset="utf-8">
  12 + <title>SIGEM WEB | LOGIN</title>
  13 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  14 + <!-- INICIO CSS LTE -->
  15 + <!-- Bootstrap 3.3.2 -->
  16 + <link href="../bower_components/admin-lte/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
  17 + <!-- Font Awesome Icons 4.3.0 -->
  18 + <link href="../bower_components/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
  19 + <!-- Ionicons 2.0.0 -->
  20 + <link href="../bower_components/Ionicons/css/ionicons.min.css" rel="stylesheet" type="text/css" />
  21 +
  22 + <!-- Theme style -->
  23 + <link href="../bower_components/admin-lte/dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css" />
  24 + <!-- TODO: SKIN DINAMICO -->
  25 + <!-- SKIN LTE -->
  26 + <link href="../bower_components/admin-lte/dist/css/skins/skin-blue.min.css" rel="stylesheet" type="text/css" />
  27 + <!-- Pace style -->
  28 + <link rel="stylesheet" href="../bower_components/admin-lte/plugins/pace/pace.min.css">
  29 + <!-- FIN CSS LTE -->
  30 + <link href="../dist/css/main.css" rel="stylesheet" media="screen">
  31 + </head>
  32 +
  33 + <body>
  34 + <div class="container">
  35 +
  36 + <form class="form-signin" name="form1" method="post" action="checklogin.php">
  37 + <div class="form-group">
  38 + <h2 align="center" class="form-signin-heading"><b>SIGEM</b>WEB</h2>
  39 + <p align="center"><label class="form-control-select-heading-entidad">LICENCIA DE USO OTORGADO A:</label></p>
  40 + <select name="myentidad" id="myentidad" class="form-control-select-entidad">
  41 + <option value="" style="text-align: center">SELECCIONAR ENTIDAD</option>
  42 + <?php
  43 + //PREPARA EL QUERY Y TRAE LAS ENTIDADES POR PDO
  44 + try {
  45 + $listar = new DbConn();
  46 + $tbl_members = $listar->tbl_members;
  47 + $err = '';
  48 + } catch (PDOException $e) {
  49 + $err = "Error: " . $e->getMessage();
  50 + }
  51 +
  52 + $lstent = $listar->conn->prepare("SELECT entidad,nombre FROM ".$tbl_members." WHERE activo = true");
  53 + $lstent->execute();
  54 +
  55 + // Si el listado de entidades no esta vacio arrastra los elementos asociados
  56 + if (($lstent->rowCount()) == 0)
  57 + {echo "<option>No existen entidades activas</option>";
  58 + } else {
  59 + while($row_list = $lstent->fetch(PDO::FETCH_ASSOC)){
  60 + ?>
  61 + <option value=<?php echo $row_list["entidad"]; ?>><?php echo $row_list["nombre"]; ?></option>
  62 + <?php
  63 + }
  64 + }
  65 + ?>
  66 + </select>
  67 +
  68 + <h2 class="form-signin-heading"> </h2>
  69 + <p align="center"><label class="form-signin-heading-entidad">Sistema de Gestion Municipal</label></p>
  70 + <input name="myusername" id="myusername" type="text" class="form-control" align="center" placeholder="Usuario" autofocus>
  71 + <input name="mypassword" id="mypassword" type="password" class="form-control" placeholder="Contraseña">
  72 + <!-- The checkbox remember me is not implemented yet...
  73 + <label class="checkbox"> <input type="checkbox" value="remember-me"> Remember me </label>
  74 + -->
  75 +
  76 + <button name="Submit" id="submit" class="btn btn-lg btn-primary btn-block" type="submit">Iniciar sesión</button>
  77 +
  78 + <div align="center" id="message"></div>
  79 + </div>
  80 + </form>
  81 + <div align="center" id="message2">
  82 + <b>SIGEM</b> - Sistema de Gestion Municipal<br>
  83 + <h4><b>REGISTRO MIC/DINAPI</b> 593 del 7/Julio/2016</h4>
  84 + <b>Registro General de Derechos de Autor</b><br>
  85 + <b>Todos los Derechos Reservados</b><br>
  86 + </div>
  87 + </div> <!-- /container -->
  88 +
  89 + <!-- FILA SUPERIOR -->
  90 + <div class="row">
  91 + <div class="col-md-3 .hidden-xs"></div>
  92 + <div class="col-md-3 col-sm-6 col-xs-6">
  93 + <img style="height: 75px; width: 179px;" src="../dist/img/sigem/logo_le_ssl.png">
  94 + </div><!-- /.col -->
  95 + <div class="col-md-1 .hidden-xs"></div>
  96 + <div class="col-md-3 col-sm-6 col-xs-6">
  97 + <img style="height: 75px; width: 161px;" src="../dist/img/sigem/logo_dinapi.png">
  98 + </div><!-- /.col -->
  99 + <div class="col-md-2 .hidden-xs"></div>
  100 + </div><!-- /FILA SUPERIOR -->
  101 +
  102 + <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
  103 + <script src="js/jquery-2.2.4.min.js"></script>
  104 + <!-- Include all compiled plugins (below), or include individual files as needed -->
  105 + <script type="text/javascript" src="js/bootstrap.js"></script>
  106 + <!-- The AJAX login script -->
  107 + <script src="js/login.js"></script>
  108 +
  109 + </body>
  110 +</html>
GIS-GEOSERVER/mapa_main.js 0 → 100644
  1 +++ a/GIS-GEOSERVER/mapa_main.js
  1 +/*** Global object that contains the app ***/
  2 +var app = app || {};
  3 +
  4 +// keep our map stuff in a part of the app object as to not pollute the global name space
  5 +app.map = (function(w,d, $, _){
  6 + var el = {
  7 + map:null,cdbURL:null,styles: null,params:null,
  8 + styleCur:null,sql:null,
  9 + mapboxTiles:null,satellite:null,taxLots:null,
  10 + baseLayers:null,capaMANZ:null,capaCALLES:null,capasinCCC:null,polygon:null,
  11 + bushwick:null,colony : null,linden : null,groveSt : null,featureGroup : null,
  12 + template:null,menu:null,
  13 + legend:null,menud:null, mostrar: null,
  14 + taxLotActions:null,story:null
  15 + };
  16 +
  17 + //SE CARGAN VALORES REUTILIZABLES
  18 + el.styles = app.mapStyles; //ESTILOS
  19 + el.params = app.param; //PARAMETROS
  20 + el.cdbURL = app.url; //URL MAPA BASE
  21 +
  22 + // compile the underscore legend template for rendering map legends for choropleth layers
  23 + _.templateSettings.variable = "legend";
  24 + el.template = _.template($("script.template").html());
  25 +
  26 + el.legendcontainer = $('#ui-leyenda-contenedor');
  27 + el.legend = $('#ui-legend');
  28 + el.menu = $('#accordion');
  29 +
  30 + // Configuramos el mapa y sus capas!
  31 + var initMap = function() {
  32 + // Ocultamos datos, resumen y tooltip
  33 + $('#box2').hide();$('#tool-tip').hide();
  34 +
  35 + // Parametros del mapa de FONDO
  36 + var params = {center:[lat,lng],minZoom:minzoom,maxZoom:maxzoom,zoom:zoom,maxBounds:L.latLngBounds(corner1,corner2),zoomControl:false,infoControl:false,attributionControl:true}
  37 + el.map = new L.map('map', params);
  38 +
  39 +
  40 +
  41 + // tileLayer for mapbox basemap
  42 + el.mapboxTiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  43 + maxZoom: 19,
  44 + attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
  45 + });
  46 + el.map.addLayer(el.mapboxTiles);
  47 +
  48 + //TODO: Capa Nokia layer.tileLayer('http://{s}.maps.nlp.nokia.com/maptile/2.1/maptile/newest/satellite.day/{z}/{x}/{y}/256/jpg?lg=eng&token=A7tBPacePg9Mj_zghvKt9Q&app_id=KuYppsdXZznpffJsKT24', {
  49 + // subdomains:"1234", attribution: '&copy; <a href="http://maps.nokia.com/copyright">Nokia Maps</a> contributors, &copy; <a href="http://yvyape.yvaga.com/attributions">YVAGA</a>'}).addTo(map);
  50 + // add mapbox and osm attribution
  51 + var attr = "<a href='https://www.mapbox.com/about/maps/' target='_blank'>&copy; Mapbox &copy; OpenStreetMap</a>"
  52 + el.map.attributionControl.addAttribution(attr);
  53 +
  54 + // add Bing satelitte imagery layer
  55 + el.satellite = new L.BingLayer('AkuX5_O7AVBpUN7ujcWGCf4uovayfogcNVYhWKjbz2Foggzu8cYBxk6e7wfQyBQW');
  56 +
  57 + // Capas bases para leaflet
  58 + el.baseLayers = {geometrico: el.mapboxTiles,foto: el.satellite};
  59 +
  60 + // inits UI element for toggling base tile layers
  61 + L.control.layers(el.baseLayers, {}, {position: 'bottomleft'}).addTo(el.map);
  62 +
  63 + // makes sure base layers stay below the cartodb data
  64 + el.map.on('baselayerchange', function(e){e.layer.bringToBack();})
  65 +
  66 + // se agregan las capas
  67 + $(document).ajaxStart(function() { Pace.restart(); });
  68 + getCDBData();
  69 + $('#box').show();
  70 + }
  71 +
  72 + // Carga capa Base y ADICIONALES
  73 +
  74 + var getCDBData = function() {
  75 + cartodb.createLayer(el.map, el.cdbURL, {cartodb_logo: false,legends: false,https: true},
  76 + function(layer) {
  77 +
  78 + //TODO: VERIFICAR QUE ESTE 'LOADER' FUNKE
  79 + var loader = new cdb.geo.ui.TilesLoader({ template: function(){ return '<div class="loader"></div>' } });
  80 +
  81 + function addLoader(layer) {
  82 + layer.bind('loading', function() { loader.show() });
  83 + layer.bind('load', function() { loader.hide(); });
  84 + }
  85 +
  86 + // se almacenan las capas en las variables correspondientes
  87 + layer.getSubLayer(0).setCartoCSS(el.styles.regular);
  88 + layer.getSubLayer(0).setSQL(el.params.morosidadtodos);
  89 + el.taxLots = layer.getSubLayer(0);
  90 +
  91 + //CAPAS ADICIONALES
  92 + el.capaMANZ = layer.createSubLayer({sql : el.params.manzanas, cartocss : el.styles.manzanas});
  93 + el.capaCALLES = layer.createSubLayer({sql : el.params.calles, cartocss : el.styles.calles});
  94 + el.capasinCCC = layer.createSubLayer({sql : el.params.lotesincc,cartocss : el.styles.lotesincc});
  95 +
  96 + // Mueve la posición del tool-tip respecto a la ubicación del mouse 5px, para no interferir en el proceso de "click"
  97 + var event = function (e) {$('#tool-tip').css({left: e.pageX + 5,top: e.pageY + 5});};
  98 +
  99 + // hide and set interactivity on the DOB permit layers
  100 + var num_sublayers = layer.getSubLayerCount();
  101 + // Se esconden todas las capas cargadas
  102 + for (var i = 1; i < num_sublayers; i++) {layer.getSubLayer(i).hide();}
  103 + //console.log(num_sublayers);
  104 +
  105 + // Se activa la interactividad y se especifica los campos activados para dicho fin
  106 + layer.getSubLayer(0).setInteraction(true);
  107 + layer.getSubLayer(0).setInteractivity('cartodb_id, ultimo_pago, trb_total_deuda, ccc, cc_man, cc_lote, layer, obs, inm_ficha');
  108 +
  109 + //Feature on Mouse CLICK
  110 + layer.on('featureClick', function(e, pos, latlng, data) {
  111 + if (typeof impuesto !== "undefined") {
  112 + showFeature(data.cartodb_id, data.ccc);
  113 + }else{showFeature(data.cartodb_id, data.ccc);}
  114 + });
  115 +
  116 + //Feature Mouse OVER
  117 + layer.getSubLayer(0).on('featureOver', function(e, pos, latlng, data) {
  118 + ultimo_pago = data.ultimo_pago;
  119 + cuenta = data.ccc;
  120 + if (data.ultimo_pago == null){ultimo_pago = "N/A";}else{ultimo_pago = data.ultimo_pago;}
  121 + if (data.inm_ficha == null){ficha = "SIN FICHA";}else{ficha = data.inm_ficha;}
  122 + if (data.obs == null){observaciones = "SIN OBSERVACIONES";}else{observaciones = data.obs;}
  123 + $('#map').css('cursor', 'pointer');
  124 + $('#tool-tip').show().html(
  125 + // Contenido del Tool-Tip
  126 + '<h4>Informacion Adicional</h4>' +
  127 + '<hr>' +
  128 + '<p><strong> FICHA:</strong> ' + ficha + '</p>' +
  129 + '<p><strong>Manzana:</strong> ' + data.cc_man + '</p>' +
  130 + '<p><strong>Numero de Lote:</strong> ' + data.cc_lote + '</p>' +
  131 + '<p><strong>OBS.:</strong> ' + observaciones + '</p>'
  132 + );
  133 + $(document).bind('mousemove', event);
  134 + document.getElementById("ultimo").innerHTML = ultimo_pago;
  135 + document.getElementById("ccc").innerHTML = cuenta;
  136 + });
  137 + //Feature Mouse OUT
  138 + layer.getSubLayer(0).on('featureOut', function(e,pos,latlng,data){
  139 + $('#tool-tip').hide();
  140 + $(document).unbind('mousemove', event, false);
  141 + });
  142 +
  143 + el.map.addLayer(layer, false);
  144 + // make sure the base layer stays below the cdb layer
  145 + el.mapboxTiles.bringToBack();
  146 + }).on('done', function() {
  147 + }); // end cartodb.createLayer!
  148 +
  149 + };
  150 +
  151 + var showFeature = function (cartodb_id, ccc) {
  152 + $('#box2').show();
  153 + $('#tool-tip').hide();
  154 + $.ajax({
  155 + url: "api/callREAD.php",
  156 + type: "POST",
  157 + data: {cartodb_id: cartodb_id, type: 'lote', entidad: entidad},
  158 + dataType: 'json',
  159 + success: function (geojson) {
  160 + if (el.polygon) {el.map.removeLayer(el.polygon);}
  161 + el.polygon = L.geoJson(geojson, {
  162 + style: {
  163 + color: "#000",
  164 + fillColor: "#edd711",
  165 + weight: 6,
  166 + opacity: 0.8,
  167 + fillOpacity: 0.2
  168 + }
  169 + });
  170 + el.map.fitBounds(el.polygon.getBounds(), {maxZoom: 17});
  171 + el.polygon.addTo(el.map);
  172 + //console.log(polygon.getBounds()); //DEFINICION DEL POLIGONO
  173 + if (typeof impuesto !== "undefined") {
  174 + //console.log(entidad, impuesto, estado);
  175 + $.ajax
  176 + ({
  177 + url: 'login/get_liquidacion.php', //Se parsea el numero de ccc a fin de obtener los datos del lote
  178 + type: 'POST',
  179 + data: {ccc: ccc, entidad: entidad, impuesto: impuesto, estado: estado},//parseo de ccc
  180 + dataType: "json", //text or html or json or script
  181 + success:function(data)
  182 + {
  183 + var largo = data.length;
  184 + //SE LIMPIA EL DIV DE RESULTADOS
  185 + $("#toggle_resumen").html("").append('<a href="#" id="toggle_all" style="tex-alignment: left; padding-right: 3em" onclick="limpiar()">Mostrar Todos</a>');
  186 + $("#box").css({'opacity':'0.8'});
  187 + //TODO: aca podria haber sido overlowY en el "scroll" para contemplar solo el scroll vertical, preferi dejar ambos para que se "note que hay algo"
  188 + //console.log(largo);
  189 +
  190 + if (largo > 0){
  191 + // SE CREA EL INFORME POR LOTE
  192 + $("#resumen").html("").css({display: 'block', height: '90%', overflow: 'scroll'}
  193 + ).append('' +
  194 + '<p style="text-align: center;color:black;font-size: 20px">Informe Catastral</p>' +
  195 + '<p style="color:black"><b>Lote: </b>'+ccc+' <b>Ficha:</b> '+data[0].inm_ficha+'</p>'+
  196 + //SE CREA LA TABLA PARA EL RESUMEN
  197 + '<table id="resumen_table" class="table">'+
  198 + '<tr>'+
  199 + '<th>Ejercicio Fiscal</th>'+
  200 + '<th>Tributo</th>'+
  201 + '<th>Estado</th>'+
  202 + '<th>Importe</th>'+
  203 + '<th>Fecha de pago</th>'+
  204 + '</tr>');
  205 + //SE IMPRIMEN LOS DATOS DEL LOTE
  206 + var sum = 0;
  207 + $.each(data,function (i,item) {
  208 + switch (item.liq_estado){
  209 + case 'REG':
  210 + estadopago = 'PENDIENTE';
  211 + tiporesumen = 'ADEUDADO';
  212 + break;
  213 + case 'PAG':
  214 + tiporesumen = 'PAGADO';
  215 + estadopago = item.liq_fecpago;
  216 + break;
  217 + }
  218 + sum += parseInt(item.liq_importe_apagar);
  219 +
  220 + $('#resumen_table').append(
  221 + '<tr>' +
  222 + '<td>'+item.ejer_fisca+'</td>' +
  223 + '<td>'+item.trb_tributo+'</td>' +
  224 + '<td>'+item.liq_estado+'</td>' +
  225 + '<td>'+$.number(item.liq_importe_apagar,0,',','.')+'</td>' +
  226 + '<td>'+estadopago+'</td>' +
  227 + '</tr>'
  228 + );
  229 + //console.log(sum, item);
  230 + });
  231 + $('#resumen').append(
  232 + '</table><p style="text-align: left; font-size: 20px; color:black;">Total '+tiporesumen+': <b>'+ $.number(sum,0,',','.')+' Gs.</b></p>');
  233 + $('#toggle_resumen').append('<a href="#" id="toggle_msg" style="text-align: center; padding-right: 3em;" onclick="mostrarResumen()">Ocultar Resumen</a>'+
  234 + '<input type="button" style="color: black" id="print_resumen" value="Imprimir Resumen" onclick="printDiv();">'
  235 + );
  236 + }else{
  237 + $("#box2").css({display: 'block', height: 'auto'});
  238 + $("#resumen").html("").css({display: 'block', height: 'auto', overflow: ''}).append('<p style="text-align: center">No se encontraron Datos<p>');
  239 + }
  240 + },
  241 + error:function(data){
  242 + $('#resumen').html("").append('<p style="text-align: center; font-size: 10px; color:black;">No se encontraron datos</p>')
  243 + }
  244 + });;
  245 + }else {
  246 + //alert("FAVOR ELIJA TIPO DE IMPUESTO!");
  247 + }
  248 + }
  249 + });
  250 + };
  251 +
  252 + // change the cartoCSS of a layer
  253 + var changeCartoCSS = function(layer, css) {layer.setCartoCSS(css);};
  254 +
  255 + // change SQL query of a layer
  256 + var changeSQL = function(layer, sql) {layer.setSQL(sql);};
  257 +
  258 + // corresponding cartoCSS & SQL changes to tax lot layer buttons
  259 + // legends are displayed or hidden as needed
  260 + el.taxLotActions = {
  261 + regular : function() {
  262 + changeCartoCSS(el.taxLots, el.styles.regular);
  263 + changeSQL(el.taxLots, el.params.morosidadtodos);
  264 + renderLegend(null);
  265 + return true;
  266 + },
  267 + totales : function() {
  268 + //TODO: MEJORAR LOGICA!!
  269 + switch (estado){
  270 + case 'REG':
  271 + colormaximo = '#BD0026';
  272 + color80 = '#F03B20';
  273 + color60 = '#FFCC00';
  274 + color40 = '#95ad42';
  275 + color20 = '#2a722f';
  276 + colorminimo = '#8e8e8e';
  277 + titulo = 'ADEUDADO';
  278 + label_leyenda = 'NO REGISTRADOS/NO LIQUIDADOS';
  279 + break;
  280 + case 'PAG':
  281 + colormaximo = '#2a722f';
  282 + color80 = '#95ad42';
  283 + color60 = '#FFCC00';
  284 + color40 = '#F03B20';
  285 + color20 = '#BD0026';
  286 + colorminimo= '#8e8e8e';
  287 + titulo = 'PAGADO';
  288 + label_leyenda = 'NO REGISTRADOS/NO PAGADOS';
  289 + break;
  290 + }
  291 +
  292 + if (porciento80 === minimo) {
  293 + lotetotales = '#e'+entidad+'_lotes_conccc{polygon-fill: #FFFFB2;polygon-opacity: 0.8;line-color: #FFF;line-width: 0.5;line-opacity: 1;}'+
  294 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' > ' +porciento80+ ' ] {polygon-fill: '+colormaximo+';}' +
  295 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' = ' +porciento80+ '] {polygon-fill: '+color80+';}' +
  296 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' < ' +minimo+ '] {polygon-fill: '+colorminimo+';}'+
  297 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' = null] {polygon-fill: '+colorminimo+';}'
  298 + ;
  299 + }
  300 + else {
  301 + lotetotales = '' +
  302 + '#e'+entidad+'_lotes_conccc{polygon-fill: #FFFFB2;polygon-opacity: 0.8;line-color: #FFF;line-width: 0.5;line-opacity: 1;}'+
  303 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' > ' +porciento80+ ' ] {polygon-fill: '+colormaximo+';}' +
  304 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' <= ' +porciento80+ '] {polygon-fill: '+color80+';}' +
  305 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' <= ' +porciento60+ '] {polygon-fill: '+color60+';}' +
  306 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' <= ' +porciento40+'] {polygon-fill: '+color40+';}' +
  307 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' <= ' +porciento20+ '] {polygon-fill: '+color20+';}' +
  308 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' < ' +minimo+ '] {polygon-fill: '+colorminimo+';}'+
  309 + '#e'+entidad+'_lotes_conccc [ '+tipodeuda+' = null] {polygon-fill: '+colorminimo+';}'
  310 + ;
  311 + }
  312 + changeCartoCSS(el.taxLots, lotetotales);
  313 + //el.params.morosidadtodos+ " where (trb_tributo ilike '"+impuesto+"' and "+tipodeuda+" > 0) or trb_tributo is null";
  314 + sqltotales = el.params.morosidadtodos + " where (trb_tributo ilike '"+impuesto+"' or trb_tributo is null) ";
  315 +
  316 + if (sqlnuevo === "") {
  317 + changeSQL(el.taxLots, sqltotales);
  318 + }else{
  319 + filtro = parseInt(array.rows[idactual][filtroactual]);
  320 + //console.log (typeof filtro);
  321 + sqlnuevo = sqlnuevo + " and "+tipodeuda+" " + op + " " + eval(filtro);
  322 + //console.log(sqlnuevo);
  323 + changeSQL(el.taxLots, sqlnuevo);
  324 + changeCartoCSS(el.taxLots, lotetotales);
  325 + sqlnuevo = "";
  326 + filtro = "";
  327 + }
  328 + //TODO: MEJORAR LOGICA DE RENDER LEGENDA!
  329 + if (porciento80 === minimo){
  330 + renderLegend(
  331 + {title : "Total "+ titulo,
  332 + items : [
  333 + {color : colormaximo, label : "> " +$.number(porciento80,0,',','.')+" Gs", filtroid : "porciento80", op : " > " },
  334 + {color : color80, label : "= "+$.number(porciento80,0,',','.')+" Gs", filtroid : "porciento80", op : " = " },
  335 + {color : "hsl(48, 100%, 50%)", label : label_leyenda, filtroid : "minimo", op : " < " }
  336 + ]
  337 + }
  338 + );
  339 + }
  340 + else{
  341 + renderLegend(
  342 + {title : "Total "+ titulo,
  343 + items : [
  344 + {color : colormaximo, label : "> " +$.number(porciento80,0,',','.')+" Gs", filtroid : "porciento80", op : " > " },
  345 + {color : color80, label : "<= "+$.number(porciento80,0,',','.')+" Gs", filtroid : "porciento80", op: " <= " },
  346 + {color : color60, label : "<= "+$.number(porciento60,0,',','.')+" Gs", filtroid : "porciento60", op: " <= "},
  347 + {color : color40, label : "<= "+$.number(porciento40,0,',','.')+" Gs", filtroid : "porciento40", op: " <= " },
  348 + {color : color20, label : "<= "+$.number(porciento20,0,',','.')+" Gs", filtroid : "porciento20", op: " <= " },
  349 + {color : "#787878", label : label_leyenda, filtroid : "minimo", op: "<"}
  350 + ]
  351 + }
  352 + );
  353 + }
  354 + $('#tool-tip').show();
  355 + $('#box').show();
  356 + //TODO: seguir //getCDBData().getSubLayer(0).hide();
  357 + return true;
  358 + },
  359 + ultimopagado : function(){
  360 + switch (estado){
  361 + case 'REG': //TODO: REVISAR LOGICA
  362 + colormaximo = '#2a722f';
  363 + color80 = '#95ad42';
  364 + color60 = '#FFCC00';
  365 + color40 = '#F03B20';
  366 + color20 = '#BD0026';
  367 + colorminimo= '#8e8e8e';
  368 + titulo = 'ADEUDADO';
  369 + break;
  370 + case 'PAG':
  371 + colormaximo = '#2a722f';
  372 + color80 = '#95ad42';
  373 + color60 = '#FFCC00';
  374 + color40 = '#F03B20';
  375 + color20 = '#BD0026';
  376 + colorminimo= '#8e8e8e';
  377 + titulo = 'PAGADO';
  378 + break;
  379 + }
  380 + //TODO: Dinamico
  381 + lotesultimopagado = '#e'+entidad+'_lotes_conccc{polygon-fill: #006D2C;polygon-opacity: 0.8;line-color: #FFF;line-width: 0.5;line-opacity: 1;}'+
  382 + '#e'+entidad+'_lotes_conccc [ ultimo_pago = '+periodo+'] {polygon-fill: '+colormaximo+';}'+
  383 + '#e'+entidad+'_lotes_conccc [ ultimo_pago <= '+periodo1+'] {polygon-fill: '+color80+';}'+
  384 + '#e'+entidad+'_lotes_conccc [ ultimo_pago <= '+periodo2+'] {polygon-fill: '+color60+';}'+
  385 + '#e'+entidad+'_lotes_conccc [ ultimo_pago <= '+periodo3+'] {polygon-fill: '+color40+';}'+
  386 + '#e'+entidad+'_lotes_conccc [ ultimo_pago <= '+periodo4+'] {polygon-fill: '+color20+';}'+
  387 + '#e'+entidad+'_lotes_conccc [ ultimo_pago <= '+periodo5+'] {polygon-fill: '+color20+';}'+
  388 + '#e'+entidad+'_lotes_conccc [ ultimo_pago = null] {polygon-fill: '+colorminimo+';}';
  389 + changeCartoCSS(el.taxLots, lotesultimopagado);
  390 + sqlultimopagado = el.params.morosidadtodos+ " where (trb_tributo ilike '"+impuesto+"' and "+tipodeuda+" > 0) or trb_tributo is null";
  391 + //console.log(sqlultimopagado);
  392 + if (sqlnuevo === ""){changeSQL(el.taxLots, sqlultimopagado);}
  393 + else {
  394 + sqlnuevo = sqlnuevo + "and ultimo_pago " +op+ " " + eval(filtroactual);
  395 + //console.log(sqlnuevo);
  396 + changeSQL(el.taxLots, sqlnuevo);
  397 + changeCartoCSS(el.taxLots, lotesultimopagado);
  398 + sqlnuevo = "";
  399 + filtro = "";
  400 + }
  401 + //TODO: Debe ser dinamico
  402 + renderLegend({
  403 + title : "Ultimo "+ titulo,
  404 + items : [
  405 + {color : colormaximo, label : "= " + periodo, filtroid : periodo, op : " = " }, // igual a ultimo anho
  406 + {color : color80, label : " <= " + periodo1, filtroid : periodo1, op : " <= " },
  407 + {color : color60, label : "<= "+ periodo2, filtroid : periodo2, op : " <= " },
  408 + {color : color40, label : "<= "+ periodo3, filtroid : periodo3, op : " <= " },
  409 + {color : color20, label : "<= "+ periodo4, filtroid : periodo4, op : " <= " },
  410 + {color : color20, label : "<= "+ periodo5, filtroid : periodo5, op : " <= " },
  411 + {color : colorminimo, label : "SIN DEUDA O DEUDAS PRESCRIPTAS", filtroid : periodo6, op : "=<" }
  412 + ]
  413 + });
  414 + return true;
  415 + }
  416 + };
  417 +
  418 + // add tax lot layer button event listeners
  419 + var initButtons = function() {
  420 + $('.button').click(function(e) {
  421 + //e.preventDefault();
  422 + $(document).ajaxStart(function() { Pace.restart(); });
  423 + limpiar();
  424 + $('.button').removeClass('active');
  425 + $(this).addClass('active');
  426 + idactual = $(this).attr('name');
  427 + impuesto = array.rows[idactual].trb_tributo;
  428 + estado = array.rows[idactual].estado;
  429 + switch (estado) {
  430 + case 'REG':tipodeuda = "trb_total_deuda";break;
  431 + case 'PAG':tipodeuda = "trb_total_pago";break;
  432 + }
  433 + maximo = parseInt(array.rows[idactual].maximo);
  434 + minimo = parseInt(array.rows[idactual].minimo);
  435 + porciento20 = parseInt(array.rows[idactual].porciento20);
  436 + porciento40 = parseInt(array.rows[idactual].porciento40);
  437 + porciento60 = parseInt(array.rows[idactual].porciento60);
  438 + porciento80 = parseInt(array.rows[idactual].porciento80);
  439 + tipofiltro = $(this).attr('id');
  440 + app.map.el.taxLotActions[tipofiltro]();
  441 + var sqlnuevo = "";
  442 + //console.log(tipofiltro);
  443 + //console.log(idactual, impuesto, estado, maximo, minimo, porciento20, porciento40, porciento60, porciento80);
  444 + //console.log(tipodeuda);
  445 + //app.map.el.taxLots.show();
  446 + });
  447 + }
  448 +
  449 + //SUBFILTRO ONCLICK EN LA LEYENDA
  450 + var initsubfiltro = function(e) {
  451 + $(".subfiltro").click(function() {
  452 + //TODO: AL ELGIR UN FILTRO, PONER EN GRIS LOS DEMAS
  453 + //limpiarfiltros();
  454 + $(this).addClass("selected");
  455 + filtroactual = $(this).attr(toString("filtroid"));
  456 + op = $(this).attr("op");
  457 + //console.log(filtroactual, op);
  458 + //TODO: HASTA LLEGUE POR HOY 11/12/2017 12:26
  459 + sqlnuevo = el.params.morosidadtodos + " where trb_tributo ilike '"+impuesto+"'";
  460 +
  461 + app.map.el.taxLotActions[tipofiltro]();
  462 +
  463 + });
  464 + }
  465 +
  466 +
  467 + // Muestra las capas adicionales a medida que son marcados los checkboxes
  468 + var initCheckboxes = function() {
  469 + var checkboxDOB = $('input.dob:checkbox'), $manz = $('#manz'), $calle = $('#calle'), $sinccc = $('#sinccc');
  470 + $manz.change(function() {if ($manz.is(':checked')) {el.capaMANZ.show()} else {el.capaMANZ.hide()}});
  471 + $calle.change(function() {if ($calle.is(':checked')) {el.capaCALLES.show()}else {el.capaCALLES.hide()}});
  472 + $sinccc.change(function(){if ($sinccc.is(':checked')){el.capasinCCC.show()}else {el.capasinCCC.hide()}});
  473 + }
  474 +
  475 + // function to render choropleth legends
  476 + var renderLegend = function(data) {
  477 + if (data === null) {
  478 + //el.legend.addClass('hidden');
  479 + el.legend.removeClass('hidden');
  480 + return;
  481 + }
  482 + var legendData = {title : data.title,items : data.items,};
  483 + el.legend.html(el.template(legendData));
  484 + if (el.legend.hasClass('hidden')) el.legend.removeClass('hidden');
  485 + initsubfiltro();
  486 + }
  487 +
  488 + // Botones de Zoom Custom
  489 + var initZoomButtons = function(){
  490 + $('#zoom-in').on('click', function(){el.map.zoomIn();});
  491 + $('#zoom-out').on('click', function(){el.map.zoomOut();});
  492 + }
  493 +
  494 +
  495 +
  496 + // get it all going!
  497 + var init = function() {
  498 + //searchAddress();
  499 + initZoomButtons();
  500 + $(document).ajaxStart(function() { Pace.restart(); }); //EFECTO "CARGANDO..."
  501 + initCheckboxes();
  502 + initButtons();
  503 + $(document).ajaxStart(function() { Pace.restart(); }); //EFECTO "CARGANDO..."
  504 + initMap();
  505 + }
  506 +
  507 + // only return init() and the stuff in the el object
  508 + return {
  509 + init : init,
  510 + el : el
  511 + }
  512 +
  513 +})(window, document, jQuery, _);
  514 +
  515 +// call app.map.init() once the DOM is loaded
  516 +window.addEventListener('DOMContentLoaded', function(){
  517 + app.conf.init();
  518 + app.map.init();
  519 +});
0 \ No newline at end of file 520 \ No newline at end of file
GIS-GEOSERVER/mapa_mapStyles.js 0 → 100644
  1 +++ a/GIS-GEOSERVER/mapa_mapStyles.js
  1 +/**** CartoCSS for styling tax lot data ****/
  2 +var app = app || {};
  3 +
  4 +var conficha, sinficha = '';
  5 +
  6 +var actualizar_navegacion = function () {
  7 + switch (mapa) {
  8 + case 'morosidad':
  9 + subseccion = 'Por tipo de Impuestos';
  10 + break;
  11 + case 'zonas':
  12 + subseccion = 'Por Zona Tributaria';
  13 + ttc1 = 'FICHA';
  14 + ttc2 = 'ZONA';
  15 + ttc3 = 'OBS';
  16 + break;
  17 + case 'frentes': subseccion = 'Por tipo de Pavimento'; break;
  18 + case 'notificacion': subseccion = 'Estado de Notificación'; break;
  19 + case 'migracion': subseccion = 'Seguimiento de actualizaciones'; break;
  20 + case 'baldios': subseccion = 'Lotes Baldios'; break;
  21 + case 'baches':
  22 + //render pagina baches
  23 + break;
  24 + }
  25 +
  26 + //Nombrar Seccion y Subseccion
  27 + $("#seccion").text(seccion);
  28 + $("#subseccion").text(subseccion);
  29 +
  30 + //Mostrar elementos ocultos (template)
  31 + $("#search-container").removeAttr('hidden');
  32 + $("#ui-zoom").removeAttr('hidden');
  33 + $("#ui-legend").removeAttr('hidden');
  34 + $("#tool-tip").removeAttr('hidden');
  35 +
  36 + Pace.restart();
  37 +
  38 +}
  39 +
  40 +
  41 +//app.mapStyles = (function(idactual){
  42 +app.mapStyles = (function(){
  43 + return {
  44 + // default style, all lots are the same color
  45 + regular : '' +
  46 + '#e'+entidad+'_lotes_conccc{'+
  47 + 'polygon-fill: hsl(200,40%,90%);' +'polygon-opacity: 0.2;' +'line-color: #000;' +'line-width: 0.2;' +'line-opacity: 0.5;' +
  48 + '}',
  49 + inicio : '' +
  50 + '#e'+entidad+'_lotes_conccc{'+
  51 + 'polygon-fill: #FFFFFF;'+'polygon-opacity: 0.7;'+'line-color: #000000;'+'line-width: 0.5;'+'line-opacity: 1;'+
  52 + '}',
  53 + iniciomanz : '' +
  54 + '#e'+entidad+'_lotes_conccc{'+
  55 + 'polygon-fill: #FFFFFF;'+'polygon-opacity: 0.7;'+'line-color: #000000;'+'line-width: 0.5;'+'line-opacity: 1;'+
  56 + '}',
  57 + manzanas : ''+
  58 + '#e'+entidad+'_manzanas{' +
  59 + 'polygon-fill: #FFA300; polygon-opacity: 0.2; line-color: #FFF; line-width: 0.5; line-opacity: 1;' +
  60 + '}' +
  61 + '#e'+entidad+'_manzanas::labels [zoom >= 16] {'+
  62 + 'text-name: [cc_man];'+ 'text-face-name: "DejaVu Sans Book";'+
  63 + 'text-size: 16;'+ 'text-label-position-tolerance: 10;'+ 'text-fill: #000;'+
  64 + 'text-halo-fill: #7f7676;'+ 'text-halo-radius: 3;'+
  65 + 'text-dy: 0;'+ 'text-opacity: 0.2;'+ 'text-allow-overlap: false;'+
  66 + 'text-placement: point;'+ 'text-placement-type: simple;'+
  67 + '}'+
  68 + '#e'+entidad+'_manzanas::labels [zoom >= 18] {'+
  69 + 'text-name: [cc_man];'+ 'text-face-name: "DejaVu Sans Book";'+
  70 + 'text-size: 40;'+ 'text-label-position-tolerance: 10;'+ 'text-fill: #000;'+
  71 + 'text-halo-fill: #3f3e3e;'+ 'text-halo-radius: 5;'+
  72 + 'text-dy: 0;'+'text-opacity: 0.2;'+'text-allow-overlap: false;'+
  73 + 'text-placement: point;'+'text-placement-type: simple;'+
  74 + '}',
  75 + manzanascarga : ''+
  76 + '#e'+entidad+'_manzanas{' +
  77 + 'polygon-fill: #FFA300; polygon-opacity: 0; line-color: #FFF; line-width: 1; line-opacity: 1;' +
  78 + '}' +
  79 + '#e'+entidad+'_manzanas::labels [zoom >= 16] {'+
  80 + 'text-name: [cc_man];'+ 'text-face-name: "DejaVu Sans Book";'+
  81 + 'text-size: 16;'+ 'text-label-position-tolerance: 10;'+ 'text-fill: #FFF;'+
  82 + 'text-halo-fill: #7f7676;'+ 'text-halo-radius: 3;'+
  83 + 'text-dy: 0;'+ 'text-opacity: 0.5;'+ 'text-allow-overlap: false;'+
  84 + 'text-placement: point;'+ 'text-placement-type: simple;'+
  85 + '}'+
  86 + '#e'+entidad+'_manzanas::labels [zoom >= 18] {'+
  87 + 'text-name: [cc_man];'+ 'text-face-name: "DejaVu Sans Book";'+
  88 + 'text-size: 40;'+ 'text-label-position-tolerance: 10;'+ 'text-fill: #FFF;'+
  89 + 'text-halo-fill: #3f3e3e;'+ 'text-halo-radius: 5;'+
  90 + 'text-dy: 0;'+'text-opacity: 0.5;'+'text-allow-overlap: false;'+
  91 + 'text-placement: point;'+'text-placement-type: simple;'+
  92 + '}',
  93 + calles : '#e'+entidad+'_calles{line-color: #0F3B82; line-width: 2; line-opacity: 0.7; }',
  94 + lotesincc : '#e'+entidad+'_lotes_sinccc{polygon-fill: #A53ED5; polygon-opacity: 0.6; line-color: #FFF; line-width: 0.5; line-opacity: 1;}',
  95 + capazonastrib : '' +
  96 + '#e'+entidad+'_zonas_tributarias{'+
  97 + 'polygon-fill: #FF6600;'+'polygon-opacity: 0;'+'line-color: #000000;'+'line-width: 3;'+'line-opacity: 1;'+
  98 + '}'+
  99 + '#e'+entidad+'_zonas_tributarias::labels {'+
  100 + 'text-name: [description];'+
  101 + 'text-face-name: "DejaVu Sans Book";'+
  102 + 'text-size: 20;'+
  103 + 'text-label-position-tolerance: 0;'+
  104 + 'text-fill: #000;'+
  105 + 'text-halo-fill: #FFF;'+
  106 + 'text-halo-radius: 3;'+
  107 + 'text-dy: -10;'+
  108 + 'text-allow-overlap: true;'+
  109 + 'text-placement: line;'+
  110 + 'text-placement-type: simple;'+
  111 + '}',
  112 + //POR ZONAS - ZONAS TRIBUTARIAS
  113 + zonas : {
  114 + todos : '' +
  115 + '#e'+entidad+'_lotes_conccc {'+
  116 + 'polygon-opacity: 0.7;'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+
  117 + '}'+
  118 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur="R"] {'+'polygon-fill: #229A00;'+'}'+
  119 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur="U"] {'+'polygon-fill: #2167AB;'+'}'+
  120 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur=null] {'+'polygon-fill: #FFA300;'+'}'
  121 + ,
  122 + R : '' +
  123 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur="R"] {'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+'polygon-fill: #229A00;'+'}'
  124 + ,
  125 + U : '' +
  126 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur="U"] {'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+'polygon-fill: #2167AB;'+'}'
  127 + ,
  128 + null : '' +
  129 + '#e'+entidad+'_lotes_conccc[inm_tipo_ur=null] {'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+'polygon-fill: #FFA300;'+'}'
  130 + }
  131 + ,
  132 + //ZONAS TRIBUTARIAS
  133 + zonastributarias : {
  134 + todos : '' +
  135 + '#e'+entidad+'_lotes_conccc {'+
  136 + 'polygon-opacity: 0.7;'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+
  137 + '}'+
  138 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="0-0-0"] {'+'polygon-fill: #000000;'+'}'+
  139 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="R-1-1"] {'+'polygon-fill: #229A00;'+'}'+
  140 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-1-0"] {'+'polygon-fill: #F84F40;'+'}'+
  141 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-2-0"] {'+'polygon-fill: #0F3B82;'+'}'+
  142 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-3-0"] {'+'polygon-fill: #ffff00;'+'}'+
  143 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-4-0"] {'+'polygon-fill: #ff0000;'+'}'
  144 + ,
  145 + //{color: "#ffff00", label: "U-3-0"},
  146 + //{color: "#ff0000", label: "U-4-0"},
  147 + null : '' +
  148 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="0-0-0"] {'+'polygon-fill: #000000;'+'}'
  149 + ,
  150 + R11 : '' +
  151 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="R-1-1"] {'+'polygon-fill: #229A00;'+'}'
  152 + ,
  153 + U10 : '' +
  154 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-1-0"] {'+'polygon-fill: #F84F40;'+'}'
  155 + ,
  156 + U20 : '' +
  157 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-2-0"] {'+'polygon-fill: #0F3B82;'+'}'
  158 + ,
  159 + U30 : '' +
  160 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-3-0"] {'+'polygon-fill: #ffff00;'+'}'
  161 + ,
  162 + U40 : '' +
  163 + '#e'+entidad+'_lotes_conccc[zonas_tributarias="U-4-0"] {'+'polygon-fill: #ff0000;'+'}'
  164 + }
  165 + ,
  166 + //TIPO PAVIMENTO
  167 + frentepavimento : {
  168 + todos : '' +
  169 + '#e'+entidad+'_lotes_conccc{'+
  170 + 'polygon-opacity: 0.7;'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+
  171 + '}'+
  172 + '#e'+entidad+'_lotes_conccc[inm_tpav="T"] {'+'polygon-fill: #FF2900;'+'}'+
  173 + '#e'+entidad+'_lotes_conccc[inm_tpav="R"] {'+'polygon-fill: #894c4c;'+'}'+
  174 + '#e'+entidad+'_lotes_conccc[inm_tpav="E"] {'+'polygon-fill: #305784;'+'}'+
  175 + '#e'+entidad+'_lotes_conccc[inm_tpav="D"] {'+'polygon-fill: #6ba75f;'+'}'+
  176 + '#e'+entidad+'_lotes_conccc[inm_tpav="A"] {'+'polygon-fill: #222222;'+'}'+
  177 + '#e'+entidad+'_lotes_conccc[inm_tpav="H"] {'+'polygon-fill: #6ba75f;'+'}'+
  178 + '#e'+entidad+'_lotes_conccc[inm_tpav=null] {'+'polygon-fill: #FFCC00;'+'}'//TODOS
  179 + ,
  180 + asfalto : '' +
  181 + '#e'+entidad+'_lotes_conccc[inm_tpav="A"] {'+'polygon-fill: #222222;'+'}'//TODO: VARIABLE DINAMICA
  182 + ,
  183 + hormigon : '' +
  184 + '#e'+entidad+'_lotes_conccc[inm_tpav="H"] {'+'polygon-fill: #6ba75f;'+'}'//TODO: VARIABLE DINAMICA
  185 + ,
  186 + empedrado : '' +
  187 + '#e'+entidad+'_lotes_conccc[inm_tpav="E"] {'+'polygon-fill: #305784;'+'}'
  188 + ,
  189 + adoquin : '' +
  190 + '#e'+entidad+'_lotes_conccc[inm_tpav="D"] {'+'polygon-fill: #6ba75f;'+'}'
  191 + ,
  192 + tierra : '' +
  193 + '#e'+entidad+'_lotes_conccc[inm_tpav="T"] {'+'polygon-fill: #FF2900;'+'}'
  194 + ,
  195 + ripio : '' +
  196 + '#e'+entidad+'_lotes_conccc[inm_tpav="R"] {'+'polygon-fill: #894c4c;'+'}'
  197 + ,
  198 + nohab : '' +
  199 + '#e'+entidad+'_lotes_conccc[inm_tpav="R"] {'+'polygon-fill: #894c4c;'+'}'
  200 + ,
  201 + sindatos : '' +
  202 + '#e'+entidad+'_lotes_conccc[inm_tpav=null] {'+'polygon-fill: #FFCC00;'+'}'
  203 + }
  204 + ,
  205 + // red highlight
  206 + red : '' +
  207 + '#e'+entidad+'_lotes_conccc{'+
  208 + 'polygon-fill: #006D2C;' +'polygon-opacity: 0.8;' +'line-color: #FFF;' +'line-width: 0.5;' +'line-opacity: 1;' +
  209 + '}'
  210 + ,
  211 + notificaciones: '' +
  212 + '#e'+entidad+'_lotes_conccc {'+
  213 + 'polygon-opacity: 0.7;'+'line-color: #000000;'+'line-width: 0.5;'+'line-opacity: 0.5;'+
  214 + '}'+
  215 + '#e'+entidad+'_lotes_conccc[tipo_instancia=9] {'+'polygon-fill: #69A9DC;'+'}'+
  216 + '#e'+entidad+'_lotes_conccc[tipo_instancia=6] {'+'polygon-fill: #95AD42;'+'}'+
  217 + '#e'+entidad+'_lotes_conccc[tipo_instancia=7] {'+'polygon-fill: #38A73B;'+'}'+
  218 + '#e'+entidad+'_lotes_conccc[tipo_instancia=4] {'+'polygon-fill: #2A722F;'+'}'+
  219 + '#e'+entidad+'_lotes_conccc[tipo_instancia=1] {'+'polygon-fill: #FDD344;'+'}'+
  220 + '#e'+entidad+'_lotes_conccc[tipo_instancia=2] {'+'polygon-fill: #CD9335;'+'}'+
  221 + '#e'+entidad+'_lotes_conccc[tipo_instancia=3] {'+'polygon-fill: #DF7C2B;'+'}'+
  222 + '#e'+entidad+'_lotes_conccc[tipo_instancia=8] {'+'polygon-fill: #F73235;'+'}'+
  223 + '#e'+entidad+'_lotes_conccc[tipo_instancia=5] {'+'polygon-fill: #FF9900;'+'}'+
  224 + '#e'+entidad+'_lotes_conccc[tipo_instancia=null] {'+'polygon-fill: #FFFFFF;'+'}',
  225 + migracion: '' +
  226 + '#e'+entidad+'_lotes_conccc {'+
  227 + 'polygon-opacity: 0.7;'+'line-color: #FFF;'+'line-width: 0.5;'+'line-opacity: 1;'+
  228 + '}'+
  229 + '#e'+entidad+'_lotes_conccc[actualizacion_status=0] {'+'polygon-fill: #5CA2D1;'+'}'+
  230 + '#e'+entidad+'_lotes_conccc[actualizacion_status=1] {'+'polygon-fill: #229A00;'+'}'
  231 + ,
  232 + migraciontipo: '' +
  233 + '#e'+entidad+'_lotes_conccc {'+
  234 + 'polygon-opacity: 0.7;'+ 'line-color: #FFF;'+ 'line-width: 0.5;'+ 'line-opacity: 1;'+
  235 + '}'+
  236 + '#e'+entidad+'_lotes_conccc[actualizacion_codigo=1] {'+'polygon-fill: #79797a;'+'}'+
  237 + '#e'+entidad+'_lotes_conccc[actualizacion_codigo=2] {'+'polygon-fill: #f73235;'+'}'+
  238 + '#e'+entidad+'_lotes_conccc[actualizacion_codigo=3] {'+'polygon-fill: #447fbf;'+'}'+
  239 + '#e'+entidad+'_lotes_conccc[actualizacion_codigo=4] {'+'polygon-fill: #154a18;'+'}',
  240 + baldios : {
  241 + todos: '' +
  242 + '#e' + entidad + '_lotes_conccc {' + 'polygon-opacity: 0.7;' + 'line-color: #FFF;' + 'line-width: 0.5;' + 'line-opacity: 1;' + '}' +
  243 + '#e' + entidad + '_lotes_conccc{' +
  244 + '[valor_porcentaje=0] {polygon-fill: #F11810;}' +
  245 + '[valor_porcentaje >0][valor_porcentaje <=10]{polygon-fill: #FF6600;}' +
  246 + '[valor_porcentaje > 10] {polygon-fill: #229A00;}' +
  247 + '[valor_porcentaje=null] {polygon-fill: #FFCC00;}' +
  248 + '}',
  249 + baldio: '#e' + entidad + '_lotes_conccc[valor_porcentaje = 0] {' + 'polygon-fill: #F11810;' + '}',
  250 + baldioconst: '#e' + entidad + '_lotes_conccc[valor_porcentaje >0][valor_porcentaje <=10] {' + 'polygon-fill: #FF6600;' + '}',
  251 + nobaldio: '#e' + entidad + '_lotes_conccc[valor_porcentaje > 10] {' + 'polygon-fill: #229A00;' + '}',
  252 + sindatos: '#e' + entidad + '_lotes_conccc[valor_porcentaje = null] {' + 'polygon-fill: #FFCC00;' + '}'
  253 + },
  254 + lotes_recoleccion: '' +
  255 + '#e9999_lotes_conccc {' + 'polygon-opacity: 0.7;' + 'line-color: #FFF;' + 'line-width: 0.5;' + 'line-opacity: 1;' + '}' +
  256 + '#e9999_lotes_conccc[ruta_id="1"] {' + 'polygon-fill: #A53ED5;' + '}' +
  257 + '#e9999_lotes_conccc[ruta_id="2"] {' + 'polygon-fill: #229A00;' + '}',
  258 + sigem: {
  259 + todos: '' +
  260 + '#e'+entidad+'_lotes {' + 'polygon-opacity: 0.7;' + 'line-color: #FFF;' + 'line-width: 0.5;' + 'line-opacity: 1;' + '}' +
  261 + '#e9999_lotes[inm_estado="ACT"] {' + 'polygon-fill: #229A00;' + '}' +
  262 + '#e9999_lotes[inm_estado="FRA"] {' + 'polygon-fill: #229A00;' + '}' +
  263 + '#e9999_lotes[inm_estado="NOT"] {' + 'polygon-fill: #229A00;' + '}' +
  264 + '#e9999_lotes[inm_estado=null] {' + 'polygon-fill: #F11810;' + '}',
  265 + conficha: ''+
  266 + '#e9999_lotes[inm_estado="ACT"] {' + 'polygon-fill: #229A00;' + '}' +
  267 + '#e9999_lotes[inm_estado="FRA"] {' + 'polygon-fill: #229A00;' + '}' +
  268 + '#e9999_lotes[inm_estado="NOT"] {' + 'polygon-fill: #229A00;' + '}',
  269 + sinficha: '#e9999_lotes[inm_estado=null] {' + 'polygon-fill: #F11810;' + '}'
  270 + },
  271 + nuevos: '' +
  272 + '#e' + entidad + '_lotes_conccc {' + 'polygon-opacity: 0.3;' + 'line-color: #FFF;' + 'line-width: 0.7;' + 'line-opacity: 0.5;' + '}' +
  273 + '#e' + entidad + '_lotes_conccc{' +
  274 + '[valor_porcentaje=0] {polygon-fill: #F11810;}' +
  275 + '[valor_porcentaje >0][valor_porcentaje <=10]{polygon-fill: #FF6600;}' +
  276 + '[valor_porcentaje > 10] {polygon-fill: #229A00;}' +
  277 + '[valor_porcentaje=null] {polygon-fill: #FFCC00;}' +
  278 + '}',
  279 + nuevoszoom: '' +
  280 + '#e' + entidad + '_lotes_conccc {' + 'polygon-opacity: 0.3;' + 'line-color: #FFF;' + 'line-width: 0.5;' + 'line-opacity: 1;' + '}' +
  281 + '#e' + entidad + '_lotes_conccc{' +
  282 + '[valor_porcentaje=0] {polygon-fill: #F11810;}' +
  283 + '[valor_porcentaje >0][valor_porcentaje <=10]{polygon-fill: #FF6600;}' +
  284 + '[valor_porcentaje > 10] {polygon-fill: #229A00;}' +
  285 + '[valor_porcentaje=null] {polygon-fill: #FFCC00;}' +
  286 + '}'+
  287 + '#e'+entidad+'_lotes_concc::labels [zoom > 18] {'+
  288 + 'text-name: [cc_lote];'+ 'text-face-name: "DejaVu Sans Book";'+
  289 + 'text-size: 20;'+ 'text-label-position-tolerance: 10;'+ 'text-fill: #FFF;'+
  290 + 'text-dy: 0;'+'text-opacity: 0.5;'+'text-allow-overlap: false;'+
  291 + 'text-placement: point;'+'text-placement-type: simple;'+
  292 + '}',
  293 + mejoras: '' +
  294 + '#e'+entidad+'_mejoras{polygon-fill: #A53ED5; polygon-opacity: 0.6; line-color: #FFF; line-width: 0.5; line-opacity: 1;}',
  295 + estado_mejoras: '' +
  296 + '#e505_mejoras {' + 'polygon-opacity: 0.7;' + 'line-color: #000000;' + 'line-width: 0.5;' + ' line-opacity: 0;' + '}' +
  297 + '#e505_mejoras[layer="MEJORAS-CARGADAS"] {' + 'polygon-fill: #229A00;' + '}' +
  298 + '#e505_mejoras[layer=null] {' + 'polygon-fill: #1F78B4;' + '}',
  299 + estado_lotes: '' +
  300 + '#e505_lotes_conccc {' + 'polygon-opacity: 0.7;' + 'line-color: #000000;' + 'line-width: 0.1;' + 'line-opacity: 0.6;' + '}' +
  301 + '#e505_lotes_conccc[layer="DATOS-EDITADOS"] {' + 'polygon-fill: #229A00;' + '}' +
  302 + '#e505_lotes_conccc[layer="LOTES-EDITADOS"] {' + 'polygon-fill: #5CA2D1;' + '}' +
  303 + '#e505_lotes_conccc[layer=null] {' + 'polygon-fill: #FFFFFF;' + '}'
  304 + };
  305 +})();
  306 +
  307 +app.leyendas = (function () {
  308 + return {
  309 + pavimento: {title: "Tipo de Pavimento",
  310 + items: [
  311 + {color: "#222222", label: "Asfalto"},
  312 + {color: "#6ba75f", label: "Hormigón"},
  313 + {color: "#305784", label: "Empedrado"},
  314 + {color: "#6ba75f", label: "Adoquín"},
  315 + {color: "#FF2900", label: "Tierra"},
  316 + {color: "#894c4c", label: "Ripio"},
  317 + {color: "#FFCC00", label: "Sin Datos"},
  318 + ]
  319 + },
  320 + zonas: {title: "Tipos de Zona",
  321 + items: [
  322 + {color: "#229A00", label: "Rural"},
  323 + {color: "#2167AB", label: "Urbano"},
  324 + {color: "#FFA300", label: "Sin Datos"},
  325 + ]
  326 + },
  327 + zonastributarias: {title: "Zonas Tributarias",
  328 + items: [
  329 + {color: "#229A00", label: "R-1-1"},
  330 + {color: "#F84F40", label: "U-1-0"},
  331 + {color: "#0F3B82", label: "U-2-0"},
  332 + {color: "#ffff00", label: "U-3-0"},
  333 + {color: "#ff0000", label: "U-4-0"},
  334 + {color: "#000000", label: "Sin Datos"},
  335 + ]
  336 + },
  337 + notificaciones: {title: "Notificaciones",
  338 + items: [
  339 + {color: "#69a9dc", label: "INICIO SEGUIMIENTO"},
  340 + {color: "#95ad42", label: "RELIQUID. y ACTUALIZ."},
  341 + {color: "#38a73b", label: "EMIS. 1RA NOTIF."},
  342 + {color: "#2a722f", label: "1RA NOTIF. ENTREGADA"},
  343 + {color: "#fdd344", label: "EMIS. 2DA NOTIF."},
  344 + {color: "#cd9335", label: "2DA NOTIF. ENTREGADA"},
  345 + {color: "#df7c2b", label: "EMIS. CERTIF. DEUDA"},
  346 + {color: "#f73235", label: "JUICIO EJECUTIVO"},
  347 + {color: "#FFFFFF", label: "SIN DATOS"},
  348 + ]
  349 + },
  350 + migracion: {title: "Estado Migracion",
  351 + items: [
  352 + {color: "#5CA2D1", label: "SIN ACTUALIZACIONES"},
  353 + {color: "#229A00", label: "ACTUALIZADO"},
  354 + ]
  355 + },
  356 + migraciontipo: {title: "Estado Migracion",
  357 + items: [
  358 + {color: "#79797a", label: "Linea de Base"},
  359 + {color: "#f73235", label: "Zonas Tributarias"},
  360 + {color: "#447fbf", label: "Frentes"},
  361 + {color: "#154a18", label: "Frentes y Zonas"},
  362 + ]
  363 + },
  364 + baldios: {title: "Estado LOTE",
  365 + items: [
  366 + {color: "#F11810", label: "LOTE BALDIO"},
  367 + {color: "#FF6600", label: "BALDIO C/ CONSTRUC."},
  368 + {color: "#229A00", label: "LOTE NO BALDIO"},
  369 + {color: "#FFCC00", label: "SIN DATOS"},
  370 + ]
  371 + },
  372 + estado_lotes: {title: "ACT. DE LOTES",
  373 + items: [
  374 + {color: "#229A00", label: "DATOS EDITADOS"},
  375 + {color: "#5CA2D1", label: "LOTES EDITADOS"},
  376 + {color: "#FFFFFF", label: "LINEA BASE"},
  377 + ]
  378 + },
  379 + estado_mejoras: {title: "ACT. DE MEJORAS",
  380 + items: [
  381 + {color: "#229A00", label: "MEJORAS NUEVAS"},
  382 + {color: "#5CA2D1", label: "CARGA MASIVA"},
  383 + ]
  384 + }
  385 + }
  386 +
  387 +})();
GIS-GEOSERVER/mapa_parametros.js 0 → 100644
  1 +++ a/GIS-GEOSERVER/mapa_parametros.js
  1 +/**** SQL para los distintos tipos de mapas ****/
  2 +var app = app || {};
  3 +
  4 +//VARIABLES GLOBALES
  5 +var tipofiltro = "";
  6 +var param_subfiltro = "";
  7 +var sqlnuevo = "";
  8 +var filtroactual = "";
  9 +var filtro = "";
  10 +var query = "";
  11 +var estado, idactual = '';
  12 +var array, arraymenu, menus, capas_adicionales = '';
  13 +var seccion, subseccion = '';
  14 +var ttc1, ttc2, ttc3 = '';
  15 +var loteactual = '';
  16 +
  17 +//FUNCIONES GLOBALES
  18 +
  19 +
  20 +var mapa_zonas = function () {
  21 + mapa = 'zona';
  22 + app.map.el.map.remove();
  23 + app.map.init();
  24 +}
  25 +
  26 +//muestra/oculta resumen de lote
  27 +var mostrarResumen = function() {
  28 + if($('#resumen').css('display') != 'none'){
  29 + $('#resumen').css({
  30 + display: 'none'
  31 + });
  32 + $("#toggle_msg").html('Mostrar Resumen');
  33 + document.getElementById('print_resumen').type = 'hidden';
  34 + $("#box2").css({display: 'block', height: 'auto'});
  35 + }else{
  36 + $('#resumen').css({display: 'block'});
  37 + $("#toggle_msg").html('Ocultar Resumen');
  38 + document.getElementById('print_resumen').type = 'button';
  39 + $("#box2").css({display: 'block', height: '500px'});
  40 + }
  41 +};
  42 +
  43 +//funcion para limpiar el mapa cuando se elija un nuevo filtro/operacion
  44 +var limpiar = function() {
  45 + el = app.map.el;
  46 + el.map.setView([lat, lng], zoom);
  47 + $("#resumen").html("");
  48 + $("#resumen").css({display: 'none'});
  49 + $("#toggle_resumen").html("");
  50 + //document.getElementById("box").style.opacity = "0.7";
  51 + $("#box").css({
  52 + 'opacity': '0.7'
  53 + }
  54 + )
  55 + $('#box2').hide();
  56 + if (el.polygon) {
  57 + el.map.removeLayer(el.polygon);
  58 + }
  59 +};
  60 +
  61 +window.forceReload = function(){
  62 + if( !window.fetch)return document.location.reload( true);
  63 + var els = document.getElementsByTagName( "*");
  64 + for( var i = 0; i < els.length; i++){
  65 + var src = "";
  66 + if( els[i].tagName == "A")continue;
  67 + if( !src && els[i].src)src = els[i].getAttribute( "src");
  68 + if( !src && els[i].href)src = els[i].getAttribute( "href");
  69 + if( !src)continue;
  70 + fetch( src, { cache: "reload"});
  71 + }
  72 + return document.location.reload( true);
  73 +};
  74 +
  75 +var procesar = function (identificador, operacion) {
  76 + console.log('identificador: ', identificador, ' operacion: ', operacion);
  77 + switch (operacion){
  78 + case 'actualizar':
  79 + var ccc = document.getElementById("infoModalCCC").value;
  80 + var zona = document.getElementById("infoModalZona").value;
  81 + var mz = document.getElementById("infoModalManzana").value;
  82 + var lote = document.getElementById("infoModalLote").value;
  83 + $.ajax({
  84 + url: "login/set_valores.php",
  85 + type: "POST",
  86 + data: {id: identificador, operacion: operacion, ccc: ccc, zona: zona, mz: mz, lote: lote}, async: false, dataType: 'json',
  87 + success: function (data) {
  88 + array = JSON.parse(data);
  89 + alert(array[0].total_rows + ' de ' + array[1].total_rows + ' agregado');
  90 + $('#modal_editar_lotes')[0].reset();
  91 + console.log(array);
  92 + },
  93 + error:function(data){console.log('ndoikoi!', data);}
  94 + });
  95 + break;
  96 + case 'eliminar':
  97 + $.ajax({
  98 + url: "login/set_valores.php", type: "POST", data: {id: identificador, operacion: operacion}, async: false, dataType: 'json',
  99 + success: function (data) {
  100 + array = JSON.parse(data);
  101 + alert('Se ha eliminado '+ array.total_rows + ' registro/s');
  102 + },
  103 + error:function(data){console.log('ndoikoi!', data);}
  104 + });
  105 + break;
  106 + case 'cancelar':
  107 + map.removeLayer(polygon);
  108 + $('#modal_editar_lotes')[0].reset();
  109 + break;
  110 + default:
  111 + alert('Operacion no valida');
  112 + }
  113 +
  114 + $("#infoModal").toggle();
  115 + //forceReload();
  116 +};
  117 +
  118 +//Se imprime el div que contiene el informe del lote
  119 +var printDiv = function() {
  120 + var divToPrint=document.getElementById('resumen');
  121 + var newWin=window.open('','Print-Window');
  122 + newWin.document.open();
  123 + newWin.document.write('<html>' +
  124 + '<head>' +
  125 + '<link href="css/normalize.css" rel="stylesheet">'+
  126 + '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">'+
  127 + '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">'+
  128 + '<script src="js/accordion-menu.js"></script>'+
  129 + '<link rel="stylesheet" type="text/css" href="css/styles.css">'+
  130 + '</head>'+
  131 + '<body onload="window.print()">'+divToPrint.innerHTML+'</body></html>');
  132 + newWin.document.close();
  133 + setTimeout(function(){newWin.close();},10);
  134 +};
  135 +
  136 +app.conf = (
  137 + function () {
  138 + //mapa = "zonas";
  139 + //MENU DINAMICO
  140 + var initMenu = function() {
  141 + //console.log(mapa);
  142 + seccion = 'Mapas';
  143 + actualizar_navegacion();
  144 +
  145 + $.ajax({
  146 + url: "login/get_valores.php", type: "POST", data: {mapa: mapa}, async: false, dataType: 'json',
  147 + success: function (data) {
  148 + //console.log(data);
  149 + switch (mapa) {
  150 + case 'morosidad':
  151 + array = JSON.parse(data);
  152 + //console.log(array);
  153 + var estado = '';
  154 + var idactual;
  155 + var actual = 0;
  156 + var tipo = 0;
  157 + creg = 0;
  158 + cpag = 0;
  159 +
  160 + for (var p = 0; p < array.total_rows; p++) {
  161 + var pimpuesto = array.rows[p];
  162 + if (pimpuesto.estado === 'REG') {
  163 + if (creg === 0){
  164 + creg = creg + 1;
  165 + estado = 'ADEUDADOS';
  166 + menus = "" +
  167 + "<li>" +
  168 + "<a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;IMPUESTOS " + estado + "</a>" +
  169 + "<ul class='inner' id='uno'>"+
  170 + "<li>" +
  171 + "<a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;" + pimpuesto.descripcion + " </a>" +
  172 + "<ul class='inner'>" +
  173 + "<li><a href='#totales' id='totales' class='button' name = '" + p + "'><i class='fa fa-money'></i>&nbsp;POR TOTAL</a></li>" +
  174 + "<li><a href='#ultimopagado' id='ultimopagado' class='button' name = '" + p + "'><i class='fa fa-clock-o'></i>&nbsp;ULTIMO PAGO</a></li>" +
  175 + "</ul>" +
  176 + "</li>"
  177 + }else{
  178 + creg = creg + 1;
  179 + menus = menus +
  180 + "<li>" +
  181 + "<a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;" + pimpuesto.descripcion + " </a>" +
  182 + "<ul class='inner'>" +
  183 + "<li><a href='#' id='totales' class='button' name = '" + p + "'><i class='fa fa-money'></i>&nbsp;POR TOTAL</a></li>" +
  184 + "<li><a href='#' id='ultimopagado' class='button' name = '" + p + "'><i class='fa fa-clock-o'></i>&nbsp;ULTIMO PAGO</a></li>" +
  185 + "</ul>" +
  186 + "</li>"
  187 + }
  188 + } else {
  189 + if (pimpuesto.estado === 'PAG') {
  190 + if (cpag === 0){
  191 + cpag = cpag + 1;
  192 + estado = 'PAGADOS';
  193 + menus = menus +
  194 + "</ul>" +
  195 + "</li>"+
  196 + "<li><a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;IMPUESTOS " + estado + "</a>" +
  197 + "<ul class='inner' id='dos'>"+
  198 + "<li><a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;" + pimpuesto.descripcion + " </a>" +
  199 + "<ul class='inner'>" +
  200 + "<li><a href='#' id='totales' class='button' name = '" + p + "'><i class='fa fa-money'></i>&nbsp;POR TOTAL</a></li>" +
  201 + "<li><a href='#' id='ultimopagado' class='button' name = '" + p + "'><i class='fa fa-clock-o'></i>&nbsp;ULTIMO PAGO</a></li>" +
  202 + "</ul>" +
  203 + "</li>"
  204 + }else{
  205 + menus = menus +
  206 + "<li><a class='toggle' href='#'><i class='fa fa-plus'></i>&nbsp;" + pimpuesto.descripcion + " </a>" +
  207 + "<ul class='inner'>" +
  208 + "<li><a href='#' id='totales' class='button' name = '" + p + "'><i class='fa fa-money'></i>&nbsp;POR TOTAL</a></li>" +
  209 + "<li><a href='#' id='ultimopagado' class='button' name = '" + p + "'><i class='fa fa-clock-o'></i>&nbsp;ULTIMO PAGO</a></li>" +
  210 + "</ul>" +
  211 + "</li>"
  212 + }
  213 + }
  214 + }
  215 + }
  216 + menus = menus +
  217 + "</ul>" +
  218 + "</li>"
  219 + break;
  220 +
  221 + case 'zonas':
  222 + array = JSON.parse(data);
  223 +
  224 + ///ZONAS///
  225 + menus = "" +
  226 + "<li>" +
  227 + "<a class='toggle' href='javascript:void(0);'><i class='fa fa-plus'></i>&nbsp;"+ mapa.toUpperCase() + "</a>" +
  228 + "<ul class='inner' id='uno'>"
  229 +
  230 + for (var l = 0; l < array.total_rows; l++) {//INICIO DINAMICO
  231 + zona = array.rows[l];
  232 + //console.log(zona.inm_tipo_ur);
  233 + switch (zona.inm_tipo_ur){
  234 + case 'R': tzona = 'RURAL'; break;
  235 + case 'U': tzona = 'URBANO'; break;
  236 + case '': case null: tzona = 'Sin Datos'; break;
  237 + }
  238 + if (zona.inm_tipo_ur === '' || zona.inm_tipo_ur === null || zona.inm_tipo_ur === 'C'){
  239 +
  240 + }else{
  241 + menus = menus +
  242 + "<li>" +
  243 + "<a href='#' id='zonas' class='button' name = '"+zona.inm_tipo_ur+"'>"+tzona+"</a>" +
  244 + "</li>"
  245 + }
  246 + }//FIN DINAMICO
  247 + menus = menus +
  248 + "<li><a href='#' id='zonas' class='button' name='null'>SIN DATOS</a></li>" +
  249 + "<li><a href='#' id='zonas' class='button' name='todos'>TODOS</a></li>" +
  250 + "</ul>"+
  251 + "</li>"
  252 +
  253 + ///ZONAS TRIBUTARIAS
  254 + $(document).ajaxStart(function() { Pace.restart(); });
  255 + $.ajax({
  256 + url: "login/get_valores.php", type: "POST", data: {mapa: 'zonastributarias'}, async: false, dataType: 'json',
  257 + success: function (zonastrib) {
  258 + array = JSON.parse(zonastrib);
  259 + //console.log(array);
  260 +
  261 + menus = menus +
  262 + "<li>" +
  263 + "<a class='toggle' href='javascript:void(0);'><i class='fa fa-plus'></i> ZONAS TRIBUTARIAS</a>" +
  264 + "<ul class='innner' id='dos'>"
  265 +
  266 + for (var l = 0; l < array.total_rows; l++) {//INICIO DINAMICO
  267 + zona = array.rows[l];
  268 + //console.log(zona.zonas_tributarias, zona.codigo);
  269 + switch (zona.zonas_tributarias){
  270 + case '': case null: ztrib = 'Sin Datos'; break;
  271 + default: ztrib = zona.zonas_tributarias;
  272 + }
  273 + if (zona.codigo === '' || zona.codigo === null){ztrib = ztrib + ' (null)';}
  274 + menus = menus +
  275 + "<li><a href='#' id='zonastributarias' class='button' name = '"+zona.codigo+"'>"+ztrib+"</a></li>"
  276 + }//FIN DINAMICO
  277 +
  278 + menus = menus +
  279 + "<li><a href='#' id='zonastributarias' class='button' name = 'null'>SIN DATOS</a></li>" +
  280 + "<li><a href='#' id='zonastributarias' class='button' name = 'todos'>TODOS</a></li>" +
  281 + "</ul>"+
  282 + "</li>"
  283 + },
  284 + error:function(data){console.log('ndoikoi!', data);}
  285 + });
  286 + break;
  287 +
  288 + case 'frentes':
  289 + array = JSON.parse(data);
  290 + //console.log(array, array.total_rows);
  291 + menus = ""+
  292 + "<li>" +
  293 + "<a class='toggle' href='javascript:void(0);'><i class='fa fa-plus'></i> Tipos de "+ mapa.toUpperCase() + "</a>" +
  294 + "<ul class='inner' id='uno'>"
  295 +
  296 + //Dibujado dinamico del MENU
  297 + for (var l = 0; l < array.total_rows; l++) {
  298 + pavimento = array.rows[l];
  299 + //console.log(pavimento.inm_tpav);
  300 + switch (pavimento.inm_tpav){
  301 + case 'A': tpavimento = 'Asfalto'; nombre = 'asfalto'; break;
  302 + case 'H': tpavimento = 'Hormigon'; nombre = 'hormigon'; break;
  303 + case 'D': tpavimento = 'Adoquin'; nombre = 'adoquin'; break;
  304 + case 'E': tpavimento = 'Empedrado'; nombre = 'empedrado'; break;
  305 + case 'T': tpavimento = 'Tierra'; nombre = 'tierra'; break;
  306 + case 'R': tpavimento = 'Ripio'; nombre = 'ripio'; break;
  307 + case 'N': tpavimento = 'No Habilitado'; nombre = 'nohab'; break;
  308 + case '':
  309 + case null: tpavimento = 'Sin Datos'; nombre = 'sindatos';break;
  310 + }
  311 + menus = menus +
  312 + "<li>" +
  313 + "<a href='#' id='pavimento' class='button' name = '"+nombre+"'>"+tpavimento+"</a>" +
  314 + "</li>"
  315 + }
  316 + menus = menus +
  317 + "<li><a href='#' id='pavimento' class='button' name = 'todos'>TODOS</a></li>" +
  318 + "</ul>"+
  319 + "</li>"
  320 + break;
  321 +
  322 + case 'notificacion':
  323 + //NOTIFICACIONES!
  324 + array = JSON.parse(data);
  325 + //console.log(array, array.total_rows);
  326 +
  327 + menus = "" +
  328 + "<li>" +
  329 + "<a class='toggle' href='javascript:void(0);'><i class='fa fa-plus'></i> Tipos de "+ mapa.toUpperCase() + "</a>" +
  330 + "<ul class='inner' id='dos'>"
  331 +
  332 + //Dibujado dinamico del MENU
  333 + for (var l = 0; l < array.total_rows; l++) {
  334 + notificaciones = array.rows[l];
  335 + //console.log(notificaciones.tipo_instancia);
  336 + switch (notificaciones.tipo_instancia){
  337 + case 9: estado = 'INICIO SEGUIMIENTO'; break;
  338 + case 6: estado = 'RELIQUIDACION Y ACT.'; break;
  339 + case 7: estado = 'EMISION 1RA NOTIF.'; break;
  340 + case 4: estado = '1RA NOTIF. ENTREGADA'; break;
  341 + case 1: estado = 'EMISION 2DA NOTIF.'; break;
  342 + case 2: estado = '2DA NOTIF ENTREGADA'; break;
  343 + case 3: estado = 'EMISION CERT. DEUDA'; break;
  344 + case 8: estado = 'PRES. JUICIO EJECUTIVO'; break;
  345 + default: estado = notificaciones.tipo_instancia; break;
  346 + }
  347 + //console.log(notificaciones.inm_tpav);
  348 + menus = menus +
  349 + "<li><a href='#' id='notificaciones' class='button' name = '"+notificaciones.tipo_instancia+"'>"+estado+"</a></li>"
  350 + }
  351 + menus = menus +
  352 + "<li><a href='#' id='notificaciones' class='button' name = 'sindatos'>SIN DATOS</a></li>" +
  353 + "<li><a href='#' id='notificaciones' class='button' name = 'todos'>TODOS</a></li>" +
  354 + "</ul>"+
  355 + "</li>"
  356 + break;
  357 +
  358 + case 'migracion':
  359 +
  360 + menus = "" +
  361 + "<li>" +
  362 + "<a class='toggle'><i class='fa fa-plus'></i> Lotes Actualizados </a>" +
  363 + "<ul class='inner' id='uno'>"+
  364 + "<li><a href='#' id='migracion' class='button' name = 'act'>Actualizado</a></li>"+
  365 + "<li><a href='#' id='migracion' class='button' name = 'todos'>Todos</a></li>"+
  366 + "</ul>"+
  367 + "</li>"+
  368 + "<li>"+
  369 + "<a class='toggle'><i class='fa fa-plus'></i> Tipo Actualizacion </a>" +
  370 + "<ul class='inner' id='dos'>"+
  371 + "<li><a href='#' id='migraciontipo' class='button' name = '1'>Linea de Base</a></li>"+
  372 + "<li><a href='#' id='migraciontipo' class='button' name = '2'>Zonas Tributarias</a></li>"+
  373 + "<li><a href='#' id='migraciontipo' class='button' name = '3'>Frentes</a></li>"+
  374 + "<li><a href='#' id='migraciontipo' class='button' name = '4'>Frentes y Zonas</a></li>"+
  375 + "<li><a href='#' id='migraciontipo' class='button' name = 'todos'>Todos</a></li>"+
  376 + "</ul>"+
  377 + "</li>"
  378 + break;
  379 +
  380 + case 'baldios':
  381 + //console.log(data);
  382 +
  383 + menus = "" +
  384 + "<li>" +
  385 + "<a class='toggle'><i class='fa fa-plus'></i> Situacion de LOTES</a>" +
  386 + "<ul class='inner' id='dos'>"
  387 +
  388 + menus = menus +
  389 + "<li><a href='#' id='baldios' class='button' name = 'baldio'> BALDIO SIN CONSTRUCCION </a></li>"+
  390 + "<li><a href='#' id='baldios' class='button' name = 'baldioconst'> BALDIO CON CONSTRUCCION </a></li>"+
  391 + "<li><a href='#' id='baldios' class='button' name = 'nobaldio'> NO BALDIO </a></li>"+
  392 + "<li><a href='#' id='baldios' class='button' name = 'sindatos'> SIN DATOS </a></li>"
  393 +
  394 + menus = menus +
  395 + "<li><a href='#' id='baldios' class='button' name = 'todos'>TODOS</a></li>" +
  396 + "</ul>"+
  397 + "</li>"
  398 + break;
  399 +
  400 + case 'sigem':
  401 + array = JSON.parse(data);
  402 + //console.log(array);
  403 +
  404 + conficha = array.rows[0].conficha;
  405 + sinficha = array.rows[0].sinficha;
  406 +
  407 + console.log('Con ficha: ', conficha, ' sin ficha: ', sinficha);
  408 +
  409 + menus = "" +
  410 + "<li>" +
  411 + "<a class='toggle'><i class='fa fa-plus'></i> Situacion de LOTES</a>" +
  412 + "<ul class='inner' id='dos'>"
  413 +
  414 + menus = menus +
  415 + "<li><a href='#' id='sigem' class='button' name = 'conficha'> CON FICHA </a></li>"+
  416 + "<li><a href='#' id='sigem' class='button' name = 'sinficha'> SIN FICHA </a></li>"
  417 +
  418 + menus = menus +
  419 + "<li><a href='#' id='sigem' class='button' name = 'todos'>TODOS</a></li>" +
  420 + "</ul>"+
  421 + "</li>"
  422 + break;
  423 + case 'actualotes':
  424 + case 'mejoras':
  425 + //console.log(data);
  426 +
  427 + menus = ""
  428 +
  429 + break;
  430 + }
  431 + },
  432 + error:function(data){console.log('ndoikoi!', data);}
  433 + });
  434 + switch (mapa){
  435 + case 'sigem':
  436 + titulo = 'MAPA DE LOTES SIN FICHAS';
  437 + break;
  438 + case 'actualotes':
  439 + titulo = 'ACTUALIZACION DE LOTES';
  440 + break;
  441 + default:
  442 + titulo = 'MAPA DE '+ mapa;
  443 + break;
  444 + }
  445 +
  446 + if (mapa === 'zonas'){
  447 + shape_zonas = ""+
  448 + "<input type='checkbox' name='dob' class='regular-checkbox dob' value='a2a3' id='capazonastrib' />" +
  449 + "<label for='capazonastrib'></label><span>Zonas Tributarias</span>" +
  450 + "<br/>";
  451 + }else{
  452 + shape_zonas = "";
  453 + }
  454 +
  455 + //MENU DINAMICO
  456 + arraymenu = "" +
  457 + "<div id='div1' class='box box-primary text-center'>" +
  458 + "<h4 style='padding: 0; margin: 0; color: #275f7b;" +
  459 + "font-family: ProximaNovaBold, Helvetica, Arial, sans-serif;" +
  460 + "letter-spacing: 1px; font-size: 16px; display: inline-block;'>"+titulo.toUpperCase() + "</h4>"+
  461 + "<div class='box-tools pull-right'>"+
  462 + "<button type='button' class='btn btn-box-tool' data-widget='collapse'><i class='fa fa-minus'></i>"+"</button>"+
  463 + //"<button type='button' class='btn btn-box-tool' data-widget='remove'><i class='fa fa-times'></i>"+"</button>"+
  464 + "</div>"+
  465 + "<div class='box-body no-padding text-left'>"+
  466 + "<ul class='accordion'>" +
  467 + menus +
  468 + "</ul>" +
  469 + "</div>"+
  470 + "</div>";
  471 +
  472 + //CAPAS ADICIONALES
  473 + capas_adicionales = "" +
  474 + "<div id='capas_inner' class='box box-primary text-center ui'>" +
  475 + "<h4>CAPAS ADICIONALES</h4>"+
  476 + "<div class='box-tools pull-right'>"+
  477 + "<button type='button' class='btn btn-box-tool' data-widget='collapse'><i class='fa fa-minus'></i>"+"</button>"+
  478 + //"<button type='button' class='btn btn-box-tool' data-widget='remove'><i class='fa fa-times'></i>"+"</button>"+
  479 + "</div>"+
  480 + "<div class='box-body no-padding text-justify'>"+
  481 + "<input type='checkbox' name='dob' class='regular-checkbox dob' value='sinccc' id='sinccc'/>" +
  482 + "<label for='sinccc'></label><span>Lotes sin CCC</span>" +
  483 + "<br/>" +
  484 + "<input type='checkbox' name='dob' class='regular-checkbox dob' value='a1' id='manz' />" +
  485 + "<label for='manz'></label><span>Manzanas</span>" +
  486 + "<br/>" +
  487 + "<input type='checkbox' name='dob' class='regular-checkbox dob' value='a2a3' id='calle' />" +
  488 + "<label for='calle'></label><span>Calles</span>" +
  489 + "<br/>" +
  490 + shape_zonas +
  491 + "</div>"+
  492 + "</div>";
  493 +
  494 + //console.log(arraymenu);
  495 + $('#accordion').html("").html(arraymenu);
  496 + $('#capas_adicionales').append(capas_adicionales);
  497 + $('.toggle').click(function(e) {
  498 + e.preventDefault();
  499 +
  500 + var $this = $(this);
  501 +
  502 + if ($this.next().hasClass('show')) {
  503 + $this.next().removeClass('show');
  504 + $this.next().slideUp(150);
  505 + $('.carets').open();
  506 + } else {
  507 + $this.parent().parent().find('li .inner').removeClass('show');
  508 + $this.parent().parent().find('li .inner').slideUp(150);
  509 + $this.next().toggleClass('show');
  510 + }
  511 + });
  512 + }
  513 +
  514 + var initPage = function () {
  515 + switch (mapa){
  516 + case 'zonas':
  517 + //$('#contenido').html("").append("");
  518 + break;
  519 + }
  520 + }
  521 + // get it all going!
  522 + var init = function() {
  523 + initPage();
  524 + initMenu();
  525 + }
  526 +
  527 + return {init : init}
  528 + })();
  529 +
  530 +var mostrarLOTE = function (cartodb_id, ccc) {
  531 + $('#box2').show();
  532 + $('#tool-tip').hide();
  533 + $.ajax({
  534 + url: "api/callREAD.php",
  535 + type: "POST",
  536 + data: {cartodb_id: cartodb_id, type: 'lote', entidad: entidad},
  537 + dataType: 'json',
  538 + success: function (geojson) {
  539 + if (app.map.el.polygon) {app.map.el.map.removeLayer(app.map.el.polygon);}
  540 + //Trae el poligono por ajax
  541 + app.map.el.polygon = L.geoJson(geojson, {
  542 + style: {
  543 + color: "#000",
  544 + fillColor: "#edd711",
  545 + weight: 6,
  546 + opacity: 0.8,
  547 + fillOpacity: 0.2
  548 + }
  549 + });
  550 + //Fija los limites del mapa de cuardo al poligono
  551 + app.map.el.map.fitBounds(app.map.el.polygon.getBounds(), {maxZoom: 17});
  552 + //Agrega el poligono al mapa
  553 + app.map.el.polygon.addTo(app.map.el.map);
  554 + switch (mapa){
  555 + case 'morosidad':
  556 + var deuda_todal = ccc;
  557 + if (typeof impuesto !== "undefined") {
  558 + //console.log(entidad, impuesto, estado);
  559 + $.ajax
  560 + ({
  561 + url: 'login/get_liquidacion.php', //Se parsea el numero de ccc a fin de obtener los datos del lote
  562 + type: 'POST',
  563 + data: {ccc: deuda_todal, entidad: entidad, impuesto: impuesto, estado: estado},//parseo de ccc
  564 + dataType: "json", //text or html or json or script
  565 + success:function(data)
  566 + {
  567 + var largo = data.length;
  568 + //SE LIMPIA EL DIV DE RESULTADOS
  569 + $("#resumen").html("");
  570 + $("#toggle_resumen").html("");
  571 + $('#toggle_resumen').append('<a href="#" id="toggle_all" style="tex-alignment: left; padding-right: 3em" onclick="limpiar()">Mostrar Todos</a>');
  572 + $("#box").css({'opacity': '0.8'});
  573 + //TODO: aca podria haber sido overlowY en el "scroll" para contemplar solo el scroll vertical, preferi dejar ambos para que se "note que hay algo"
  574 + //console.log(largo);
  575 +
  576 + if (largo > 0){
  577 + // SE CREA EL INFORME POR LOTE
  578 + $('#resumen').append('' +
  579 + '<p style="text-align: center;color:black;font-size: 20px">Informe Catastral</p>' +
  580 + '<p style="color:black"><b>Lote: </b>'+ccc+' <b>Ficha:</b> '+data[0].inm_ficha+'</p>');
  581 + //SE CREA LA TABLA PARA EL RESUMEN
  582 + $("#resumen").append(
  583 + '<table id="resumen_table" class="table">'+
  584 + '<tr>'+
  585 + '<th>Ejercicio Fiscal</th>'+
  586 + '<th>Tributo</th>'+
  587 + '<th>Estado</th>'+
  588 + '<th>Importe</th>'+
  589 + '<th>Fecha de pago</th>'+
  590 + '</tr>');
  591 + //SE IMPRIMEN LOS DATOS DEL LOTE
  592 + var sum = 0;
  593 + $.each(data,function (i,item) {
  594 + switch (item.liq_estado){
  595 + case 'REG':
  596 + estadopago = 'PENDIENTE';
  597 + tiporesumen = 'ADEUDADO';
  598 + break;
  599 + case 'PAG':
  600 + tiporesumen = 'PAGADO';
  601 + estadopago = item.liq_fecpago;
  602 + break;
  603 + }
  604 + sum += parseInt(item.liq_importe_apagar);
  605 +
  606 + $('#resumen_table').append(
  607 + '<tr>' +
  608 + '<td>'+item.ejer_fisca+'</td>' +
  609 + '<td>'+item.trb_tributo+'</td>' +
  610 + '<td>'+item.liq_estado+'</td>' +
  611 + '<td>'+$.number(item.liq_importe_apagar,0,',','.')+'</td>' +
  612 + '<td>'+estadopago+'</td>' +
  613 + '</tr>'
  614 + );
  615 + //console.log(sum, item);
  616 + });
  617 + $('#resumen').append(
  618 + '</table><p style="text-align: left; font-size: 20px; color:black;">Total '+tiporesumen+': <b>'+ $.number(sum,0,',','.')+' Gs. </b></p>');
  619 + $('#toggle_resumen').append('<a href="#" id="toggle_msg" style="text-align: center; padding-right: 3em;" onclick="mostrarResumen()">Ocultar Resumen</a>');
  620 + $('#toggle_resumen').append('<input type="button" style="color: black" id="print_resumen" value="Imprimir Resumen" onclick="printDiv();">');
  621 + }else{
  622 + $("#resumen").html("");
  623 + $("#resumen").css({display: 'block', height: 'auto', overflow: ''});
  624 + $("#box2").css({display: 'block', height: 'auto'});
  625 + $('#resumen').append('<p style="text-align: center">No se encontraron Datos<p>');
  626 + }
  627 + },
  628 + error:function(data)
  629 + {
  630 + $('#resumen').append('<p style="text-align: center; font-size: 10px; color:black;">No se encontraron datos</p>')
  631 + }
  632 + });;
  633 + }else {
  634 + //alert("FAVOR ELIJA TIPO DE IMPUESTO!");
  635 + }
  636 + break;
  637 + }
  638 + //console.log(polygon.getBounds());
  639 + }
  640 + });
  641 +};
  642 +
  643 +//Buscador
  644 +$('#ctactastral').focus(function(){if ($(this).val()==="Ingrese Cta Catastral") {$(this).val("");}});
  645 +$('#ctactastral').on('blur',function(){if ($(this).val()!=="") {buscador();$(this).val("")}});
  646 +$(document).keyup(function (e) {if ($("#ctactastral:focus") && (e.keyCode === 13)) {buscador();$(this).val("")}});
  647 +
  648 +var buscador = function () {
  649 + var numficha = document.getElementById("ctactastral").value;
  650 + if (numficha === null || numficha === ''){alert('Favor ingrese datos!');$('#ctactastral').value('');
  651 + }else{
  652 + $.ajax({
  653 + url: "login/buscar.php", type: "POST", data: {lote: numficha, busqueda: 'lote'}, dataType: 'json',
  654 + success: function (data) {
  655 + busqueda = JSON.parse(data);
  656 + if (busqueda.total_rows === 0){
  657 + alert('NO SE ENCONTRARON DATOS!');
  658 + $('#ctactastral').val("");
  659 + }else{
  660 + cartoid = busqueda.rows[0].cartodb_id;mostrarLOTE(cartoid, numficha);
  661 + $('#ctactastral').val("");
  662 + }
  663 + }
  664 + })
  665 + }
  666 +
  667 +}
  668 +
  669 +//FIN FUNCIONES GLOBALES
  670 +
  671 +//URL yvyape
  672 +app.url = 'https://yvyape.yvaga.com.py/user/yvaga/api/v2/viz/'+basemap+'/viz.json';
  673 +
  674 +//QUERY's mapas
  675 +app.param = (
  676 + function(){
  677 + return {
  678 + //CAPAS EXTRA
  679 + manzanas: 'SELECT * FROM e'+entidad+'_manzanas',
  680 + calles : 'SELECT * FROM e'+entidad+'_calles',
  681 + lotesincc : 'SELECT * FROM e'+entidad+'_lotes_sinccc where borrado is not true',
  682 + capazonastrib : 'SELECT * from e'+entidad+'_zonas_tributarias',
  683 + /////////////////////////////
  684 + //BASE
  685 + all: 'SELECT * FROM e'+entidad+'_lotes_conccc',
  686 + /////////////////////////////
  687 + //MOROSIDAD
  688 + morosidadtodos : 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_liq_entidad_totalxobjeto on ccc = inm_ctacatastral',
  689 + morosidadRenSTab : 'SELECT * FROM e'+entidad+'_lotes_conccc',
  690 + morosidadVacant : "SELECT * FROM bushwick_pluto14v1 WHERE landuse = '11'",
  691 + /////////////////
  692 + //FRENTES/
  693 + frentetodos: 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  694 + frentepavimento: 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  695 + frentepavimentolb: 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'lb.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  696 + fplbresumen: 'SELECT b.inm_tpav, count(inm_tpav) as total FROM e'+entidad+'_lotes_conccc a left join sigem'+entidad+'lb.v_inmuebles_zona_pavimento b on ccc = inm_ctacatastral where b.inm_tpav is not null and b.inm_tpav <> \'\' GROUP BY b.inm_tpav',
  697 + ////////////////
  698 + //ZONAS
  699 + zonas : 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  700 + zonaslb : 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'lb.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  701 + zonastributarias: "SELECT *," +
  702 + " (coalesce(inm_tipo_ur, '0')" +
  703 + " || '-' || " +
  704 + " coalesce(inm_zona_tributaria, '0')" +
  705 + " || '-' || " +
  706 + "coalesce(sub_zona_rural,'0')) as zonas_tributarias " +
  707 + "FROM e"+entidad+"_lotes_conccc " +
  708 + "left join sigem"+entidad+".v_inmuebles_zona_pavimento " +
  709 + "on ccc = inm_ctacatastral",
  710 + zonastributariaslb: "SELECT *," +
  711 + " (coalesce(inm_tipo_ur, '0')" +
  712 + " || '-' || " +
  713 + " coalesce(inm_zona_tributaria, '0')" +
  714 + " || '-' || " +
  715 + "coalesce(sub_zona_rural,'0')) as zonas_tributarias " +
  716 + "FROM e"+entidad+"_lotes_conccc " +
  717 + "left join sigem"+entidad+"lb.v_inmuebles_zona_pavimento " +
  718 + "on ccc = inm_ctacatastral",
  719 + /////////////////////
  720 + ///NOTIFICACIONES////
  721 + notificaciones: 'SELECT * FROM e'+entidad+'_lotes_conccc LEFT JOIN sigem'+entidad+'.v_seguimiento_notificaciones ON ccc = obj_numero',
  722 + ////////////////////
  723 + ///MIGRACION////////
  724 + migracion: 'SELECT DISTINCT ON (actualizacion_proceso, obj_imponible_ficha) * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.actualizaciones on ccc = obj_imponible_id where obj_imponible_ficha is not null ORDER BY actualizacion_proceso, obj_imponible_ficha, fec_graba DESC NULLS LAST',
  725 + migraciontipo: 'SELECT DISTINCT ON (actualizacion_proceso, obj_imponible_ficha) * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.actualizaciones on ccc = obj_imponible_id where obj_imponible_ficha is not null ORDER BY actualizacion_proceso, obj_imponible_ficha, fec_graba DESC NULLS LAST',
  726 + ///////////////////////
  727 + ///RECOLECION BASURA///
  728 + recoleccion: 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  729 + lotes_recoleccion: 'select a.cartodb_id, a.ccc, a.ccc_guion, a.the_geom, a.the_geom_webmercator, b.ruta_id, b.name, b.ruta_descripcion from e'+entidad+'_lotes_conccc a, e'+entidad+'_cobertura_recoleccion b WHERE ST_DWithin(a.the_geom_webmercator, b.the_geom_webmercator, 20)',
  730 + ///////////////////////
  731 + ///ESTADO SIGEM////
  732 + sigem: 'SELECT * FROM e'+entidad+'_lotes_conccc left join sigem'+entidad+'.v_inmuebles_zona_pavimento on ccc = inm_ctacatastral',
  733 + estado_mejoras: 'SELECT * FROM e'+entidad+'_mejoras where borrado is not true',
  734 + estado_lotes: 'SELECT * FROM e'+entidad+'_lotes_conccc where borrado is not true'
  735 + };
  736 + }
  737 +)();
0 \ No newline at end of file 738 \ No newline at end of file
GIS-GEOSERVER/mapas.html 0 → 100644
  1 +++ a/GIS-GEOSERVER/mapas.html
  1 +<!DOCTYPE html>
  2 +<html lang="es">
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6 + <title>SIGEM GIS | Dashboard Institucional</title>
  7 + <!-- AdminLTE 3 & Bootstrap 4 -->
  8 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/3.2.0/css/adminlte.min.css">
  9 + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  10 + <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css">
  11 + <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
  12 +
  13 + <style>
  14 + body { font-family: 'Roboto', sans-serif; height: 100vh; background: #0b0e14; overflow: hidden; }
  15 + #map { position: absolute; top: 0; bottom: 0; left: 0; right: 0; }
  16 +
  17 + /* Tema Oscuro Personalizado */
  18 + .main-sidebar { background-color: #0f172a !important; width: 280px !important; }
  19 + .content-wrapper { background: transparent !important; }
  20 + .main-header { background-color: #0f172a !important; border-bottom: 1px solid #1e293b !important; }
  21 +
  22 + .nav-link p { color: #94a3b8; font-weight: 500; }
  23 + .nav-link.active { background-color: #3b82f6 !important; color: white !important; }
  24 + .nav-link.active p { color: white !important; }
  25 +
  26 + .info-box { background: #1e293b; color: white; border-radius: 8px; margin-bottom: 15px; border: 1px solid #334155; }
  27 + .info-box-text { color: #94a3b8; text-transform: uppercase; font-size: 0.7rem; font-weight: 700; }
  28 + .info-box-number { font-size: 1.2rem; color: #fff; }
  29 +
  30 + .map-section-title { color: #475569; font-size: 0.65rem; font-weight: 700; text-transform: uppercase; padding: 10px 15px; letter-spacing: 1px; }
  31 +
  32 + /* Widget Superior */
  33 + .top-widget { position: absolute; top: 15px; left: 50%; transform: translateX(-50%); background: rgba(15, 23, 42, 0.9); padding: 8px 25px; border-radius: 50px; border: 1px solid #334155; color: white; font-weight: 700; font-size: 0.85rem; z-index: 10; box-shadow: 0 4px 20px rgba(0,0,0,0.5); backdrop-filter: blur(5px); }
  34 +
  35 + /* Leyenda Inferior Derecha */
  36 + .legend-card { position: absolute; bottom: 30px; right: 20px; width: 220px; background: rgba(15, 23, 42, 0.9); border-radius: 12px; border: 1px solid #334155; padding: 15px; color: white; z-index: 10; box-shadow: 0 4px 20px rgba(0,0,0,0.5); display: none; }
  37 + .legend-title { font-size: 0.7rem; font-weight: 800; color: #3b82f6; text-transform: uppercase; margin-bottom: 10px; border-bottom: 1px solid #334155; padding-bottom: 5px; }
  38 + .legend-item { display: flex; align-items: center; margin-bottom: 4px; font-size: 0.75rem; color: #cbd5e1; }
  39 + .legend-color { width: 15px; height: 10px; border-radius: 2px; margin-right: 12px; }
  40 +
  41 + /* Estilo Botones Menú MVT/PNG */
  42 + .btn-map-mode { background: #1e293b; border: 1px solid #334155; border-radius: 6px; margin: 5px 15px; padding: 10px; cursor: pointer; transition: 0.3s; display: flex; align-items: center; color: #cbd5e1; font-size: 0.85rem; }
  43 + .btn-map-mode:hover { background: #334155; }
  44 + .btn-map-mode.active { background: #3b82f6; color: white; border-color: #60a5fa; box-shadow: 0 0 15px rgba(59, 130, 246, 0.4); }
  45 + .btn-map-mode i { margin-right: 12px; font-size: 1rem; }
  46 +
  47 + .btn-sync { background: rgba(34, 197, 94, 0.1); border: 1px dashed #22c55e; color: #22c55e; padding: 8px; margin: 15px; border-radius: 6px; cursor: pointer; font-size: 0.8rem; font-weight: 700; display: flex; justify-items: center; align-items: center; justify-content: center; }
  48 + .btn-sync:hover { background: #22c55e; color: white; }
  49 + </style>
  50 +</head>
  51 +<body class="hold-transition sidebar-mini layout-fixed">
  52 + <div class="wrapper">
  53 + <!-- Header -->
  54 + <nav class="main-header navbar navbar-expand navbar-dark">
  55 + <ul class="navbar-nav">
  56 + <li class="nav-item"><a class="nav-link" data-widget="pushmenu" href="#" role="button"><i class="fas fa-bars"></i></a></li>
  57 + <li class="nav-item d-none d-sm-inline-block">
  58 + <span class="nav-link text-white font-weight-bold">SIGEM GIS | <small class="text-gray">Bienvenido, OPERADOR SISTEMA</small></span>
  59 + </li>
  60 + </ul>
  61 + <ul class="navbar-nav ml-auto">
  62 + <li class="nav-item"><a href="login.html" class="btn btn-sm btn-outline-danger mr-3 font-weight-bold">Cerrar Sesión</a></li>
  63 + </ul>
  64 + </nav>
  65 +
  66 + <!-- Sidebar -->
  67 + <aside class="main-sidebar sidebar-dark-primary elevation-4">
  68 + <div class="sidebar">
  69 + <div class="user-panel mt-3 pb-3 mb-3 d-flex">
  70 + <div class="image"><i class="fas fa-globe-americas text-primary p-2"></i></div>
  71 + <div class="info"><a href="#" class="d-block font-weight-bold">SIGEM GIS</a></div>
  72 + </div>
  73 +
  74 + <div class="container-fluid px-3">
  75 + <div class="map-section-title">Resumen Municipal</div>
  76 + <div class="info-box shadow-none">
  77 + <div class="info-box-content">
  78 + <span class="info-box-text">Total Lotes</span>
  79 + <span class="info-box-number" id="val-total">-</span>
  80 + </div>
  81 + </div>
  82 + <div class="info-box shadow-none">
  83 + <div class="info-box-content">
  84 + <span class="info-box-text">Morosidad</span>
  85 + <span class="info-box-number text-danger" id="val-morosos">-</span>
  86 + </div>
  87 + </div>
  88 +
  89 + <div class="map-section-title">Control de Gestión</div>
  90 + <div class="btn-map-mode active" id="btn-base" onclick="setMapMode('base')">
  91 + <i class="fas fa-satellite"></i> Capas Base
  92 + </div>
  93 +
  94 + <div class="map-section-title">Mapas Tributarios</div>
  95 + <div class="btn-map-mode" id="btn-pago" onclick="setMapMode('pago')">
  96 + <i class="fas fa-calendar-alt"></i> Por Último Pago
  97 + </div>
  98 + <div class="btn-map-mode" id="btn-total" onclick="setMapMode('total')">
  99 + <i class="fas fa-chart-pie"></i> Por Total (Percentiles)
  100 + </div>
  101 + <div class="btn-map-mode" id="btn-png" onclick="setMapMode('png')">
  102 + <i class="fas fa-image text-warning"></i> Vista PNG (Full) <small class="ml-1 text-muted">[M]</small>
  103 + </div>
  104 +
  105 + <div class="map-section-title">Administración</div>
  106 + <div class="btn-sync" onclick="location.reload()">
  107 + <i class="fas fa-sync-alt mr-2"></i> Actualizar Datos MUNI
  108 + </div>
  109 + </div>
  110 + </div>
  111 + </aside>
  112 +
  113 + <!-- Main Content (Map) -->
  114 + <div class="content-wrapper">
  115 + <div id="map"></div>
  116 + <div class="top-widget" id="top-widget">📊 MOROSIDAD - ÚLTIMO ADEUDADO</div>
  117 +
  118 + <div class="legend-card" id="legend">
  119 + <div class="legend-title">Último Adeudado</div>
  120 + <div class="legend-item"><span class="legend-color" style="background:#71de75;"></span> 🟢 <= 2026</div>
  121 + <div class="legend-item"><span class="legend-color" style="background:#bef264;"></span> 🎾 <= 2025</div>
  122 + <div class="legend-item"><span class="legend-color" style="background:#ffaa00;"></span> 🟡 <= 2024</div>
  123 + <div class="legend-item"><span class="legend-color" style="background:#fb923c;"></span> 🟠 <= 2023</div>
  124 + <div class="legend-item"><span class="legend-color" style="background:#f87171;"></span> 🔴 <= 2022</div>
  125 + <div class="legend-item"><span class="legend-color" style="background:#e11d48;"></span> 📢 <= 2021</div>
  126 + <div class="legend-item"><span class="legend-color" style="background:#475569;"></span> 🔘 SIN DEUDA / PRESCRIPTAS</div>
  127 + <div class="mt-2 pt-2 border-top border-secondary text-muted" style="font-size:0.6rem">Fuente: Sistema SIGEM</div>
  128 + </div>
  129 + </div>
  130 + </div>
  131 +
  132 + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  133 + <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.1/js/bootstrap.bundle.min.js"></script>
  134 + <script src="https://cdnjs.cloudflare.com/ajax/libs/admin-lte/3.2.0/js/adminlte.min.js"></script>
  135 + <script src="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js"></script>
  136 +
  137 + <script>
  138 + const entidad = localStorage.getItem('entidad') || '505';
  139 + const contextPath = '/gis-geoserver';
  140 + let map;
  141 +
  142 + async function init() {
  143 + try {
  144 + const r = await fetch(`${contextPath}/api/gis/entidad/${entidad}`);
  145 + const data = await r.json();
  146 + const res = await fetch(`${contextPath}/api/gis/entidad/${entidad}/resumen`);
  147 + const stats = await res.json();
  148 +
  149 + document.getElementById('val-total').textContent = stats.total_lotes.toLocaleString();
  150 + document.getElementById('val-morosos').textContent = stats.lotes_con_deuda.toLocaleString();
  151 +
  152 + const center = data.latlong.split(',').map(Number);
  153 +
  154 + map = new maplibregl.Map({
  155 + container: 'map',
  156 + style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
  157 + center: [center[1], center[0]],
  158 + zoom: parseInt(data.zoom) || 15,
  159 + pitch: 0,
  160 + bearing: 0,
  161 + dragRotate: false
  162 + });
  163 +
  164 + map.on('load', () => {
  165 + // Fuente Vectorial (MVT) compatible con Regla 23
  166 + map.addSource('lotes-mvt', {
  167 + type: 'vector',
  168 + tiles: [ `${window.location.origin}${contextPath}/geoserver/gwc/service/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&LAYER=sigem:vw_lotes_morosidad_${entidad}&STYLE=&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&FORMAT=application/x-protobuf` ],
  169 + scheme: 'xyz'
  170 + });
  171 +
  172 + map.addLayer({
  173 + id: 'lotes-layer',
  174 + type: 'line',
  175 + source: 'lotes-mvt',
  176 + 'source-layer': `vw_lotes_morosidad_${entidad}`,
  177 + paint: { 'line-color': '#475569', 'line-width': 0.8 }
  178 + });
  179 +
  180 + // Fuente PNG (WMS) - Alineada a Regla 5 (EPSG:4326)
  181 + map.addSource('lotes-wms', {
  182 + type: 'raster',
  183 + tiles: [ `${window.location.origin}${contextPath}/geoserver/wms?service=WMS&version=1.1.1&request=GetMap&layers=sigem:vw_lotes_wms_${entidad}&bbox={bbox-epsg-4326}&width=256&height=256&srs=EPSG:4326&styles=morosidad_style_wms&format=image/png&transparent=true` ],
  184 + tileSize: 256
  185 + });
  186 +
  187 + map.addLayer({
  188 + id: 'lotes-color-wms',
  189 + type: 'raster',
  190 + source: 'lotes-wms',
  191 + paint: { 'raster-opacity': 0 }
  192 + }, 'lotes-layer');
  193 + });
  194 +
  195 + map.on('click', 'lotes-layer', (e) => {
  196 + const p = e.features[0].properties;
  197 + const content = `<div class="p-2"><b class="text-primary">CCC: ${p.ccc || 'N/A'}</b><hr class="my-1">Deuda: Gs. ${Number(p.trb_total_deuda || 0).toLocaleString()}<br>Último Pago: ${p.ultimo_pago || 'Nunca'}</div>`;
  198 + new maplibregl.Popup().setLngLat(e.lngLat).setHTML(content).addTo(map);
  199 + });
  200 +
  201 + } catch (e) {
  202 + console.error("Error cargando dashboard:", e);
  203 + // Si hay 503, re-intentar en 5s
  204 + setTimeout(init, 5000);
  205 + }
  206 + }
  207 +
  208 + function setMapMode(mode) {
  209 + $('.btn-map-mode').removeClass('active');
  210 + const legend = document.getElementById('legend');
  211 + const topWidget = document.getElementById('top-widget');
  212 +
  213 + if (mode === 'base' || mode === 'general') {
  214 + $('#btn-base').addClass('active');
  215 + map.setPaintProperty('lotes-color-wms', 'raster-opacity', 0);
  216 + legend.style.display = 'none';
  217 + topWidget.style.display = 'none';
  218 + } else {
  219 + $(`#btn-${mode}`).addClass('active');
  220 + map.setPaintProperty('lotes-color-wms', 'raster-opacity', 0.8);
  221 + legend.style.display = 'block';
  222 + topWidget.style.display = 'block';
  223 + }
  224 + }
  225 +
  226 + init();
  227 + </script>
  228 +</body>
  229 +</html>
GIS-GEOSERVER/mapas_legacy.html 0 → 100644
  1 +++ a/GIS-GEOSERVER/mapas_legacy.html
  1 +<!DOCTYPE html>
  2 +<html lang="es">
  3 +
  4 +<head>
  5 + <meta charset="UTF-8">
  6 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7 + <title>SISTEMA GIS - MapLibre 3D Elite</title>
  8 + <script>
  9 + if (!localStorage.getItem('jwt')) {
  10 + window.location.href = '/gis-geoserver/login';
  11 + }
  12 + </script>
  13 + <!-- MapLibre GL JS -->
  14 + <script src="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js"></script>
  15 + <link href="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css" rel="stylesheet" />
  16 + <style>
  17 + body,
  18 + html {
  19 + height: 100%;
  20 + margin: 0;
  21 + font-family: 'Inter', Arial, sans-serif;
  22 + background-color: #0f172a;
  23 + color: #fff;
  24 + overflow: hidden;
  25 + }
  26 +
  27 + .header {
  28 + height: 60px;
  29 + background: #1e293b;
  30 + display: flex;
  31 + align-items: center;
  32 + padding: 0 20px;
  33 + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
  34 + font-weight: bold;
  35 + justify-content: space-between;
  36 + position: relative;
  37 + z-index: 1001;
  38 + }
  39 +
  40 + .logout-btn {
  41 + background: rgba(255, 255, 255, 0.1);
  42 + border: 1px solid rgba(255, 255, 255, 0.3);
  43 + color: white;
  44 + padding: 8px 16px;
  45 + border-radius: 8px;
  46 + cursor: pointer;
  47 + transition: all 0.2s;
  48 + }
  49 +
  50 + .logout-btn:hover {
  51 + background: #ef4444;
  52 + border-color: #ef4444;
  53 + }
  54 +
  55 + .app-container {
  56 + display: flex;
  57 + height: calc(100vh - 60px);
  58 + }
  59 +
  60 + .sidebar {
  61 + width: 340px;
  62 + background: #0f172a;
  63 + border-right: 1px solid rgba(255, 255, 255, 0.1);
  64 + overflow-y: auto;
  65 + padding: 20px;
  66 + flex-shrink: 0;
  67 + }
  68 +
  69 + .menu-title {
  70 + font-size: 11px;
  71 + color: #64748b;
  72 + font-weight: 700;
  73 + text-transform: uppercase;
  74 + margin: 25px 0 10px;
  75 + letter-spacing: 1px;
  76 + }
  77 +
  78 + .menu-item {
  79 + padding: 12px 16px;
  80 + border-radius: 10px;
  81 + cursor: pointer;
  82 + display: flex;
  83 + align-items: center;
  84 + gap: 12px;
  85 + color: #94a3b8;
  86 + transition: all 0.2s;
  87 + margin-bottom: 4px;
  88 + border: 1px solid transparent;
  89 + text-decoration: none;
  90 + }
  91 +
  92 + .menu-item:hover {
  93 + background: rgba(255, 255, 255, 0.05);
  94 + color: #fff;
  95 + }
  96 +
  97 + .menu-item.active {
  98 + background: rgba(59, 130, 246, 0.1);
  99 + color: #3b82f6;
  100 + border-color: rgba(59, 130, 246, 0.3);
  101 + }
  102 +
  103 + .submenu {
  104 + padding-left: 10px;
  105 + margin-bottom: 15px;
  106 + }
  107 +
  108 + #map {
  109 + flex: 1;
  110 + position: relative;
  111 + }
  112 +
  113 + /* Stats Dashboard Overlay */
  114 + .stats-grid {
  115 + display: grid;
  116 + grid-template-columns: 1fr 1fr;
  117 + gap: 10px;
  118 + margin-bottom: 20px;
  119 + }
  120 +
  121 + .stat-card {
  122 + background: rgba(255, 255, 255, 0.03);
  123 + padding: 15px;
  124 + border-radius: 12px;
  125 + border: 1px solid rgba(255, 255, 255, 0.05);
  126 + }
  127 +
  128 + .stat-label {
  129 + font-size: 11px;
  130 + color: #64748b;
  131 + text-transform: uppercase;
  132 + font-weight: 600;
  133 + }
  134 +
  135 + .stat-value {
  136 + font-size: 18px;
  137 + font-weight: 700;
  138 + color: #fff;
  139 + margin-top: 5px;
  140 + }
  141 +
  142 + /* Map Title Overlay */
  143 + .map-title-overlay {
  144 + position: absolute;
  145 + top: 20px;
  146 + left: 50%;
  147 + transform: translateX(-50%);
  148 + background: rgba(15, 23, 42, 0.9);
  149 + padding: 8px 24px;
  150 + border-radius: 50px;
  151 + border: 1px solid rgba(255, 255, 255, 0.1);
  152 + color: #fff;
  153 + font-weight: 700;
  154 + font-size: 13px;
  155 + z-index: 1000;
  156 + backdrop-filter: blur(8px);
  157 + text-transform: uppercase;
  158 + letter-spacing: 1px;
  159 + }
  160 +
  161 + /* Toggle 3D Control */
  162 + .map-controls-floating {
  163 + position: absolute;
  164 + top: 20px;
  165 + right: 20px;
  166 + z-index: 1000;
  167 + display: flex;
  168 + flex-direction: column;
  169 + gap: 10px;
  170 + }
  171 +
  172 + .map-btn {
  173 + background: rgba(15, 23, 42, 0.9);
  174 + border: 1px solid rgba(255, 255, 255, 0.1);
  175 + color: white;
  176 + padding: 10px;
  177 + border-radius: 10px;
  178 + cursor: pointer;
  179 + backdrop-filter: blur(8px);
  180 + display: flex;
  181 + align-items: center;
  182 + gap: 8px;
  183 + font-weight: 600;
  184 + font-size: 12px;
  185 + transition: all 0.2s;
  186 + }
  187 +
  188 + .map-btn:hover {
  189 + background: #1e293b;
  190 + border-color: #3b82f6;
  191 + }
  192 +
  193 + .map-btn.active {
  194 + background: #3b82f6;
  195 + border-color: #3b82f6;
  196 + }
  197 +
  198 + /* Legend */
  199 + .legend {
  200 + position: absolute;
  201 + bottom: 30px;
  202 + right: 30px;
  203 + background: rgba(15, 23, 42, 0.9);
  204 + padding: 15px;
  205 + border-radius: 12px;
  206 + border: 1px solid rgba(255, 255, 255, 0.1);
  207 + backdrop-filter: blur(10px);
  208 + color: white;
  209 + font-size: 12px;
  210 + z-index: 1000;
  211 + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
  212 + display: none;
  213 + }
  214 +
  215 + .legend-item {
  216 + display: flex;
  217 + align-items: center;
  218 + gap: 8px;
  219 + margin-bottom: 5px;
  220 + }
  221 +
  222 + .legend-color {
  223 + width: 12px;
  224 + height: 12px;
  225 + border-radius: 3px;
  226 + }
  227 +
  228 + /* Custom Popup Style */
  229 + .maplibregl-popup-content {
  230 + background: #1e293b;
  231 + color: white;
  232 + border-radius: 12px;
  233 + padding: 0;
  234 + border: 1px solid rgba(255, 255, 255, 0.1);
  235 + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  236 + }
  237 +
  238 + .maplibregl-popup-tip {
  239 + border-top-color: #1e293b;
  240 + }
  241 +
  242 + .popup-header {
  243 + background: #3b82f6;
  244 + padding: 12px;
  245 + border-radius: 10px 10px 0 0;
  246 + font-weight: 700;
  247 + font-size: 13px;
  248 + text-transform: uppercase;
  249 + }
  250 +
  251 + .popup-body {
  252 + padding: 15px;
  253 + }
  254 +
  255 + .popup-stat {
  256 + margin-bottom: 10px;
  257 + }
  258 +
  259 + .popup-label {
  260 + font-size: 10px;
  261 + color: #64748b;
  262 + text-transform: uppercase;
  263 + }
  264 +
  265 + .popup-value {
  266 + font-size: 13px;
  267 + font-weight: 600;
  268 + }
  269 +
  270 + /* Leyenda de morosidad con Glassmorphism */
  271 + .map-legend {
  272 + position: absolute;
  273 + bottom: 30px;
  274 + right: 20px;
  275 + background: rgba(15, 23, 42, 0.85);
  276 + padding: 18px;
  277 + border-radius: 16px;
  278 + border: 1px solid rgba(255, 255, 255, 0.1);
  279 + color: #f1f5f9;
  280 + font-size: 11px;
  281 + z-index: 1000;
  282 + backdrop-filter: blur(12px);
  283 + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
  284 + max-width: 240px;
  285 + }
  286 +
  287 + .legend-item {
  288 + display: flex;
  289 + align-items: center;
  290 + margin-bottom: 8px;
  291 + gap: 10px;
  292 + }
  293 +
  294 + .legend-color {
  295 + width: 30px;
  296 + height: 12px;
  297 + border-radius: 4px;
  298 + border: 1px solid rgba(255, 255, 255, 0.1);
  299 + }
  300 +
  301 + /* Capas Switcher */
  302 + .layer-switcher {
  303 + position: absolute;
  304 + top: 20px;
  305 + right: 50px;
  306 + background: rgba(13, 17, 23, 0.9);
  307 + padding: 10px;
  308 + border-radius: 8px;
  309 + border: 1px solid rgba(255, 255, 255, 0.1);
  310 + z-index: 10;
  311 + }
  312 + </style>
  313 +</head>
  314 +
  315 +<body>
  316 + <div class="header">
  317 + <div>🌍 SIGEM GIS <span id="user-greeting"
  318 + style="font-size: 13px; font-weight: normal; margin-left: 10px; opacity: 0.7;"></span></div>
  319 + <button class="logout-btn" onclick="logout()">Cerrar Sesión</button>
  320 + </div>
  321 + <div class="app-container">
  322 + <div class="sidebar">
  323 + <div id="stats-dashboard">
  324 + <div class="menu-title">Resumen Municipal</div>
  325 + <div class="stats-grid">
  326 + <div class="stat-card">
  327 + <div class="stat-label">Total Lotes</div>
  328 + <div id="stat-lotes" class="stat-value">...</div>
  329 + </div>
  330 + <div class="stat-card">
  331 + <div class="stat-label">Morosidad</div>
  332 + <div id="stat-morosos" class="stat-value" style="color: #f87171;">...</div>
  333 + </div>
  334 + </div>
  335 + </div>
  336 +
  337 + <div class="menu-title">Control de Gestión</div>
  338 + <div id="menu-reset" class="menu-item active" onclick="resetMap()">🌍 Capas Base</div>
  339 +
  340 + <div class="menu-title">Mapas Tributarios</div>
  341 + <div class="submenu">
  342 + <div id="menu-ultimo-pago" class="menu-item" onclick="setHeatmap('ultimo-pago')">📅 Por Último Pago
  343 + </div>
  344 + <div id="menu-percentiles" class="menu-item" onclick="setHeatmap('percentiles')">📈 Por Total
  345 + (Percentiles)</div>
  346 + <div id="menu-wms-test" class="menu-item" onclick="toggleWmsLayer()"
  347 + style="color: #fbbf24; border-top: 1px dashed #444; margin-top: 5px; font-weight: bold; display: none;">
  348 + 🖼️ Vista PNG (Full) <span id="wms-status" style="font-size: 9px; opacity: 0.6;">[OFF]</span>
  349 + </div>
  350 + </div>
  351 +
  352 + <div class="menu-title">Administración</div>
  353 + <div id="btn-update-data" class="menu-item" onclick="updateMunicipalData()" style="color: #60a5fa;">
  354 + <span id="update-icon">🔄</span> <span id="update-text">Actualizar Datos MUNI</span>
  355 + </div>
  356 +
  357 + </div>
  358 +
  359 + <div id="map">
  360 + <!-- Leyenda Dinámica -->
  361 + <div class="map-legend" id="legend" style="display: none;">
  362 + <div id="legend-content"></div>
  363 + <div
  364 + style="font-size: 10px; margin-top: 10px; border-top: 1px solid #333; padding-top: 5px; color: #888;">
  365 + Fuente: Sistema SIGEM</div>
  366 + </div>
  367 +
  368 + <!-- Selector de Capas Base -->
  369 + <div class="layer-switcher" style="position: absolute; top: 15px; left: 15px; z-index: 1000;">
  370 + <select id="base-layer-select"
  371 + style="background: rgba(15, 23, 42, 0.9); color: white; border: 1px solid rgba(255,255,255,0.2); padding: 5px 10px; border-radius: 8px; font-size: 11px; cursor: pointer; backdrop-filter: blur(8px);">
  372 + <option value="dark">🌙 CartoDB Dark</option>
  373 + <option value="streets">🗺️ OpenStreetMap</option>
  374 + <option value="satellite">📡 Esri Satélite</option>
  375 + </select>
  376 + </div>
  377 + <div id="map-title" class="map-title-overlay">Vista Cartográfica General</div>
  378 + </div>
  379 + </div>
  380 +
  381 + <script>
  382 + const userName = localStorage.getItem('user_name');
  383 + if (userName) document.getElementById('user-greeting').innerText = `| Bienvenido, ${userName}`;
  384 +
  385 + const entidad = localStorage.getItem('entidad') || '505';
  386 + const token = localStorage.getItem('jwt');
  387 + const geoserverBase = 'gwc/service/wmts';
  388 +
  389 + function logout() {
  390 + localStorage.clear();
  391 + window.location.href = '/gis-geoserver/login';
  392 + }
  393 +
  394 + // --- Inicialización del Mapa ---
  395 + const lat = parseFloat(localStorage.getItem('map_lat')) || -25.449;
  396 + const lng = parseFloat(localStorage.getItem('map_lng')) || -56.443;
  397 + const zoom = parseInt(localStorage.getItem('map_zoom')) || 15;
  398 +
  399 + const map = new maplibregl.Map({
  400 + container: 'map',
  401 + style: {
  402 + version: 8,
  403 + sources: {
  404 + 'raster-tiles': {
  405 + type: 'raster',
  406 + tiles: ['https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png'],
  407 + tileSize: 256,
  408 + attribution: '&copy; CartoDB'
  409 + }
  410 + },
  411 + layers: [{
  412 + id: 'basemap',
  413 + type: 'raster',
  414 + source: 'raster-tiles',
  415 + minzoom: 0,
  416 + maxzoom: 20
  417 + }]
  418 + },
  419 + center: [lng, lat],
  420 + zoom: zoom,
  421 + pitch: 0,
  422 + bearing: 0,
  423 + antialias: true
  424 + });
  425 +
  426 + map.addControl(new maplibregl.NavigationControl({ position: 'bottom-left' }));
  427 +
  428 + // --- Carga de Capas Vectoriales ---
  429 + map.on('load', () => {
  430 + initGisSources();
  431 + loadMunicipalStats();
  432 + });
  433 +
  434 + function initGisSources() {
  435 + console.log("Cargando fuentes vectoriales (MVT)...");
  436 +
  437 + // Fuente de Lotes (MVT) - TMS Nativo de GeoServer
  438 + if (!map.getSource('lotes-mvt')) {
  439 + map.addSource('lotes-mvt', {
  440 + type: 'vector',
  441 + tiles: [
  442 + `${window.location.origin}/gis-geoserver/gwc/service/tms/1.0.0/sigem:vw_lotes_morosidad_${entidad}@XYZ-900913@pbf/{z}/{x}/{y}.pbf`
  443 + ],
  444 + scheme: 'tms'
  445 + });
  446 + }
  447 +
  448 + // Capa de Lotes (2D) - Visibilidad Inicial Mejorada
  449 + if (!map.getLayer('lotes-layer')) {
  450 + map.addLayer({
  451 + id: 'lotes-layer',
  452 + type: 'fill',
  453 + source: 'lotes-mvt',
  454 + 'source-layer': `vw_lotes_morosidad_${entidad}`,
  455 + paint: {
  456 + 'fill-color': 'rgba(59, 130, 246, 0.1)', // Azul tenue inicial
  457 + 'fill-outline-color': 'rgba(255, 255, 255, 0.3)' // Borde blanco visible
  458 + }
  459 + });
  460 + }
  461 +
  462 + // Fuente de Mejoras (MVT) - TMS Nativo de GeoServer
  463 + if (!map.getSource('mejoras-mvt')) {
  464 + map.addSource('mejoras-mvt', {
  465 + type: 'vector',
  466 + tiles: [
  467 + `${window.location.origin}/gis-geoserver/gwc/service/tms/1.0.0/sigem:e${entidad}_mejoras@XYZ-900913@pbf/{z}/{x}/{y}.pbf`
  468 + ],
  469 + scheme: 'tms'
  470 + });
  471 + }
  472 +
  473 + // [PRUEBA CONTROLADA] Fuente Raster WMS (Renderizado en Servidor)
  474 + if (!map.getSource('lotes-wms')) {
  475 + map.addSource('lotes-wms', {
  476 + 'type': 'raster',
  477 + 'tiles': [
  478 + `${window.location.origin}/gis-geoserver/sigem/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=sigem:vw_lotes_morosidad_${entidad}&STYLES=morosidad_style_wms&FORMAT=image/png&TRANSPARENT=TRUE&WIDTH=256&HEIGHT=256&SRS=EPSG:3857&BBOX={bbox-epsg-3857}`
  479 + ],
  480 + 'tileSize': 256
  481 + });
  482 + }
  483 +
  484 + if (!map.getLayer('lotes-wms-layer')) {
  485 + map.addLayer({
  486 + 'id': 'lotes-wms-layer',
  487 + 'type': 'raster',
  488 + 'source': 'lotes-wms',
  489 + 'paint': { 'raster-opacity': 0.8 },
  490 + 'layout': { 'visibility': 'none' }
  491 + }); // Agregamos al final
  492 + }
  493 +
  494 + // Capa de Mejoras (Inicialmente oculta o 2D)
  495 + if (!map.getLayer('mejoras-layer')) {
  496 + map.addLayer({
  497 + id: 'mejoras-layer',
  498 + type: 'fill',
  499 + source: 'mejoras-mvt',
  500 + 'source-layer': `e${entidad}_mejoras`,
  501 + paint: {
  502 + 'fill-color': 'rgba(59, 130, 246, 0.2)',
  503 + 'fill-outline-color': 'rgba(59, 130, 246, 0.5)'
  504 + }
  505 + });
  506 + }
  507 + }
  508 +
  509 + // --- Lógica de Capas Base ---
  510 + const baseLayers = {
  511 + 'dark': 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
  512 + 'streets': 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
  513 + 'satellite': {
  514 + 'version': 8,
  515 + 'sources': {
  516 + 'raster-tiles': {
  517 + 'type': 'raster',
  518 + 'tiles': ['https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'],
  519 + 'tileSize': 256,
  520 + 'attribution': 'Tiles &copy; Esri'
  521 + }
  522 + },
  523 + 'layers': [{ 'id': 'simple-tiles', 'type': 'raster', 'source': 'raster-tiles', 'minzoom': 0, 'maxzoom': 18 }]
  524 + }
  525 + };
  526 +
  527 + document.getElementById('base-layer-select').addEventListener('change', (e) => {
  528 + const style = baseLayers[e.target.value];
  529 + map.setStyle(style);
  530 + map.once('style.load', () => {
  531 + initGisSources();
  532 + });
  533 + });
  534 +
  535 + // Lógica de 3D eliminada por requerimiento de usuario
  536 +
  537 +
  538 + // --- Mapa de Calor (Heatmap) via Expresiones ---
  539 + function setHeatmap(type) {
  540 + document.querySelectorAll('.menu-item').forEach(el => el.classList.remove('active'));
  541 + const titleEl = document.getElementById('map-title');
  542 + const legendEl = document.getElementById('legend');
  543 + const legendContent = document.getElementById('legend-content');
  544 + legendEl.style.display = 'block';
  545 +
  546 + if (type === 'ultimo-pago') {
  547 + document.getElementById('menu-ultimo-pago').classList.add('active');
  548 + titleEl.textContent = '🗺️ Morosidad - Último Adeudado';
  549 + map.setLayoutProperty('lotes-layer', 'visibility', 'visible');
  550 +
  551 + // Mostrar botón de prueba WMS solo en este modo
  552 + document.getElementById('menu-wms-test').style.display = 'block';
  553 +
  554 + legendContent.innerHTML = `
  555 + <strong style="color: #60a5fa;">ÚLTIMO ADEUDADO</strong><br><br>
  556 + <div class="legend-item"><div class="legend-color" style="background: #6b9070;"></div> = 2026</div>
  557 + <div class="legend-item"><div class="legend-color" style="background: #b5c47a;"></div> <= 2025</div>
  558 + <div class="legend-item"><div class="legend-color" style="background: #ffd966;"></div> <= 2024</div>
  559 + <div class="legend-item"><div class="legend-color" style="background: #f08060;"></div> <= 2023</div>
  560 + <div class="legend-item"><div class="legend-color" style="background: #d05660;"></div> <= 2022</div>
  561 + <div class="legend-item"><div class="legend-color" style="background: #a91d1d;"></div> <= 2021</div>
  562 + <div class="legend-item"><div class="legend-color" style="background: #64748b;"></div> SIN DEUDA / PRESCRIPTAS</div>
  563 + `;
  564 +
  565 + map.setPaintProperty('lotes-layer', 'fill-color', [
  566 + 'step',
  567 + ['get', 'ultimo_pago'],
  568 + '#a91d1d', // < 2021
  569 + 2021, '#a91d1d',
  570 + 2022, '#d05660',
  571 + 2023, '#f08060',
  572 + 2024, '#ffd966',
  573 + 2025, '#b5c47a',
  574 + 2026, '#6b9070'
  575 + ]);
  576 + } else if (type === 'percentiles') {
  577 + document.getElementById('menu-percentiles').classList.add('active');
  578 + titleEl.textContent = '🗺️ Morosidad - Total Adeudado';
  579 + map.setLayoutProperty('lotes-layer', 'visibility', 'visible');
  580 +
  581 + // Ocultar botón de prueba WMS
  582 + document.getElementById('menu-wms-test').style.display = 'none';
  583 +
  584 + legendContent.innerHTML = `
  585 + <strong style="color: #60a5fa;">TOTAL ADEUDADO</strong><br><br>
  586 + <div class="legend-item"><div class="legend-color" style="background: #a91d1d;"></div> > 2.099.321 Gs</div>
  587 + <div class="legend-item"><div class="legend-color" style="background: #f08060;"></div> <= 2.099.321 Gs</div>
  588 + <div class="legend-item"><div class="legend-color" style="background: #ffd966;"></div> <= 1.226.945 Gs</div>
  589 + <div class="legend-item"><div class="legend-color" style="background: #b5c47a;"></div> <= 714.968 Gs</div>
  590 + <div class="legend-item"><div class="legend-color" style="background: #6b9070;"></div> <= 351.584 Gs</div>
  591 + <div class="legend-item"><div class="legend-color" style="background: #64748b;"></div> NO REGISTRADOS</div>
  592 + `;
  593 +
  594 + map.setPaintProperty('lotes-layer', 'fill-color', [
  595 + 'step',
  596 + ['get', 'trb_total_deuda'],
  597 + '#6b9070', // < 351k
  598 + 351585, '#b5c47a',
  599 + 714969, '#ffd966',
  600 + 1226946, '#f08060',
  601 + 2099322, '#a91d1d'
  602 + ]);
  603 + }
  604 + // Aseguramos que el borde sea visible en modo heatmap
  605 + map.setPaintProperty('lotes-layer', 'fill-outline-color', 'rgba(255, 255, 255, 0.4)');
  606 + }
  607 +
  608 + function resetMap() {
  609 + document.querySelectorAll('.menu-item').forEach(el => el.classList.remove('active'));
  610 + document.getElementById('menu-reset').classList.add('active');
  611 + document.getElementById('map-title').textContent = 'Vista Cartográfica General';
  612 + document.getElementById('legend').style.display = 'none';
  613 + map.setPaintProperty('lotes-layer', 'fill-color', 'rgba(255, 255, 255, 0.05)');
  614 +
  615 + // Ocultamos WMS si está activo al resetear
  616 + if(map.getLayer('lotes-wms-layer')) {
  617 + map.setLayoutProperty('lotes-wms-layer', 'visibility', 'none');
  618 + document.getElementById('wms-status').innerText = '[OFF]';
  619 + document.getElementById('menu-wms-test').classList.remove('active');
  620 + }
  621 + // Ocultar botón de prueba WMS al resetear
  622 + document.getElementById('menu-wms-test').style.display = 'none';
  623 + }
  624 +
  625 + // --- Control de Prueba Controlada WMS ---
  626 + function toggleWmsLayer() {
  627 + const entidad = localStorage.getItem('entidad') || '505';
  628 +
  629 + // Si la capa no existe, la creamos
  630 + if (!map.getSource('lotes-wms')) {
  631 + map.addSource('lotes-wms', {
  632 + 'type': 'raster',
  633 + 'tiles': [
  634 + `${window.location.origin}/gis-geoserver/sigem/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&LAYERS=sigem:vw_lotes_morosidad_${entidad}&STYLES=morosidad_style_wms&FORMAT=image/png&TRANSPARENT=TRUE&WIDTH=256&HEIGHT=256&SRS=EPSG:3857&BBOX={bbox-epsg-3857}`
  635 + ],
  636 + 'tileSize': 256
  637 + });
  638 +
  639 + map.addLayer({
  640 + 'id': 'lotes-wms-layer',
  641 + 'type': 'raster',
  642 + 'source': 'lotes-wms',
  643 + 'layout': { 'visibility': 'none' },
  644 + 'paint': { 'raster-opacity': 0.8 }
  645 + }, 'lotes-layer'); // Debajo de la capa de interacción MVT
  646 + }
  647 +
  648 + const isVisible = map.getLayoutProperty('lotes-wms-layer', 'visibility') === 'visible';
  649 + const nextVisibility = isVisible ? 'none' : 'visible';
  650 + const statusEl = document.getElementById('wms-status');
  651 + const menuEl = document.getElementById('menu-wms-test');
  652 +
  653 + map.setLayoutProperty('lotes-wms-layer', 'visibility', nextVisibility);
  654 +
  655 + if (nextVisibility === 'visible') {
  656 + statusEl.innerText = '[ON]';
  657 + menuEl.classList.add('active');
  658 + // Opcional: Ocultar MVT para mejor rendimiento visual en PNG Full
  659 + // map.setLayoutProperty('lotes-layer', 'visibility', 'none');
  660 + } else {
  661 + statusEl.innerText = '[OFF]';
  662 + menuEl.classList.remove('active');
  663 + map.setLayoutProperty('lotes-layer', 'visibility', 'visible');
  664 + }
  665 + }
  666 +
  667 + // --- Popups Instantáneos (MVT Data) ---
  668 + map.on('click', 'lotes-layer', (e) => {
  669 + const props = e.features[0].properties;
  670 + const content = `
  671 + <div class="popup-header">ESTADO DE CUENTA: ${props.ccc || 'N/A'}</div>
  672 + <div class="popup-body">
  673 + <div class="popup-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
  674 + <div class="popup-stat">
  675 + <div class="popup-label">Nro Ficha</div>
  676 + <div class="popup-value">${props.inm_ficha || '0'}</div>
  677 + </div>
  678 + <div class="popup-stat">
  679 + <div class="popup-label">Cta. Catastral</div>
  680 + <div class="popup-value" style="font-size: 11px;">${props.inm_ctacatastral || 'N/A'}</div>
  681 + </div>
  682 + </div>
  683 + <hr style="opacity: 0.1; margin: 10px 0;">
  684 + <div class="popup-stat">
  685 + <div class="popup-label">Total Adeudado</div>
  686 + <div class="popup-value" style="color: #f87171; font-size: 16px;">Gs. ${props.trb_total_deuda ? parseFloat(props.trb_total_deuda).toLocaleString('es-PY') : '0'}</div>
  687 + </div>
  688 + <div class="popup-grid" style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 10px;">
  689 + <div class="popup-stat">
  690 + <div class="popup-label">Total Pagado</div>
  691 + <div class="popup-value" style="color: #10b981;">Gs. ${props.trb_total_pago ? parseFloat(props.trb_total_pago).toLocaleString('es-PY') : '0'}</div>
  692 + </div>
  693 + <div class="popup-stat">
  694 + <div class="popup-label">Último Pago</div>
  695 + <div class="popup-value">${props.ultimo_pago || 'Nunca'}</div>
  696 + </div>
  697 + </div>
  698 + <button class="logout-btn" style="width: 100%; margin-top: 15px; font-size: 11px; background: #60a5fa; color: #fff;">📄 Ver Detalles SIGEM</button>
  699 + </div>
  700 + `;
  701 +
  702 + new maplibregl.Popup()
  703 + .setLngLat(e.lngLat)
  704 + .setHTML(content)
  705 + .addTo(map);
  706 + });
  707 +
  708 + map.on('mouseenter', 'lotes-layer', () => map.getCanvas().style.cursor = 'pointer');
  709 + map.on('mouseleave', 'lotes-layer', () => map.getCanvas().style.cursor = '');
  710 +
  711 + async function updateMunicipalData() {
  712 + const btn = document.getElementById('btn-update-data');
  713 + const icon = document.getElementById('update-icon');
  714 + const text = document.getElementById('update-text');
  715 +
  716 + btn.style.pointerEvents = 'none';
  717 + btn.style.opacity = '0.5';
  718 + text.innerText = 'Procesando FDW...';
  719 + icon.classList.add('rotating'); // Podríamos añadir CSS para rotar
  720 +
  721 + try {
  722 + const res = await fetch(`/gis-geoserver/api/admin/fdw/update/${entidad}`, {
  723 + method: 'POST',
  724 + headers: { 'Authorization': `Bearer ${token}` }
  725 + });
  726 + const data = await res.json();
  727 +
  728 + if (data.success) {
  729 + alert("✅ Éxito: " + data.message);
  730 + location.reload(); // Recargamos para ver los cambios
  731 + } else {
  732 + alert("❌ Error: " + data.message);
  733 + }
  734 + } catch (err) {
  735 + console.error("Error en update:", err);
  736 + alert("❌ Error de conexión con el servidor de administración.");
  737 + } finally {
  738 + btn.style.pointerEvents = 'auto';
  739 + btn.style.opacity = '1';
  740 + text.innerText = 'Actualizar Datos MUNI';
  741 + }
  742 + }
  743 +
  744 + async function loadMunicipalStats() {
  745 + try {
  746 + const res = await fetch(`/gis-geoserver/api/gis/entidad/${entidad}/resumen`, {
  747 + headers: { 'Authorization': `Bearer ${token}` }
  748 + });
  749 + const data = await res.json();
  750 + document.getElementById('stat-lotes').innerText = data.total_lotes.toLocaleString();
  751 + document.getElementById('stat-morosos').innerText = data.lotes_con_deuda.toLocaleString();
  752 + } catch (err) { console.error("Error stats:", err); }
  753 + }
  754 + </script>
  755 +</body>
  756 +
  757 +</html>
0 \ No newline at end of file 758 \ No newline at end of file
GitLab Appliance - Powered by TurnKey Linux