Public/GeneratedValues/Reset-JIMGeneratedValueDecision.ps1

# Copyright (c) Tetron Limited. All rights reserved.
# Licensed under the Tetron Commercial License. See LICENSE file in the project root.

function Reset-JIMGeneratedValueDecision {
    <#
    .SYNOPSIS
        Tries generated values held for a decision again: releases their held exports so the next export run tries
        the same values.
 
    .DESCRIPTION
        For when the clash behind a held value has been resolved in the target (the other account renamed or
        removed there). The held export is released and the next export run tries the same value; if the target
        rejects it again, it is held for a decision again. Values whose rename has been allowed are left as they
        are.
 
        Whatever it covers, this is one request: a pipeline of held values is collected and sent together. Each
        value released is recorded as its own Activity, so every object's history says who released it.
 
    .PARAMETER Id
        The IDs of the values to try again. Accepts held values from Get-JIMGeneratedValueDecision through the
        pipeline. Combines with the other criteria rather than replacing them.
 
    .PARAMETER ConnectedSystemId
        Try again every held value involving one Connected System.
 
    .PARAMETER SyncRuleId
        Try again every held value generated by one Synchronisation Rule's Attribute Flows.
 
    .PARAMETER MetaverseObjectId
        Try again every held value of one Metaverse Object.
 
    .PARAMETER AllDecisions
        Try again every value needing a decision. Required when nothing else narrows the request, so a command that
        names no criteria cannot act on everything by accident.
 
    .PARAMETER Force
        Skips the confirmation prompt.
 
    .OUTPUTS
        How many values were released. Zero is a valid outcome: a value already released, or whose rename has been
        allowed, no longer matches.
 
    .EXAMPLE
        Reset-JIMGeneratedValueDecision -SyncRuleId 2
 
        Tries again every value held from Synchronisation Rule 2, after confirmation.
 
    .EXAMPLE
        Get-JIMGeneratedValueDecision -Status NeedsDecision -ConnectedSystemId 3 | Reset-JIMGeneratedValueDecision -Force
 
        Tries again every value involving Connected System 3 that needs a decision, in one request.
 
    .EXAMPLE
        $result = Reset-JIMGeneratedValueDecision -AllDecisions -WhatIf
 
        Shows that every value needing a decision would be tried again, without doing it.
 
    .LINK
        Get-JIMGeneratedValueDecision
        Approve-JIMGeneratedValueRename
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
    [OutputType('JIM.GeneratedValueDecisionActionResponse')]
    param(
        [Parameter(ValueFromPipelineByPropertyName)]
        [guid[]]$Id,

        [Parameter()]
        [int]$ConnectedSystemId,

        [Parameter()]
        [int]$SyncRuleId,

        [Parameter()]
        [guid]$MetaverseObjectId,

        [Parameter()]
        [switch]$AllDecisions,

        [Parameter()]
        [switch]$Force
    )

    begin {
        # Collected here and sent in end: one request for the whole pipeline.
        $collectedIds = [System.Collections.Generic.List[guid]]::new()
    }

    process {
        if ($Id) {
            foreach ($valueId in $Id) {
                $collectedIds.Add($valueId)
            }
        }
    }

    end {
        if (-not $script:JIMConnection) {
            Write-Error "You are not connected to JIM. Run Connect-JIM -Url <your JIM URL> to authenticate, then try again."
            return
        }

        # An empty pipeline is a successful no-op: "try again everything held" on a day nothing is held.
        $named = $PSBoundParameters.ContainsKey('ConnectedSystemId') -or $PSBoundParameters.ContainsKey('SyncRuleId') -or $PSBoundParameters.ContainsKey('MetaverseObjectId')
        if ($collectedIds.Count -eq 0 -and $PSCmdlet.MyInvocation.ExpectingInput -and -not $named) {
            Write-Verbose "Nothing reached Reset-JIMGeneratedValueDecision from the pipeline; there is nothing to try again."
            return
        }

        $body = @{}
        if ($collectedIds.Count -gt 0) { $body.ids = @($collectedIds | ForEach-Object { $_.ToString() }) }
        if ($PSBoundParameters.ContainsKey('ConnectedSystemId')) { $body.connectedSystemId = $ConnectedSystemId }
        if ($PSBoundParameters.ContainsKey('SyncRuleId')) { $body.syncRuleId = $SyncRuleId }
        if ($PSBoundParameters.ContainsKey('MetaverseObjectId')) { $body.metaverseObjectId = $MetaverseObjectId.ToString() }

        if ($body.Count -eq 0) {
            if (-not $AllDecisions) {
                Write-Error "This command names no generated values. Supply -Id, -ConnectedSystemId, -SyncRuleId or -MetaverseObjectId, or use -AllDecisions to try again every value needing a decision."
                return
            }

            $body.applyToAllDecisions = $true
        }

        $target = if ($collectedIds.Count -eq 1) { "1 generated value" }
        elseif ($collectedIds.Count -gt 1) { "$($collectedIds.Count) generated values" }
        elseif ($AllDecisions -and -not $named) { "every generated value needing a decision" }
        else { "the matching generated values needing a decision" }

        if (-not (Confirm-JIMAction -Cmdlet $PSCmdlet -Target $target -Action "Try again at the next export" -Force:$Force)) {
            return
        }

        Invoke-JIMApi -Endpoint '/api/v1/generated-values/decisions/try-again' -Method 'POST' -Body $body
    }
}