← Volver al índice
🔒 M365 — Monitor de licencias

License Monitoring

Monitoriza licencias Microsoft 365 del tenant. Sincroniza usuarios y SKUs desde Graph API, analiza patrones de uso e identifica licencias reasignables con ahorro estimado en euros.

🌟 Python 3 + Flask + Waitress
Graph API (certificado)
🌐 Puerto 8088
🏠 WinSW Service
En producción
24h
Intervalo sync (configurable)
7
Categorías de alerta
6
Tablas SQLite
Ahorro mensual estimado

Cómo funciona

Un scheduler en background sincroniza el tenant completo contra Graph API cada 24 horas. El alert engine analiza los datos y clasifica licencias por riesgo de desperdicio.

1
scheduler.py — arranca con la app, espera 10s, ejecuta el primer sync. Repite cada sync.interval_hours.
2
sync.run_sync() — mutex garantiza un único sync concurrente. Etapas: SKUs → Usuarios → user_licenses → user_service_plans → Cleanup
3
Usuarios: paginación 999/página, incluye assignedLicenses + signInActivity. Calcula days_inactive. Degradación elegante si AuditLog.Read.All no está concedido.
4
analyzer.get_alerts() — 7 categorías de recomendación con lista de usuarios y coste estimado mensual de cada grupo.

Categorías de recomendación

El motor de análisis clasifica licencias por nivel de urgencia y calcula el ahorro potencial mensual en euros basándose en el coste anual configurado por SKU.

PrioridadCategoríaDescripción
CRITICALDeshabilitados con licenciaCuentas OFF que siguen consumiendo — reclamo inmediato
HIGHNunca iniciaron sesiónCuenta creada pero sin uso — reclamo muy probable
HIGHInactivos >180 días+6 meses sin actividad — reclamo muy probable
MEDIUMInactivos >90 díasPosible inactividad legítima — revisar caso por caso
MEDIUMGuests con licenciaUsuarios B2B con licencia full — downgrade posible
MEDIUMOverlap E3+E5Asignación redundante (E5 ⊃ E3) — quitar E3
INFOSlots disponiblesCapacidad comprada no asignada — indicativo de sobrecompra

Esquema SQLite

TablaDescripción
license_skusSKUs del tenant: total/consumido/disponible, annual_cost (editable), is_free
usersSnapshot completo por sync: last_seen, days_inactive, is_licensed, user_type
user_licensesAsignaciones usuario→SKU. Rebuild completo cada sync.
user_service_plansPlanes de servicio por usuario-SKU (opcional, fetch_license_details=true)
app_usersSSO con flag is_admin
sync_logHistorial de sincronizaciones: estado, duración, conteos, errores

Páginas principales

📈 Dashboard (/)

KPI cards: usuarios totales, con licencia, deshabilitados con licencia, inactivos, potencial reclamo, ahorro estimado. Indicador de sync (barra de progreso live via /api/sync/status).

👥 Usuarios (/usuarios)

DataTable filtrable: búsqueda por nombre/UPN/dept, filtros por SKU/status/inactividad/tipo. Paginación. Exportación CSV.

📦 Inventario (/inventario)

SKU inventory: total/consumido/disponible/%, barra visual, annual_cost editable por admin (se persiste en config JSON).

🔔 Alertas (/alertas)

7 secciones por prioridad. Cada sección: n.º usuarios afectados, coste mensual total estimado, lista expandible con detalle por usuario.

Deploy y configuración

Deploy

cd C:\apps\jmfernandez\license_monitoring .\deploy.ps1 # git pull + pip install sisapps-ui + restart

Trigger manual de sync desde Admin → Sincronizar ahora. El sync corre en background — el navbar muestra el estado en tiempo real.

Config clave (app-config.json)

port8088
graph.certificate_thumbprintCert Windows store
sync.interval_hoursIntervalo sync (default 24)
sync.fetch_license_detailsService plans vía batch (más lento)
analysis.inactivity_threshold_daysUmbral MEDIUM (default 90)
analysis.high_inactivity_daysUmbral HIGH (default 180)
bootstrap_adminAdmin inicial al arrancar
License Monitoring · Equipo de Sistemas · 2026