UblionConnect.psm1

$LogManagement = @{}


function Get-UblionFile {
    [CmdletBinding()]
    param($id, $filename, $path)
      #get the pdf as a file base 64 stream
       $apiGetPDF = "api/services/app/Document/GetDocumentPDF?id="+$id
       $result   = Get-LeftConnectResult -request $apiGetPDF
       $b64      = $result.result.fileBase64

       # construct the filename for the pdf
       $filename = $path+"\"+$filename
       $fileOutputPdf = $filename+".pdf"

       # convert the file from base 64 to byte and write it to disk
       $bytes    = [Convert]::FromBase64String($b64)
       [IO.File]::WriteAllBytes($fileOutputPdf, $bytes)    
   
       
       $apiGetUbl = "api/services/app/Ubl/DownloadUbl"
       $body = "{""id"": ""$id""}"
       $result   = Get-LeftConnectResult -request $apiGetUbl -body $body
       $fileOutputUbl = $filename+".xml"
       $downloadFile = "/File/DownloadTempFile?FileType="+$result.result.fileType+"&FileToken="+$result.result.fileToken+"&FileName="+$result.result.filename
     
       log -msg ("Download file to $fileOutputPdf")
       Invoke-RestMethod ((Get-LeftConnectUrlHost)+$downloadFile) -OutFile $fileOutputUbl  
   
   }

   <#
   .SYNOPSIS
   Get modified documents
    
   .DESCRIPTION
   A document is deleiered when it is changing the state and it's not send before with GetModifiedDocuments, It's a infinitely loop
    
   .EXAMPLE
   An example
    
   .NOTES
   General notes
   #>

function Get-LeftConnectResultFiles {
    [CmdletBinding()]
    param()

    $DocumentType = @{Outgoing = 25}

    $ublionConfiguration = Get-UblionConfiguration
    While ($true) {
        if( -not (Test-path $resultFolder))
        {
            mkdir $resultFolder
        }
        try {
            # Check for incoming documents
            $apiGetModifiedFiles = "api/services/app/Document/GetModifiedDocuments"
            $result = Get-LeftConnectResult -request $apiGetModifiedFiles
            if ($result.result.GetType().Name -eq "Object[]") {
                #foreach available document
                foreach ($document in $result.result){
                    Write-Host $document.type.id $DocumentType.Outgoing
                    if ($document.type.id -eq $DocumentType.Outgoing) {
                        $outbresultFolderound = Join-Path $ublionConfiguration.baseFolder  $ublionConfiguration.incomingFolderOrders
                    } 
                    else {
                        $outbresultFolderound = Join-Path $ublionConfiguration.baseFolder  $ublionConfiguration.incomingFolderInvoices
                    }
                    Get-UblionFile -id ($document.id) -filename ($document.name) -path ($outbresultFolderound)
                }
            } 
        } 
        catch {
            write-host error $_
        }
        Start-Sleep -Seconds 10
    }
}




