Metodología
El sistema aplica un conjunto de reglas deterministas sobre los
datos de contratación pública del Ayuntamiento de Móstoles y, complementariamente,
un análisis con modelos de IA por expediente. Esta página documenta cada regla
para que cualquier persona pueda reproducir y discutir los hallazgos.
Los hallazgos del panel son indicios estadísticos para revisión
humana: nunca constituyen una afirmación de irregularidad. Cualquier
expediente listado puede explicarse por causas legítimas (urgencia, mercado
restringido, agrupación de unidades funcionales, etc.).
Reglas deterministas
1. Contratos a 14.999,00 € (umbral de contrato menor)
art. 118 LCSP · severidad alta
- Qué hace
- Lista los contratos menores cuyo importe coincide exactamente con 14.999 € o cae en los 500 € inmediatamente inferiores al umbral de 15.000 € (obras) y 40.000 € (suministros y servicios).
- Por qué
- Bordear sistemáticamente el umbral es indicio de adjudicación directa para esquivar la concurrencia.
- Falsos positivos
- Servicios estandarizados de mercado cuyo precio real ronda esa cifra (suministros recurrentes pequeños, mantenimientos puntuales).
- Cómo se calcula
- SQL sobre
contratos.importe_licitacion con filtro tipo = CONTRATO_MENOR. Las variantes BIS, -2, etc. se excluyen del conteo.
2. Importes exactos repetidos
indicador estadístico · severidad media
- Qué hace
- Detecta importes idénticos al céntimo que aparecen en múltiples contratos menores de objeto distinto.
- Por qué
- La coincidencia perfecta es estadísticamente poco probable; puede indicar un cap presupuestario informal o adjudicaciones plantilladas.
- Falsos positivos
- Importes de mercado fijos (mensualidades de servicios, suministros catalogados).
3. Desviación licitación → adjudicación > 20 %
art. 205 LCSP · severidad alta
- Qué hace
- Marca contratos donde la adjudicación supera la licitación en más de un 20 % al alza, o cae por debajo del 1 % de la licitación (rebajas implausibles).
- Por qué
- La LCSP establece que las modificaciones superiores al 20 % exigen nueva licitación. Las "rebajas" de −99 % suelen indicar datos vacíos o contratos anulados.
- Falsos positivos
- Modificaciones legales documentadas y prórrogas previstas en el pliego original.
- Salvaguardas activas
- Los valores con
adj > lic × 1.30 se descartan en el ETL (eran el VEC de PLACSP, no la adjudicación real). Los adj < lic × 0.01 con licitación > 1 000 € también.
4. Prórrogas múltiples (3 o más)
art. 29 LCSP · severidad alta
- Qué hace
- Lista contratos con tres o más prórrogas formalizadas.
- Por qué
- La LCSP limita la duración total del contrato y de sus prórrogas. Un contrato prorrogado más de dos veces sugiere falta de planificación o intención de mantener al mismo adjudicatario sin nueva licitación.
- Falsos positivos
- Contratos plurianuales con prórrogas anuales explícitamente previstas en el pliego.
5. Concentración del gasto por organismo
indicador estructural · severidad media
- Qué hace
- Identifica concejalías u organismos donde una sola adjudicataria concentra más del 50 % del gasto.
- Por qué
- La excesiva dependencia de un proveedor reduce la competencia futura y dificulta el control.
- Falsos positivos
- Servicios técnicos especializados con poca oferta en el mercado.
6. Posible fraccionamiento por objeto
art. 99.2 LCSP · severidad media
- Qué hace
- Agrupa contratos menores cuyo objeto (título) es muy similar, total sumado > 50 000 €.
- Por qué
- La LCSP prohíbe fraccionar un contrato único en varios menores para esquivar la licitación pública.
- Falsos positivos
- Servicios verdaderamente independientes con descripción genérica similar (p.ej. "mantenimiento").
7. Cruce actas ↔ base de datos de contratos
consistencia documental · informativo
- Qué hace
- Detecta expedientes citados en actas de la Mesa de Contratación que no aparecen en la base de datos oficial, y viceversa.
- Por qué
- Una incoherencia indica una laguna documental — el acta acuerda algo que no consta publicado, o la BD tiene un expediente sin acta.
- Falsos positivos
- Diferencias de formato en el código de expediente; expedientes que existen en PLACSP pero no han llegado al scraper aún.
Análisis IA por expediente
Independientemente de las reglas anteriores, los expedientes con suficiente
documentación (≥ 5 documentos vinculados) se envían a un modelo de lenguaje
grande (Claude Sonnet) que emite un análisis estructurado con severidad,
resumen y lista de riesgos detectados.
El análisis IA se almacena en analisis_ia_expediente y se muestra
en la ficha de cada contrato. Cada riesgo viene etiquetado con su severidad
individual (CRITICA / ALTA / MEDIA / BAJA), descripción y evidencia textual
extraída del documento original.
Origen de los datos
- PLACSP
- Plataforma de Contratos del Sector Público (contrataciondelestado.es). Fuente canónica para todos los datos estructurados de licitación y adjudicación.
- Portal de Transparencia
- mostoles.es/es/portal-transparencia — enlaza al Perfil del Contratante y publica las actas de la Mesa en PDF.
- BORME
- Boletín Oficial del Registro Mercantil — referencia ciudadana para verificar la titularidad legal de cualquier empresa adjudicataria por su NIF.
Salvaguardas activas en el ETL
El sistema descarta sistemáticamente datos que el control de calidad ha
identificado como erróneos en origen:
- Guarda anti-x10/x100: si
adj > lic × 1.30, se descarta (era el Valor Estimado del Contrato confundido con la adjudicación).
- Guarda anti-baja extrema: si
adj < lic × 0.01 con lic > 1 000 €, se descarta (suele ser un campo vacío en origen, no una rebaja real).
- Blacklist de literales: cadenas como "Ver detalle de la adjudicación" o "Nº de Licitadores Presentados" nunca se admiten como nombre de empresa.
- Normalización de NIFs: deduplicación por NIF canónico (UPPER, sin separadores).
API pública
Toda la información que ves está disponible vía API REST. La documentación
interactiva con todos los endpoints está en /api/docs.
Ejemplos rápidos:
Estadísticas globales
# curl
curl https://auditoria.mlopezpalma.es/api/v1/stats
# Python
import httpx
r = httpx.get("https://auditoria.mlopezpalma.es/api/v1/stats")
print(r.json())
# JavaScript (fetch)
fetch("https://auditoria.mlopezpalma.es/api/v1/stats")
.then(r => r.json())
.then(console.log);
Exportar todos los contratos (CSV / JSON)
# CSV (separador ;, UTF-8 con BOM, abrible en Excel directamente)
curl -O https://auditoria.mlopezpalma.es/v4/api/v1/export/contratos.csv
# JSON
curl https://auditoria.mlopezpalma.es/v4/api/v1/export/contratos.json?tipo=licitacion
# Python (filtrado por año)
import httpx
items = httpx.get(
"https://auditoria.mlopezpalma.es/v4/api/v1/export/contratos.json",
params={"tipo": "menor", "anio": "2025"},
).json()["items"]
Réplicas oficiales (contradictorio)
# Enviar réplica oficial a un hallazgo
curl -X POST https://auditoria.mlopezpalma.es/api/v1/contradictorio \
-F "hallazgo_clave=contrato:C/048/CON/2025-001" \
-F "autor=Nombre Apellidos" \
-F "cargo=Secretaría General" \
-F "texto=Esta licitación se justificó por…"
# Listar réplicas a un hallazgo
curl https://auditoria.mlopezpalma.es/api/v1/contradictorio/contrato:C/048/CON/2025-001
Webhooks de alertas (Fase 3.1)
# Ver contrato del webhook (firma esperada + payload de ejemplo)
curl https://auditoria.mlopezpalma.es/api/v1/webhooks/test
# El envío real se firma con HMAC-SHA256(SHARED_SECRET, payload_json)
# y llega en la cabecera X-Audit-Sig. El integrador lo verifica así:
import hmac, hashlib
sig = hmac.new(secret, body, hashlib.sha256).hexdigest()
assert sig == request.headers["X-Audit-Sig"]
Si detectas un error en un hallazgo concreto o crees que aplica un falso
positivo, abre un issue en el repositorio del proyecto o escribe a
Click Aplicaciones Informáticas. Cada corrección queda documentada y se
incorpora a la próxima iteración del ETL.