Scripts/WorkAreaUpdates/CDOT_UpdatePWStructures_v01.ps1

#####################################################################################################################################################################################################################
##############################| |####################################################################################################################################################################################
##############################| |#
############## ########| |# Name : CDOT ProjectWise Project Structures Document Update Tool
########### #####| |# Type : Script
######### ####### ####| |# Purpose : Update ProjectWise Documents with Project Info from CDOTDATA Database
######## ############ ####| |# Author : Adrian Crowfoot
####### ##### ##### ####| |# Creation Date : 01/23/2020
############## ##### #####| |# Modified By :
############# ### ######| |# Modified Date :
########## #######| |# Script Version : 1.1
######## ##########| |# PowerShell Version : 5.1.16299.1146
######## ##############| |# ProjectWise Version : 10.00.03.167
######### #########| |# PWPS Module Version : 10.0.2.1
######## ###### ########| |# PWPS_DAB Module Version : 1.16.3.0
####### ######### #######| |# PWPS_CDOT Module Version : 1.0.1.0
####### ########## #######| |#
###### ######### ########| |# Requirements:
###### #### ########| |# - Ability to log into a ProjectWise Datasource with Administrative privileges.
###### ##########| |# - Data Table using Get-PWRichProjectReport and other parameters
######### #############| |# - Logged into a ProjectWise datasource.
##############################| |# -
##############################| |#
#####################################################################################################################################################################################################################
##
## Description/Notes:
## - [AJC 20200123] Initial creation
## - [AJC 20200127] Updated to leverage two new functions in PWPS_CDOT: New-CDOTPWAssetDocument and Update-CDOTPWAssetDocument
## -
## -
##
#####################################################################################################################################################################################################################
##
## This script is provided for example purposes only. Bentley makes no warranty as to the effectiveness of this script in a specific situation or for a specific user.
## Use of this script or a similar script in a production environment is entirely at the risk of the user. Bentley suggests extensive testing before deployment.
##
#####################################################################################################################################################################################################################

#Requires -Version 5.0
#Requires -Modules @{ModuleName="PWPS_DAB";ModuleVersion='1.16.0.0'}
#Requires -Modules @{ModuleName="PWPS_CDOT";ModuleVersion='1.0.1.0'}
##Requires -RunAsAdministrator

<#PSScriptInfo
 
.VERSION 1.1
 
.GUID
 
.AUTHOR adrian.crowfoot@state.co.us
 
.COMPANYNAME Colorado DOT
 
.TAGS ProjectWise
 
.EXTERNALMODULEDEPENDENCIES
 PWPS_DAB
 PWPS_CDOT
 
.REQUIREDSCRIPTS
 CDOT_GetPWRichProjectDataTable_v01
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
#>



[CmdletBinding()]
param(

    #############################################################################################
    # Parameters to select pertinent data from a Data Table (DataTable Parameter Set)
    #############################################################################################
    [Parameter(
            HelpMessage = 'Datatable listing input project paths and project numbers',
            Mandatory =$true,
            ParameterSetName ='DataTable')]
    [System.Data.DataTable] $dtPWRichProjects, # Input Rich Project Datatable
    [Parameter(
            HelpMessage = 'Work Area Properties Type',
            Mandatory =$true,
            ParameterSetName ='DataTable')]
    [String]$PWProjectNumberProperty,

    #############################################################################################
    # Parameters to select pertinent data from a list of projects (ArrayList Parameter Set)
    #############################################################################################
    [Parameter(
            HelpMessage = 'Array listing input project numbers',
            Mandatory =$true,
            ParameterSetName ='ArrayList')]
    [String[]] $ProjectCodes, # Input Rich Project Datatable
    
    ###########################################################################################
    # Define SQL Parameters
    ###########################################################################################

    # SQL Server Information (uses Windows Authentication)
    [Parameter(
            HelpMessage = "SQL Server that houses input database and table",
            Mandatory = $true )]
    [string] $SQLServer, # = 'IntProdListener',
    [Parameter(
            HelpMessage = "SQL Server Instance that houses input database and table",
            Mandatory = $true )]
    [string] $SQLInstanceName, # = 'Default',
    [Parameter(
            HelpMessage = "SQL database that contains input table(s)",
            Mandatory = $true )]
    [string] $SQLDatabase, # = 'CDOTDATA',


    ###########################################################################################
    # Define Parameters for the Input Table
    ###########################################################################################

    # Define table to read
    [Parameter(
            HelpMessage = "Name of Table that contains the assets",
            Mandatory = $true )]
    [string] $inputTableName, # = 'PROJ_STRUCTURES',

    # Define project and asset ID columns and additional column names
    # NOTE: For now, the column names in the input datable need to match the column names in the PW Environment
    [Parameter(
            HelpMessage = "Project Code Column Name (must match column name in PW Environment)",
            Mandatory = $true )]
    [string] $projectIDColumnName, # = 'projCode',
    [Parameter(
            HelpMessage = "Asset Code Column Name (must match column name in PW Environment)",
            Mandatory = $true )]
    [string] $assetIDColumnName, # = 'assetID',
    [Parameter(
            HelpMessage = "Asset Name Column Name (must match column name in PW Environment)",
            Mandatory = $true )]
    [string] $assetNameColumnName, # = 'assetCode',

    ###########################################################################################
    # Define Parameters for the Environment that tracks the Assets
    ###########################################################################################
    [Parameter(
            HelpMessage = "PW Environment that tracks the Assets",
            Mandatory = $true )]
    [string] $assetPWEnvironmentName, # = 'CDOT Data - Project Highways',
    [Parameter(
            HelpMessage = "Prefix for naming assets",
            Mandatory = $true )]
    [string] $PWDocumentNamePrefix, # = "ST",
    [Parameter(
            HelpMessage = "PW Path to store asset documents",
            Mandatory = $true )]
    [string]$PWFolderRootPath, # = "04 Admin Configuration\Project Structures\",

    ###########################################################################################
    # Script and Log File Information
    ###########################################################################################
    [ValidateNotNullOrEmpty()]
    [ValidateScript( { Test-Path -Path $_ -PathType Container })]
    [Parameter( 
            HelpMessage = "Location of script file.",
            Mandatory = $true,
        Position = 3 )]
    [string] $Path,    
    [ValidateNotNullOrEmpty()]
    [Parameter(
            HelpMessage = "Log file to be generated for each run of the script.",
            Mandatory = $true,
        Position = 7 )]
    [string] $LogFilePathName

)

