Public/Get-UKGProEmploymentDetails.ps1
|
function Get-UKGProEmploymentDetails { <# .SYNOPSIS Retrieves employment record details from UKG Pro. .DESCRIPTION Wraps GET /personnel/v1/employment-details. Returns employment records including status, job, work location, supervisor, and key dates (hire, termination, retirement) — the fields most useful for offboarding and IAM workflows. All filters are optional and applied server-side. Results are paginated automatically (page/per_Page) unless -MaxResults caps them. Termination date is filtered via one of four intent-named parameters (mutually exclusive, enforced by parameter sets): -TerminatedOn <date> terminated on that exact date -TerminatedSince <date> terminated on or after that date -TerminatedBefore <date> terminated on or before that date -TerminatedBetweenStart / -TerminatedBetweenEnd range .PARAMETER CompanyId Filter by company identifier. .PARAMETER EmployeeId Filter by employee identifier. .PARAMETER EmailAddress Filter by the employee's UKG-registered email address. The email is resolved to one or more employee IDs via GET /personnel/v1/person-details (a read-only endpoint requiring only the View role) and an employment-details query is issued for each. If multiple distinct employees share the email, records for all of them are returned; callers who want just one should switch to -EmployeeId. Mutually exclusive with -EmployeeId. .PARAMETER EmployeeNumber Filter by employee number. .PARAMETER EmployeeStatusCode Filter by employee status code (e.g. active/terminated codes as defined in your tenant). .PARAMETER EmployeeTypeCode Filter by employee type code. .PARAMETER SupervisorId Filter by supervisor ID. .PARAMETER JobTitle Filter by job title. .PARAMETER PrimaryJobCode Filter by primary job code. .PARAMETER PrimaryWorkLocationCode Filter by primary work location code. .PARAMETER TerminatedOn Return only records with dateOfTermination equal to this date. .PARAMETER TerminatedSince Return records with dateOfTermination greater than this date — the "terminated in the last N days" pattern. .PARAMETER TerminatedBefore Return records with dateOfTermination less than this date. .PARAMETER TerminatedBetweenStart / -TerminatedBetweenEnd Return records with dateOfTermination within an inclusive date range. .PARAMETER ChangedSince Return records whose dateTimeChanged is greater than this date/time (useful for incremental syncs). .PARAMETER MaxResults Cap total records across all pages. 0 = all. .PARAMETER PageSize Rows per page to request (default 100). .EXAMPLE Get-UKGProEmploymentDetails -EmployeeId '000123' Retrieves employment details for one employee. .EXAMPLE Get-UKGProEmploymentDetails -EmailAddress 'alex.doe@example.com' Looks up the employee by email (via person-details) and returns their employment details. Equivalent to -EmployeeId but avoids needing to know the ID up front. .EXAMPLE Get-UKGProEmploymentDetails -TerminatedOn '8/28/26' Employees terminated on exactly 2026-08-28. .EXAMPLE Get-UKGProEmploymentDetails -TerminatedSince (Get-Date).AddDays(-30) Employees terminated in the last 30 days (offboarding candidates). .EXAMPLE Get-UKGProEmploymentDetails -TerminatedBefore '2026-01-01' Employees terminated before the start of 2026. .EXAMPLE Get-UKGProEmploymentDetails -TerminatedBetweenStart '2026-01-01' -TerminatedBetweenEnd '2026-03-31' Employees terminated in Q1 2026. .EXAMPLE Get-UKGProEmploymentDetails -ChangedSince (Get-Date).AddHours(-24) Records changed in the last day, for an incremental sync. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Public API name matches the underlying UKG response schema (EmpEmploymentDetails). Renaming to singular would break every existing caller and diverge from UKG''s own naming.')] [CmdletBinding(DefaultParameterSetName = 'Standard')] [OutputType([pscustomobject])] param ( [Parameter()] [string]$CompanyId, [Parameter()] [string]$EmployeeId, [Parameter()] [string]$EmailAddress, [Parameter()] [string]$EmployeeNumber, [Parameter()] [string]$EmployeeStatusCode, [Parameter()] [string]$EmployeeTypeCode, [Parameter()] [string]$SupervisorId, [Parameter()] [string]$JobTitle, [Parameter()] [string]$PrimaryJobCode, [Parameter()] [string]$PrimaryWorkLocationCode, # --- Termination date: intent-named, mutually exclusive via parameter sets --- [Parameter(Mandatory, ParameterSetName = 'TerminatedOn')] [datetime]$TerminatedOn, [Parameter(Mandatory, ParameterSetName = 'TerminatedSince')] [datetime]$TerminatedSince, [Parameter(Mandatory, ParameterSetName = 'TerminatedBefore')] [datetime]$TerminatedBefore, [Parameter(Mandatory, ParameterSetName = 'TerminatedRange')] [datetime]$TerminatedBetweenStart, [Parameter(Mandatory, ParameterSetName = 'TerminatedRange')] [datetime]$TerminatedBetweenEnd, # --- Incremental sync helper --- [Parameter()] [datetime]$ChangedSince, [Parameter()] [int]$MaxResults = 0, [Parameter()] [int]$PageSize = 100 ) if ($EmailAddress -and $EmployeeId) { throw "-EmailAddress and -EmployeeId cannot be used together. Choose one." } # Resolve email -> one or more employeeIds. Non-email paths iterate once # with $EmployeeId as-is (which may be empty for list-mode, in which case # the query-builder just doesn't add an employeeId filter). The email # path fans out: if person-details returns multiple distinct employees # sharing that email, we run employment-details for each and emit the # union rather than throwing. if ($EmailAddress) { $resolved = @(Resolve-UKGProEmployeeIdByEmail -EmailAddress $EmailAddress) $idsToQuery = @($resolved | ForEach-Object { $_.EmployeeId }) } else { $idsToQuery = @($EmployeeId) } foreach ($eid in $idsToQuery) { $q = @{} if ($CompanyId) { $q['companyId'] = $CompanyId } if ($eid) { $q['employeeId'] = $eid } if ($EmployeeNumber) { $q['employeeNumber'] = $EmployeeNumber } if ($EmployeeStatusCode) { $q['employeeStatusCode'] = $EmployeeStatusCode } if ($EmployeeTypeCode) { $q['employeeTypeCode'] = $EmployeeTypeCode } if ($SupervisorId) { $q['supervisorID'] = $SupervisorId } if ($JobTitle) { $q['jobTitle'] = $JobTitle } if ($PrimaryJobCode) { $q['primaryJobCode'] = $PrimaryJobCode } if ($PrimaryWorkLocationCode) { $q['primaryWorkLocationCode'] = $PrimaryWorkLocationCode } switch ($PSCmdlet.ParameterSetName) { 'TerminatedOn' { $q['dateOfTermination'] = ConvertTo-UKGProDateFilter -Operator EqualTo -Date $TerminatedOn } 'TerminatedSince' { $q['dateOfTermination'] = ConvertTo-UKGProDateFilter -Operator GreaterThan -Date $TerminatedSince } 'TerminatedBefore' { $q['dateOfTermination'] = ConvertTo-UKGProDateFilter -Operator LessThan -Date $TerminatedBefore } 'TerminatedRange' { $q['dateOfTermination'] = ConvertTo-UKGProDateFilter -Operator Between ` -RangeStart $TerminatedBetweenStart -RangeEnd $TerminatedBetweenEnd } } if ($PSBoundParameters.ContainsKey('ChangedSince')) { $q['dateTimeChanged'] = ConvertTo-UKGProDateFilter -Operator GreaterThan -Date $ChangedSince } # Tag each returned record with a module-scoped TypeName so # PowerShell's default formatter picks up the compact 4-column view # defined in UKGPro.format.ps1xml. `| Format-List` on tagged objects # still shows every property (the format file deliberately defines # no ListControl for this type). Invoke-UKGProRequest -Method Get -Path '/personnel/v1/employment-details' ` -Query $q -PageSize $PageSize -MaxResults $MaxResults | ForEach-Object { $_.PSObject.TypeNames.Insert(0, 'UKGPro.EmploymentDetails') $_ } } } |