Mi cuenta

ODSLocal Municipios

Manual de usuario completo · Plugin núcleo de la plataforma ODSLocal para España
Versión 1.2.9
PHP ≥ 8.1
WordPress ≥ 6.0
GPL-2.0+
Baqueiro · odslocal.es

1. Introducción y arquitectura

ODSLocal Municipios es el plugin núcleo de la plataforma odslocal.es, desarrollada en colaboración con la Universidade de Vigo. Gestiona la jerarquía territorial española, los 178 indicadores oficiales ODS (Objetivos de Desarrollo Sostenible) definidos por UVigo, las mediciones y los permisos finos de usuarios.

Todos los demás plugins odslocal-* son extensiones que dependen de este.

Componentes principales

Módulo Responsabilidad
class-territories.php Jerarquía territorial (país → CCAA → diputación → provincia → municipio), CRUD, búsqueda, breadcrumbs.
class-indicators.php Catálogo inmutable de 178 indicadores ODS (generado desde XLS de UVigo).
class-measurements.php Upsert, agregación, comparativa, rollback de mediciones.
class-scopes.php Permisos finos: usuario × territorio × grupo ODS.
class-import.php Pipeline de importación: ingest → staging → preview → publish → rollback.
class-roles.php Registra los 6 roles específicos de ODSLocal.
class-rest.php Endpoints REST públicos en /wp-json/odslocal/v1/.
class-audit.php Registro auditoría (INSERT, UPDATE, DELETE, VALIDATE, …).

Mejoras respecto a v1.0

Componente v1.0 v1.1 – v1.2.9
Jerarquía territorial Taxonomías WP Tabla relacional odslocal_territories con parent_id
Datos odslocal_datos (key-value) odslocal_measurements con validación, origen, auditoría
Permisos user_meta serializado odslocal_user_scope relacional
Importación Directo a tabla final Pipeline staging + rollback

2. Requisitos e instalación

2.1 Requisitos

  • WordPress 6.0 o superior.
  • PHP 8.1 o superior.
  • MySQL 5.7+ o MariaDB 10.3+ (necesario utf8mb4).
  • PhpSpreadsheet (opcional): sólo si se necesita importar .xlsx. Instalar vía composer require phpoffice/phpspreadsheet. Sin él, la importación funciona con CSV.

2.2 Instalación paso a paso

  1. Subir la carpeta odslocal-municipios/ a wp-content/plugins/ (o instalar el ZIP desde Plugins → Añadir nuevo).
  2. Activar el plugin en Plugins → Instalados. En la activación se crean automáticamente las 5 tablas, los 6 roles ODSLocal y se añade la opción odslocal_db_version.
  3. Colocar el fichero municipios-es.geojson en assets/geojson/ (ver sección 12).
  4. Si se desea cargar los 8 100+ territorios españoles oficiales, instalar además el plugin ODSLocal INE Importer.
  5. Asignar roles a los usuarios en Usuarios → Perfil.
  6. Configurar los ámbitos (scopes) de cada colaborador en Municipios → Gestión de accesos.
⚠ Orden de activación
Si tienes otros plugins odslocal-* instalados, activa siempre este primero. Los demás dependen de sus clases (ODSLocal_DB, ODSLocal_Territories, ODSLocal_Roles…) y mostrarán un aviso si no está presente.

3. Modelo de datos (tablas)

El plugin crea cinco tablas con el prefijo wp_ (o el configurado en wp-config.php):

odslocal_territories

Jerarquía territorial completa. Un registro por territorio. Relación parent-child a través de parent_id.

Campo Tipo Descripción
id BIGINT PK Identificador interno.
code_ine VARCHAR(10) Código INE oficial (5 dígitos municipio, 2 provincia, 2 CCAA).
name VARCHAR(255) Nombre oficial.
type ENUM country, ccaa, deputation, province, municipality.
parent_id BIGINT FK Territorio padre (NULL en country).
status ENUM active o inactive.
lat, lng DECIMAL Coordenadas (opcional).
wp_post_id BIGINT ID del CPT municipio asociado (fachada editorial).

odslocal_measurements

Corazón analítico: un registro por combinación territorio × indicador × año.