BEGIN {
    $CmdletName = $MyInvocation.MyCommand.Name
    
    Write-PWPSLog -Message " - " -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
    Write-PWPSLog -Message "[BEGIN] Entering Update Project Structures Documents script." -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
    
    $ScriptStartTime = Get-Date
    Write-PWPSLog -Message "[BEGIN] Start time: $ScriptStartTime" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
    
    #region Check Datatable for Unique Values and rows
        try {
            if ($dtPWRichProjects) { # Process datatable
                $projectList = $dtPWRichProjects.Rows.$PWProjectNumberProperty | Sort-Object -Unique | Where-Object $PWProjectNumberProperty -ne 0 | Where-Object $PWProjectNumberProperty -ne ''
                if($projectList.Count -eq 0) {
                    throw "No Projects to Process"
                }
                Write-PWPSLog -Message "[BEGIN] $($projectList.Count) distinct $($projectList.Count) values in Data table" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
            }
            else { # Process array
                $projectList = $ProjectCodes | Sort-Object -Unique
                if($projectList.Count -eq 0) {
                    throw "No Projects to Process"
                }
                Write-PWPSLog -Message "[BEGIN] $($projectList.Count) distinct Project Codes in Array" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
            }
            

            # SQL Connection string to load from correct instance of CDOTDATA
            $SQLConnectionString = "Server=$SQLServer; Database=$SQLDatabase; Integrated Security=true;Connect Timeout=30"

        }
        catch {
            $Line = $($Error[0].InvocationInfo.ScriptLineNumber)
            $ErrorMessage = $($Error[0].Exception.Message)      
            Write-PWPSLog -Message "[BEGIN] Occurred on line: $Line. $ErrorMessage" -Path $LogFilePathName -Level Warn -Cmdlet $CmdletName
            Write-PWPSLog -Message "[BEGIN] Exiting Script." -Path $LogFilePathName -Level Warn -Cmdlet $CmdletName
            break
        } # End Try Catch
        
    #endregion Check Datatable for Unique Values and rows

} #End BEGIN

