Src/Private/Get-AbrIntuneTermsAndConditions.ps1

function Get-AbrIntuneTermsAndConditions {
    <#
    .SYNOPSIS
        Documents Intune Terms and Conditions policies.
    .DESCRIPTION
        Collects and reports on:
          - T&C policy name, title, version, and acceptance status
          - Assignments (groups that must accept)
    .NOTES
        Version: 0.1.0
        Added: v0.2.51 — addresses CRITICAL gap from gap tracker
        Endpoint: beta/deviceManagement/termsAndConditions
    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0, Mandatory)]
        [string]$TenantId
    )

    begin {
        Write-PScriboMessage -Message "Collecting Terms and Conditions policies for $TenantId."
        Show-AbrDebugExecutionTime -Start -TitleMessage 'Terms and Conditions'
    }

    process {
        try {
            Write-Host " - Retrieving Terms and Conditions policies..."
            $TaCResp = $null
            try {
                $TaCResp = Invoke-MgGraphRequest -Method GET `
                    -Uri "$($script:GraphEndpoint)/beta/deviceManagement/termsAndConditions?`$expand=assignments" `
                    -ErrorAction Stop
            } catch {
                Write-AbrDebugLog "termsAndConditions unavailable: $($_.Exception.Message)" 'WARN' 'TaC'
            }

            if ($TaCResp -and $TaCResp.value -and @($TaCResp.value).Count -gt 0) {
                Section -Style Heading2 'Terms and Conditions' {
                    Paragraph "Terms and Conditions policies are presented to users during enrollment. Users must accept before gaining access. The following documents T&C policies configured in tenant $TenantId."
                    BlankLine

                    $TaCObj = [System.Collections.ArrayList]::new()
                    foreach ($TaC in ($TaCResp.value | Sort-Object displayName)) {
                        $assignResolved = Resolve-IntuneAssignments -Assignments $TaC.assignments -CheckMemberCount:$script:CheckEmptyGroups

                        # Fetch acceptance status summary
                        $acceptCount = '--'
                        try {
                            $AccResp = $null
                            try { $AccResp = Invoke-MgGraphRequest -Method GET -Uri "$($script:GraphEndpoint)/beta/deviceManagement/termsAndConditions/$($TaC.id)/acceptanceStatuses" -ErrorAction Stop } catch { }
                            if ($AccResp -and $AccResp.value) {
                                $accepted = @($AccResp.value | Where-Object { $_.acceptedVersion -ge $TaC.version }).Count
                                $total    = @($AccResp.value).Count
                                $acceptCount = "$accepted / $total accepted"
                            }
                        } catch { }

                        $TaCObj.Add([pscustomobject]([ordered]@{
                            'Policy Name'     = $TaC.displayName
                            'Title'           = if ($TaC.title) { $TaC.title } else { '--' }
                            'Version'         = if ($null -ne $TaC.version) { "$($TaC.version)" } else { '--' }
                            'Acceptance'      = $acceptCount
                            'Included Groups' = $assignResolved.IncludedGroups
                            'Excluded Groups' = $assignResolved.ExcludedGroups
                            'Last Modified'   = if ($TaC.lastModifiedDateTime) { ([datetime]$TaC.lastModifiedDateTime).ToString('yyyy-MM-dd') } else { '--' }
                        })) | Out-Null
                    }

                    $TaCParams = @{ Name = "Terms and Conditions - $TenantId"; ColumnWidths = 20, 20, 8, 16, 16, 12, 8 }
                    if ($Report.ShowTableCaptions) { $TaCParams['Caption'] = "- $($TaCParams.Name)" }
                    $TaCObj | Table @TaCParams
                }
            } else {
                Write-AbrDebugLog 'No Terms and Conditions policies found.' 'INFO' 'TaC'
            }
        } catch {
            if (Test-AbrGraphForbidden -ErrorRecord $_) { Write-AbrPermissionError -Section 'Terms and Conditions' -RequiredRole 'Intune Service Administrator or Global Administrator' }
            else { Write-AbrSectionError -Section 'Terms and Conditions' -Message "$($_.Exception.Message)" }
        }
    }

    end { Show-AbrDebugExecutionTime -End -TitleMessage 'Terms and Conditions' }
}