Private/Select-SFWorkforceRetentionResource.ps1

function Select-SFWorkforceRetentionResource {
    [CmdletBinding()]
    [OutputType([hashtable])]
    param (
        [Parameter(Mandatory)]
        [hashtable]$ResourcesByType,

        [Parameter(Mandatory)]
        [ValidateRange(1, 36500)]
        [int]$RetentionDays,

        [Parameter(Mandatory)]
        [DateTimeOffset]$AsOfDate
    )

    if (-not $ResourcesByType.ContainsKey('EmpEmployment')) {
        throw 'Workforce retention requires an EmpEmployment resource type.'
    }

    $cutoffDate = $AsOfDate.UtcDateTime.Date.AddDays(-$RetentionDays)
    $retainedUserIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
    $retainedPersonIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
    $retainedEmployments = [System.Collections.Generic.List[object]]::new()

    foreach ($employment in @($ResourcesByType.EmpEmployment)) {
        $userId = [string](Get-SFNestedValue -InputObject $employment -Path 'userId')
        $personId = [string](Get-SFNestedValue -InputObject $employment -Path 'personIdExternal')
        if ([string]::IsNullOrWhiteSpace($userId) -or [string]::IsNullOrWhiteSpace($personId)) {
            throw 'Workforce retention requires every EmpEmployment row to contain userId and personIdExternal.'
        }

        $endDateValue = Get-SFNestedValue -InputObject $employment -Path 'endDate'
        $retain = $null -eq $endDateValue -or [string]::IsNullOrWhiteSpace([string]$endDateValue)
        if (-not $retain) {
            $endDate = ConvertTo-SFDateTimeOffset -Value $endDateValue
            $retain = $endDate.UtcDateTime.Date -ge $cutoffDate
        }

        if ($retain) {
            $retainedEmployments.Add($employment)
            [void]$retainedUserIds.Add($userId)
            [void]$retainedPersonIds.Add($personId)
        }
    }

    $filteredResources = @{}
    foreach ($entry in $ResourcesByType.GetEnumerator()) {
        $filteredResources[$entry.Key] = @(switch ($entry.Key) {
            'EmpEmployment' {
                $retainedEmployments
            }
            'EmpJob' {
                $entry.Value | Where-Object {
                    $retainedUserIds.Contains([string](Get-SFNestedValue -InputObject $_ -Path 'userId'))
                }
            }
            'User' {
                $entry.Value | Where-Object {
                    $userId = [string](Get-SFNestedValue -InputObject $_ -Path 'userId')
                    $retainedUserIds.Contains($userId)
                }
            }
            { $_ -in @('PerPerson', 'PerPersonal') } {
                $entry.Value | Where-Object {
                    $retainedPersonIds.Contains([string](Get-SFNestedValue -InputObject $_ -Path 'personIdExternal'))
                }
            }
            default {
                $entry.Value
            }
        })
    }

    Write-ConnectorVerbose (
        "Applied workforce retention of $RetentionDays day(s) at cutoff " +
        "$($cutoffDate.ToString('yyyy-MM-dd')): retained $($retainedEmployments.Count) " +
        "EmpEmployment row(s), $($retainedUserIds.Count) user ID(s), and " +
        "$($retainedPersonIds.Count) person ID(s)."
    )

    return $filteredResources
}