PROCESS {
    # Build Datatable with all Asset Information for Projects stored in ProjectWise


    #########################################################################################
    #########################################################################################
    # FINISH PROCESS TOMORROW - 01/24/2020
    # We have $SQLConnectionString and $projectList[] from BEGIN block

    # Cycle through each project in array
    foreach ($projectCode in $projectList) {
          
        # We have the following to build the table
        # $SQLConnectionString
        # $inputTableName = 'PROJ_STRUCTURES'
        # $assetPWEnvironmentName = 'CDOT Data - Project Structures'
        # $assetIDColumnName = 'assetID'
        # $assetNameColumnName = 'assetCode'
        
        # Select all structure rows from SQL table for project (don't add assetID yet)
        $sqlAssetStatement = "SELECT PSPID $projectIDColumnName, 'ST' assetType, STRUCTUREID $assetNameColumnName,
                              MANDT, SEQNR, IMTYPE, PROGCODE, ROUTE, REFPT, STRTYPE, RUN_LEN_REF_POINT, USEKEY, COUNTY, CON_DT, RDCS
                              FROM $inputTableName
                              WHERE PSPID = '$projectCode'"

        $dtProjectAssetRows = Select-CDOTSQLDataTable -SQLConnectionString $SQLConnectionString -SqlQuery $sqlAssetStatement -TableName $inputTableName

        # Select all structure documents from PW for project
        $arrProjectAssetDocs = Get-PWDocumentsBySearch -FolderPath $PWFolderRootPath -Attributes @{$projectIDColumnName = $projectCode}

        $NumberOfProjectAssetRows = $dtProjectAssetRows.Rows.Count
        $NumberOfProjectAssetDocs = $arrProjectAssetDocs.Count

        if ($NumberOfProjectAssetRows -ge 1) {
            Write-PWPSLog -Message "[PROCESS] $projectCode - Found $($dtProjectAssetRows.Rows.Count) Structures in Input Table ($inputTableName)" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
            
            # Add column to table for Asset ID
            $dtProjectAssetRows.Columns.Add($assetIDColumnName,'int')
            
            foreach ($assetRow in $dtProjectAssetRows.Rows) {
                # Set projectId, assetID and assetName
                $projectID = $assetRow.$projectIDColumnName
                $assetID = $dtProjectAssetRows.Rows.IndexOf($assetRow) + 1
                $assetName = $assetRow.$assetNameColumnName
                
                # Assign assetID to assetRow as row number
                $assetRow.$assetIDColumnName = $dtProjectAssetRows.Rows.IndexOf($assetRow)+1

                $assetLookupAttributes = @{
                    $projectIDColumnName = $assetRow.$projectIDColumnName
                    $assetIDColumnName = $assetRow.$assetIDColumnName
                    }

                if($assetDocument = Get-PWDocumentsBySearch -Attributes $assetLookupAttributes -Environment $assetPWEnvironmentName -GetAttributes){
    
                    # Update EXISTING Asset document using Update-CDOTPWAssetDocument Function in PWPS_CDOT
                    $Splat_UpdateAssetDocument = @{
                        assetDocument = $assetDocument
                        assetRow = $assetRow
                        projectIDColumnName = $projectIDColumnName
                        assetIDColumnName = $assetIDColumnName
                        assetNameColumnName = $assetNameColumnName
                        Path = $Path
                        LogFilePathName = $LogFilePathName
                        CmdletName = $CmdletName
                    }                    
                    Update-CDOTPWAssetDocument @Splat_UpdateAssetDocument 
                    $msg = "$projectCode/$assetID ($assetName) EXISTS - FINISHED PROCESSING"
                    Write-PWPSLog -Message "[PROCESS] $msg" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName

                } # end if document exists
                else {
                    # Create NEW Asset document using New-CDOTPWAssetDocument Function in PWPS_CDOT
                    $Splat_NewAssetDocument = @{
                        assetRow = $assetRow
                        projectIDColumnName = $projectIDColumnName
                        assetIDColumnName = $assetIDColumnName
                        PWDocumentNamePrefix = $PWDocumentNamePrefix
                        PWFolderRootPath = $PWFolderRootPath
                        Path = $Path
                        LogFilePathName = $LogFilePathName
                        CmdletName = $CmdletName
                    }
                    New-CDOTPWAssetDocument @Splat_NewAssetDocument
                    Write-PWPSLog -Message "[PROCESS] [$projectCode/$assetID] ($assetName) ROUTE WAS ADDED" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName

                } # end else to create new asset document

            } # next $assetRow

        } # end if ($NumberOfProjectAssetRows -ge 1)
        else {
            Write-PWPSLog -Message "[PROCESS] $projectCode - No Structures Found in Input Table ($inputTableName)" -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
        
        }

    } # Next projectCode

    # Get Table from CDODATA


    # Cycle through each line in table
        # If document exists, check attribute values
            # Create new hash table to store updated values

            # If attribute value differs,
                # Add to hash table

            # Else
                # Don't add to Hash Table

            # If hash table has keys, update attributes to document

        # Else, create new document and add attributes


    #########################################################################################
    #########################################################################################


} # end PROCESS

END {
    $ScriptEndTime = Get-Date
    Write-PWPSLog -Message "[END] It took $([Math]::Round($ScriptEndTime.Subtract($ScriptStartTime).TotalMinutes, 2)) minutes to complete the process." -Path $LogFilePathName -Level Info -Cmdlet $CmdletName

    Write-PWPSLog -Message "[END] Leaving script." -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
    Write-PWPSLog -Message " - " -Path $LogFilePathName -Level Info -Cmdlet $CmdletName
     
} # end END