Patch/Get-PatchInfo.ps1

<#
.SYNOPSIS
    Provides information about latest patches installed on each level
.DESCRIPTION
    Provides information about latest patches installed on each level
.EXAMPLE
    Get-PatchInfo.ps1 -instanceName n721
    Outputs latest patch numbers on each level
 
    Level Latest
    ----- ------
        1 3
        3 2
.EXAMPLE
    Get-PatchInfo.ps1 -instanceName n721 -serverName BCserver01 -port 7048
.EXAMPLE
    Get-PatchInfo -instanceName n721 1 3 | Format-Table
    Outputs list of objects for 3-rd patch on Core level
.EXAMPLE
    Get-PatchInfo -instanceName n721 | Get-PatchInfo -instanceName n721 | Format-Table
    Outputs list of bjects for all latest patches
.NOTES
 
#>

function Get-PatchInfo {
    [alias("gpai")]
    [CmdletBinding()]
    param(
        # Destination BC instance where objects should be imported to.
        [Parameter(Mandatory = $false, ValueFromPipeline, Position = 1)]
        [ValidateScript( { $_ -ne ""} )]
        [string]$instanceName = $PatchHelperConfig.DefaultInstance,
        # Level of the patch you interested in
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName, Position = 2)]
        $level = $null,
        # Number of the patch you interested in
        [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName, Position = 3)]
        $number = $null,
        # Address of BC server where source instance is hosted.
        [Parameter(Mandatory = $false)]
        [string]$serverName = "localhost",
        # Port of API endpoint of source BC instance.
        [Parameter(Mandatory = $false)]
        [int]$port
    )
    begin {
        $ErrorActionPreference = "Stop"
        if (!$port) {
            if ($serverName -ne "localhost") {
                throw "The port parameter is mandatory if serverName is specified as it can not be determined automatically."
            }
            Import-NavModule -Service
            $port = Get-NAVServerConfiguration $instanceName -KeyName ODataServicesPort
            Write-Verbose "Port automatically detected as $port"
        }
    }
    process {
        $destBaseUrl = "http://$serverName`:$port/$instanceName/api/v1.0/companies"
        $company = (Invoke-RestMethod -Uri ($destBaseUrl) -UseDefaultCredentials -ErrorAction Stop).value[0].id

        if ($null -ne $level -and $null -ne $number) {
            $destUrl = "$destBaseUrl($company)/tfsPatches?`$filter=Level eq $level and Number eq $number"
            $current = (Invoke-RestMethod -Uri $destUrl -UseDefaultCredentials -Method Get -ContentType "application/json").Value
            $destUrl = "$destBaseUrl($company)/tfsPatchLines?`$filter=Patch_ID eq $($current.ID)"
            $info = (Invoke-RestMethod -Uri $destUrl -UseDefaultCredentials -Method Get -ContentType "application/json").Value | `
                    Select-Object -Property @{ Name = "Level"; Expression = { $level } }, @{ Name = "Number"; Expression = { $number } }, Type, ID, File_Type, Version, Patch_ID
        }
        else {
            $lvls = if ($null -ne $level) { $level } else { (1, 2, 3) }
            $info = $lvls | % {
                $destUrl = "$destBaseUrl($company)/tfsPatches?`$filter=Level eq $_&`$top=1&`$orderby=Number desc"
                $current = (Invoke-RestMethod -Uri $destUrl -UseDefaultCredentials -Method Get -ContentType "application/json").Value
                if ($current) {
                    [PSCustomObject]@{ Level = $_; Number = $current[0].Number; }
                }
            }
        }

        $info
    }
}

. (Join-Path $PSScriptRoot "Cmdlets\Misc\ArgumentCompleter.ps1")
Register-ArgumentCompleter -CommandName Get-PatchInfo -ParameterName instanceName -ScriptBlock $InstanceNameArgumentCompleter

Export-ModuleMember -Alias "gpai" -Function "Get-PatchInfo"