Campo Tipo Descripción
territory_id BIGINT FK Referencia a territorios.
indicator_key VARCHAR(255) Slug del indicador (p. ej. ods_ods_1_1_1__tasa_de_pobreza).
year INT Año de la medición.
value DOUBLE Valor numérico.
source VARCHAR(255) Fuente (INE, Ministerio, elaboración propia…).
evidence_url VARCHAR(1000) URL a documento de evidencia.
notes TEXT Notas libres.
rejection_reason TEXT Motivo de rechazo (si aplica).
validation_status ENUM draft, pending, approved, rejected.
validated_by, validated_at BIGINT, DATETIME Quién y cuándo validó.
updated_by, updated_at BIGINT, DATETIME Autoría y última edición.
import_run_id BIGINT FK Origen de importación (NULL si entrada manual).

Otras tablas

Tabla Propósito
odslocal_user_scope Permisos: user_id × territory_id × ods_group. NULL = global.
odslocal_import_runs Registro de cada importación (filename, status, ok_rows, error_rows, user, fecha).
odslocal_import_rows Staging de filas brutas antes de publicar.
odslocal_audit Trazabilidad: acción, recurso, user_id, IP, timestamp.

4. Roles y capacidades

El plugin crea seis roles específicos además de los de WordPress. Un administrador de WordPress conserva todos los permisos.

Rol Slug Uso típico
Gestor de la plataforma ods_platform_manager Gestión completa de la plataforma sin tocar WordPress core.
Gestor municipal (Concello) ods_municipal_manager Edita los datos del o de los municipios que le han sido asignados.
Consejo ciudadano ods_citizen_council Igual que el anterior, pensado para grupos de veeduría.
Investigador/a ods_researcher Edita únicamente los territorios y grupos ODS asignados.
Validador/a ods_validator Cambia el validation_status de las mediciones.
Visitante ods_viewer Sólo lectura del panel.

Capacidades clave

Capability Significado
ods_edit_own Editar mediciones propias (sin aprobación de terceros si son draft).
ods_edit_assigned Editar territorios asignados vía scopes.
ods_edit_all Editar cualquier territorio.
ods_validate Aprobar / rechazar mediciones pendientes.
ods_upload_data Usar las importaciones (CSV / XLSX / INE).
ods_manage_settings Tocar opciones globales de la plataforma.

5. Ámbitos (scopes) de permisos

Un mismo usuario puede tener múltiples scopes que delimitan qué territorios y qué grupos ODS puede editar. La tabla es odslocal_user_scope.

{ territory_id: 42,   ods_group: null }    → municipio 42, todos los ODS
{ territory_id: 42,   ods_group: 'ODS3' }  → municipio 42, solo ODS3
{ territory_id: null, ods_group: null }    → acceso global (equivale a admin)
{ territory_id: null, ods_group: 'ODS11'}  → ODS11 en cualquier territorio
ℹ Herencia territorial
Si un usuario tiene ámbito sobre una provincia, hereda acceso a todos los municipios dentro de ella. Lo mismo aplica a CCAA y diputación.

Configuración

En Municipios → Gestión de accesos:

  1. Selecciona el usuario (autocompletado).
  2. Añade filas de ámbito: territorio (con buscador) + grupo ODS (ODS1..ODS17 o Todos).
  3. Pulsa Guardar. Los cambios se aplican inmediatamente: no necesita cerrar sesión.

6. Guía del administrador

Todas las páginas están bajo el menú Municipios en el panel de WordPress.

Submenú Contenido Capability
Todos los municipios Lista de CPT municipio (fachada editorial de los territorios tipo municipality). edit_municipios
Territorios CRUD territorial completo: alta manual, búsqueda, estadísticas por tipo. manage_options o ods_manage_settings
Gestión de accesos Asignación de ámbitos user × territorio × ODS. manage_options
Importar datos Subida CSV/XLSX, staging, preview, publicación, rollback. ods_upload_data
Compara Panel analítico con comparativa entre municipios. edit_municipios
Auditoría Histórico de acciones (inserción, edición, validación, rollback). manage_options
Cobertura Matriz de cobertura territorio × indicador × año. ods_manage_settings

7. Gestión de territorios

7.1 Alta manual

  1. En Municipios → Territorios, rellena el formulario: tipo, nombre, código INE, padre (autocompletado), coordenadas.
  2. Al guardar, el plugin crea un registro en odslocal_territories y (para municipios) también un CPT municipio asociado.

7.2 Alta masiva vía INE Importer

Instalar el plugin ODSLocal INE Importer y ejecutar Poblar municipios → crea de una sola vez CCAA, provincias y los ~8 100 municipios oficiales.

7.3 Búsqueda y breadcrumb