function Start-Ublion {
    [CmdletBinding()]
    Param (
        [Parameter()] 
        [String]$WatchFolder,
        [Parameter()]
        [String]$DestinationFolder
        )
        
    # start watcher for outgoing invoices
    $ublionConfiguration = Get-UblionConfiguration

    $filter = '*.JSON'
    
    $outbound = Join-Path $ublionConfiguration.baseFolder $ublionConfiguration.outgoingFolderInvoices
    $resultFolder = Join-Path $ublionConfiguration.baseFolder $ublionConfiguration.outgoingFolderInvoices
    $fsw = New-Object IO.FileSystemWatcher $outbound, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 
    $action = {
        try{ 
            import-module UblionConnect
            
            $ublionConfiguration = Get-UblionConfiguration
            $copyFolder1 =  ($ublionConfiguration.copyLocation1)
            $copyFolder2 =  ($ublionConfiguration.copyLocation2)
            Start-Sleep -Seconds 1
            $documentCreateApi = "api/services/app/Document/Create"
            $path              = $Event.SourceEventArgs.FullPath
            $FileName          = $Event.SourceEventArgs.Name
            $hashfunction      = '[IO.File]::ReadAllLines($path)'
            $base64            = (Invoke-Expression $hashfunction).Replace("""","\""")
            $sendFile          = "{""name"": """+$FileName.Replace(".JSON","")+""",""type"": ""invoiceJson"", ""description"": ""PSUpload"",""file"": """+$base64+"""}"

            write-host ("Sending: " + "{""name"": """+$FileName.Replace(".JSON","")+""",""type"": ""invoiceJson"", ""file"": fileContent}")
            Get-LeftConnectResult -request $documentCreateApi -body $sendFile
             
            if (-not ([string]::IsNullOrEmpty($copyFolder1))) {
                $newPath = Join-Path $copyFolder1 "invoice"
                $newPath = Join-Path $newPath  $Event.SourceEventArgs.Name
                $newPath = Join-Path $newPath  (Get-Date).ToString("yyyyMMddHHmmss")
                write-host Copy file to $newPath
                mkdir $newPath
                Copy-Item  $Event.SourceEventArgs.FullPath  $newPath
                write-host Copy file to $newPath
            } else {
                Write-host "copyFolder1 1 not known $copyFolder1"
            }
            if (-not ([string]::IsNullOrEmpty($copyFolder2))) {
                mkdir $copyFolder2
                Copy-Item  $Event.SourceEventArgs.FullPath  $copyFolder2
                write-host Copy file to $copyFolder2
            } else {
                Write-host "copyFolder2 1 not known $copyFolder2"
            }

            Remove-Item $Event.SourceEventArgs.FullPath
        }
        catch {
            write-host -ForegroundColor Red $_.Exception.Message
            write-host -ForegroundColor Red $_.Exception.ItemName
            write-host "ERROR in file "$Event.SourceEventArgs.FullPath -ForegroundColor Red
        }
    }
    
    $backupscript = Register-ObjectEvent -EventName "Created" -InputObject $fsw -Action $action -MessageData $resultFolder 
    Write-Host "WatchFolder: `"Invoice To Ublion $($baseFolder)`" DestinationFolder: `"$($resultFolder)`" started. Job is in: $backupscript" -ForegroundColor Green


    #start watcher for incoming invoices
    if (-not [string]::IsNullOrEmpty($ublionConfiguration.outgoingFolderOrders)){
            $filter = '*.JSON'
            $outbound = Join-Path $ublionConfiguration.baseFolder $ublionConfiguration.outgoingFolderOrders
            $resultFolder = Join-Path $ublionConfiguration.baseFolder $ublionConfiguration.outgoingFolderOrders
            $fsw = New-Object IO.FileSystemWatcher $outbound, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 
            $action = {
                try{ 
                    import-module UblionConnect

                    
                    $ublionConfiguration = Get-UblionConfiguration
                    $copyFolder1 =  ($ublionConfiguration.copyLocation1)
                    $copyFolder2 =  ($ublionConfiguration.copyLocation2)
                    Start-Sleep -Seconds 1
                    $documentCreateApi = "api/services/app/Document/Create"
                    $path              = $Event.SourceEventArgs.FullPath
                    $FileName          = $Event.SourceEventArgs.Name
                    $hashfunction      = '[IO.File]::ReadAllLines($path)'
                    $base64            = (Invoke-Expression $hashfunction).Replace("""","\""")
                    $sendFile          = "{""name"": """+$FileName.Replace(".JSON","")+""",""type"": ""order"", ""file"": """+$base64+"""}"
                    
                    write-host ("Sending: " + "{""name"": """+$FileName.Replace(".JSON","")+""",""type"": ""order"", ""file"": fileContent}")
                    Get-LeftConnectResult -request $documentCreateApi -body $sendFile
                    if (-not ([string]::IsNullOrEmpty($copyFolder1))) {
                        $newPath = Join-Path $copyFolder1 "order"
                        $newPath = Join-Path $newPath  $Event.SourceEventArgs.Name
                        $newPath = Join-Path $newPath  (Get-Date).ToString("yyyyMMddHHmmss")
                        write-host Copy file to $newPath
                        mkdir $newPath
                        Copy-Item  $Event.SourceEventArgs.FullPath  $newPath
                    } else {
                        Write-host "copyFolder1 1 not known $copyFolder1"
                    }
                    if (-not ([string]::IsNullOrEmpty($copyFolder2))) {
                        mkdir $copyFolder2
                        Copy-Item  $Event.SourceEventArgs.FullPath  $copyFolder2
                        write-host Copy file to $copyFolder2
                    } else {
                        Write-host "copyFolder2 1 not known $copyFolder2"
                    }

                    Remove-Item $Event.SourceEventArgs.FullPath
                }
                catch {
                    write-host -ForegroundColor Red $_.Exception.Message
                    write-host -ForegroundColor Red $_.Exception.ItemName
                    write-host "ERROR in file "$Event.SourceEventArgs.FullPath -ForegroundColor Red
                }
            }
            
            $backupscript = Register-ObjectEvent -EventName "Created" -InputObject $fsw -Action $action -MessageData $resultFolder 
            Write-Host "WatchFolder: `"Order to Ublion$($baseFolder)`" DestinationFolder: `"$($resultFolder)`" started. Job is in: $backupscript" -ForegroundColor Green
        }
        Log("Start ublion watchers")


        Get-LeftConnectResultFiles
        Log("Start downloading items")
}

function Install-Ublion{
    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [String]$Tenant,
        
        # The base folder
        [Parameter(Mandatory)]
        [String]$BaseFolder,

        [System.Management.Automation.PSCredential]
        $Credential = $(Get-Credential),

        # The incoming folder for invoices from ublion
        [String]$IncomingFolder = "FromUblion",

        # The folder which contains the document to upload
        [String]$OutgoingFolder = "ToUblion",

        #the order folder
        [String]$OrderPrefix = "Order",

        #the order folder
        [String]$InvoicePrefix = "Invoice",

        ##the template folder
        [String]$TemplateFolder = "Templates",
        ##CopyLocation
        [String]$CopyLocation1 = "",
        ##CopyLocation
        [String]$CopyLocation2 = ""
    )

    Install-LeftConnectionBase -Tenant $Tenant -Credential $Credential
    $folder = Get-LeftConnectConfigurationFolder
    
    
    Install-AppData -DirectoryToCreate ($BaseFolder + "\" + $InvoicePrefix + $OutgoingFolder)
    Install-AppData -DirectoryToCreate ($BaseFolder + "\"+ $InvoicePrefix + $IncomingFolder)

    Install-AppData -DirectoryToCreate ($BaseFolder + "\"+ $InvoicePrefix + $TemplateFolder)

    if (-not [string]::IsNullOrEmpty($OrderPrefix)) {        
        
        $OutgoingFolderOrder = $OrderPrefix + $OutgoingFolder     
        $IncomingFolderOrder = $OrderPrefix + $IncomingFolder

        Install-AppData -DirectoryToCreate ($BaseFolder + "\" + $OutgoingFolderOrder)
        Install-AppData -DirectoryToCreate ($BaseFolder + "\"+  $IncomingFolderOrder)

    }
    Set-Content "$folder\ublion.cfg" (
        #Root folder for data
        $BaseFolder + "`n" + 
        # Outgoing folder invoices
        $InvoicePrefix + $OutgoingFolder + "`n" + 
        # Incoming folder invoices
        $InvoicePrefix + $IncomingFolder + "`n" +
        # Outgoing folder orders
        $OutgoingFolderOrder + "`n" + 
        # Incoming folder orders
        $IncomingFolderOrder + "`n" + 
        # Incoming template folder
        $InvoicePrefix + $TemplateFolder + "`n"+
        # Copy Location 1
        $CopyLocation1  + "`n" +
        # Copy Location 2
        $CopyLocation2  + "`n"
        )

    Log("Install ublion configuration to $folder")
}


function Remove-LeftConnectInstallation {
    $folder = Get-LeftConnectConfigurationFolder
    if (Test-Path -LiteralPath $folder) {
        Remove-Item $folder
        "LeftConnect configuration removed"
    }
}

function Get-UblionConfiguration {
    $folder = Get-LeftConnectConfigurationFolder
    $data = (Get-Content "$folder\ublion.cfg").split("`n")

    @{
        baseFolder = $data[0]
        outgoingFolderInvoices = $data[1]
        incomingFolderInvoices = $data[2]
        outgoingFolderOrders = $data[3]
        incomingFolderOrders = $data[4] 
        incomingFolderTemplate = $data[5] 
        copyLocation1 = $data[6] 
        copyLocation2 = $data[7] 
    }
}

<#
.SYNOPSIS
Upload invoice templates
 
.DESCRIPTION
Upload invoice template for footer, main and header. The template is a html file with complete styling.
 
.EXAMPLE
An example
 
.NOTES
General notes
#>
#
function Start-UploadTemplate{
    [CmdletBinding()]
    param()

    $ublionConfiguration = Get-UblionConfiguration

    $filter = '*.JSO'
    $templateFolder = Join-Path $ublionConfiguration.baseFolder $ublionConfiguration.incomingFolderTemplate

    $filter = '*.html'
    $fsw = New-Object IO.FileSystemWatcher $templateFolder, $filter -Property @{IncludeSubdirectories = $false;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'} 
    $action = {
            write-host Start uploading $Event.SourceEventArgs.FullPath 
            try{
                import-module UblionConnect
                Start-Sleep -Seconds 2
                $documentCreateApi = "api/services/app/EmailTemplate/CreateOrEdit"
                $path              = $Event.SourceEventArgs.FullPath
                $FileName          = $Event.SourceEventArgs.Name
                $hashfunction      = '[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes([IO.File]::ReadAllLines($path)))'
                $base64            = (Invoke-Expression $hashfunction).Replace("""","\""")
                $sendFile          = "{""name"": """+$FileName.replace(".html","")+""",""type"": ""INVOICE"",""description"": ""PSUpload"", ""template"": """+$base64+"""}"
                write-host request file
                Get-LeftConnectResult -request $documentCreateApi -body $sendFile
            }
            catch {
                write-host -ForegroundColor Red $_.Exception.Message
                write-host -ForegroundColor Red $_.Exception.ItemName
                write-host "ERROR in file "$Event.SourceEventArgs.FullPath -ForegroundColor Red
            }
    }
    $backupscript = Register-ObjectEvent -EventName "Changed" -InputObject $fsw -Action $action -MessageData $resultFolder 
    Write-Host "Template watcher is started. WatchFolder: `"$($templateFolder)`" Job is in: $ backupscript" -ForegroundColor Green    
}





function Start-LeftConnectJobFile{
    param ($taskInformation)
}

function Get-LeftConnectReleaseNotes {
    $logData = @(
                    "24/10/2020: Updating template service",
                    "20/08/2020: Fix logic to route order to outgoing folder",
                    "22/07/2020: Add order ",
                    "15/07/2020: Added order functionality, remove connection code, make order folder ",
                    "24/02/2022: Create Remote Controller",
                    "27/10/2022: Add channel for remote controller and sql threading jobs, setting default thread to 2 with a startup frequency of 5 seconds"
                )
    Write-host $logData
}

function Start-LeftConnectSelfUpdate{
param()
    Update-Module ublionconnect
    Import-Module ublionconnect

}

    



function Get-LeftConnectResult{
[CmdletBinding()]
param($request, $body, $token)


    $urlHost = Get-LeftConnectConfigurationFolder
    $headers = @{"Authorization"="Bearer "+$token;}
    $requestUrl = $urlHost + $request
    Log("Requesting url: $requestUrl")
    try {
        if ($body) {
            $answer = Invoke-RestMethod $requestUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8" -Headers $headers
        } else {
            $answer = Invoke-RestMethod $requestUrl -Headers $headers
        } 
        } catch {
           
            write-host "Token not accepected. Try renewing"
           
            $token = Get-LeftConnectToken -force $true
            $headers = @{"Authorization"="Bearer "+$token;}
            if ($body) {
                $answer = Invoke-RestMethod $requestUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8" -Headers $headers
            } else {
                $answer = Invoke-RestMethod $requestUrl -Headers $headers
            }
    }
}

 function Get-LeftConnectResult{
        [CmdletBinding()]
        param($request, $body)
        $token = Get-LeftConnectToken
        $headers = @{"Authorization"="Bearer "+$token;}
        $requestUrl = (Get-LeftConnectUrlHost) + $request
        Log("Requesting url: $requestUrl")
        try {
            if ($body) {
                $answer = Invoke-RestMethod $requestUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8" -Headers $headers
            } else {
                $answer = Invoke-RestMethod $requestUrl -Headers $headers
            } } catch {
                write-host "Token not accepected. Try renewing"
                if ($global:token) {
                    Remove-Variable token -Scope Global
                }
                $token = Get-LeftConnectToken -force $true
                $headers = @{"Authorization"="Bearer "+$token;}
            if ($body) {
                $answer = Invoke-RestMethod $requestUrl -Method Post -Body $body -ContentType "application/json; charset=utf-8" -Headers $headers
            } else {
                $answer = Invoke-RestMethod $requestUrl -Headers $headers
            }
        }

        return $answer
    }
    function Get-LeftConnectRemoteJob{
        param ($configuration)
            $channelId = ""
            #$configuration = Get-LeftConnectSqlConfiguration
            if ($configuration.channelId) {
                $channelId = "?channelId=$($configuration.channelId)"
            }

            $getTask= "api/services/app/RemoteControl/GetAssignment$channelId"
    

            #Get the job from the server
            $job = (Get-LeftConnectResult -request $getTask).result
            if (-not $job){
                return $false
            }
            Start-JobExecution -job $job   
            return $true  
    }


    


function Start-JobExecution {
    param ($job)
        $deliverResult = "api/services/app/RemoteControl/SetDeliveries"
        
        Log("Receive the following job: $job")
        if ($job.Action -eq "SQL") {
            $result = Start-LeftConnectJobSql -taskInformation $job
            $result | Add-Member -MemberType NoteProperty -Name "Id" -value $job.Id -Force -ErrorAction SilentlyContinue
        } elseif ($job.Action -eq "PIPELINE_CREATE") {
            $result = Create-Pipeline -taskInformation $job
            $result | Add-Member -MemberType NoteProperty -Name "Id" -value $job.Id -Force -ErrorAction SilentlyContinue
        } elseif ($job.Action -eq "PIPELINE_REMOVE") {
            $result = Remove-Pipeline -taskInformation $job
            $result | Add-Member -MemberType NoteProperty -Name "Id" -value $job.Id -Force -ErrorAction SilentlyContinue
        } elseif ($job.Action -eq "FILE") {
            $result = Start-LeftConnectJobFile -taskInformation $job
            $result | Add-Member -MemberType NoteProperty -Name "Id" -value $job.Id -Force -ErrorAction SilentlyContinue
        } elseif ($job.Action -eq "SELFUPDATE") {
            $result = [PSCustomObject]@{
                success = $false
                message = Start-LeftConnectSelfUpdate
            }
        }else {
            $result = [PSCustomObject]@{
                success = $false
                message = ("There is no handler known for given action: " + $job.Action)
            }
        }

        # Send result to server
        $result | Add-Member -MemberType NoteProperty -Name "CreationDate" -value (Get-Date).ToString("o") 
        Get-LeftConnectResult -request $deliverResult -body  ($result | ConvertTo-Json)
        

        if ($result.success) {
            Remove-Variable result
            Get-LeftConnectRemoteJob
        }
        Remove-Variable result
}

Export-ModuleMember -function  Install-Ublion
Export-ModuleMember -function  Install-LeftConnectRemoteControllerSQL
Export-ModuleMember -function  Get-UblionFile
Export-ModuleMember -function  Get-LeftConnectResultFiles
Export-ModuleMember -function  Get-LeftConnectUrlHost
Export-ModuleMember -function  Get-LeftConnectToken
Export-ModuleMember -function  Get-LeftConnectResult
Export-ModuleMember -function  Start-Ublion 
Export-ModuleMember -function  Start-UploadTemplate
Export-ModuleMember -function  Get-LeftConnectReleaseNotes
Export-ModuleMember -function  Remove-LeftConnectInstallation
Export-ModuleMember -function  Get-LeftConnectLog
Export-ModuleMember -function  Start-LeftConnectJobSql
Export-ModuleMember -function  Start-LeftConnectJobSqlThread
Export-ModuleMember -function  Get-LeftConnectRemoteJob
Export-ModuleMember -function  Start-LeftConnectSqlQuery
Export-ModuleMember -function  Start-LeftConnectSelfUpdate
Export-ModuleMember -function  Start-LeftConnectRemoteListener