# Update-StaffAD.ps1 # Reads Staff_Extract.csv and updates AD email addresses and account status. # Matches users by sAMAccountName (PAYROLL_REC_NO column). # If duplicate entries exist, ACTV takes priority over INAC/LEFT. # Creates new AD accounts for ACTV users not found in AD. # Applies changes automatically and appends results to a log file. # # Usage: # .\Update-StaffAD.ps1 - Run normally, apply all changes # .\Update-StaffAD.ps1 -DryRun - Preview only, no changes made param( [switch]$DryRun ) # --- Configuration --- $CsvPath = "C:\Scripts\Staff_Extract.csv" $LogFile = "C:\Scripts\Logs\StaffAD_Changes.log" $NewUserOU = "OU=Staff,DC=school,DC=vic,DC=edu,DC=au" # Update this $DefaultPassword = ConvertTo-SecureString "P@ssword123!" -AsPlainText -Force # Update this # --- Setup --- if (-not (Test-Path $CsvPath)) { Write-Error "CSV not found: $CsvPath" exit 1 } $LogDir = Split-Path $LogFile if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Path $LogDir | Out-Null } $Staff = Import-Csv -Path $CsvPath $DisableStatuses = @("INAC", "LEFT") $RunHeader = "=" * 60 $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" function Write-Log { param([string]$Message, [string]$Color = "White") Write-Host $Message -ForegroundColor $Color if (-not $DryRun) { Add-Content -Path $LogFile -Value $Message } } # --- Deduplicate: ACTV wins over INAC/LEFT --- $Deduped = @{} foreach ($entry in $Staff) { $key = $entry.PAYROLL_REC_NO.Trim() if (-not $Deduped.ContainsKey($key)) { $Deduped[$key] = $entry } elseif ($entry.STAFF_STATUS.Trim() -eq "ACTV") { $Deduped[$key] = $entry } } # --- Run Header --- if ($DryRun) { Write-Host "" Write-Host $RunHeader -ForegroundColor Magenta Write-Host " DRY RUN - NO CHANGES WILL BE MADE" -ForegroundColor Magenta Write-Host " $Timestamp" -ForegroundColor Magenta Write-Host $RunHeader -ForegroundColor Magenta } else { Write-Log "" Write-Log $RunHeader Write-Log " RUN: $Timestamp" Write-Log $RunHeader } $emailUpdates = 0 $disables = 0 $noChanges = 0 $notFound = 0 $created = 0 $notFoundList = @() foreach ($entry in $Deduped.Values) { $samAccount = $entry.PAYROLL_REC_NO.Trim() $status = $entry.STAFF_STATUS.Trim() $email = $entry.E_MAIL.Trim() # Parse name from email $firstName = "Unknown" $lastName = "Unknown" if ($email -match "^([^.]+)\.([^@]+)@") { $firstName = $Matches[1] $lastName = $Matches[2] } $displayName = "$firstName $lastName" # Find user in AD by sAMAccountName try { $adUser = Get-ADUser -Identity $samAccount ` -Properties EmailAddress, Enabled, DisplayName ` -ErrorAction Stop } catch { # Not found in AD - create if ACTV, otherwise log and skip if ($status -ne "ACTV") { $notFound++ $notFoundList += "$samAccount, $displayName (skipped - status: $status)" continue } Write-Log "" Write-Log " User : $displayName ($samAccount)" Write-Log " Status : $status" if ($DryRun) { Write-Log " Account : WOULD BE CREATED in $NewUserOU" "Magenta" Write-Log " Email : $email [WOULD BE SET]" "Magenta" } else { try { New-ADUser ` -SamAccountName $samAccount ` -UserPrincipalName $email ` -GivenName $firstName ` -Surname $lastName ` -DisplayName $displayName ` -Name $displayName ` -EmailAddress $email ` -AccountPassword $DefaultPassword ` -Enabled $true ` -Path $NewUserOU Write-Log " Account : CREATED in $NewUserOU [CREATED]" "Green" Write-Log " Email : $email [SET]" "Green" $created++ } catch { Write-Log " Account : FAILED to create - $_" "Red" } } $created++ continue } $willDisable = ($status -in $DisableStatuses) -and $adUser.Enabled $willUpdateEmail = ($adUser.EmailAddress -ne $email) if (-not $willDisable -and -not $willUpdateEmail) { $noChanges++ continue } Write-Log "" Write-Log " User : $($adUser.DisplayName) ($samAccount)" Write-Log " Status : $status" # Update email if ($willUpdateEmail) { if ($DryRun) { Write-Log " Email : $($adUser.EmailAddress) --> $email [WOULD UPDATE]" "Magenta" } else { try { Set-ADUser -Identity $samAccount -EmailAddress $email Write-Log " Email : $($adUser.EmailAddress) --> $email [UPDATED]" "Green" $emailUpdates++ } catch { Write-Log " Email : FAILED to update - $_" "Red" } } $emailUpdates++ } # Disable account if ($willDisable) { if ($DryRun) { Write-Log " Account : WOULD BE DISABLED (status: $status)" "Magenta" } else { try { Disable-ADAccount -Identity $samAccount Write-Log " Account : DISABLED (status: $status) [UPDATED]" "Green" $disables++ } catch { Write-Log " Account : FAILED to disable - $_" "Red" } } $disables++ } } # --- Summary --- Write-Log "" Write-Log " --- Summary $(if ($DryRun) { '(DRY RUN)' }) ---" if ($emailUpdates -eq 0 -and $disables -eq 0 -and $created -eq 0) { Write-Log " No changes $(if ($DryRun) { 'would be' } else { 'were' }) made on this run." "Cyan" } Write-Log " Accounts $(if ($DryRun) { 'to create' } else { 'created' }) : $created" Write-Log " Email updates : $emailUpdates" Write-Log " Accounts disabled : $disables" Write-Log " No changes needed : $noChanges" Write-Log " Not found in AD : $notFound" if ($notFoundList.Count -gt 0) { foreach ($missing in $notFoundList) { Write-Log " - $missing" "Yellow" } } Write-Log $RunHeader Write-Log ""