El buscador tolera acentos y minúsculas. Los resultados muestran el breadcrumb completo (p. ej. España › Galicia › A Coruña › Ferrol).

8. Importación de datos (pipeline)

La importación sigue 5 fases para garantizar que nunca se corrompan los datos en producción:

  1. Ingest — Se sube un CSV/XLSX. Cada fila se graba cruda en odslocal_import_rows con su import_run_id. Si se cae el navegador a mitad, el run queda processing y puede reintentarse.
  2. Normalización — El plugin resuelve cada codigo_ine a su territory_id, valida indicator_key contra el catálogo de 178 indicadores y marca cada fila como OK o error con el motivo.
  3. Preview — Se muestra una tabla con el total de filas OK y errores. El usuario puede descargar el CSV de errores para corregir fuera.
  4. Publicar — Copia sólo las filas OK a odslocal_measurements. Cada medición guarda su import_run_id.
  5. Rollback — Mientras un run no esté rechazado ni reemplazado, puede eliminarse por completo: un único click borra todas las mediciones asociadas.

8.1 Formato CSV

codigo_ine,indicator_key,anio,valor,fuente
36038,ods_ods_1_1_1__tasa_de_pobreza_respecto_a_los_valores_i,2023,3.5,INE
36057,ods_ods_3_1_1__esperanza_de_vida_al_nacer,2023,83.2,INE

Separador: coma. Codificación: UTF-8 (con o sin BOM). Decimales: punto o coma (el plugin normaliza).

8.2 Descargar plantilla

Desde Importar datos hay un enlace Descargar plantilla CSV que produce un CSV vacío con los 178 indicator_key de referencia.

⚠ XLSX requiere PhpSpreadsheet
Si no está instalado, el plugin rechaza .xlsx con un mensaje claro. Instálalo vía Composer o convierte el fichero a CSV.

9. Mediciones y validación

9.1 Estados

Estado Significado
draft Borrador del colaborador, no visible para terceros.
pending Enviado para revisión.
approved Publicado: aparece en mapa, comparativa, API, exportaciones.
rejected Devuelto al colaborador con motivo. Editable y re-submetible.

9.2 Flujo habitual

  1. Colaborador edita en el frontend (plugin ODSLocal Data Editor) o en el admin.
  2. Guarda como borrador o envía a revisión.
  3. Usuario con ods_validate entra en Revisión de datos, aprueba o rechaza.
  4. Colaborador recibe email con la decisión.

10. Shortcodes frontend

Se pegan en cualquier página o post. La página en la que estén cargará automáticamente el CSS/JS necesario.

Shortcode Atributos Descripción
Selecciona primero un grupo ODS para habilitar esta lista.
height, center_lat, center_lng, zoom Mapa coroplético interactivo de España con selector de indicador y año.

