Public/Employees/Set-UKGEmployee.ps1

function Set-UKGEmployee {
    <#
    .SYNOPSIS
        Updates an existing employee in the UKG HR Service Delivery system.

    .DESCRIPTION
        Updates employee properties using either PUT (full replacement) or PATCH (partial update).

    .PARAMETER Id
        The unique identifier of the employee to update.

    .PARAMETER ExternalId
        The external identifier of the employee to update.

    .PARAMETER Email
        The employee's email address.

    .PARAMETER FirstName
        The employee's first name.

    .PARAMETER LastName
        The employee's last name.

    .PARAMETER EmployeeNumber
        The employee number.

    .PARAMETER OrganizationId
        The organization ID the employee belongs to.

    .PARAMETER HireDate
        The employee's hire date.

    .PARAMETER TerminationDate
        The employee's termination date.

    .PARAMETER ManagerId
        The ID of the employee's manager.

    .PARAMETER Title
        The employee's job title.

    .PARAMETER Department
        The employee's department.

    .PARAMETER Status
        The employee's status (active, terminated, etc.).

    .PARAMETER Properties
        Hashtable of properties to update.

    .PARAMETER InputObject
        A hashtable or PSCustomObject containing the properties to update.

    .PARAMETER Patch
        Use PATCH method for partial update (default). If not specified with Properties/InputObject, uses PUT.

    .PARAMETER Replace
        Use PUT method for full replacement.

    .EXAMPLE
        Set-UKGEmployee -Id "emp123" -Title "Senior Developer"

    .EXAMPLE
        Set-UKGEmployee -ExternalId "EXT001" -Properties @{ department = "Engineering" }

    .EXAMPLE
        Get-UKGEmployee -Id "emp123" | Set-UKGEmployee -Status "terminated"

    .OUTPUTS
        UKG.Employee object representing the updated employee.
    #>

    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'ById')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory, ParameterSetName = 'ById', ValueFromPipelineByPropertyName)]
        [Parameter(Mandatory, ParameterSetName = 'ByIdInput', ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias('EmployeeId')]
        [string]$Id,

        [Parameter(Mandatory, ParameterSetName = 'ByExternalId')]
        [Parameter(Mandatory, ParameterSetName = 'ByExternalIdInput')]
        [ValidateNotNullOrEmpty()]
        [string]$ExternalId,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$Email,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$FirstName,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$LastName,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$EmployeeNumber,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$OrganizationId,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [datetime]$HireDate,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [datetime]$TerminationDate,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$ManagerId,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$Title,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [string]$Department,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [ValidateSet('active', 'terminated', 'pending', 'inactive')]
        [string]$Status,

        [Parameter(ParameterSetName = 'ById')]
        [Parameter(ParameterSetName = 'ByExternalId')]
        [hashtable]$Properties,

        [Parameter(Mandatory, ParameterSetName = 'ByIdInput')]
        [Parameter(Mandatory, ParameterSetName = 'ByExternalIdInput')]
        [object]$InputObject,

        [Parameter()]
        [switch]$Patch,

        [Parameter()]
        [switch]$Replace
    )

    process {
        # Determine the endpoint
        $endpoint = if ($ExternalId) {
            "/employees/by_external_id/$ExternalId"
        }
        else {
            "/employees/$Id"
        }

        # Build the request body
        $body = @{}

        if ($InputObject) {
            if ($InputObject -is [hashtable]) {
                $body = $InputObject.Clone()
            }
            else {
                foreach ($prop in $InputObject.PSObject.Properties) {
                    if ($prop.Name -notin @('id', 'created_at', 'updated_at', 'PSTypeName')) {
                        $body[$prop.Name] = $prop.Value
                    }
                }
            }
        }
        else {
            # Build from parameters
            if ($Email) { $body['email'] = $Email }
            if ($FirstName) { $body['first_name'] = $FirstName }
            if ($LastName) { $body['last_name'] = $LastName }
            if ($EmployeeNumber) { $body['employee_number'] = $EmployeeNumber }
            if ($OrganizationId) { $body['organization_id'] = $OrganizationId }
            if ($HireDate) { $body['hire_date'] = $HireDate.ToString('yyyy-MM-dd') }
            if ($TerminationDate) { $body['termination_date'] = $TerminationDate.ToString('yyyy-MM-dd') }
            if ($ManagerId) { $body['manager_id'] = $ManagerId }
            if ($Title) { $body['title'] = $Title }
            if ($Department) { $body['department'] = $Department }
            if ($Status) { $body['status'] = $Status }

            # Merge additional properties
            if ($Properties) {
                foreach ($key in $Properties.Keys) {
                    $body[$key] = $Properties[$key]
                }
            }
        }

        if ($body.Count -eq 0) {
            Write-Warning "No properties specified to update."
            return
        }

        # Determine HTTP method
        $method = if ($Replace) { 'PUT' } else { 'PATCH' }

        $identifier = if ($ExternalId) { $ExternalId } else { $Id }

        if ($PSCmdlet.ShouldProcess($identifier, "Update Employee ($method)")) {
            $response = Invoke-UKGRequest -Endpoint $endpoint -Method $method -Body $body

            if ($response) {
                $response.PSObject.TypeNames.Insert(0, 'UKG.Employee')
            }

            return $response
        }
    }
}

function Remove-UKGEmployee {
    <#
    .SYNOPSIS
        Removes (terminates) an employee from the UKG HR Service Delivery system.

    .DESCRIPTION
        Sets the employee status to terminated. Note: This typically doesn't delete the record.

    .PARAMETER Id
        The unique identifier of the employee to remove.

    .PARAMETER TerminationDate
        The termination date. Defaults to today.

    .EXAMPLE
        Remove-UKGEmployee -Id "emp123"

    .EXAMPLE
        Remove-UKGEmployee -Id "emp123" -TerminationDate (Get-Date).AddDays(14)

    .OUTPUTS
        UKG.Employee object representing the terminated employee.
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [Alias('EmployeeId')]
        [string]$Id,

        [Parameter()]
        [datetime]$TerminationDate = (Get-Date)
    )

    process {
        if ($PSCmdlet.ShouldProcess($Id, 'Terminate Employee')) {
            $body = @{
                status           = 'terminated'
                termination_date = $TerminationDate.ToString('yyyy-MM-dd')
            }

            $response = Invoke-UKGRequest -Endpoint "/employees/$Id" -Method PATCH -Body $body

            if ($response) {
                $response.PSObject.TypeNames.Insert(0, 'UKG.Employee')
            }

            return $response
        }
    }
}