Public/Get-EhInactiveLicense.ps1
|
function Get-EhInactiveLicense { <# .SYNOPSIS Reporta licencias asignadas a cuentas inactivas, con el impacto en costo. .DESCRIPTION Cada licencia sobre una cuenta que no se usa es dinero que se va todos los meses sin que nadie lo note. Esta función cruza las cuentas obsoletas (ver Get-EhStaleAccount) con sus licencias asignadas y estima el gasto recuperable si se liberan. El costo mensual por SKU no lo sabe Graph: lo pasás vos en -CostosPorSku, porque depende de tu contrato. Sin ese dato, la función igual lista las licencias pero deja el costo en cero — nunca inventa un precio. SOLO LECTURA. Devuelve objetos. Permisos de Graph mínimos: User.Read.All, AuditLog.Read.All (solo lectura). .PARAMETER DiasInactividad Umbral para considerar una cuenta obsoleta. Por defecto 90. .PARAMETER CostosPorSku Hashtable de skuPartNumber -> costo mensual. Opcional. .PARAMETER InvokeGraph Solo para pruebas: inyecta un mock de Invoke-EhGraph. .OUTPUTS PSCustomObject con: Upn, DiasInactiva, Licencias, CostoMensualEstimado #> [CmdletBinding()] [OutputType([pscustomobject])] param( [ValidateRange(1, 3650)] [int] $DiasInactividad = 90, [hashtable] $CostosPorSku = @{}, [scriptblock] $InvokeGraph ) $leer = if ($InvokeGraph) { $InvokeGraph } else { { param($u) Invoke-EhGraph -Uri $u } } $limite = (Get-Date).ToUniversalTime().AddDays(-$DiasInactividad) $uri = '/users?$select=userPrincipalName,signInActivity,assignedLicenses,licenseAssignmentStates' $usuarios = & $leer $uri foreach ($u in $usuarios) { $licencias = @($u.licenseAssignmentStates | ForEach-Object { $_.skuId } | Where-Object { $_ }) if ($licencias.Count -eq 0) { continue } $ultimo = $u.signInActivity.lastSignInDateTime $fecha = if ($ultimo) { [datetime]::Parse($ultimo).ToUniversalTime() } else { $null } $obsoleta = (-not $fecha) -or ($fecha -lt $limite) if (-not $obsoleta) { continue } $skus = @($u.licenseAssignmentStates | ForEach-Object { $_.skuId }) $costo = 0.0 foreach ($s in $skus) { if ($CostosPorSku.ContainsKey($s)) { $costo += [double]$CostosPorSku[$s] } } $dias = if ($fecha) { [int]((Get-Date).ToUniversalTime() - $fecha).TotalDays } else { $null } [pscustomobject]@{ Upn = $u.userPrincipalName DiasInactiva = $dias Licencias = ($skus -join ', ') CostoMensualEstimado = [math]::Round($costo, 2) } } } |