Comparativa de municipios

    — Comparativa multi-municipio para un indicador y año concretos.
    code_ine Ficha completa del municipio: últimos valores por ODS.

    Ejemplos

    Selecciona primero un grupo ODS para habilitar esta lista.
    Cargando…

    Comparativa de municipios

      11. REST API

      Namespace público: /wp-json/odslocal/v1/. Todas las rutas devuelven JSON y sólo exponen mediciones approved.

      Método Ruta Descripción
      GET /territories?search=vigo Búsqueda de territorios.
      GET /territories/{id}?year=2023 Ficha del territorio.
      GET /indicators?group=ODS1 Lista de indicadores por grupo ODS.
      GET /measurements?territory_id=42&year=2023 Mediciones con filtros.
      GET /map/{indicator_key}/{year} Valores para pintar un choropleth.
      GET /compare?ids=42,55,81&indicator=...&year=2023 Comparativa entre municipios.

      Ejemplo

      curl "https://odslocal.es/wp-json/odslocal/v1/territories?search=vigo"

      12. GeoJSON del mapa

      El fichero assets/geojson/municipios-es.geojson debe añadirse manualmente por motivos de peso y licencia.

      Fuentes recomendadas

      • IGN (Instituto Geográfico Nacional): cartografía oficial, ~60 MB simplificado.
      • OpenDataSoft: versión más ligera (~4 MB), ideal para producción.

      Campo de cruce

      El frontend identifica cada feature por una de estas propiedades:

      • properties.codigo_ine
      • properties.CMUN
      • properties.cusec

      Si tu GeoJSON usa otra propiedad, edita assets/js/frontend.js (línea ~50) añadiéndola al array.

      ✓ Fallback visual
      Si falta el GeoJSON o falla la descarga, el mapa muestra un aviso elegante con instrucciones en lugar de romper la página.

      13. Auditoría y trazabilidad

      Cada acción relevante queda registrada en odslocal_audit:

      • Tipos de acción: insert, update, delete, validate, reject, import, rollback, news_submit, event_checkin (registros de plugins adjacentes).
      • Campos capturados: usuario, IP (ver sección 15), recurso, payload JSON, timestamp.
      • Paginación: 50 registros por página, ordenados por fecha descendente.

      Acceso: Municipios → Auditoría (sólo manage_options).

      14. Integración con otros plugins

      ODSLocal Municipios es la base sobre la que corren:

      Plugin Qué aporta
      ODSLocal Contributor Profiles Perfiles públicos, hub, QR, cartas académicas.
      ODSLocal Data Editor Editor frontend con flujo de aprobación.
      ODSLocal Data Export Exportación CSV/XLSX/JSON, API pública.
      ODSLocal INE Importer Importación automática desde la API oficial del INE.
      ODSLocal News Artículos y noticias vinculadas a ODS y territorios.
      ODSLocal Events Calendario, reservas, tickets QR, certificados.
      ODSLocal Geo Display Visualización cartográfica avanzada.
      ODSLocal RGPD Cumplimiento legal RGPD/LSSI/LOPDGDD.
      b-ods-display Componentes visuales premium (dashboards, tarjetas ODS).

      Cada extensión verifica class_exists('ODSLocal_DB') antes de ejecutarse y degrada con un aviso si el plugin núcleo está desactivado.

      15. Seguridad y privacidad

      • Nonces en todos los endpoints AJAX y acciones sensibles.
      • Capabilities verificadas en servidor (nunca solo en la UI).
      • Prepared statements ($wpdb->prepare) en todas las consultas con valores dinámicos.
      • IP del cliente resuelta priorizando REMOTE_ADDR; sólo se consultan X-Forwarded-For / CF-Connecting-IP cuando hay un proxy reverso real o vía filtro opt-in odslocal_audit_trust_proxy_headers.
      • Sanitización exhaustiva: sanitize_text_field, sanitize_key, esc_url_raw, absint.
      • Rollback transaccional: cualquier import puede revertirse sin pérdida de datos.
      • Auditoría inmutable: la tabla odslocal_audit no se actualiza, sólo se inserta (append-only).

      16. Solución de problemas (FAQ)

      El mapa no carga

      • ¿Está el GeoJSON en assets/geojson/municipios-es.geojson?
      • Comprueba la consola del navegador (F12): ¿error 404 o de CORS?
      • ¿El campo properties.codigo_ine existe? Si no, edita frontend.js.

      “Permisos insuficientes” al importar

      Asegúrate de que el rol del usuario tiene ods_upload_data. Administrador lo tiene por defecto.

      La importación se queda en processing

      Probablemente se cortó la conexión. En Importar datos → Historial, cancela el run y vuelve a intentarlo. El rollback no deja datos colgados.

      XLSX no funciona

      Requiere PhpSpreadsheet. Alternativa: exporta a CSV desde tu hoja de cálculo.

      Un usuario ve territorios que no debería

      Revisa sus scopes. Recuerda la herencia: si tiene provincia, hereda sus municipios.

      Quiero activar el trust de proxies (Cloudflare / reverse proxy real)

      add_filter('odslocal_audit_trust_proxy_headers', '__return_true');

      17. Mantenimiento

      17.1 Actualización

      Al subir una versión nueva, el plugin ejecuta migraciones automáticas en el hook plugins_loaded. La versión se guarda en odslocal_db_version y las migraciones se saltan si ya se aplicaron.

      17.2 Backup recomendado

      Hacer dump de:

      • Las 5 tablas odslocal_*
      • La tabla wp_options (al menos filas odslocal_*)
      • La tabla wp_usermeta para preservar perfiles y scopes

      17.3 Desinstalación

      Al desactivar no se borra nada. Al eliminar desde el panel de plugins, las tablas quedan (por seguridad). Si se desea limpieza total, hacer DROP manual tras exportar los datos.

      17.4 Traducciones

      Text domain: odslocal. Los ficheros .mo se buscan en languages/ del plugin. Se aceptan PRs de nuevos idiomas en el repo oficial.

      Saltar al contenido principal