Public/Get-AtwsInvoiceInfo.ps1
#Requires -Version 4.0 <# .COPYRIGHT Copyright (c) ECIT Solutions AS. All rights reserved. Licensed under the MIT license. See https://github.com/ecitsolutions/Autotask/blob/master/LICENSE.md for license information. #> Function Get-AtwsInvoiceInfo { <# .SYNOPSIS This function collects information about a specific Autotask invoice object and returns a generic powershell object with all relevant information as a starting point for import into other systems. .DESCRIPTION The function accepts an invoice object or an invoice id and makes a special API call to get a complete invoice description, including billingitems. For some types of billingitems additional information may be collected. All information is collected and stored in a PSObject which is returned. .INPUTS An Autotask invoice object or an invoice id .OUTPUTS A custom PSObject with detailed information about an invoice .EXAMPLE $Invoice | Get-AtwsInvoiceInfo Gets information about invoices passed through the pipeline .EXAMPLE Get-AtwsInvoiceInfo -InvoiceID $Invoice.id Gets information about invoices based on the ids passed as a parameter .NOTES NAME: Get-AtwsInvoiceInfo #> [cmdletbinding( DefaultParameterSetName = 'By_parameters' )] Param ( [Parameter( Mandatory = $true, ValueFromPipeLine = $true, ParameterSetName = 'Input_Object' )] [Parameter( Mandatory = $true, ValueFromPipeLine = $true, ParameterSetName = 'Input_Object_as_XML' )] [Parameter( Mandatory = $true, ValueFromPipeLine = $true, ParameterSetName = 'Input_Object_as_XLSX' )] [Autotask.Invoice[]] $InputObject, [Parameter( Mandatory = $true, ParameterSetName = 'By_parameters' )] [Parameter( Mandatory = $true, ParameterSetName = 'By_parameters_as_XML' )] [Parameter( Mandatory = $true, ParameterSetName = 'By_parameters_as_XLSX' )] [string[]] $InvoiceId, [Parameter( Mandatory = $true, ParameterSetName = 'Input_Object_as_XML' )] [Parameter( Mandatory = $true, ParameterSetName = 'By_parameters_as_XML' )] [switch] $XML, [Parameter( Mandatory = $true, ParameterSetName = 'Input_Object_as_XLSX' )] [Parameter( Mandatory = $true, ParameterSetName = 'By_parameters_as_XLSX' )] [switch] $XLSX, [Parameter( ParameterSetName = 'Input_Object_as_XML' )] [Parameter( ParameterSetName = 'Input_Object_as_XLSX' )] [Parameter( ParameterSetName = 'By_parameters_as_XML' )] [Parameter( ParameterSetName = 'By_parameters_as_XLSX' )] [String] $OutputFile ) begin { # Enable modern -Debug behavior if ($PSCmdlet.MyInvocation.BoundParameters['Debug'].IsPresent) { $DebugPreference = 'Continue' } Write-Debug ('{0}: Begin of function' -F $MyInvocation.MyCommand.Name) if (-not($Script:Atws.integrationsValue)) { # Not connected. Try to connect, prompt for credentials if necessary Connect-AtwsWebAPI } # Empty container to return with results if ($XML.IsPresent) { $result = New-Object XML.XmlDocument $root = $result.CreateNode('element', 'invoice_batch_generic', $null) $null = $result.AppendChild($root) } else { $result = @() } # If $OutputFile is relative, make sure it is relative to $PWD, not module directory if ($OutputFile) { if (-not(Split-Path -Path $OutputFile -IsAbsolute)) { $OutputFile = Join-Path $PWD -ChildPath $OutputFile } } } process { # Input was by object. Extract invoice ids into an array and proceed if ($PSCmdlet.ParameterSetName -eq 'Input_Object') { $InvoiceId = $InputObject.id } # Get detailed invoice info through special API call. Have to call # API once for each invoice. Second parameter says we want the result # as XML. Actually we don't, but the alternative (HTML) is worse. Write-Verbose ('{0}: Asking for details on Invoice IDs {1}' -F $MyInvocation.MyCommand.Name, ($InvoiceId -join ', ')) ForEach ($id in $InvoiceId) { # The API call. Make sure to query the correct WebServiceProxy object # specified by the $Prefix name. If the Id does not exist we get a # SOAP exception for some inexplicable reason try { [Xml]$invoiceInfo = $Script:Atws.GetInvoiceMarkup($Script:Atws.integrationsValue, $id, 'XML') } catch { Write-Warning ('{0}: FAILED on Invoice ID {1}. No data returned.' -F $MyInvocation.MyCommand.Name, $id) # try the next ID Continue } Write-Verbose ('{0}: Converting Invoice ID {1} to a PSObject' -F $MyInvocation.MyCommand.Name, $id) if ($XML.IsPresent) { # Import node with deep clone = $true $batch = $result.ImportNode($invoiceInfo.invoice_batch_generic.invoice_batch, $true) $account = $result.ImportNode($invoiceInfo.invoice_batch_generic.account, $true) $null = $batch.LastChild.AppendChild($account) $null = $result.FirstChild.AppendChild($batch) } else { $result += $invoiceInfo.invoice_batch_generic | ConvertFrom-XML } } } end { if ($XLSX.IsPresent) { Write-Verbose ('{0}: Output as XLSX has been requested, loading ImportExcel module.' -F $MyInvocation.MyCommand.Name) # Import the ImportExcel module or fail Import-Module -Name ImportExcel -ErrorAction Stop # Make Excel package $excelOptions = @{ PassThru = ($OutputFile) -xor $true # If ($outputfile), no passthrough AutoSize = $true AutoFilter = $true ClearSheet = $true TableName = 'AutotaskInvoiceInfo' WorksheetName = 'AutotaskInvoiceInfo' } if ($OutputFile) { # Add .xlsx file extension if missing if (-not($OutputFile -like '*.xlsx')) { $OutputFile = '{0}{1}' -f $OutputFile, '.xlsx' } $excelOptions['Path'] = $OutputFile } if ($excelOptions.Passthru) { Write-Verbose ('{0}: Returning {1} lines as an Excel Package ' -F $MyInvocation.MyCommand.Name, $result.account.invoice.invoice_item.count) } else { Write-Verbose ('{0}: Writing output to file {1}' -F $MyInvocation.MyCommand.Name, $OutputFile) } $result = $result.account.invoice.invoice_item | Export-Excel @excelOptions } elseif ($OutputFile -and $XML.IsPresent) { # Add .xml file extension if missing if (-not($OutputFile -like '*.xml')) { $OutputFile = '{0}{1}' -f $OutputFile, '.xml' } Write-Verbose ('{0}: Writing output to file {1}' -F $MyInvocation.MyCommand.Name, $OutputFile) $result.save($OutputFile) } Write-Debug ('{0}: End of function' -F $MyInvocation.MyCommand.Name) If (-not($OutputFile)) { return $result } } } |