Public/Projects.ps1


## Projects

<#
.SYNOPSIS
    Gets the projects from a TM instance.
 
.DESCRIPTION
    The `Get-TMProject` function gets projects from a TM instance specified in a TMSession object.
 
    By default it calls the REST endpoint of a TM server.
    A value of "$false" can be passed to the -UseAPI parameter to call the Web Service endpoint instead.
 
.PARAMETER TMSession
    Specifies the name of the TMSession whose projects will be fetched.
 
.PARAMETER CurrentProject
    Gets the TMSession.UserContext.Project property of a TMSession object and returns a corresponding TMProject object.
 
.PARAMETER UseAPI
    If a value of $false is passed to this parameter, the function uses web service calls to get the project data.
 
    NOTE:Currently, the REST Endpoint and the Web Services endpoint return different set of properties.
        For more information check the TMProject class source code.
 
.PARAMETER Project
Gets a project where the Project Name or Project Code matches the specified value.
 
.PARAMETER ResetIDs
 
.NOTES
    An existing TMSession needs to be created before Get-TMProject can be used.
 
.INPUTS
    You can pipe a TMSession object or a string with the name of an existing TMSession.
 
.OUTPUTS
    [TMProject]
        This function outputs a TMProject class object.
 
.EXAMPLE
    Get the current project, as specified in the TMSession.UserContext.Project property of the TMSession
    Get-TM-Project -Current
 
.EXAMPLE
    Get a list of projects from a TMSession named 'Default'
    Get-TMProject -TMSession 'Default'
 
.EXAMPLE
    Get a list of projects from a TMSession named 'Default', using web service calls instead of a REST endpoint.
    Get-TMProject -TMSession 'Default'
#>

