Public/Update-Employees.ps1

function Update-Employees
{
    [CmdletBinding(PositionalBinding = $true)]
    param
    (
        [Parameter(Mandatory = $true)][object[]]$AdUsers,
        [Parameter(Mandatory = $true)][object[]]$SyncHrEmployees,
        [Parameter(Mandatory = $false)][string[]]$ExemptOu
    )

    $employees = $SyncHrEmployees | ? {
        $_.empNo.Length -gt 3
    }
    

    $validAdUsers = $AdUsers | ? {
        $_.SamAccountName -notmatch '^da\.|^svc\.'
    }
    

    $progressObj = @{
        count     = $employees.Count
        countDown = $employees.Count
        countUp   = 0
    }

    $returnObj = New-Object -TypeName psobject -Property @{
        updates      = @()
        terminations = @()
        newHires     = @()
    }
    

    try
    {
        foreach ($emp in $employees)
        {

            Write-Progress -Activity "Processing SHR User: $($emp.fname) $($emp.lname)" -Status "$(($progressObj).countDown) Users Remaining.."  `
                -PercentComplete (($($progressObj.countUp) / $($progressObj.count)) * 100) -ErrorAction Ignore

            $progressObj.countDown--
            $progressObj.countUp++

            $userEmployeeNumber = Convert-SyncHrEmpNo -SyncHrEmpNo $emp.empNo
            
            if ($userEmployeeNumber -notmatch '\d+')
            {
                continue
            }


            $adUser = $null
            $adUser = $validAdUsers | ? { $_.EmployeeNumber -eq $userEmployeeNumber }

            
            if (!$adUser)
            {
                $newSam = $emp.fName + "." + $emp.lname

                $adUser = $validAdUsers | ? { $_.SamAccountName -eq $newSam }

                if ($adUser)
                {
                    Write-Log "Skipping new user creation becasue user with SamAccountName ""$newSam"" already exists." -EmployeeId $emp.empNo -LogType: warning
                    continue
                }

            }
            
        
            if (!$adUser)
            {
                if ($emp.emplStatusDescription -eq 'Active Employee') 
                {
                    # new hire!
                    
                    $newAdUser = New-AdUserFromSyncHr -SyncHrNewHire $emp

                    $newUserObjProps = @{
                        Action         = 'NewUser'
                        Result         = $newAdUser.Result
                        FirstName      = $emp.fname
                        LastName       = $emp.lname
                        LoginName      = $newAdUser.SamAccountName
                        Password       = $newAdUser.newPassword
                        Title          = $emp.positionTitle
                        Manager        = $newAdUser.managerName
                        Office         = $newAdUser.Office
                        HireDate       = $emp.emplHireDate
                        EmployeeNumber = $newAdUser.EmployeeNumber
                    }

                    $returnObj.newHires += New-Object psobject -Property $newUserObjProps
     
                }
                
                continue
            }

            if ($adUser.Count -gt 1)
            {
                Write-Log -LogText "MULTIPLE MATCHES in AD. SyncHR User: $($emp.fName) $($emp.lName) $($emp.empNo) ($($userEmployeeNumber)). AD Matches: $($adUser.SamAccountName -join ', ')" -LogType warning -EmployeeId $emp.empNo
                continue
            }

            if ($emp.emplStatusDescription.Length -lt 1) 
            {
                Write-Log "Skipping user with invalid emplStatusDescription: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> emplStatusDescription: ""$($emp.emplStatusDescription)""" -LogType: warning -EmployeeId $emp.empNo
                continue
            }

            # check to see if user is in exempt ou
            $userOU = ($adUser.DistinguishedName -split ",", 2)[1]
            $ouMatch = $null
            $ouMatch = $ExemptOu | ? { $_ -eq $userOU } | select -First 1

            if ($ouMatch) 
            {
                Write-Log "Skipping user in exempt OU: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> $($adUser.DistinguishedName) in OU: ""$($ouMatch)""" -LogType: warning -EmployeeId $emp.empNo
                continue
            }

            if ($adUser.Enabled -eq $false)
            {
                continue
            }

            $changeObjProps = [ordered]@{

                Action      = $null
                Result      = $null

                FirstName   = $adUser.GivenName
                LastName    = $adUser.Surname
                LoginName   = $adUser.SamAccountName

                SHR_EmpNo   = $emp.empNo
                SHR_Status  = $emp.emplStatusDescription

                Manager_old = $null
                Manager_new = $null

                Title_old   = $null
                Title_new   = $null

                Office_old  = $null
                Office_new  = $null

                Address_old = $null
                Address_new = $null

            }

            $changeObj = New-Object psobject -Property $changeObjProps



            $changes = @{}

            # enabled
            if ($emp.emplStatusDescription -notmatch 'Active Employee|On Leave') 
            {
                Write-Log "Disabling employee: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> emplStatusDescription: ""$($emp.emplStatusDescription)""" -EmployeeId $emp.empNo

                $changes += @{
                    Enabled     = $false
                    Description = "Disabled by SyncHR Script $((Get-Date).ToString('yyyy-MM-dd hh:mm tt')) :: SHR Status: $($emp.emplStatusDescription)"
                }

            }
            else
            {

                # manager
                if ($emp.manager_empNo.Length -gt 3)
                {
                    $managerEmployeeNumber = Convert-SyncHrEmpNo -SyncHrEmpNo $emp.manager_empNo

                    $adManager = $null
                    $adManager = $validAdUsers | ? { $_.EmployeeNumber -eq $managerEmployeeNumber }

                    if ($adManager -and ($adUser.Manager -ne $adManager.DistinguishedName))
                    {
                        if ($adManager.SamAccountName -eq 'ACCOBCM') 
                        {
                            Write-Log "Skipping manager update for someone reporting to due to known issue." -LogType: warning -EmployeeId $emp.empNo
                        }
                        else 
                        {
                            Write-Log "Manager update: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> Old Manager: ""$($adUser.Manager)"" >> New Manager: ""$($adManager.DistinguishedName)""" -EmployeeId $emp.empNo

                            $changes += @{Manager = $adManager.DistinguishedName }
    
                            $changeObj.Manager_old = "$($adUser.GivenName) $($adUser.Surname)"
                            $changeObj.Manager_new = "$($adManager.GivenName) $($adManager.Surname)"
                        }

                    }

                }


                # title
                if ($adUser.Title -ne $emp.positionTitle)
                {
                    Write-Log "Title update: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> Old Title: ""$($adUser.Title)"" >> New Title: ""$($emp.positionTitle)""" -EmployeeId $emp.empNo
                
                    $changes += @{Title = $emp.positionTitle }

                    $changeObj.Title_old = $adUser.Title
                    $changeObj.Title_new = $emp.positionTitle

                }

                # office
                if ($adUser.Office -ne $emp.location_name)
                {
                    Write-Log "Office update: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> Old Office: ""$($adUser.Office)"" >> New Office: ""$($emp.location_name)""" -EmployeeId $emp.empNo
                
                    $changes += @{Office = $emp.location_name }

                    $changeObj.Office_old = $adUser.Office
                    $changeObj.Office_new = $emp.location_name
                }

                # address
                if (
                    $adUser.StreetAddress -ne $emp.location_street -or 
                    $adUser.City -ne $emp.location_city -or 
                    $adUser.State -ne $emp.location_state -or 
                    $adUser.PostalCode -ne $emp.location_zip)
                {

                    $changeObj.Address_old = @($adUser.StreetAddress, $adUser.City, $adUser.State, $adUser.PostalCode) -join " "
                    $changeObj.Address_new = @($emp.location_street, $emp.location_city, $emp.location_state, $emp.location_zip) -join " "


                    Write-Log "Address update: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)) >> Old Address: ""$($changeObj.Address_old)"" >> New Address: ""$($changeObj.Address_new)""" -EmployeeId $emp.empNo
                
                    $changes += @{
                        StreetAddress = $emp.location_street
                        City          = $emp.location_city
                        State         = $emp.location_state
                        PostalCode    = $emp.location_zip
                    }


                }

            }



            # perform changes if there are any
            if ($changes.Count -gt 0)
            {

                $changes += @{Identity = $adUser.ObjectGUID.GUID }

                try
                {
                    Set-ADUser @changes -ErrorAction: Stop -Verbose
                    $changeObj.Result = 'OK'
                }
                catch
                {
                    Write-Log "Error performing Set-AdUser on user: $($emp.fName) $($emp.lName) $($emp.empNo) ($($adUser.EmployeeNumber)). Changes: $($changes | ConvertTo-Json -Compress)"  -LogType: error -ErrorObject $_ -EmployeeId $emp.empNo
                    $changeObj.Result = "ERROR: $($_.Exception.Message)"
                }

                if ($changes.Enabled -eq $false)
                {
                    $changeObj.Action = 'Termination'
                    $returnObj.terminations += $changeObj | select Action, Result, FirstName, LastName, LoginName, SHR_EmpNo, SHR_Status
                }
                else
                {
                    $changeObj.Action = 'Update'
                    $returnObj.updates += $changeObj
                }

            }

            

        }
    }
    catch
    {
        Write-Log "Unhandled exception" -LogType: error -ErrorObject $_ -EmployeeId $emp.empNo
        return
    }

    Write-Progress -Activity "Complete"  -Completed: $true

    $returnObj.updates = $returnObj.updates | Sort-Object Title_new, Manager_new, Office_new, Address_new

    return $returnObj
    


}