function Get-TMProject {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)][psobject]$TMSession = 'Default',
        [Alias('Current')][Parameter(Mandatory = $false)][Switch]$CurrentProject,
        [Parameter(Mandatory = $false)][Bool]$UseAPI = $true,
        [Alias('Name', 'ProjectCode', 'ProjectName')][Parameter(Mandatory = $false, Position = 0)][string]$Project,
        [Parameter(Mandatory = $false)][Switch]$ResetIDs
    )
    begin {
        $PSBoundParameters.Remove('UseWebServices') | Out-Null
    }
    process {
        try {
            if ($UseAPI) {
                Get-TMProjectRestApi @PSBoundParameters
            } else {
                Get-TMProjectWebService @PSBoundParameters
            }
        } catch {
            throw $_
        }

    }
    end {
    }
}
function Enter-TMProject {
    param(
        [Parameter(Mandatory = $false)][psobject]$TMSession = 'Default',
        [Parameter(Mandatory = $false, ParameterSetName = 'ByProjectId', Position = 0)][int]$ProjectID,
        [Alias('Project')][Parameter(
            Mandatory = $false,
            ParameterSetName = 'ByProjectNameOrCode',
            Position = 0)][string]$ProjectNameOrCode
    )

    $TMSession = Get-TMSession $TMSession

    ## If either the Project ID or Project Code were known, they could be used.
    ## However, support for changing based just on the project name is possible

    switch ($PSCmdlet.ParameterSetName) {
        'ByProjectId' {
            $Project = Get-TMProject -Project $ProjectID -TMSession $TMSession
        }

        'ByProjectNameOrCode' {
            $Project = Get-TMProject -Project $ProjectNameOrCode -TMSession $TMSession
        }
    }

    if (-not $Project.Id) {
        $idType = $PSCmdlet.ParameterSetName -replace '^By'
        $projectVar = Get-Variable -Name $idType
        throw 'Project with {1}="{0}" does not exist. Please create it and run the script again.' -f $projectVar.Value, $idType
    }

    $uri = 'https://{0}/{1}/{2}' -f $TMSession.TMServer, 'tdstm/ws/project/viewEditProject', $Project.Id
    $response = Invoke-WebRequest -Method Get -Uri $uri -WebSession $TMSession.TMWebSession -SkipCertificateCheck:$TMSession.AllowInsecureSSL

    if ($response.StatusCode -in @(200, 204)) {
        $newProject = ($Response.Content | ConvertFrom-Json).data.projectInstance
        $TMSession.UserContext.project.id = $newProject.id
        $TMSession.UserContext.project.name = $newProject.name

        ## The code property has not been consistent in builds between 4.7 -> 6.0-alpha. Simply force it
        Add-Member -InputObject $TMSession.UserContext.Project -NotePropertyName 'code' -NotePropertyValue $newProject.projectCode -Force

        if ($VerbosePreference -eq 'Continue') {
            Write-Host 'Project has been changed to: ' -NoNewline
            Write-Host $ProjectName -ForegroundColor Cyan
        }
    } else {
        throw 'Unable to Set Projects.'
    }
}

    function New-TMProject {
        <#
    .SYNOPSIS
    Creates a Transition Manager project in a TM instance.
 
    .DESCRIPTION
    Sends a REST API request to a TM instance to create a project and returns a TMProject object with the new project details if created successfully.
 
    .PARAMETER Name
    The project Name
 
    .PARAMETER TMSession
    The name of the Transition Manager session
 
    .PARAMETER Company
    The TM Client name. It should already exist in Transition Manager.
 
    .PARAMETER Code
    The Project Code of the project.
 
    .PARAMETER StartDate
    The start date of the project. This parameter expects a date in the "yyyy-MM-ddTHH:mm:ssZ" format. If not specified, the current date and time will be used as the start date.
 
    .PARAMETER EndDate
    The end date of the project. This parameter expects a date in the "yyyy-MM-ddTHH:mm:ssZ" format. If not specified, the current date and time a year from now will be used as the end date.
 
    .PARAMETER UseAPI
 
 
    .EXAMPLE
    New-TMProjectRestApi -Name 'Test Project' -TMSession 'Default' -Company 'TDS'
    Creates a project named 'Test Project' in the TransitionManager instance in the TMSession named 'Default', if it does not exist.
 
    .OUTPUTS
    One ore more TMProject objects
    #>

        param(
            [Parameter(Mandatory = $true)]
            [string]$Name,

            [Parameter(Mandatory = $false)]
            [string]$Company = 'TM Demo',

            [Parameter(Mandatory = $false)]
            [ValidateLength(1, 20)]
            [string]$Code = $Name,

            [Parameter(Mandatory = $false)]
            [psobject]$TMSession = 'Default',

            [Parameter(Mandatory = $false)]
            [DateTime]$StartDate = (Get-Date -AsUTC),

            [Parameter(Mandatory = $false)]
            [DateTime]$EndDate = (Get-Date -AsUTC).AddYears(1),

            [Parameter(Mandatory = $false)]
            [Bool]$UseAPI = $true,

            [Parameter(Mandatory = $false)]
            [Switch]$Passthru
        )

        begin {

            try {
                ## Get Session Configuration
                $TMSession = Get-TMSession $TMSession
                #Get "Company" ('Client' in TM) id.
                $ClientId = (Get-TMCompany -Name $Company -TMSession $TMSession.Name).Id
            } catch {
                throw $_
            }
        }

        process {
            try {
                if ($UseAPI) {

                    $RestBody = @{
                        name              = $Name
                        projectType       = 'Standard'
                        projectCode       = $Code
                        clientId          = $ClientId
                        collectMetrics    = $true
                        defaultBundleName = 'TBD'
                        startDate         = $StartDate.ToString('yyyy-MM-ddTHH:mm:ssZ')
                        completionDate    = $EndDate.ToString('yyyy-MM-ddTHH:mm:ssZ')
                    }

                    $Response = Invoke-TMRestMethod -Api project -Method Post -BodyParams $RestBody
                    return [TMProject]::new($Response)
                } else {
                    $WebServiceParams = @{
                        Name      = $Name
                        Company   = $Company
                        Code      = $Code
                        TMSession = $TMSession
                        StartDate = $StartDate
                        EndDate   = $EndDate
                        Passthru  = $Passthru
                    }

                    New-TMProjectWebService @WebServiceParams
                }
            } catch {
                throw $_
            }
        }
        end {

        }
    }

    function Get-TMProjectWebService {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $false)][psobject]$TMSession = 'Default',
            [Alias('Name', 'ProjectCode', 'ProjectName')][Parameter(Mandatory = $false, Position = 0)][string]$Project,
            [Parameter(Mandatory = $false)][Switch]$ResetIDs
        )

        begin {
            ## Get Session Configuration
            $TMSession = Get-TMSession $TMSession

            #Honor SSL Settings
            $TMCertSettings = @{SkipCertificateCheck = $TMSession.AllowInsecureSSL }
            # Format the uri
            $instance = $instance = $TMSession.TMServer.Replace('/tdstm', '').Replace('https://', '').Replace('http://', '')
            $uri = "https://$instance/tdstm/ws/projects"

        }

        process {

            try {
                $response = Invoke-WebRequest -Method Get -Uri $uri -WebSession $TMSession.TMWebSession @TMCertSettings
            } catch {
                throw $_
            }

            if ($response.StatusCode -in 200, 204) {
                $Results = ($response.Content | ConvertFrom-Json).data | ForEach-Object { [TMProject]::New($_) }
            } else {
                throw 'Unable to collect Projects.'
            }

            if ($ResetIDs) {
                ## Clear Active Projects
                for ($i = 0; $i -lt $Results.Count; $i++) {
                    $Results[$i].id = $null
                }
            }

            if ($Project) {
                $Results = $Results | Where-Object {
                    $_.name -eq $Project -or $_.projectCode -eq $Project
                }
            }

            return $Results
        }

        end {

        }
    }
    function Get-TMProjectRestApi {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $false)][psobject]$TMSession = 'Default',
            [Alias('Current')][Parameter(Mandatory = $false)][Switch]$CurrentProject,
            [Alias('Name', 'ProjectCode', 'ProjectName')][Parameter(Mandatory = $false, Position = 0)][string]$Project,
            [Parameter(Mandatory = $false)][Switch]$ResetIDs
        )

        begin {
            ## Get Session Configuration
            $TMSession = Get-TMSession $TMSession
            $Api = $CurrentProject ? 'project/{0}' -f $TMSession.userContext.Project.id : 'project'
        }

        process {

            $Response = Invoke-TMRestMethod -Api $Api -Method Get
            $Results = $Response | ForEach-Object { [TMProject]::New($_) }

            if ($ResetIDs) {
                ## Clear Active Projects
                foreach ($Result in $Results) {
                    $Result.Id = $null
                }
            }

            if ($Project) {
                $Results = $Results | Where-Object {
                    $_.name -eq $Project -or $_.projectCode -eq $Project
                }
            }

            return $Results
        }

        end {

        }
    }

    function Remove-TMProject {
        <#
    .SYNOPSIS
    Deletes a Transition Manager project in a TM instance.
 
    .DESCRIPTION
    Sends a REST API request to a TM instance to delete a project and returns a TMProject object with the deleted project details if deleted successfully.
 
    .PARAMETER Name
    The project name of the project to be deleted.
 
    .PARAMETER TMSession
    The name of the Transition Manager session
 
    .EXAMPLE
    Remove-TMProject -Name 'Test Project' -TMSession 'Default'
    Deletes a project named 'Test Project' in the TransitionManager instance in the TMSession named 'Default', if it exists.
 
    .OUTPUTS
    A TMProject object.
    #>

        param(
            [Parameter(Mandatory = $true)]
            [string]$Name,

            [Parameter(Mandatory = $false)]
            [psobject]$TMSession = 'Default'
        )

        begin {
            try {
                $TMSession = Get-TMSession $TMSession
                $Project = Get-TMProject -Project $Name -TMSession $TMSession
                $ProjectId = $Project.Id
            } catch {
                throw $_
            }
            if ( $Project.Count -gt 1 ) {
                throw 'More than 1 project found with given Name "{1}": IDs {0}' -f
                $($Project.id -join ', '),
                $Name
            }
        }

        process {
            Invoke-TMRestMethod -Api project/$ProjectID -Method Delete
            $okMessage = "Project '{0}' (id: {1}) has been successfully deleted." -f
            $Project.Name, $Project.Id
            Write-Host $okMessage
        }

    }