PSTANSS.psm1
$script:ModuleRoot = $PSScriptRoot $script:ModuleVersion = (Import-PowerShellDataFile -Path "$($script:ModuleRoot)\PSTANSS.psd1").ModuleVersion # Detect whether at some level dotsourcing was enforced $script:doDotSource = Get-PSFConfigValue -FullName PSTANSS.Import.DoDotSource -Fallback $false if ($PSTANSS_dotsourcemodule) { $script:doDotSource = $true } <# Note on Resolve-Path: All paths are sent through Resolve-Path/Resolve-PSFPath in order to convert them to the correct path separator. This allows ignoring path separators throughout the import sequence, which could otherwise cause trouble depending on OS. Resolve-Path can only be used for paths that already exist, Resolve-PSFPath can accept that the last leaf my not exist. This is important when testing for paths. #> # Detect whether at some level loading individual module files, rather than the compiled module was enforced $importIndividualFiles = Get-PSFConfigValue -FullName PSTANSS.Import.IndividualFiles -Fallback $false if ($PSTANSS_importIndividualFiles) { $importIndividualFiles = $true } if (Test-Path (Resolve-PSFPath -Path "$($script:ModuleRoot)\..\.git" -SingleItem -NewChild)) { $importIndividualFiles = $true } if ("<was compiled>" -eq '<was not compiled>') { $importIndividualFiles = $true } function Import-ModuleFile { <# .SYNOPSIS Loads files into the module on module import. .DESCRIPTION This helper function is used during module initialization. It should always be dotsourced itself, in order to proper function. This provides a central location to react to files being imported, if later desired .PARAMETER Path The path to the file to load .EXAMPLE PS C:\> . Import-ModuleFile -File $function.FullName Imports the file stored in $function according to import policy #> [CmdletBinding()] Param ( [string] $Path ) $resolvedPath = $ExecutionContext.SessionState.Path.GetResolvedPSPathFromPSPath($Path).ProviderPath if ($doDotSource) { . $resolvedPath } else { $ExecutionContext.InvokeCommand.InvokeScript($false, ([scriptblock]::Create([io.file]::ReadAllText($resolvedPath))), $null, $null) } } #region Load individual files if ($importIndividualFiles) { # Execute Preimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\preimport.ps1")) { . Import-ModuleFile -Path $path } # Import all internal functions foreach ($function in (Get-ChildItem "$ModuleRoot\internal\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Import all public functions foreach ($function in (Get-ChildItem "$ModuleRoot\functions" -Filter "*.ps1" -Recurse -ErrorAction Ignore)) { . Import-ModuleFile -Path $function.FullName } # Execute Postimport actions foreach ($path in (& "$ModuleRoot\internal\scripts\postimport.ps1")) { . Import-ModuleFile -Path $path } # End it here, do not load compiled code below return } #endregion Load individual files #region Load compiled code <# This file loads the strings documents from the respective language folders. This allows localizing messages and errors. Load psd1 language files for each language you wish to support. Partial translations are acceptable - when missing a current language message, it will fallback to English or another available language. #> Import-PSFLocalizedString -Path "$($script:ModuleRoot)\en-us\*.psd1" -Module 'PSTANSS' -Language 'en-US' function Assert-CacheRunspaceRunning { <# .Synopsis Assert-CacheRunspaceRunning .DESCRIPTION Check cache validation runspace on status .EXAMPLE PS C:\> Assert-CacheRunspaceRunning Check cache validation runspace on status .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] Param( ) Write-PSFMessage -Level Debug -Message "Check cache validationRunspace" if ([TANSS.Cache]::StopValidationRunspace -eq $true) { Write-PSFMessage -Level Debug -Message "ValidationRunspace is stopped. Going to start the runspace again" # force to stop the runspace [TANSS.Cache]::StopValidationRunspace = $true Get-PSFRunspace -Name "TANSS.LookupValidation" | Stop-PSFRunspace # Restart the runspace try { [TANSS.Cache]::StopValidationRunspace = $false Start-PSFRunspace -Name "TANSS.LookupValidation" -ErrorAction Stop -ErrorVariable invokeError } catch { Stop-PSFFunction -Message "Error Starting ValidationRunspace. Unknown module behaviour. Please restart your powershell console!" -EnableException $true -Exception $invokeError -Tag "RunSpace" throw $invokeError } } } function ConvertFrom-Base64StringWithNoPadding( [string]$Data ) { <# .SYNOPSIS Helper function build valid Base64 strings from JWT access tokens .DESCRIPTION Helper function build valid Base64 strings from JWT access tokens .PARAMETER Data The Token to convert .EXAMPLE PS C:\> ConvertFrom-Base64StringWithNoPadding -Data $data build valid base64 string the content from variable $data #> $Data = $Data.Replace('-', '+').Replace('_', '/') switch ($Data.Length % 4) { 0 { break } 2 { $Data += '==' } 3 { $Data += '=' } default { throw New-Object ArgumentException('data') } } [System.Convert]::FromBase64String($Data) } function ConvertFrom-JWTtoken { <# .SYNOPSIS Converts access tokens to readable objects .DESCRIPTION Converts access tokens to readable objects .PARAMETER TokenText The Token to convert .EXAMPLE PS C:\> ConvertFrom-JWTtoken -Token $TokenText Converts the content from variable $TokenText to an object #> [cmdletbinding()] param( [Parameter(Mandatory = $true)] [string] $TokenText ) # Validate as per https://tools.ietf.org/html/rfc7519 - Access and ID tokens are fine, Refresh tokens will not work if ((-not $TokenText.Contains(".")) -or (-not $TokenText.StartsWith("eyJ"))) { $msg = "Invalid data or not an access/refresh token. $($TokenText)" Stop-PSFFunction -Message $msg -Tag "JWT" -EnableException $true -Exception ([System.Management.Automation.RuntimeException]::new($msg)) } # Split the token in its parts $tokenParts = $TokenText.Split(".") # Work on header $tokenHeader = [System.Text.Encoding]::UTF8.GetString( (ConvertFrom-Base64StringWithNoPadding $tokenParts[0]) ) $tokenHeaderJSON = $tokenHeader | ConvertFrom-Json # Work on payload $tokenPayload = [System.Text.Encoding]::UTF8.GetString( (ConvertFrom-Base64StringWithNoPadding $tokenParts[1]) ) $tokenPayloadJSON = $tokenPayload | ConvertFrom-Json # Work on signature $tokenSignature = ConvertFrom-Base64StringWithNoPadding $tokenParts[2] # Output $resultObject = [PSCustomObject]@{ "alg" = $tokenHeaderJSON.alg "typ" = $tokenHeaderJSON.typ "kid" = $tokenHeaderJSON.kid "sub" = $tokenPayloadJSON.sub "exp" = [datetime]::new(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc).AddSeconds($tokenPayloadJSON.exp).ToLocalTime() "type" = $tokenPayloadJSON.type "signature" = $tokenSignature } $resultObject } function ConvertFrom-NameCache { <# .Synopsis ConvertFrom-NameCache .DESCRIPTION Convert Name to ID from cached TANSS.Lookup values .PARAMETER Name Name to convert into ID .PARAMETER Id Id to convert into Name .PARAMETER Type Lookup type where the name should convert from .EXAMPLE PS C:\> ConvertFrom-NameCache -Name "User X" -Type "Employee" Example .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "FromName", SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "FromName", Mandatory = $true )] [string] $Name, [Parameter( ParameterSetName = "FromId", Mandatory = $true )] [int] $Id, [Parameter(Mandatory = $true)] [ValidateSet("Companies", "Contracts", "CostCenters", "Departments", "Employees", "OrderBys", "Phases", "Tags", "Tickets", "TicketStates", "TicketTypes", "VacationAbsenceSubTypes", "VacationTypesPredefinedApi")] [string] $Type ) $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { "FromName" { Write-PSFMessage -Level Verbose -Message "Start converting '$($Name)' of type '$($Type)' to ID" if ( ([TANSS.Lookup]::$Type).ContainsValue($Name) ) { foreach ($key in [TANSS.Lookup]::$Type.Keys) { if ([TANSS.Lookup]::$Type[$key] -like $Name) { Write-PSFMessage -Level Verbose -Message "Found ID '$key' for name '$($Name)' of type '$($Type)'" return $key } } } else { Write-PSFMessage -Level Error -Message "Unable to convert '$($Name)' of type '$($Type)' in ID. Name is not in present in cache." } } "FromId" { Write-PSFMessage -Level Verbose -Message "Start converting ID '$($Id)' of type '$($Type)' to name" if ( ([TANSS.Lookup]::$Type).ContainsKey("$($Id)") ) { $output = [TANSS.Lookup]::$Type["$($Id)"] Write-PSFMessage -Level Verbose -Message "Found '$output' with ID '$($Id)' of type '$($Type)'" return $output } else { Write-PSFMessage -Level Error -Message "Unable to convert '$($Id)' of type '$($Type)' into Name. Id is not in present in cache." } } Default { Stop-PSFFunction -Message "Unhandeled ParameterSetName. Developers mistake." -EnableException $true throw } } } Function ConvertFrom-UnixEpochTime { <# .SYNOPSIS Converts UNIX Epoch Time to DateTime object .DESCRIPTION Converts UNIX Epoch Time to DateTime object .PARAMETER EpochTime The time value to convert .PARAMETER UTC convert the given Epoch without following the lcoal timezone .EXAMPLE PS C:\> ConvertFrom-UnixEpochTime -EpochTime "1641769200" Converts the content from variable $TokenText to an object #> param( # Parameter help description [Parameter( ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true )] [int[]] $EpochTime, [switch] $UTC ) Process { foreach ($item in $EpochTime) { if ($UTC) { ([datetime]'1/1/1970').AddSeconds($item) } else { [timezone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddSeconds($item)) } } } } function Format-ApiPath { <# .Synopsis Format-ApiPath .DESCRIPTION Ensure the right format and the existense of api prefix in the given path .PARAMETER Path Path to format .PARAMETER QueryParameter A hashtable for all the parameters to the api route .EXAMPLE PS C:\> Format-ApiPath -Path $ApiPath Api path data from variable $ApiPath will be tested and formatted. .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] Param( [Parameter(Mandatory = $true)] [string] $Path, [hashtable] $QueryParameter ) # Start Function Write-PSFMessage -Level System -Message "Formatting API path '$($Path)'" # receive module cental configuration for prefix on api path (default is 'backend/') $apiPrefix = Get-PSFConfigValue -FullName 'PSTANSS.API.RestPathPrefix' -Fallback "" # remove no more need slashes $apiPath = $Path.Trim('/') # check on API path prefix if (-not $ApiPath.StartsWith($apiPrefix)) { $ApiPath = $apiPrefix + $ApiPath Write-PSFMessage -Level Debug -Message "Add API prefix, formatting path to '$($ApiPath)'" } else { Write-PSFMessage -Level Debug -Message "Prefix API path already present" } # If specified, process hashtable QueryParameters to valid parameters into uri if ($MyInvocation.BoundParameters['QueryParameter'] -and $QueryParameter) { Write-PSFMessage -Level Debug -Message "Add query parameters '$([string]::Join("' ,'", $QueryParameter.Keys))'" $apiPath = "$($apiPath)?" $i = 0 foreach ($key in $QueryParameter.Keys) { if ($i -gt 0) { $apiPath = "$($apiPath)&" } if ("System.Array" -in ($QueryParameter[$Key]).psobject.TypeNames) { $parts = $QueryParameter[$Key] | ForEach-Object { "$($key)=$($_)" } $apiPath = "$($apiPath)$([string]::Join("&", $parts))" } else { $apiPath = "$($apiPath)$($key)=$($QueryParameter[$Key])" } $i++ } } # Output Result $ApiPath } function Invoke-CacheRefresh { <# .Synopsis Invoke-CacheRefresh .DESCRIPTION Invokes api calls to fill mostly used lookup values .PARAMETER Token AccessToken object to register as default connection for TANSS .EXAMPLE PS C:\> Invoke-CacheRefresh -Token $token Example .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] Param( [Parameter(Mandatory = $true)] [TANSS.Connection] $Token ) Write-PSFMessage -Level Verbose -Message "Start updating lookup cache from current tickets in TANSS" -Tag "Cache" $tickets = @() $tickets += Get-TANSSTicket -MyTickets -Token $token $tickets += Get-TANSSTicket -NotAssigned -Token $token $tickets += Get-TANSSTicket -AllTechnician -Token $token Write-PSFMessage -Level Verbose -Message "Built cache from $($tickets.count) tickets" -Tag "Cache" $null = Get-TANSSVacationAbsenceSubType -Token $token $null = Get-TANSSDepartment -Token $token $null = Get-TANSSTicketStatus -Token $token $null = Get-TANSSTicketType -Token $token } function Push-DataToCacheRunspace { <# .Synopsis Push-DataToCacheRunspace .DESCRIPTION Push meta information to runspace cache .PARAMETER MetaData The metadata PSCusomobject to push to Cache .EXAMPLE PS C:\> Push-DataToCacheRunspace -MetaData $response.meta Push meta information to runspace cache .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding( SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Alias("Meta", "Data")] $MetaData ) Write-PSFMessage -Level Debug -Message "Pushing data to cache validationRunspace" [TANSS.Cache]::Data.Add((New-Guid), $MetaData) } function Update-CacheLookup { <# .Synopsis Update-CacheLookup .DESCRIPTION Update a cache lookup hashtable with an object .PARAMETER LookupName Name of LokkupClass where to update .PARAMETER Id The Id to of the record to cache .PARAMETER Name The name of the record to cache .EXAMPLE PS C:\> Update-CacheLookup -LookupName "Departments" -Id $department.Id -Name $department.Name Update or insert the key from variable $department.Id of the cache-lookup-hashtable [TANSS.Lookup]::Departments with the name $department.Name .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding( SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [string] $LookupName, [int] $Id, [string] $Name ) if ([TANSS.Lookup]::$LookupName["$($Id)"] -notlike $Name) { if ([TANSS.Lookup]::$LookupName["$($Id)"]) { Write-PSFMessage -Level Debug -Message "Update existing id '$($Id)' in [TANSS.Lookup]::$($LookupName) with value '$($Name)'" -Tag "Cache", $LookupName [TANSS.Lookup]::$LookupName["$($Id)"] = $Name } else { Write-PSFMessage -Level Debug -Message "Insert in [TANSS.Lookup]::$($LookupName): $($Id) - '$($($Name))'" -Tag "Cache", $LookupName ([TANSS.Lookup]::$LookupName).Add("$($Id)", $Name) } } } function Connect-TANSS { <# .Synopsis Connect-TANSS .DESCRIPTION Connect to TANSS Service .PARAMETER Server Name of the service to connect to .PARAMETER Credential The credentials to login .PARAMETER LoginToken If the user needs an login token, this field must be set as well .PARAMETER Protocol Specifies if the connection is done with http or https .PARAMETER DoNotRegisterConnection Do not register the connection as default connection .PARAMETER NoCacheInit Do not query current existing tickets and various types to fill cache data for lookup types .PARAMETER PassThru Outputs the token to the console, even when the register switch is set .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Connect-TANSS -Server "tanss.company.com" -Credential (Get-Credential "username") Connects to "tanss.company.com" via HTTPS protocol and the specified credentials. Connection will be set as default connection for any further action. .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] [CmdletBinding( DefaultParameterSetName = 'Credential', SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Connection])] Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Alias("ComputerName", "Hostname", "Host", "ServerName")] [String] $Server, [Parameter( Mandatory = $true, ParameterSetName = 'Credential' )] [System.Management.Automation.PSCredential] $Credential, [Parameter(ParameterSetName = 'Credential')] [string] $LoginToken, [ValidateSet("HTTP", "HTTPS")] [ValidateNotNullOrEmpty()] [String] $Protocol = "HTTPS", [Alias('NoRegistration')] [Switch] $DoNotRegisterConnection, [switch] $NoCacheInit, [switch] $PassThru ) begin { $ApiPath = Format-ApiPath -Path "api/v1/user/login" } process { if ($protocol -eq 'HTTP') { Write-PSFMessage -Level Important -Message "Unsecure $($protocol) connection with possible security risk detected. Please consider switch to HTTPS!" -Tag "Connection" $prefix = 'http://' } else { Write-PSFMessage -Level System -Message "Using secure $($protocol) connection." -Tag "Connection" $prefix = 'https://' } if ($Server -match '//') { if ($Server -match '\/\/(?<Server>(\w+|\.)+)') { $Server = $Matches["Server"] } Remove-Variable -Name Matches -Force -Verbose:$false -Debug:$false -Confirm:$false } if ($PsCmdlet.ParameterSetName -eq 'Credential') { if (($credential.UserName.Split('\')).count -gt 1) { $userName = $credential.UserName.Split('\')[1] } else { $userName = $credential.UserName } Write-PSFMessage -Level Verbose -Message "Authenticate user '$($userName)' to service '$($Prefix)$($server)'" -Tag "Connection", "Authentication" $param = @{ "Uri" = "$($prefix)$($server)/$($ApiPath)" "Headers" = @{ "user" = $userName "password" = $credential.GetNetworkCredential().Password "logintoken" = "$($LoginToken)" } "Verbose" = $false "Debug" = $false "ErrorAction" = "Stop" "ErrorVariable" = "invokeError" } try { $response = Invoke-RestMethod @param } catch { Stop-PSFFunction -Message "Error invoking rest call on service '$($Prefix)$($server)'. $($invokeError)" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } if ($response.meta.text -like "Unsuccesful login attempt") { $msgText = "$($response.meta.text) to service '$($Prefix)$($server)'. Maybe wrong password" if (-not $LoginToken) { $msgText = "$($msgText) or LoginToken (OTP) is needed" } else { $msgText = "$($msgText) or LoginToken (OTP) wrong/expired" } Stop-PSFFunction -Message $msgText -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } if (-not $response.content.apiKey) { Stop-PSFFunction -Message "Something went wrong on authenticating user $($userName). No apiKey found in response. Unable login to service '$($Prefix)$($server)'" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } } Write-PSFMessage -Level System -Message "Creating TANSS.Connection" -Tag "Connection" $token = [TANSS.Connection]@{ Server = "$($Prefix)$($Server)" UserName = $userName EmployeeId = $response.content.employeeId EmployeeType = $response.content.employeeType AccessToken = ($response.content.apiKey | ConvertTo-SecureString -AsPlainText -Force) RefreshToken = ($response.content.refresh | ConvertTo-SecureString -AsPlainText -Force) Message = $response.meta.text TimeStampCreated = Get-Date TimeStampExpires = [datetime]::new(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc).AddSeconds($response.content.expire).ToLocalTime() TimeStampModified = Get-Date } if (-not $NoCacheInit) { Invoke-CacheRefresh -Token $token } if (-not $DoNotRegisterConnection) { # Make the connection the default connection for further commands Register-TANSSAccessToken -Token $token Write-PSFMessage -Level Significant -Message "Connected to service '($($token.Server))' as '$($token.UserName)' as default connection" -Tag "Connection" if ($PassThru) { Write-PSFMessage -Level System -Message "Outputting TANSS.Connection object" -Tag "Connection" $token } } else { Write-PSFMessage -Level Significant -Message "Connected to service '($($token.Server))' as '$($token.UserName)', outputting TANSS.Connection" -Tag "Connection" $token } } end { } } function Find-TANSSObject { <# .Synopsis Find-TANSSObject .DESCRIPTION Find a object via global search in TANSS The search has to be initiated on one of three areas. (Company, Employees, Tickets) .PARAMETER Company Initiate a search in the company area of TANSS .PARAMETER Employee Initiate a search within the employee/person database of TANSS .PARAMETER TicketPreview Initiate a search in the tickets of TANSS .PARAMETER Text The Text (id or name) to seach for .PARAMETER ShowInactive Search company records that are marked as inactive By default, only companies that are marked as "active" This is bound to company search only .PARAMETER ShowLocked Search company records that are marked as locked By default, only companies that are marked as "Unlocked" This is bound to company search only .PARAMETER CompanyId Return tickets or employees of the specified company id This is bound to ticket- and employee-search only .PARAMETER CompanyName Return tickets or employees of the specified company name This is bound to ticket- and employee-search only .PARAMETER Status Return "All", only "Active" or only "Inactive" employees. .PARAMETER GetCategories If true, categories will be fetches as well. The names are given in the "linked entities"-"employeeCategories" Default is $false .PARAMETER GetCallbacks If true, expected callbacks will be fetched as well Default is $false .PARAMETER PreviewContentMaxChars If defined, it overrides the to preview the content Default values within the api is 60 .PARAMETER ResultSize The amount of objects the query will return To avoid long waitings while query a large number of items, the api by default only query an amount of 100 items within one call .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Find-TANSSObject -Company -Text "Customer X" Search for "Customer X" within all company data .EXAMPLE PS C:\> Find-TANSSObject -TicketPreview -Text "Issue Y" Search for "Issue Y" within all tickets .EXAMPLE PS C:\> "Mister T" | Find-TANSSObject -Employee Search "Mister T" in the employee records of all companies .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "Company", PositionalBinding = $true, SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] [OutputType([TANSS.TicketPreview], [TANSS.Company], [TANSS.EmployeeSearched])] Param( [Parameter(ParameterSetName = "Company")] [switch] $Company, [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [switch] $Employee, [Parameter(ParameterSetName = "Ticket-UserFriendly")] [Parameter(ParameterSetName = "Ticket-ApiNative")] [Alias("Ticket")] [switch] $TicketPreview, [Parameter(ParameterSetName = "Company", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "Employee-UserFriendly", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "Employee-ApiNative", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "Ticket-UserFriendly", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "Ticket-ApiNative", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateLength(2, [int]::MaxValue)] [string[]] $Text, [Parameter(ParameterSetName = "Company")] [switch] $ShowInactive, [Parameter(ParameterSetName = "Company")] [switch] $ShowLocked, [Parameter(ParameterSetName = "Employee-ApiNative")] [Parameter(ParameterSetName = "Ticket-ApiNative")] [int] $CompanyId, [Parameter(ParameterSetName = "Employee-UserFriendly", Mandatory = $true)] [Parameter(ParameterSetName = "Ticket-UserFriendly", Mandatory = $true)] [string] $CompanyName, [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [ValidateSet("All", "Active", "Inactive")] [string] $Status = "All", [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [bool] $GetCategories = $false, [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [bool] $GetCallbacks = $false, [Parameter(ParameterSetName = "Ticket-UserFriendly")] [Parameter(ParameterSetName = "Ticket-ApiNative")] [int] $PreviewContentMaxChars, [Parameter(ParameterSetName = "Company")] [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [Parameter(ParameterSetName = "Ticket-UserFriendly")] [Parameter(ParameterSetName = "Ticket-ApiNative")] [int] $ResultSize, [Parameter(ParameterSetName = "Company")] [Parameter(ParameterSetName = "Employee-UserFriendly")] [Parameter(ParameterSetName = "Employee-ApiNative")] [Parameter(ParameterSetName = "Ticket-UserFriendly")] [Parameter(ParameterSetName = "Ticket-ApiNative")] [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/search" if ((-not $ResultSize) -or ($ResultSize -eq 0)) { $ResultSize = 100 } if ($Status) { switch ($Status) { "All" { $inactive = $true } "Active" { $inactive = $false } "Inactive" { $inactive = $true } Default { Stop-PSFFunction -Message "Unhandeled Status. Developers mistake." -EnableException $true -Cmdlet $pscmdlet } } } if($MyInvocation.BoundParameters['CompanyName'] -and $CompanyName) { $CompanyId = ConvertFrom-NameCache -Name CompanyName -Type "Companies" if(-not $CompanyId) { Write-PSFMessage -Level Warning -Message "No Id for company '$($Company)' found. Ticket will be created with blank value on CompanyId" } } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { "Company" { foreach ($textItem in $Text) { $body = @{ areas = @("COMPANY") query = $textItem.replace("*", "") configs = @{ company = @{ maxResults = $ResultSize } } } $response = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token if ($response.content.companies) { $countCompanyAll = ([array]($response.content.companies)).count Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - $($countCompanyAll) records returned" if (-not $ShowInactive) { $countCompanyFiltered = ([array]($response.content.companies | Where-Object { $_.inactive -like "False" })).Count Write-PSFMessage -Level Verbose -Message "Filtering companies marked as inactive - keeping $($countCompanyFiltered) of $($countCompanyAll) records" } else { $countCompanyFiltered = $countCompanyAll } if (-not $ShowLocked) { $countCompanyFiltered = $countCompanyFiltered - ([array]($response.content.companies | Where-Object { $_.lockout -like "True" })).Count Write-PSFMessage -Level Verbose -Message "Filtering companies marked as locked - keeping $($countCompanyFiltered) of $($countCompanyAll) records" } foreach ($companyItem in $response.content.companies) { # Filtering if(-not $ShowInactive) { if($companyItem.inactive -like "True") { continue } } if(-not $ShowLocked) { if($companyItem.lockout -like "True") { continue } } # Output data [TANSS.Company]@{ BaseObject = $companyItem Id = $companyItem.id } } } else { Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - no records returned from global search" } } } {$_ -like "Employee-ApiNative" -or $_ -like "Employee-UserFriendly"} { foreach ($textItem in $Text) { $body = @{ areas = @("EMPLOYEE") query = $textItem configs = @{ employee = @{ maxResults = $ResultSize } } } if($CompanyId) { $body.configs.employee.Add("companyId", $CompanyId) } if($Status) { $body.configs.employee.Add("inactive", $inactive) } if("GetCategories" -in $PSCmdlet.MyInvocation.BoundParameters.Keys) { $body.configs.employee.Add("categories", $GetCategories) } if("GetCallbacks" -in $PSCmdlet.MyInvocation.BoundParameters.Keys) { $body.configs.employee.Add("callbacks", $GetCallbacks) } $response = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token if ($response.content.employees) { $countEmployeeAll = ([array]($response.content.employees)).count Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - $($countEmployeeAll) records returned" Push-DataToCacheRunspace -MetaData $response.meta foreach ($employeeItem in $response.content.employees) { # Output data [TANSS.EmployeeSearched]@{ BaseObject = $employeeItem Id = $employeeItem.id } } } else { Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - no records returned from global search" } } } {$_ -like "Ticket-ApiNative" -or $_ -like "Ticket-UserFriendly"} { foreach ($textItem in $Text) { $body = @{ areas = @("TICKET") query = $textItem configs = @{ employee = @{ maxResults = $ResultSize } } } if($CompanyId) { $body.configs.employee.Add("companyId", $CompanyId) } if($PreviewContentMaxChars) { $body.configs.employee.Add("previewContentMaxChars", $PreviewContentMaxChars) } $response = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token if ($response.content.Tickets) { $countTicketsAll = ([array]($response.content.Tickets)).count Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - $($countTicketsAll) records returned" Push-DataToCacheRunspace -MetaData $response.meta foreach ($ticketItem in $response.content.Tickets) { # Output data [TANSS.TicketPreview]@{ BaseObject = $ticketItem Id = $ticketItem.id } } } else { Write-PSFMessage -Level Verbose -Message "API response: $($response.meta.text) - no records returned from global search" } } } Default { Stop-PSFFunction -Message "Unhandeled ParameterSetName. Developers mistake." -EnableException $true -Cmdlet $pscmdlet } } } end {} } function Get-TANSSDepartment { <# .Synopsis Get-TANSSDepartment .DESCRIPTION Get department from TANSS .PARAMETER Id Id of the department to get .PARAMETER Name Name of the department to get .PARAMETER IncludeEmployeeId Include assigned employees .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSDepartment Get departments from TANSS .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "All", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Department])] Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ById" )] [int[]] $Id, [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ByName" )] [string[]] $Name, [switch] $IncludeEmployeeId, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning if ($IncludeEmployeeId) { Write-PSFMessage -Level Verbose -Message "IncludeEmployeeId switch is specified, going to ask for linked IDs" -Tag "Department", "IncludeEmployeeId" $deparmentsWithEmployeeId = Invoke-TANSSRequest -Type GET -ApiPath "api/v1/companies/departments?withEmployees=true" -Token $Token | Select-Object -ExpandProperty content $departments = foreach ($department in $departments) { [array]$_employeeIds = $deparmentsWithEmployeeId | Where-Object id -like $department.id | Select-Object -ExpandProperty employeeIds $department | Add-Member -MemberType NoteProperty -Name employeeIds -Value $_employeeIds $department } Remove-Variable -Name deparmentsWithEmployeeId, _employeeIds, deparment -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false -ErrorAction:Ignore -WarningAction:Ignore -InformationAction:Ignore } else { $departments = Invoke-TANSSRequest -Type GET -ApiPath "api/v1/employees/departments" -Token $Token | Select-Object -ExpandProperty content } [array]$filteredDepartments = @() } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { "ById" { foreach ($item in $Id) { $filteredDepartments += $departments | Where-Object id -eq $item } } "ByName" { foreach ($item in $Name) { $filteredDepartments += $departments | Where-Object name -like $item } } "All" { $filteredDepartments = $departments } Default { Stop-PSFFunction -Message "Unhandled ParameterSet '$($parameterSetName)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "Department", "SwitchException", "ParameterSet" } } } end { $filteredDepartments = $filteredDepartments | Sort-Object name, id -Unique Write-PSFMessage -Level Verbose -Message "Going to return $($filteredDepartments.count) departments" -Tag "Department", "Output" foreach ($department in $filteredDepartments) { Write-PSFMessage -Level System -Message "Working on department '$($department.name)' with id '$($department.id)'" -Tag "Department" # put id and name to cache lookups Update-CacheLookup -LookupName "Departments" -Id $department.Id -Name $department.Name # output result [TANSS.Department]@{ Baseobject = $department Id = $department.id } } } } function Get-TANSSRegisteredAccessToken { <# .Synopsis Get-TANSSRegisteredAccessToken .DESCRIPTION Retrieve the registered LoginToken for default TANSS connection .EXAMPLE PS C:\> Get-TANSSRegisteredAccessToken Retrieve the registered LoginToken for TANSS .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] Param( ) begin {} process { Write-PSFMessage -Level Verbose -Message "Retrieving the registered LoginToken for '$($script:TANSSToken.UserName)' on '$($script:TANSSToken.Server)'" -Tag "AccessToken" $script:TANSSToken } end {} } function Invoke-TANSSRequest { <# .Synopsis Invoke-TANSSRequest .DESCRIPTION Invoke a API request to TANSS Server .PARAMETER Type Type of web request .PARAMETER ApiPath Uri path for the REST call in the API .PARAMETER QueryParameter A hashtable for all the parameters to the api route .PARAMETER AdditionalHeader Hashtable with additional values to put in the header of the request .PARAMETER Body The body as a hashtable for the request .PARAMETER Pdf if a PDF should be queried, this switch must be specified .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Invoke-TANSSRequest -Type GET -ApiPath "api/v1/something" Invoke a GET request to API with path api/v1/something by using the default registered token within the module .EXAMPLE PS C:\> Invoke-TANSSRequest -Type GET -ApiPath "api/v1/something" -Token $Token Invoke a GET request to API with path api/v1/something by using the explicit token from the variale $Token .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = 'Default', SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] param ( [Parameter(Mandatory = $true)] [ValidateSet("GET", "POST", "PUT", "DELETE")] [string] $Type, [Parameter(Mandatory = $true)] [string] $ApiPath, [hashtable] $QueryParameter, [hashtable] $Body, [hashtable] $AdditionalHeader, [switch] $Pdf, [TANSS.Connection] $Token ) begin { } process { } end { if(-not $Token) { $Token = Get-TANSSRegisteredAccessToken } $ApiPath = Format-ApiPath -Path $ApiPath -QueryParameter $QueryParameter # Body if ($Body) { $bodyData = $Body | ConvertTo-Json } else { $bodyData = $null } # Header $header = @{ "apiToken" = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Token.AccessToken)) } if($Pdf) { $header.Add("Accept","pdf") } if ($MyInvocation.BoundParameters['AdditionalHeader'] -and $AdditionalHeader) { foreach ($key in $AdditionalHeader.Keys) { $header.Add($key, $AdditionalHeader[$key]) } } # Invoke request $param = @{ "Uri" = "$($Token.Server)/$($ApiPath)" "Headers" = $header "Body" = $bodyData "Method" = $Type "ContentType" = 'application/json; charset=UTF-8' "Verbose" = $false "Debug" = $false "ErrorAction" = "Stop" "ErrorVariable" = "invokeError" } if ($pscmdlet.ShouldProcess("$($Type) web REST call against URL '$($param.Uri)'", "Invoke")) { Write-PSFMessage -Level Verbose -Message "Invoke $($Type) web REST call against URL '$($param.Uri)'" try { $response = Invoke-RestMethod @param Write-PSFMessage -Level System -Message "API Response: $($response.meta.text)" } catch { if($invokeError[0].Message.StartsWith("{")) { $response = $invokeError[0].Message | ConvertFrom-Json -ErrorAction SilentlyContinue } if($response) { Write-PSFMessage -Level Error -Message "$($response.Error.text) - $($response.Error.localizedText)" -Exception $response.Error.type -Tag "REST call $($Type)" } else { Write-PSFMessage -Level Error -Message "$($invokeError[0].Source) ($($invokeError[0].HResult)): $($invokeError[0].Message)" -Exception $invokeError[0].InnerException -Tag "REST call $($Type)" -ErrorRecord $invokeError[0].ErrorRecord } return } # Output $response } } } function Register-TANSSAccessToken { <# .Synopsis Register-TANSSAccessToken .DESCRIPTION Register the AccessToken as default connection setting for TANSS .PARAMETER Token AccessToken object to register as default connection for TANSS .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Register-TANSSAccessToken -Token $Token Register the LoginToken from variable $Token as a default connection for TANSS .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'Medium' )] Param( [Parameter(Mandatory = $true)] [TANSS.Connection] $Token ) begin {} process { if ($pscmdlet.ShouldProcess("AccessToken for $($Token.UserName) on '$($Token.Server)'", "Register")) { Write-PSFMessage -Level Verbose -Message "Registering AccessToken for $($Token.UserName) on '$($Token.Server)' valid until '$($Token.TimeStampExpires)'" -Tag "AccessToken" $script:TANSSToken = $Token } } end {} } function Update-TANSSAccessToken { <# .Synopsis Update-TANSSAccessToken .DESCRIPTION Updates the AccessToken from a refreshToken for TANSS connection By defaault, the new Access is registered to as default connection .PARAMETER NoCacheRefresh Do not requery tickets and various types to fill cache data for lookup types .PARAMETER DoNotRegisterConnection Do not register the connection as default connection .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the new token to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Update-TANSSAccessToken Updates the AccessToken from the default connection and register it as new AccessToken on default Connection .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] Param( [TANSS.Connection] $Token, [Alias('NoRegistration')] [Switch] $DoNotRegisterConnection, [switch] $NoCacheRefresh, [switch] $PassThru ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { if ($Token.RefreshToken) { $refreshTokenInfo = ConvertFrom-JWTtoken -TokenText ([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Token.RefreshToken))).split(" ")[1] } else { Stop-PSFFunction -Message "Invalid Token specified. No refreshToken found" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } Write-PSFMessage -Level Verbose -Message "Checking RefreshToken from TANSS.Connection of $($Token.UserName) on '$($Token.Server)'" -Tag "AccessToken", "Connection", "Authentication" if ( (Get-Date) -ge $refreshTokenInfo.exp ) { Stop-PSFFunction -Message "RefreshToken expired. Unable to refresh with current token. Please use Connect-TANSS to login again" -Tag "Connection", "Authentication" return } if ($pscmdlet.ShouldProcess("AccessToken from TANSS.Connection of $($Token.UserName) on '$($Token.Server)' with RefreshToken valid until '$($refreshTokenInfo.exp)'", "Update")) { $apiPath = Format-ApiPath -Path "api/v1/tickets/own" Write-PSFMessage -Level Verbose -Message "Updating AccessToken from TANSS.Connection of $($Token.UserName) on '$($Token.Server)' with RefreshToken valid until '$($refreshTokenInfo.exp)'" -Tag "AccessToken" $param = @{ "Uri" = "$($Token.Server)/$($ApiPath)" "Headers" = @{ "refreshToken" = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Token.RefreshToken)) } "Verbose" = $false "Debug" = $false "ErrorAction" = "Stop" "ErrorVariable" = "invokeError" } try { $response = Invoke-RestMethod @param } catch { Stop-PSFFunction -Message "Error invoking rest call on service '$($Token.Server)'. $($invokeError)" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } if ($response.meta.text -notlike "Welcome, your ApiToken is 4 hours valid.") { Stop-PSFFunction -Message "$($response.meta.text) to service '$($Token.Server)'. Apperantly, refreshToken is not valid" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } if (-not $response.content.apiKey) { Stop-PSFFunction -Message "Something went wrong on authenticating user $($Token.UserName). No apiKey found in response. Unable to refresh token from connection '$($Token.Server)'" -Tag "Connection", "Authentication" -EnableException $true -Cmdlet $pscmdlet } Write-PSFMessage -Level System -Message "Creating TANSS.Connection from refreshed AccessToken" -Tag "Connection" $token = [TANSS.Connection]@{ Server = $Token.Server UserName = $Token.UserName EmployeeId = $response.content.employeeId EmployeeType = $response.content.employeeType AccessToken = ($response.content.apiKey | ConvertTo-SecureString -AsPlainText -Force) RefreshToken = ($response.content.refresh | ConvertTo-SecureString -AsPlainText -Force) Message = $response.meta.text TimeStampCreated = $Token.TimeStampCreated TimeStampExpires = [datetime]::new(1970, 1, 1, 0, 0, 0, 0, [DateTimeKind]::Utc).AddSeconds($response.content.expire).ToLocalTime() TimeStampModified = Get-Date } if (-not $NoCacheRefresh) { Invoke-CacheRefresh -Token $token } if (-not $DoNotRegisterConnection) { # Make the connection the default connection for further commands Write-PSFMessage -Level Significant -Message "Updating AccessToken for service '($($token.Server))' as '$($token.UserName)' and register it as default connection" -Tag "Connection" Register-TANSSAccessToken -Token $token if ($PassThru) { Write-PSFMessage -Level System -Message "Outputting TANSS.Connection object" -Tag "Connection" $token } } else { Write-PSFMessage -Level Significant -Message "Updating AccessToken for service '($($token.Server))' as '$($token.UserName)'" -Tag "Connection" $token } } } end {} } function Get-TANSSEmployee { <# .Synopsis Get-TANSSEmployee .DESCRIPTION Get employees out of TANSS service. You can pipe in IDs o employee objects to get refreshed data out of the service You can also pipe in company objects to receive employees of that company .PARAMETER EmployeeId The ID of the employee to get from TANSS service .PARAMETER Employee A TANSS.Employee object to query again from the service .PARAMETER CompanyId The ID of the company to get employees from .PARAMETER Company A passed in TANSS.Company object to query employees from .PARAMETER CompanyName The name of the company to query employees from .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSEmployee -EmployeeId 2 Get the employee with ID 2 (usually the first employee created in TANSS) .EXAMPLE PS C:\> $employee | Get-TANSSEmployee Query the employee from variable $employee again .EXAMPLE PS C:\> Get-TANSSEmployee -CompanyId 100000 Get all employees from company ID 100000 (your own company) .EXAMPLE PS C:\> $company | Get-TANSSEmployee Get all employees from company $company .EXAMPLE PS C:\> Get-TANSSEmployee -CompanyName "Company X" Get all employees from "Company X" .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "Employee_ApiNative", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Employee])] Param( [Parameter( ParameterSetName = "Employee_ApiNative", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [Alias("Id")] [int[]] $EmployeeId, [Parameter( ParameterSetName = "Employee_UserFriendly", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [tanss.employee] $Employee, [Parameter( ParameterSetName = "Company_ApiNative", ValueFromPipelineByPropertyName = $true, Mandatory = $true )] [int[]] $CompanyId, [Parameter( ParameterSetName = "Company_UserFriendly", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [tanss.company] $Company, [Parameter( ParameterSetName = "Company_UserFriendlyByName", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [string[]] $CompanyName, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" # If objects are piped in -> collect IDs switch ($parameterSetName) { "Employee_UserFriendly" { $EmployeeId = $Employee.Id } "Company_UserFriendly" { $CompanyId = $Company.Id } "Company_UserFriendlyByName" { $CompanyId = foreach ($_name in $CompanyName) { Find-TANSSObject -Company -Text $_name -Token $Token -ShowLocked | Where-Object name -like $_name | Select-Object -ExpandProperty Id } } } switch ($parameterSetName) { { $_ -like "Employee_*" } { Write-PSFMessage -Level System -Message "Query personal employee record. $(([array]$EmployeeId).count) record(s)" foreach ($id in $EmployeeId) { Write-PSFMessage -Level Verbose -Message "Working on employee id $($id)" $response = Invoke-TANSSRequest -Type GET -ApiPath "api/v1/employees/$($id)" -Token $Token if ($response.meta.text -like "Object found") { # Cache refresh Push-DataToCacheRunspace -MetaData $response.meta Write-PSFMessage -Level Verbose -Message "Output employee $($response.content.name)" $output = [TANSS.Employee]@{ BaseObject = $response.content Id = $response.content.id } # ToDo: Filtering - add parameters (Isactive, FilterName, ) # Output result $output } else { Write-PSFMessage -Level Error -Message "API returned no data" } } } { $_ -like "Company_*" } { Write-PSFMessage -Level System -Message "Query corporate employee record. $(([array]$CompanyId).count) record(s)" foreach ($id in $CompanyId) { Write-PSFMessage -Level Verbose -Message "Query employee(s) for company id $($id)" $response = Invoke-TANSSRequest -Type GET -ApiPath "api/v1/companies/$($id)/employees" -Token $Token if ($response.meta.text -like "Object found") { # Cache refresh Push-DataToCacheRunspace -MetaData $response.meta foreach ($responseItem in $response.content) { Write-PSFMessage -Level Verbose -Message "Output corporate employee $($responseItem.name)" $output = [TANSS.Employee]@{ BaseObject = $responseItem Id = $responseItem.id } # ToDo: Filtering - add parameters (Isactive, FilterName, ) # Output result $output } } else { Write-PSFMessage -Level Error -Message "API returned no data" } } } Default { Stop-PSFFunction -Message "Unhandeled ParameterSetName. Developers mistake." -EnableException $true -Cmdlet $pscmdlet } } } end {} } function Get-TANSSTechnican { <# .Synopsis Get-TANSSTechnican .DESCRIPTION Gets all technicians of this system from default TANSS connection .PARAMETER Id ID of the technican to get (client side filtering) .PARAMETER Name Name of the technican to get (client side filtering) .PARAMETER FreelancerCompanyId If this parameter is given, also fetches the freelancers of this company. By default all users with a license are treated as "TANSS technicans". .PARAMETER ExcludeRestrictedLicenseUser Do not show account/ users / technicans with limited licenses .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTechnican Gets all technicians of this system .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] [OutputType([TANSS.Employee])] Param( [String[]] $Name, [int[]] $Id, [int[]] $FreelancerCompanyId, [switch] $ExcludeRestrictedLicenseUser, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } $apiPath = Format-ApiPath -Path "api/v1/employees/technicians" Assert-CacheRunspaceRunning if (-not $FreelancerCompanyId) { $FreelancerCompanyId = 0 } } process { $response = @() $response += foreach ($companyId in $FreelancerCompanyId) { $queryParameter = @{} if($MyInvocation.BoundParameters['ExcludeRestrictedLicenseUser'] -and $ExcludeRestrictedLicenseUser) { $queryParameter.Add("restrictedLicenses", $false) } else { $queryParameter.Add("restrictedLicenses", $true) } if ($companyId -ne 0) { Write-PSFMessage -Level System -Message "FreelancerCompanyId specified, compiling body to query freelancers of company '$($companyId)'" -Tag "Technican", "Freelancer" $queryParameter.Add("FreelancerCompanyId", $companyId) } $invokeParam = @{ "Type" = "GET" "ApiPath" = (Format-ApiPath -Path $apiPath -QueryParameter $queryParameter) "Token" = $Token } Invoke-TANSSRequest @invokeParam Remove-Variable -Name queryParameter, invokeParam -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore -InformationAction Ignore } if ($response) { Write-PSFMessage -Level Verbose -Message "Found $(($response.content).count) technicans" -Tag "Technican" foreach ($responseItem in $response) { # Output result foreach ($technican in $responseItem.content) { # Do filtering on name if ($MyInvocation.BoundParameters['Name'] -and $Name) { $filterSuccess = $false foreach ($filterName in $Name) { if ($technican.Name -like $filterName) { $filterSuccess = $true } } # if filter does not hit, continue with next technican if ($filterSuccess -eq $false) { continue } } # Do filtering on id if ($MyInvocation.BoundParameters['Id'] -and $Id) { $filterSuccess = $false foreach ($filterId in $Id) { if ([int]($technican.id) -eq $filterId) { $filterSuccess = $true } } # if filter does not hit, continue with next technican if ($filterSuccess -eq $false) { continue } } # Query details Write-PSFMessage -Level Verbose -Message "Getting details of '$($technican.name)' (Id $($technican.id))" -Tag "Technican" $invokeParam = @{ "Type" = "GET" "ApiPath" = (Format-ApiPath -Path "api/v1/employees/$($technican.id)") "Token" = $Token } $employeeResponse = Invoke-TANSSRequest @invokeParam if ($employeeResponse) { Push-DataToCacheRunspace -MetaData $employeeResponse.meta foreach ($employeeItem in $employeeResponse.content) { Write-PSFMessage -Level Debug -Message "Found '$($employeeItem.Name)' with id $($employeeItem.id)" # Output data [TANSS.Employee]@{ BaseObject = $employeeItem Id = $employeeItem.id } } } else { Stop-PSFFunction -Message "Unexpected error searching '$($employeeResponse.content.name)' with ID '$($technican.id)'. TANSS is unable to find details of employee" -EnableException $true -Cmdlet $pscmdlet } } } } else { Write-PSFMessage -Level Warning -Message "No technicans found." -Tag "Technican" } } end { } } function New-TANSSEmployee { <# .Synopsis New-TANSSEmployee .DESCRIPTION Create a new employee in TANSS .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE New-TANSSEmployee -Name "User, Test" Create a new employee (as technican) in your own company .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "Userfriendly", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Employee])] param ( # Fullname of the employee [Parameter( ParameterSetName = "ApiNative", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Parameter( ParameterSetName = "Userfriendly", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Alias("Fullname", "Displayname")] [string] $Name, # first name of the employee [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("Givenname")] [string] $FirstName, # Last name of the employee [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("Surname")] [string] $LastName, # Id of the salutation for this employee [Parameter(ParameterSetName = "ApiNative")] [Alias("IdSalutation")] [Int] $SalutationId = 0, # Id of the department which tis employee is assigned to [Parameter(ParameterSetName = "ApiNative")] [Alias("IdDepartment")] [Int] $DepartmentId, # Name of the department which tis employee is assigned to [Parameter(ParameterSetName = "Userfriendly")] [string] $Department, # location / room of the employee [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("Location")] [string] $Room, # Main telephone number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("TelephoneNumber")] [string] $Phone, # e-Mail address [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("EmailAddress")] [string] $Email, # if this employee is assigned to a specific car, the id goes here [Parameter(ParameterSetName = "ApiNative")] [Alias("IdCar")] $CarId = 0, # mobile telephone number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("MobilePhone")] [string] $Mobile, # initials for this employee [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [string] $Initials, # Working hour model for this employee [Parameter(ParameterSetName = "ApiNative")] [Alias("IdWorkingHourModel")] [int] $WorkingHourModelId = 0, # Id of the accounting type for this employee [Parameter(ParameterSetName = "ApiNative")] [Alias("IdAccountingType")] [int] $accountingTypeId = 0, # Private telephone number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("PrivatePhoneNumber")] [string] $PrivateNumber, # True if the employee is active [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("Active")] [bool] $IsActive = $true, # Identification number in foreign ERP system [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [string] $ERPNumber, # Fax number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("PersonalFaxNumber")] [string] $Fax, # Role for this employee [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [string] $Role, # if the employee uses a title, the id goes here [Parameter(ParameterSetName = "ApiNative")] [Alias("IdTitle")] [int] $TitleId = 0, # Language which this employee uses [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [string] $Language, # Second telephone number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("TelephoneNumberTwo")] [string] $Phone2, # second mobile telephone number [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("MobileNumberTwo")] [string] $Mobile2, # Employee birthday date [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [Alias("BirthdayDate", "DateBirthday", "DateOfBirth")] [datetime] $Birthday, # Company id of the ticket. Name is stored in the "linked entities" - "companies". Can only be set if the user has access to the company [Parameter(ParameterSetName = "ApiNative")] [Alias("CompanyAssignments", "IdCompany")] [int[]] $CompanyId, # Company name where the ticket should create for. Can only be set if the user has access to the company [Parameter(ParameterSetName = "Userfriendly")] [Alias("Company")] [String[]] $CompanyName, [Parameter(ParameterSetName = "ApiNative")] [Parameter(ParameterSetName = "Userfriendly")] [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/employees" if ($Department) { $DepartmentId = ConvertFrom-NameCache -Name $Department -Type "Departments" if (-not $DepartmentId) { Write-PSFMessage -Level Warning -Message "No Id for department '$($Department)' found. Employee will be created with blank value on departmentId" #todo implement API call for departments $DepartmentId = 0 } } if ($CompanyName) { $CompanyId = foreach ($companyItem in $CompanyName) { $_id = ConvertFrom-NameCache -Name $companyItem -Type Companies if (-not $_id) { Write-PSFMessage -Level Warning -Message "No Id for company '$($companyItem)' found. Employee will be created without assignment to this company" } else { $_id } } Remove-Variable -Name _id -Force -Confirm:$false -WhatIf:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore } if (-not $CompanyId) { $_name = ConvertFrom-NameCache -Id 100000 -Type "Companies" Write-PSFMessage -Level Important -Message "No company specified. Employee will be created within your own company $(if($_name) { "($($_name)) "})as a technican" $CompanyId = 100000 Remove-Variable -Name _name -Force -Confirm:$false -WhatIf:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "Userfriendly" -and (-not $Name)) { Write-PSFMessage -Level Error -Message "No name specified" continue } #region rest call prepare if ($Birthday) { $_birthday = Get-Date -Date $Birthday -Format "yyyy-MM-dd" } else { $_birthday = "0000-00-00" } [array]$_companies = foreach ($CompanyIdItem in $CompanyId) { @{ "companyId" = $CompanyIdItem } } if (-not $LastName) { $nameParts = $Name.split(",").Trim() if ($nameParts.Count -eq 2) { # Assuming schema "<Lastname>, <Firstname>" $LastName = $nameParts[0] } elseif ($nameParts.Count -eq 1) { $nameParts = $Name.split(" ").Trim() if ($nameParts.Count -eq 2) { # Assuming schema "<Firstname> <Lastname>" $LastName = $nameParts[1] } else { $LastName = $Name } } else { $LastName = $Name } } Remove-Variable -Name nameParts -Force -Confirm:$false -WhatIf:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore if (-not $FirstName) { $nameParts = $Name.split(",").Trim() if ($nameParts.Count -eq 2) { # Assuming schema "<Lastname>, <Firstname>" $FirstName = $nameParts[1] } elseif ($nameParts.Count -eq 1) { $nameParts = $Name.split(" ").Trim() if ($nameParts.Count -eq 2) { # Assuming schema "<Firstname> <Lastname>" $FirstName = $nameParts[0] } else { $FirstName = "" } } else { $FirstName = "" } } Remove-Variable -Name nameParts -Force -Confirm:$false -WhatIf:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore if (-not $Initials -and $FirstName -and $LastName) { $_initials = "$(([string]$FirstName)[0])$(([string]$LastName)[0])" } else { $_initials = $Initials } $body = [ordered]@{ "id" = 0 "name" = "$Name" "firstName" = "$FirstName" "lastName" = "$LastName" "salutationId" = $SalutationId "departmentId" = $DepartmentId "room" = "$Room" "telephoneNumber" = "$Phone" "emailAddress" = "$Email" "carId" = $CarId "mobilePhone" = "$Mobile" "initials" = "$_initials" "workingHourModelId" = $WorkingHourModelId "accountingTypeId" = $accountingTypeId "privatePhoneNumber" = "$PrivateNumber" "active" = $IsActive "erpNumber" = "$ERPNumber" "personalFaxNumber" = "$Fax" "role" = "$Role" "titleId" = $TitleId "language" = "$Language" "telephoneNumberTwo" = "$Phone2" "mobileNumberTwo" = "$Mobile2" "birthday" = "$_birthday" "companyAssignments" = $_companies } #endregion rest call prepare if ($pscmdlet.ShouldProcess("Employee '$($Name)' on companyID '$([string]::Join(", ", $CompanyId))'", "New")) { Write-PSFMessage -Level Verbose -Message "Creating new employee '$($Name)' on companyID '$([string]::Join(", ", $CompanyId))'" -Tag "Employee" -Data $body $response = Invoke-TANSSRequest -Type POST -ApiPath $apiPath -Body $body -Token $Token if ($response) { Write-PSFMessage -Level Verbose -Message "API Response: $($response.meta.text)" Push-DataToCacheRunspace -MetaData $response.meta [TANSS.Employee]@{ BaseObject = $response.content Id = $response.content.id } } else { Write-PSFMessage -Level Error -Message "Error creating employee, no response from API" } } } end { } } function Get-TANSSTicket { <# .Synopsis Get-TANSSTicket .DESCRIPTION Gat a ticket from TANSS service .PARAMETER Id The ticket Id (one or more) to query .PARAMETER CompanyId Get all tickets of company Id .PARAMETER MyTickets Get all tickets assigned to the authenticated account .PARAMETER NotAssigned Get all tickets not assigned to somebody .PARAMETER AllTechnician Get all tickets assigned to somebody .PARAMETER RepairTickets Get tickets marked as repair tickets .PARAMETER NotIdentified Get all unidentified tickets .PARAMETER Project Get tickets marked as a project .PARAMETER LocalTicketAdmin Get all tickets specified for a ticket admin .PARAMETER TicketWithTechnicanRole Get all tickets with a technican role .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicket Get all tickets assinged to the authenticated user .EXAMPLE PS C:\> Get-TANSSTicket -Id 100 Get ticket with Id 100 .EXAMPLE PS C:\> Get-TANSSTicket -CompanyId 12345 Get all tickets of company Id 12345 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] [CmdletBinding( DefaultParameterSetName = 'MyTickets', SupportsShouldProcess = $false, ConfirmImpact = 'Low' )] [OutputType([TANSS.Ticket])] Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "TicketId" )] [int[]] $Id, [Parameter( Mandatory = $true, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, ParameterSetName = "CompanyId" )] [int[]] $CompanyId, [Parameter( Mandatory = $false, ParameterSetName = "MyTickets" )] [Alias("Own", "OwnTickets", "MyOwn", "NyOwnTickets")] [switch] $MyTickets, [Parameter( Mandatory = $true, ParameterSetName = "NotAssigned" )] [Alias("General", "GeneralTickets")] [switch] $NotAssigned, [Parameter( Mandatory = $true, ParameterSetName = "AllTechnician" )] [Alias("TicketsAllTechnicians", "Assigned", "AssignedTickets")] [switch] $AllTechnician, [Parameter( Mandatory = $true, ParameterSetName = "RepairTickets" )] [switch] $RepairTickets, [Parameter( Mandatory = $true, ParameterSetName = "NotIdentified" )] [switch] $NotIdentified, [Parameter( Mandatory = $true, ParameterSetName = "Projects" )] [switch] [Alias("AllProjects")] $Project, [Parameter( Mandatory = $true, ParameterSetName = "LocalTicketAdmin" )] [Alias("AssignedToTicketAdmin")] [switch] $LocalTicketAdmin, [Parameter( Mandatory = $true, ParameterSetName = "TicketWithTechnicanRole" )] [switch] $TicketWithTechnicanRole, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" $response = @() # Construct query switch ($parameterSetName) { "TicketId" { # in case of "Query by Id" -> Do the query now $response += foreach ($ticketId in $Id) { Invoke-TANSSRequest -Type GET -ApiPath "api/v1/tickets/$($ticketId)" -Token $Token } } "CompanyId" { # in case of "Query by CompanyId" -> Do the query now $response += foreach ($_companyId in $CompanyId) { Invoke-TANSSRequest -Type GET -ApiPath "api/v1/tickets/company/$($_companyId)" -Token $Token } } "MyTickets" { $apiPath = Format-ApiPath -Path "api/v1/tickets/own" } "NotAssigned" { $apiPath = Format-ApiPath -Path "api/v1/tickets/general" } "AllTechnician" { $apiPath = Format-ApiPath -Path "api/v1/tickets/technician" } "RepairTickets" { $apiPath = Format-ApiPath -Path "api/v1/tickets/repair" } "NotIdentified" { $apiPath = Format-ApiPath -Path "api/v1/tickets/notIdentified" } "Projects" { $apiPath = Format-ApiPath -Path "api/v1/tickets/projects" } "LocalTicketAdmin" { $apiPath = Format-ApiPath -Path "api/v1/tickets/localAdminOverview" } "TicketWithTechnicanRole" { $apiPath = Format-ApiPath -Path "api/v1/tickets/withRole" } Default { Stop-PSFFunction -Message "Unhandeled ParameterSetName. Developers mistake." -EnableException $true -Cmdlet $pscmdlet } } # Do the constructed query, as long, as variable apiPath has a value if ($apiPath) { $response += Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token } if ($response) { Write-PSFMessage -Level Verbose -Message "Found $(($response.content).count) tickets" # Push meta to cache runspace foreach ($responseItem in $response) { Push-DataToCacheRunspace -MetaData $responseItem.meta # Output result foreach($ticket in $responseItem.content) { [TANSS.Ticket]@{ BaseObject = $ticket Id = $ticket.id } } } } else { Write-PSFMessage -Level Warning -Message "No tickets found." -Tag "Ticket" } } end { } } function Get-TANSSTicketActivity { <# .Synopsis Get-TANSSTicketActivity .DESCRIPTION Retreive support activities within a ticket .PARAMETER TicketID The ID of the ticket to receive activities of .PARAMETER Ticket TANSS.Ticket object to receive activities of .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketActivity -TicketID 555 Get all support activities from ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketActivity Get all support activities from all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketComment", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketComment", "Query" Get-TANSSTicketContent -TicketID $ticketIdItem -Type "Activity" -Token $Token | Select-Object -ExpandProperty Object } } end { } } function Get-TANSSTicketComment { <# .Synopsis Get-TANSSTicketComment .DESCRIPTION Retreive the ticket comments .PARAMETER TicketID The ID of the ticket to receive comments of .PARAMETER Ticket TANSS.Ticket object to receive comments of .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketComment -TicketID 555 Get all comments from ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketComment Get all comments from all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketComment", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketComment", "Query" Get-TANSSTicketContent -TicketID $ticketIdItem -Type "Comment" -Token $Token | Select-Object -ExpandProperty Object } } end { } } function Get-TANSSTicketContent { <# .Synopsis Get-TANSSTicketContent .DESCRIPTION Retreive the various entries from a ticket. Entries can be a comment, activity, mail, document, image .PARAMETER TicketID The ID of the ticket to receive comments of .PARAMETER Ticket TANSS.Ticket object to receive comments of .PARAMETER Type Specifies the type of content you want to get Available types: "All" = everthing within the ticket "Comment" = only comments within the ticket "Activity" = only activites within the ticket "Mail" = = only mails within the ticket "Document" = uploaded documents within the ticket "Image" = uploaded images within the ticket .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketContent -TicketID 555 Get everthing out of ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketContent -Type "Mail" Get only malis out of all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [ValidateNotNullOrEmpty()] [ValidateSet("All", "Comment", "Activity", "Mail", "Document", "Image")] [string[]] $Type = "All", [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketContent", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketContent", "Query" $content = @() # Get documents, if included in Type filter if ( ($Type | Where-Object { $_ -in @("All", "Document") }) ) { Write-PSFMessage -Level Verbose -Message "Getting documents from ticket $($ticketIdItem)" -Tag "TicketContent", "Query", "QueryDocuments" $apiPath = Format-ApiPath -Path "api/v1/tickets/$ticketIdItem/documents" $response = Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token Push-DataToCacheRunspace -MetaData $response.meta if ($response.content) { Write-PSFMessage -Level Verbose -Message "Found $($response.content.count) documents" -Tag "TicketContent", "Query", "QueryDocuments" $content += foreach ($document in $response.content) { # create output objects, but first query download uri # build api path $apiPath = Format-ApiPath -Path "api/v1/tickets/$ticketIdItem/documents/$($document.id)" # query download uri $responseDocumentUri = Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token # create output $object = [TANSS.TicketDocument]@{ BaseObject = $document Id = $document.id } if ($responseDocumentUri.content) { $object.Key = $responseDocumentUri.content.key $object.DownloadUri = Format-ApiPath -Path $responseDocumentUri.content.url } [TANSS.TicketContent]@{ TicketId = $object.TicketId Type = "Document" Id = $object.Id Date = $object.Date Text = $object.Description Object = $object } } } else { Write-PSFMessage -Level Verbose -Message "No documents found" -Tag "TicketContent", "Query", "QueryDocuments" } } # Get images, if included in Type filter if ( ($Type | Where-Object { $_ -in @("All", "Image") }) ) { Write-PSFMessage -Level Verbose -Message "Getting images from ticket $($ticketIdItem)" -Tag "TicketContent", "Query", "QueryImages" $apiPath = Format-ApiPath -Path "api/v1/tickets/$ticketIdItem/screenshots" $response = Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token Push-DataToCacheRunspace -MetaData $response.meta if ($response.content) { Write-PSFMessage -Level Verbose -Message "Found $($response.content.count) images" -Tag "TicketContent", "Query", "QueryImages" $content += foreach ($image in $response.content) { $object = [TANSS.TicketImage]@{ BaseObject = $image Id = $image.id } [TANSS.TicketContent]@{ TicketId = $object.TicketId Type = "Image" Id = $object.Id Date = $object.Date Text = $object.Description Object = $object } } } else { Write-PSFMessage -Level Verbose -Message "No images found" -Tag "TicketContent", "Query", "QueryImages" } } # Get Comments, Activities, Mails if ( ($Type | Where-Object { $_ -in @("All", "Comment", "Activity", "Mail") }) ) { Write-PSFMessage -Level Verbose -Message "Getting comments, mails and activities from ticket $($ticketIdItem)" -Tag "TicketContent", "Query", "QueryHistory" $apiPath = Format-ApiPath -Path "api/v1/tickets/history/$ticketIdItem" $response = Invoke-TANSSRequest -Type GET -ApiPath "backend/api/v1/tickets/history/$ticketID" -Token $Token Push-DataToCacheRunspace -MetaData $response.meta if ($response.content) { Write-PSFMessage -Level Verbose -Message "Found content in ticket $($ticketIdItem), going to parse content" -Tag "TicketContent", "Query", "QueryHistory" # Get comments if ( ($Type | Where-Object { $_ -in @("All", "Comment") }) ) { Write-PSFMessage -Level Verbose -Message "Working through $($response.content.comments.count) comment$(if($response.content.comments.count -gt 1) {'s'})" -Tag "TicketContent", "Query", "QueryHistory", "Comment" $content += foreach ($comment in $response.content.comments) { $object = [TANSS.TicketComment]@{ BaseObject = $comment ID = $comment.id TicketId = $ticketIdItem } [TANSS.TicketContent]@{ TicketId = $object.TicketId Type = "Comment" Id = $object.Id Date = $object.Date Text = $object.Description Object = $object } } } # Get activities if ( ($Type | Where-Object { $_ -in @("All", "Activity") }) ) { Write-PSFMessage -Level Verbose -Message "Working through $($response.content.supports.count) $(if($response.content.supports.count -gt 1) {'Activities'} else {'Activity'})" -Tag "TicketContent", "Query", "QueryHistory", "Activity" $content += foreach ($activity in $response.content.supports) { $object = [TANSS.TicketActivity]@{ BaseObject = $activity ID = $activity.id } [TANSS.TicketContent]@{ TicketId = $object.TicketId Type = "Activity" Id = $object.Id Date = $object.Date Text = $object.Description Object = $object } } } # Get mails if ( ($Type | Where-Object { $_ -in @("All", "Mail") }) ) { Write-PSFMessage -Level Verbose -Message "Working through $($response.content.mails.count) mail$(if($response.content.mails.count -gt 1) {'s'})" -Tag "TicketContent", "Query", "QueryHistory", "Mail" $content += foreach ($mail in $response.content.mails) { $object = [TANSS.TicketMail]@{ BaseObject = $mail ID = $mail.id TicketId = $ticketIdItem } [TANSS.TicketContent]@{ TicketId = $object.TicketId Type = "Mail" Id = $object.Id Date = $object.Date Text = $object.Subject Object = $object } #> } } } else { $_type = $Type | Where-Object { $_ -notlike "All" } if ($_type) { $_type = [string]::Join(', ', [array]$_type) } else { $_type = [string]::Join(', ', @("Comment", "Activity", "Mail")) } Write-PSFMessage -Level Verbose -Message "No $_type data found" -Tag "TicketContent", "Query", "QueryHistory" } } # Output result if($content) { Write-PSFMessage -Level Verbose -Message "Output $(([array]$content).count) content record$(if(([array]$content).count -gt 1){'s'}) from ticket $($ticketIdItem)" -Tag "TicketContent", "Query", "OutputResult" $content | Sort-Object Date } else { Write-PSFMessage -Level Significant -Message "No $(if($Type -notlike "All") {'matching'}) content found in ticket $($ticketIdItem)" -Tag "TicketContent", "Query", "OutputResult", "NoData" } } } end {} } function Get-TANSSTicketDocument { <# .Synopsis Get-TANSSTicketDocument .DESCRIPTION Retreive documents within a ticket .PARAMETER TicketID The ID of the ticket to receive documents of .PARAMETER Ticket TANSS.Ticket object to receive documents of .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketDocument -TicketID 555 Get all documents from ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketDocument Get all documents from all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketComment", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketComment", "Query" Get-TANSSTicketContent -TicketID $ticketIdItem -Type "Document" -Token $Token | Select-Object -ExpandProperty Object } } end { } } function Get-TANSSTicketImage { <# .Synopsis Get-TANSSTicketImage .DESCRIPTION Retreive images within a ticket .PARAMETER TicketID The ID of the ticket to receive images of .PARAMETER Ticket TANSS.Ticket object to receive images of .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketImage -TicketID 555 Get all images from ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketImage Get all images from all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketComment", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketComment", "Query" Get-TANSSTicketContent -TicketID $ticketIdItem -Type "Image" -Token $Token | Select-Object -ExpandProperty Object } } end { } } function Get-TANSSTicketMail { <# .Synopsis Get-TANSSTicketMail .DESCRIPTION Retreive mail objects within a ticket .PARAMETER TicketID The ID of the ticket to receive mails of .PARAMETER Ticket TANSS.Ticket object to receive mails of .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketMail -TicketID 555 Get all mails from ticket 555 .EXAMPLE PS C:\> $tickets | Get-TANSSTicketMail Get all mails from all tickets from variable $tickets .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int[]] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket[]] $Ticket, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $inputobjectTicketCount = ([array]$Ticket).Count Write-PSFMessage -Level System -Message "Getting IDs of $($inputobjectTicketCount) ticket$(if($inputobjectTicketCount -gt 1){'s'})" -Tag "TicketComment", "CollectInputObjects" [array]$TicketID = $Ticket.id } foreach ($ticketIdItem in $TicketID) { Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($ticketIdItem)" -Tag "TicketComment", "Query" Get-TANSSTicketContent -TicketID $ticketIdItem -Type "Mail" -Token $Token | Select-Object -ExpandProperty Object } } end { } } function Get-TANSSTicketStatus { <# .Synopsis Get-TANSSTicketStatus .DESCRIPTION Get the various status types of a ticket from tanss .PARAMETER Id The Id of the status type to get .PARAMETER Name The name of the status type to get .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketStatus Get the available status types of a ticket .EXAMPLE PS C:\> Get-TANSSTicketStatus -Id 2 Get the status types with Id 2 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "All", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.TicketStatus])] Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ById" )] [int[]] $Id, [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ByName" )] [string[]] $Name, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/tickets/status" $ticketStates = Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token | Select-Object -ExpandProperty content [array]$filteredTicketStates = @() } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { "ById" { foreach ($item in $Id) { $filteredTicketStates += $ticketStates | Where-Object id -eq $item } } "ByName" { foreach ($item in $Name) { $filteredTicketStates += $ticketStates | Where-Object name -like $item } } "All" { $filteredTicketStates = $ticketStates } Default { Stop-PSFFunction -Message "Unhandled ParameterSet '$($parameterSetName)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "TicketStatus", "SwitchException", "ParameterSet" } } } end { $filteredTicketStates = $filteredTicketStates | Sort-Object rank, id -Unique Write-PSFMessage -Level Verbose -Message "Going to return $($filteredTicketStates.count) ticket status" -Tag "TicketStatus", "Output" foreach ($ticketStatus in $filteredTicketStates) { Write-PSFMessage -Level System -Message "Working on ticketstatus '$($ticketStatus.name)' with id '$($ticketStatus.id)'" -Tag "TicketStatus" # put id and name to cache lookups Update-CacheLookup -LookupName "TicketStates" -Id $ticketStatus.Id -Name $ticketStatus.Name # output result [TANSS.TicketStatus]@{ Baseobject = $ticketStatus Id = $ticketStatus.id } } } } function Get-TANSSTicketType { <# .Synopsis Get-TANSSTicketType .DESCRIPTION Get the various types of a ticket from tanss .PARAMETER Id The Id of the ticket type to get .PARAMETER Name The name of the ticket type to get .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSTicketType Get the available ticket types .EXAMPLE PS C:\> Get-TANSSTicketType -Id 2 Get the tiket types with Id 2 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "All", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.TicketType])] Param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ById" )] [int[]] $Id, [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ByName" )] [string[]] $Name, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/tickets/types" $ticketTypes = Invoke-TANSSRequest -Type GET -ApiPath $apiPath -Token $Token | Select-Object -ExpandProperty content [array]$filteredTicketTypes = @() } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { "ById" { foreach ($item in $Id) { $filteredTicketTypes += $ticketTypes | Where-Object id -eq $item } } "ByName" { foreach ($item in $Name) { $filteredTicketTypes += $ticketTypes | Where-Object name -like $item } } "All" { $filteredTicketTypes = $ticketTypes } Default { Stop-PSFFunction -Message "Unhandled ParameterSet '$($parameterSetName)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "TicketType", "SwitchException", "ParameterSet" } } } end { $filteredTicketTypes = $filteredTicketTypes | Sort-Object Name, id -Unique Write-PSFMessage -Level Verbose -Message "Going to return $($filteredTicketTypes.count) ticket status" -Tag "TicketType", "Output" foreach ($ticketType in $filteredTicketTypes) { Write-PSFMessage -Level System -Message "Working on TicketType '$($ticketType.name)' with id '$($ticketType.id)'" -Tag "TicketType" # put id and name to cache lookups Update-CacheLookup -LookupName "TicketTypes" -Id $ticketType.Id -Name $ticketType.Name # output result [TANSS.TicketType]@{ Baseobject = $ticketType Id = $ticketType.id } } } } function New-TANSSTicket { <# .Synopsis New-TANSSTicket .DESCRIPTION Creates a ticket in the database .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> New-TANSSTicket -Title "A new Ticket" Create a ticket .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidMultipleTypeAttributes", "")] [CmdletBinding( DefaultParameterSetName = "Userfriendly", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Ticket])] param ( # Company id of the ticket. Name is stored in the "linked entities" - "companies". Can only be set if the user has access to the company [Parameter(ParameterSetName="ApiNative")] [int] $CompanyId, # Company name where the ticket should create for. Can only be set if the user has access to the company [Parameter(ParameterSetName="Userfriendly")] [String] $Company, # If the ticket has a remitter, the id goes here. Name is stored in the "linked entities" - "employees" [Parameter(ParameterSetName="ApiNative")] [Alias('ClientId')] [int] $RemitterId, # If the ticket has a remitter/client, the name of the client [Parameter(ParameterSetName="Userfriendly")] [String] $Client, # gives infos about how the remitter gave the order. Infos are stored in the "linked entities" - "orderBys" [Parameter(ParameterSetName="ApiNative")] [int] $OrderById, # gives infos about how the Client gave the order. [Parameter(ParameterSetName="Userfriendly")] [string] $OrderBy, # The title / subject of the ticket [Parameter( ParameterSetName="Userfriendly", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Parameter( ParameterSetName="ApiNative", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string] $Title, # The content / description of the ticket [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('content')] [string] $Description, # External ticket id (optional) [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('extTicketId')] [string] $ExternalTicketId, # id of employee which ticket is assigned to. Name is stored in "linked entities" - "employees" [Parameter(ParameterSetName="ApiNative")] [Alias('assignedToEmployeeId')] [int] $EmployeeIdAssigned, # Name of the employee the ticket is assigned to [Parameter(ParameterSetName="Userfriendly")] [String] $EmployeeAssigned, # id of department the ticket is assigned to. Name is stored in "linked entities" - "departments" [Parameter(ParameterSetName="ApiNative")] [Alias('assignedToDepartmentId')] [int] $DepartmentIdAssigned, # Name of the department the ticket is assigned to [Parameter(ParameterSetName="Userfriendly")] [String] $Department, # id of the ticket state. Name is give in "linked entities" - "ticketStates" [Parameter(ParameterSetName="ApiNative")] [int] $StatusId, # The name of the ticket status [Parameter(ParameterSetName="Userfriendly")] [String] $Status, # id of the ticket type. Name is give in "linked entities" - "ticketTypes" [Parameter(ParameterSetName="ApiNative")] [int] $TypeId, # The name of the ticket type [Parameter(ParameterSetName="Userfriendly")] [String] $Type, # if ticket is assigned to device / employee, linktype is given here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('LinkTypeId')] [int] $AssignmentId, # If ticket has a deadline, the date is given here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('deadlineDate')] [datetime] $Deadline, # if ticket is actually a project, this value is true [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('project')] [bool] $IsProject = $false, # if ticket is a sub-ticket of a project, the id of the project goes here. Name of the project is in the "linked entities" - "tickets" [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $ProjectId, # if the ticket is assignet to a project phase. The name of the phase is stored in the "linked entities" - "phases" [Parameter(ParameterSetName="ApiNative")] [Int] $PhaseId, # if the ticket is assignet to a project phase, the name of the phase [Parameter(ParameterSetName="Userfriendly")] [String] $Phase, # if true, this ticket is a "repair ticket" [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [Alias('repair')] [bool] $IsRepair = $false, # if ticket has a due date, the timestamp is given here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [datetime] $DueDate, # Determines the "attention" flag state of a ticket [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [ValidateSet("NO", "YES", "RESUBMISSION", "MAIL")] [string] $Attention = "NO", # If the ticket has an installation fee, this value is true [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [ValidateSet("NO", "YES", "NO_PROJECT_INSTALLATION_FEE")] [string] $InstallationFee = "NO", # Sets the installation fee drive mode. If it is set to NONE then the system config parameter "leistung.ip.fahrzeit_berechnen" will be used. If the company from the ticket has an installation fee drive mode set then that will be used instead of the system config parameter. [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [ValidateSet("NONE", "DRIVE_INCLUDED", "DRIVE_EXCLUDED")] [string] $InstallationFeeDriveMode = "NONE", #Amount for the installation fee [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $InstallationFeeAmount, # If true, the ticket shall be billed separately [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [bool] $SeparateBilling = $false, # if the ticket has a service cap, here the amount is given [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $ServiceCapAmount, # linkId of the relationship (if ticket has a relation) [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $RelationshipLinkId, # linkTypeId of the relationship (if ticket has a relation) [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $RelationshipLinkTypeId, # if the ticket as a resubmission date set, this is given here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [datetime] $ResubmissionDate, # If a resubmission text is set, this text is returned here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [string] $ResubmissionText, # Number of estimated minutes which is planned for the ticket [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [int] $EstimatedMinutes, # Determines wether the ticket is assigned to a local ticket admin or not # NONE: "normal" ticket # LOCAL_ADMIN: ticket is assigned to a local ticket admin # TECHNICIAN: local ticket admin has forwarded the ticket to a technician [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [ValidateSet("NONE", "LOCAL_ADMIN", "TECHNICIAN")] [string] $LocalTicketAdminFlag = "NONE", # if the ticket is assigned to a local ticket admin, this represents the employee (local ticket admin) who is assigned for this ticket [Parameter(ParameterSetName="ApiNative")] [int] $LocalTicketAdminEmployeeId, # if the ticket is assigned to a local ticket admin, this represents the name of the employee (local ticket admin) who is assigned for this ticket [Parameter(ParameterSetName="Userfriendly")] [ValidateNotNullOrEmpty] [string] $EmployeeTicketAdmin, # Sets the order number [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [string] $OrderNumber, # If the ticket has a reminder set, the timestamp is returned here [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [datetime] $Reminder, # When persisting a ticket, you can also send a list of tag assignments which will be assigned to the ticket [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [string[]] $Tags, [Parameter(ParameterSetName="ApiNative")] [Parameter(ParameterSetName="Userfriendly")] [TANSS.Connection] $Token ) begin { if(-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/tickets" if($EmployeeTicketAdmin) { $LocalTicketAdminEmployeeId = ConvertFrom-NameCache -Name $EmployeeTicketAdmin -Type "Employees" if(-not $LocalTicketAdminEmployeeId) { Write-PSFMessage -Level Warning -Message "No Id for employee '$($EmployeeTicketAdmin)' found. Ticket will be created with blank value on TicketAdminEmployee" #todo implement API call for employee } } if($EmployeeAssigned) { $EmployeeIdAssigned = ConvertFrom-NameCache -Name $EmployeeAssigned -Type "Employees" if(-not $EmployeeIdAssigned) { Write-PSFMessage -Level Warning -Message "No Id for employee '$($EmployeeAssigned)' found. Ticket will be created with blank value on EmployeeIdAssigned" #todo implement API call for employee } } if($Client) { $RemitterId = ConvertFrom-NameCache -Name $Client -Type "Employees" if(-not $RemitterId) { Write-PSFMessage -Level Warning -Message "No Id for client '$($Client)' found. Ticket will be created with blank value on RemitterId" #todo implement API call for employee } } if($Phase) { $PhaseId = ConvertFrom-NameCache -Name $Phase -Type "Phases" if(-not $PhaseId) { Write-PSFMessage -Level Warning -Message "No Id for phase '$($Phase)' found. Ticket will be created with blank value on Phase" } } if($Type) { $TypeId = ConvertFrom-NameCache -Name $Type -Type "TicketTypes" if(-not $TypeId) { Write-PSFMessage -Level Warning -Message "No Id for ticket type '$($Type)' found. Ticket will be created with blank value on TicketType" } } if ($OrderBy) { $OrderById = ConvertFrom-NameCache -Name $OrderBy -Type "OrderBys" if (-not $OrderById) { Write-PSFMessage -Level Warning -Message "No Id for OrderBy type '$($OrderBy)' found. Ticket will be created with blank value on OrderById" } } if($Status) { $StatusId = ConvertFrom-NameCache -Name $Status -Type "TicketStates" if(-not $StatusId) { Write-PSFMessage -Level Warning -Message "No Id for ticket state '$($Status)' found. Ticket will be created with blank value on TicketStatus" } } if($Department) { $DepartmentIdAssigned = ConvertFrom-NameCache -Name $Department -Type "Departments" if(-not $DepartmentIdAssigned) { Write-PSFMessage -Level Warning -Message "No Id for department '$($Department)' found. Ticket will be created with blank value on departmentIdAssigned" } } if($Company) { $CompanyId = ConvertFrom-NameCache -Name $Company -Type "Companies" if(-not $CompanyId) { Write-PSFMessage -Level Warning -Message "No Id for company '$($Company)' found. Ticket will be created with blank value on CompanyId" } } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "Userfriendly" -and (-not $Title)) { Write-PSFMessage -Level Error -Message "No title specified" continue } #region rest call prepare if ($Deadline) { $_deadlineDate = [int][double]::Parse((Get-Date -Date $Deadline.ToUniversalTime() -UFormat %s)) } else { $_deadlineDate = 0 } if ($ResubmissionDate) { $_resubmissionDate = [int][double]::Parse((Get-Date -Date $ResubmissionDate.ToUniversalTime() -UFormat %s)) } else { $_resubmissionDate = 0 } if ($Reminder) { $_reminder = [int][double]::Parse((Get-Date -Date $Reminder.ToUniversalTime() -UFormat %s)) } else { $_reminder = 0 } if ($DueDate) { $_dueDate = [int][double]::Parse((Get-Date -Date $DueDate.ToUniversalTime() -UFormat %s)) } else { $_dueDate = 0 } $body = [ordered]@{ companyId = $CompanyId remitterId = $RemitterId orderById = $OrderById title = "$($Title)" content = "$($Description)" extTicketId = "$($ExternalTicketId)" assignedToEmployeeId = $EmployeeIdAssigned assignedToDepartmentId = $DepartmentIdAssigned statusId = $StatusId typeId = $TypeId linkTypeId = $AssignmentId deadlineDate = $_deadlineDate project = $IsProject projectId = $ProjectId phaseId = $PhaseId repair = $IsRepair dueDate = $_dueDate attention = $Attention installationFee = $InstallationFee installationFeeDriveMode = $InstallationFeeDriveMode installationFeeAmount = $InstallationFeeAmount separateBilling = $SeparateBilling serviceCapAmount = $ServiceCapAmount relationshipLinkTypeId = $RelationshipLinkTypeId relationshipLinkId = $RelationshipLinkId resubmissionDate = $_resubmissionDate resubmissionText = "$($ResubmissionText)" estimatedMinutes = $EstimatedMinutes localTicketAdminFlag = $LocalTicketAdminFlag localTicketAdminEmployeeId = $LocalTicketAdminEmployeeId orderNumber = "$($OrderNumber)" reminder = $_reminder #subTickets = @{} tags = $Tags } #endregion rest call prepare if ($pscmdlet.ShouldProcess("Ticket with title '$($Title)' on companyID '$($CompanyId)'", "New")) { Write-PSFMessage -Level Verbose -Message "Creating Ticket with title '$($Title)' on companyID '$($CompanyId)'" -Tag "Ticket" -Data $body $response = Invoke-TANSSRequest -Type POST -ApiPath $apiPath -Body $body -Token $Token if($response) { Write-PSFMessage -Level Verbose -Message "API Response: $($response.meta.text)" Push-DataToCacheRunspace -MetaData $response.meta [TANSS.Ticket]@{ BaseObject = $response.content Id = $response.content.id } } else { Write-PSFMessage -Level Error -Message "Error creating ticket, no ticket response from API" } } } end { } } function New-TANSSTicketComment { <# .Synopsis New-TANSSTicketComment .DESCRIPTION Add a comment to a ticket .PARAMETER TicketID ID of the ticket where to put comment in .PARAMETER Ticket TANSS.Ticket object where to put comment in .PARAMETER Title Optional. A comment can have a title text. .PARAMETER Text The text to put within the comment .PARAMETER IsInternal Boolean, that specifies if the comment will be internal or public visible to customers .PARAMETER Pinned Switch parameter. If specified, the comment will be pinned at the top of the ticket .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> New-TANSSTicketComment -TicketID 555 -Title "very important info" -Text "Please note this important information" -IsInternal $true Put a comment with text "Please note this important information" within ticket 555 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.TicketComment])] Param( [Parameter( ParameterSetName = "ByTicketId", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [int] $TicketID, [Parameter( ParameterSetName = "ByTicket", ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Mandatory = $true )] [TANSS.Ticket] $Ticket, [string] $Title, [Alias("Description")] [string] $Text, [Alias("Internal")] [bool] $IsInternal = $true, [switch] $Pinned, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByTicket") { $TicketID = $Ticket.id } Write-PSFMessage -Level Verbose -Message "Working on ticket ID $($TicketID)" -Tag "TicketComment", "Add" # Prepare variables for rest call if ($Pinned) { $queryParameter = "?pinned=true" } else { $queryParameter = "?pinned=false" } $apiPath = Format-ApiPath -Path "api/v1/tickets/$ticketID/comments$($queryParameter)" $body = @{ "title" = $Title "content" = $Text "internal" = $IsInternal } if ($pscmdlet.ShouldProcess("$(if($IsInternal -eq $true) {"Internal"}else{"Public"}) comment $(if($Title){"with title '$($Title)' "})on Ticket $($TicketID)", "New")) { Write-PSFMessage -Level Verbose -Message "New $(if($IsInternal -eq $true) {"Internal"}else{"Public"}) comment $(if($Title){"with title '$($Title)' "})on Ticket $($TicketID)" -Tag "TicketComment", "Add" $response = Invoke-TANSSRequest -Type POST -ApiPath $apiPath -Body $body -Token $Token if ($response.content) { Write-PSFMessage -Level Verbose -Message "$($response.meta.text)" -Tag "TicketComment", "Added" # prepare comment object for output $object = [PSCustomObject]@{ id = $response.content.id date = $response.content.date employeeId = $response.content.employeeId categoryId = $response.content.categoryId title = $response.content.title content = $response.content.content internal = $response.content.internal } # output result [TANSS.TicketComment]@{ BaseObject = $object ID = $object.id TicketId = $response.content.commentOfId } } } } end {} } function Remove-TANSSTicket { <# .Synopsis Remove-TANSSTicket .DESCRIPTION Delete a ticket in TANSS .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Remove-TANSSTicket -ID 10 Remove ticket with ticketID 10 from TANSS .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = 'ById', SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'High' )] param ( # TANSS Ticket object to remove [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [TANSS.Ticket[]] $InputObject, # Id of the ticket to remove [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Alias("TicketId", "Ticket")] [int[]] $Id, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ById") { $InputObject = foreach ($idItem in $Id) { Get-TANSSTicket -Id $idItem -ErrorAction Continue } } foreach ($ticket in $InputObject) { Write-PSFMessage -Level Verbose -Message "Working on TicketID $($ticket.Id) '$($ticket.Title)'" $apiPath = Format-ApiPath -Path "api/v1/tickets/$($ticket.Id)" if ($pscmdlet.ShouldProcess("TicketID $($ticket.Id) '$($ticket.Title)' from TANSS", "Remove")) { Write-PSFMessage -Level Verbose -Message "Removing TicketID $($ticket.Id) '$($ticket.Title)' from TANSS" -Tag "Ticket" Invoke-TANSSRequest -Type DELETE -ApiPath $apiPath -Token $Token -ErrorAction Stop -ErrorVariable invokeError } } } end { } } function Remove-TANSSTicketComment { <# .Synopsis Remove-TANSSTicketComment .DESCRIPTION Remove a comment from a ticket .PARAMETER TicketID The ID of the ticket where to remove a comment from .PARAMETER Id The id of the comment to remove .PARAMETER Comment TANSS.TicketComment object to remove .PARAMETER Force Process the removal quietly. .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Remove-TANSSTicketComment Description .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByTicketId", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'High' )] Param( [Parameter( ParameterSetName = "ById", Mandatory = $true )] [int] $TicketID, [Parameter( ParameterSetName = "ById", Mandatory = $true )] [Alias("CommentID")] [int] $Id, [Parameter( ParameterSetName = "ByInputObject", ValueFromPipeline = $true, Mandatory = $true )] [TANSS.TicketComment] $Comment, [switch] $Force, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "ByInputObject") { $TicketID = $Comment.TicketId $Id = $Comment.Id } # Check on Force parameter, otherwise process shouldprocess if ($Force) { $processRemoval = $true } else { if ($pscmdlet.ShouldProcess("comment ID $($Id) from ticket ID $($TicketID)", "Remove")) { $processRemoval = $true } } if ($processRemoval) { Write-PSFMessage -Level Verbose -Message "Remove comment ID $($Id) from ticket ID $($TicketID)" -Tag "TicketComment", "Remove" # Remove comment from ticket $apiPath = Format-ApiPath -Path "api/v1/tickets/$($TicketID)/comments/$($Id)" Invoke-TANSSRequest -Type DELETE -ApiPath $apiPath -Token $Token -Confirm:$false } } end {} } function Set-TANSSTicket { <# .Synopsis Set-TANSSTicket .DESCRIPTION Modify a ticket in TANSS .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the token to the console, even when the register switch is set .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Set-TANSSTicket -ID 10 -NewTitle "New ticket title" Update title to "New ticket title" of ticket with ticketID 10 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidMultipleTypeAttributes", "")] [CmdletBinding( DefaultParameterSetName = 'UserFriendly-ByInputObject', SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Ticket])] param ( # TANSS Ticket object to modify [Parameter( ParameterSetName = "ApiNative-ByInputObject", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Parameter( ParameterSetName = "UserFriendly-ByInputObject", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [TANSS.Ticket[]] $InputObject, # Id of the ticket to modify [Parameter( ParameterSetName = "ApiNative-ById", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Parameter( ParameterSetName = "UserFriendly-ById", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [Alias("TicketId", "Ticket")] [int[]] $Id, # Company id of the ticket. Name is stored in the "linked entities" - "companies". Can only be set if the user has access to the company [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [int] $CompanyId, # Company name where the ticket should create for. Can only be set if the user has access to the company [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Company, # If the ticket has a remitter, the id goes here. Name is stored in the "linked entities" - "employees" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [Alias('ClientId')] [int] $RemitterId, # If the ticket has a remitter/client, the name of the client [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Client, # gives infos about how the remitter gave the order. Infos are stored in the "linked entities" - "orderBys" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [int] $OrderById, # gives infos about how the Client gave the order. [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [string] $OrderBy, # The title / subject of the ticket [Alias('Title', "NewName")] [string] $NewTitle, # The content / description of the ticket [Alias('content')] [string] $Description, # External ticket id (optional) [Alias('extTicketId')] [string] $ExternalTicketId, # id of employee which ticket is assigned to. Name is stored in "linked entities" - "employees" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [Alias('assignedToEmployeeId')] [int] $EmployeeIdAssigned, # Name of the employee the ticket is assigned to [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $EmployeeAssigned, # id of department the ticket is assigned to. Name is stored in "linked entities" - "departments" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [Alias('assignedToDepartmentId')] [int] $DepartmentIdAssigned, # Name of the department the ticket is assigned to [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Department, # id of the ticket state. Name is give in "linked entities" - "ticketStates" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [int] $StatusId, # The name of the ticket status [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Status, # id of the ticket type. Name is give in "linked entities" - "ticketTypes" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [int] $TypeId, # The name of the ticket type [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Type, # if ticket is assigned to device / employee, linktype is given here [Alias('LinkTypeId')] [int] $AssignmentId, # If ticket has a deadline, the date is given here [Alias('deadlineDate')] [datetime] $Deadline, # if ticket is a sub-ticket of a project, the id of the project goes here. Name of the project is in the "linked entities" - "tickets" [int] $ProjectId, # if the ticket is assignet to a project phase. The name of the phase is stored in the "linked entities" - "phases" [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [Int] $PhaseId, # if the ticket is assignet to a project phase, the name of the phase [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [String] $Phase, # if true, this ticket is a "repair ticket" [Alias('repair')] [bool] $IsRepair = $false, # if ticket has a due date, the timestamp is given here [datetime] $DueDate, # Determines the "attention" flag state of a ticket [ValidateSet("NO", "YES", "RESUBMISSION", "MAIL")] [string] $Attention = "NO", # If the ticket has an installation fee, this value is true [ValidateSet("NO", "YES", "NO_PROJECT_INSTALLATION_FEE")] [string] $InstallationFee = "NO", # Sets the installation fee drive mode. If it is set to NONE then the system config parameter "leistung.ip.fahrzeit_berechnen" will be used. If the company from the ticket has an installation fee drive mode set then that will be used instead of the system config parameter. [ValidateSet("NONE", "DRIVE_INCLUDED", "DRIVE_EXCLUDED")] [string] $InstallationFeeDriveMode = "NONE", #Amount for the installation fee [int] $InstallationFeeAmount, # If true, the ticket shall be billed separately [bool] $SeparateBilling = $false, # if the ticket has a service cap, here the amount is given [int] $ServiceCapAmount, # linkId of the relationship (if ticket has a relation) [int] $RelationshipLinkId, # linkTypeId of the relationship (if ticket has a relation) [int] $RelationshipLinkTypeId, # if the ticket as a resubmission date set, this is given here [datetime] $ResubmissionDate, # If a resubmission text is set, this text is returned here [string] $ResubmissionText, # Number of estimated minutes which is planned for the ticket [int] $EstimatedMinutes, # Determines wether the ticket is assigned to a local ticket admin or not # NONE: "normal" ticket # LOCAL_ADMIN: ticket is assigned to a local ticket admin # TECHNICIAN: local ticket admin has forwarded the ticket to a technician [ValidateSet("NONE", "LOCAL_ADMIN", "TECHNICIAN")] [string] $LocalTicketAdminFlag = "NONE", # if the ticket is assigned to a local ticket admin, this represents the employee (local ticket admin) who is assigned for this ticket [Parameter(ParameterSetName = "ApiNative-ByInputObject")] [Parameter(ParameterSetName = "ApiNative-ById")] [ValidateNotNullOrEmpty] [int] $LocalTicketAdminEmployeeId, # if the ticket is assigned to a local ticket admin, this represents the name of the employee (local ticket admin) who is assigned for this ticket [Parameter(ParameterSetName = "UserFriendly-ByInputObject")] [Parameter(ParameterSetName = "UserFriendly-ById")] [ValidateNotNullOrEmpty] [String] $EmployeeTicketAdmin, # Sets the order number [string] $OrderNumber, # If the ticket has a reminder set, the timestamp is returned here [datetime] $Reminder, [switch] $PassThru, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning if ($EmployeeTicketAdmin) { $LocalTicketAdminEmployeeId = ConvertFrom-NameCache -Name $EmployeeTicketAdmin -Type "Employees" if (-not $LocalTicketAdminEmployeeId) { Write-PSFMessage -Level Warning -Message "No Id for employee '$($EmployeeTicketAdmin)' found, ticket will not be modified on TicketAdminEmployee value" #todo implement API call for employee } } if ($EmployeeAssigned) { $EmployeeIdAssigned = ConvertFrom-NameCache -Name $EmployeeAssigned -Type "Employees" if (-not $EmployeeIdAssigned) { Write-PSFMessage -Level Warning -Message "No Id for employee '$($EmployeeAssigned)' found, ticket will not be modified on EmployeeIdAssigned value" #todo implement API call for employee } } if ($Client) { $RemitterId = ConvertFrom-NameCache -Name $Client -Type "Employees" if (-not $RemitterId) { Write-PSFMessage -Level Warning -Message "No Id for client '$($Client)' found, ticket will not be modified on RemitterId value" #todo implement API call for employee } } if ($Phase) { $PhaseId = ConvertFrom-NameCache -Name $Phase -Type "Phases" if (-not $PhaseId) { Write-PSFMessage -Level Warning -Message "No Id for phase '$($Phase)' found, ticket will not be modified on Phase value" } } if ($Type) { $TypeId = ConvertFrom-NameCache -Name $Type -Type "TicketTypes" if (-not $TypeId) { Write-PSFMessage -Level Warning -Message "No Id for ticket type '$($Type)' found, ticket will not be modified on TicketType value" } } if ($OrderBy) { $OrderById = ConvertFrom-NameCache -Name $OrderBy -Type "OrderBys" if (-not $OrderById) { Write-PSFMessage -Level Warning -Message "No Id for OrderBy type '$($OrderBy)' found, ticket will not be modified on OrderBy value" } } if ($Status) { $StatusId = ConvertFrom-NameCache -Name $Status -Type "TicketStates" if (-not $StatusId) { Write-PSFMessage -Level Warning -Message "No Id for ticket state '$($Status)' found, ticket will not be modified on TicketStatus value" } } if ($Department) { $DepartmentIdAssigned = ConvertFrom-NameCache -Name $Department -Type "Departments" if (-not $DepartmentIdAssigned) { Write-PSFMessage -Level Warning -Message "No Id for department '$($Department)' found, ticket will not be modified on departmentIdAssigned value" } } if ($Company) { $CompanyId = ConvertFrom-NameCache -Name $Company -Type "Companies" if (-not $CompanyId) { Write-PSFMessage -Level Warning -Message "No Id for company '$($Company)' found, ticket will not be modified on CompanyId" } } if ($Deadline) { $_deadlineDate = [int][double]::Parse((Get-Date -Date $Deadline.ToUniversalTime() -UFormat %s)) } else { $_deadlineDate = 0 } if ($DueDate) { $_dueDate = [int][double]::Parse((Get-Date -Date $DueDate.ToUniversalTime() -UFormat %s)) } else { $_dueDate = 0 } if ($ResubmissionDate) { $_resubmissionDate = [int][double]::Parse((Get-Date -Date $ResubmissionDate.ToUniversalTime() -UFormat %s)) } else { $_resubmissionDate = 0 } if ($Reminder) { $_reminder = [int][double]::Parse((Get-Date -Date $Reminder.ToUniversalTime() -UFormat %s)) } else { $_reminder = 0 } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" if ($parameterSetName -like "*ById*") { $InputObject = foreach ($idItem in $Id) { Get-TANSSTicket -Id $idItem -ErrorAction Continue } } foreach ($ticket in $InputObject) { Write-PSFMessage -Level Verbose -Message "Working on TicketID $($ticket.Id) '$($ticket.Title)'" $apiPath = Format-ApiPath -Path "api/v1/tickets/$($ticket.Id)" $body = [ordered]@{ "companyId" = (.{if ($CompanyId) { $CompanyId } else { $ticket.BaseObject.companyId }}) "remitterId" = (.{if ($RemitterId) { $RemitterId } else { $ticket.BaseObject.remitterId }}) "title" = (.{if ($NewTitle) { "$($NewTitle)" } else { $ticket.BaseObject.title }}) "content" = (.{if ($Description) { "$($Description)" } else { $ticket.BaseObject.content }}) "extTicketId" = (.{if ($ExternalTicketId) { "$($ExternalTicketId)" } else { $ticket.BaseObject.extTicketId }}) "assignedToEmployeeId" = (.{if ($EmployeeIdAssigned) { $EmployeeIdAssigned } else { $ticket.BaseObject.assignedToEmployeeId }}) "assignedToDepartmentId" = (.{if ($DepartmentIdAssigned) { $DepartmentIdAssigned } else { $ticket.BaseObject.assignedToDepartmentId }}) "statusId" = (.{if ($StatusId) { $StatusId } else { $ticket.BaseObject.statusId }}) "typeId" = (.{if ($TypeId) { $TypeId } else { $ticket.BaseObject.typeId }}) "linkTypeId" = (.{if ($AssignmentId) { $AssignmentId } else { $ticket.BaseObject.linkTypeId }}) "linkId" = $ticket.BaseObject.linkId "deadlineDate" = (.{if ($_deadlineDate) { $_deadlineDate } else { $ticket.BaseObject.deadlineDate }}) "project" = $ticket.BaseObject.project.ToString() "projectId" = (.{if ($ProjectId) { $ProjectId } else { $ticket.BaseObject.projectId }}) "repair" = (.{if ($IsRepair) { $IsRepair } else { $ticket.BaseObject.repair }}) "dueDate" = (.{if ($_dueDate) { $_dueDate } else { $ticket.BaseObject.dueDate }}) "attention" = (.{if ($Attention) { $Attention } else { $ticket.BaseObject.attention }}) "orderById" = (.{if ($OrderById) { $OrderById } else { $ticket.BaseObject.orderById }}) "installationFee" = (.{if ($InstallationFee) { $InstallationFee } else { $ticket.BaseObject.installationFee }}) "installationFeeDriveMode" = (.{if ($InstallationFeeDriveMode) { $InstallationFeeDriveMode } else { "None" }}) "installationFeeAmount" = (.{if ($InstallationFeeAmount) { $InstallationFeeAmount } else { $ticket.BaseObject.installationFeeAmount }}) "separateBilling" = (.{if ($SeparateBilling) { $SeparateBilling.ToString() } else { $ticket.BaseObject.separateBilling }}) "serviceCapAmount" = (.{if ($ServiceCapAmount) { $ServiceCapAmount } else { $ticket.BaseObject.serviceCapAmount }}) "relationshipLinkTypeId" = (.{if ($RelationshipLinkTypeId) { $RelationshipLinkTypeId } else { $ticket.BaseObject.orderById }}) "relationshipLinkId" = (.{if ($RelationshipLinkId) { $RelationshipLinkId } else { $ticket.BaseObject.relationshipLinkId }}) "resubmissionDate" = (.{if ($_resubmissionDate) { $_resubmissionDate } else { $ticket.BaseObject.resubmissionDate }}) "estimatedMinutes" = (.{if ($EstimatedMinutes) { $EstimatedMinutes } else { $ticket.BaseObject.estimatedMinutes }}) "localTicketAdminFlag" = (.{if ($LocalTicketAdminFlag) { $LocalTicketAdminFlag } else { $ticket.BaseObject.localTicketAdminFlag }}) "localTicketAdminEmployeeId" = (.{if ($LocalTicketAdminEmployeeId) { $LocalTicketAdminEmployeeId } else { $ticket.BaseObject.localTicketAdminEmployeeId }}) "phaseId" = (.{if ($PhaseId) { $PhaseId } else { $ticket.BaseObject.phaseId }}) "resubmissionText" = (.{if ($ResubmissionText) { "$($ResubmissionText)" } else { $ticket.BaseObject.resubmissionText }}) "orderNumber" = (.{if ($OrderNumber) { "$($OrderNumber)" } else { $ticket.BaseObject.orderNumber }}) "reminder" = (.{if ($_reminder) { $_reminder } else { $ticket.BaseObject.reminder }}) } if ($pscmdlet.ShouldProcess("TicketID $($ticket.Id) with $(if($NewTitle){"new "})title '$(if($NewTitle){$NewTitle}else{$ticket.Title})'", "Update")) { Write-PSFMessage -Level Verbose -Message "Updating TicketID $($ticket.Id) with $(if($NewTitle){"new "})title '$(if($NewTitle){$NewTitle}else{$ticket.Title})'" -Tag "Ticket" -Data $body $response = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token if ($response) { Write-PSFMessage -Level Verbose -Message "API Response: $($response.meta.text)" Push-DataToCacheRunspace -MetaData $response if($PassThru) { foreach ($content in $response.content) { [TANSS.Ticket]@{ BaseObject = $content Id = $content.id } } } } else { Write-PSFMessage -Level Error -Message "Error updating ticketID '$($ticket.Id)', no ticket response from API" } } } } end { } } function Approve-TANSSVacationRequest { <# .Synopsis Approve-TANSSVacationRequest .DESCRIPTION Approve a vacation request within TANSS .PARAMETER InputObject TANSS.Vacation.Request object to approve .PARAMETER Id Id of the vacation request to approve .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-TANSSVacationRequest -Id 10 | Approve-TANSSVacationRequest Approve the VacationRequest Id 10 .EXAMPLE PS C:\> Approve-TANSSVacationRequest -Id 10 Approve the VacationRequest Id 10 .EXAMPLE PS C:\> $vacationRequests | Approve-TANSSVacationRequest -PassThru Approve all requests in variable '$vacationrequests' and output the (approved) VacationRequests on the console Assuming, the variable is build on something like: PS C:\>$vacationrequests = Get-TANSSVacationRequest -Year 2022 -Month 8 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "")] [CmdletBinding( DefaultParameterSetName = "ById", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [switch] $PassThru, [TANSS.Connection] $Token ) begin { try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Set-TANSSVacationRequestStatus', [System.Management.Automation.CommandTypes]::Function) $scriptCmd = {& $wrappedCmd -Status "Approve" @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline() $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } } function Deny-TANSSVacationRequest { <# .Synopsis Deny-TANSSVacationRequest .DESCRIPTION Decline a vacation request within TANSS .PARAMETER InputObject TANSS.Vacation.Request object to approve .PARAMETER Id Id of the vacation request to approve .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-TANSSVacationRequest -Id 10 | Deny-TANSSVacationRequest Decline the VacationRequest Id 10 .EXAMPLE PS C:\> Deny-TANSSVacationRequest -Id 10 Decline the VacationRequest Id 10 .EXAMPLE PS C:\> $vacationRequests | Deny-TANSSVacationRequest -PassThru Decline all requests in variable '$vacationrequests' and output the new (declined) VacationRequests on the console Assuming, the variable is build on something like: PS C:\>$vacationrequests = Get-TANSSVacationRequest -Year 2022 -Month 8 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "")] [CmdletBinding( DefaultParameterSetName = "ById", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [switch] $PassThru, [TANSS.Connection] $Token ) begin { try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Set-TANSSVacationRequestStatus', [System.Management.Automation.CommandTypes]::Function) $scriptCmd = {& $wrappedCmd -Status "Decline" @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline() $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } } function Get-TANSSVacationAbsenceSubType { <# .Synopsis Get-TANSSVacationAbsenceSubType .DESCRIPTION Retrieve the additional absence types for the vacation type "absence". If a absence on a employee is created, one of this types can be specified as more specific information. .PARAMETER Id ID of the type to get (client side filtering) .PARAMETER Name Name of the type to get (client side filtering) .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSVacationAbsenceSubType Description .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "")] [CmdletBinding( SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Vacation.AbsenceSubType])] Param( [string[]] $Name, [int[]] $Id, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/planningAdditionalTypes" [array]$output = @() } process { $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token if ($response) { Write-PSFMessage -Level Verbose -Message "Found $(($response.content).count) vacation types" -Tag "Vacation", "VacationType" foreach ($type in $response.content) { # Do filtering on name if ($Name) { $filterSuccess = $false foreach ($filterName in $Name) { if ($type.Name -like $filterName) { $filterSuccess = $true } } # if filter does not hit, continue with next technican if ($filterSuccess -eq $false) { continue } } # Do filtering on id if ($Id) { $filterSuccess = $false foreach ($filterId in $Id) { if ([int]($type.id) -eq $filterId) { $filterSuccess = $true } } # if filter does not hit, continue with next technican if ($filterSuccess -eq $false) { continue } } # Compiling additional TANSS.Vacation.AbsenceSubType $output += [TANSS.Vacation.AbsenceSubType]@{ BaseObject = $type Id = $type.id } # Check VacationType lookup cache if ([TANSS.Lookup]::VacationAbsenceSubTypes[$type.id] -notlike $type.name) { if ([TANSS.Lookup]::VacationAbsenceSubTypes[$type.id]) { Write-PSFMessage -Level Debug -Message "Update existing id '$($id)' in [TANSS.Lookup]::VacationAbsenceSubTypes with value '$($type.name)'" -Tag "Cache" [TANSS.Lookup]::VacationAbsenceSubTypes[$type.id] = $type.name } else { Write-PSFMessage -Level Debug -Message "Insert in [TANSS.Lookup]::VacationAbsenceSubTypes: $($type.id) - '$($($type.name))'" -Tag "Cache" ([TANSS.Lookup]::VacationAbsenceSubTypes).Add($type.id, $type.name) } } } } else { Write-PSFMessage -Level Warning -Message "No technicans found." -Tag "Technican" } } end { # Outputting TANSS.VacationType $output } } function Get-TANSSVacationEntitlement { <# .Synopsis Get-VacationEntitlement .DESCRIPTION Get the available days of vacation within a year By default the current year is queried .PARAMETER Year The year to query. .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-VacationEntitlement -Year 2022 Query entitlement from all employees in year 2022 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "Default", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Vacation.Entitlement])] Param( [ValidateNotNullOrEmpty()] [int] $Year = (Get-Date).Year, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { # Query entitlement for year $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/vacationDays/year/$($Year)" $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token # Output result Write-PSFMessage -Level Verbose -Message "$($response.meta.text): Received $($response.meta.properties.extras.count) VacationEntitlement records in year $($Year)" -Tag "VacationEntitlement", "Query" foreach ($entitlement in $response.content) { $_transferred = if ($entitlement.transferred) { $entitlement.transferred } else { 0 } [TANSS.Vacation.Entitlement]@{ BaseObject = $entitlement EmployeeId = $entitlement.employeeId Year = $entitlement.year NumberOfDays = $entitlement.numberOfDays TransferedDays = $_transferred } } } end {} } function Get-TANSSVacationRequest { <# .Synopsis Get-TANSSVacationRequest .DESCRIPTION Query vacation requests of any state from TANSS By default the current year is queried .PARAMETER Id The explicit ID of the vacation request to get from TANSS .PARAMETER Year The year to list vacation requests for .PARAMETER Month The month of the year to list vacation requests .PARAMETER EmployeeId The Id of the employee to list vacation requests from .PARAMETER EmployeeName The name of the employee to list vacation requests from .PARAMETER DepartmentId Department Id filter .PARAMETER DepartmentName Department name filter .PARAMETER Type Name of the request type Values can be tabcompleted, so you don't have to type Available: "Urlaub", "Krankheit", "Abwesenheit", "Bereitschaft", "Überstunden abfeiern", "VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME" .PARAMETER AbsenceSubTypeId For type "Abwesenheit", "ABSENCE" there are subtypes available. This one specifies the Id of the subtype to use .PARAMETER AbsenceSubTypeName For type "Abwesenheit", "ABSENCE" there are subtypes available. This one specifies the name of the subtype to use Values can be tabcompleted, so you don't have to type .PARAMETER ExcludeVacationRequestId Exclude filter on specific IDs .PARAMETER State The status for requests to list. Available values: "NEW", "REQUESTED", "APPROVED", "DECLINED" .PARAMETER CheckPermission Boolean value from the api wether to check permission or not .PARAMETER AddFrontendValue Boolean value to add request object on .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Get-TANSSVacationRequest Get all requests from the current year .EXAMPLE PS C:\> Get-TANSSVacationRequest -Year ((Get-Date).Year - 1) Get all requests from last year .EXAMPLE PS C:\> Get-TANSSVacationRequest -Type ILLNESS Get all illness records from the current year .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ListUserFriendly", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Vacation.Request])] Param( [Parameter( ParameterSetName = "Id", Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [int[]] $Id, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [int] $Year = (Get-Date).Year, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [int] $Month, [Parameter( ParameterSetName = "ListApiNativ" )] [int[]] $EmployeeId, [Parameter( ParameterSetName = "ListUserFriendly" )] [int[]] $EmployeeName, [Parameter( ParameterSetName = "ListApiNativ" )] [int[]] $DepartmentId, [Parameter( ParameterSetName = "ListUserFriendly" )] [int[]] $DepartmentName, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [string[]] $Type, [Parameter( ParameterSetName = "ListApiNativ" )] [int[]] $AbsenceSubTypeId, [Parameter( ParameterSetName = "ListUserFriendly" )] [string[]] $AbsenceSubTypeName, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [int[]] $ExcludeVacationRequestId, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [ValidateSet("NEW", "REQUESTED", "APPROVED", "DECLINED")] [string[]] $State, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [bool] $CheckPermission = $true, [Parameter( ParameterSetName = "ListApiNativ" )] [Parameter( ParameterSetName = "ListUserFriendly" )] [bool] $AddFrontendValue = $false, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" switch ($parameterSetName) { { $_ -like "Id" } { foreach ($requesterId in $Id) { Write-PSFMessage -Level Verbose -Message "Query VacationRequestId $($requesterId)" -Tag "VacationRequest" # Query VacationRequest by ID $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($requesterId)" $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token # Output result Write-PSFMessage -Level Verbose -Message "$($response.meta.text): VacationRequestId $($requesterId)" -Tag "VacationRequest" [TANSS.Vacation.Request]@{ BaseObject = $response.content Id = $response.content.id } } } { $_ -like "List*" } { $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/list" #region parameter validation # Parameter EmployeeName if ($EmployeeName) { Write-PSFMessage -Level Verbose -Message "Processing lookup on filtering for Employee '$( [string]::Join("'; '", [array]$EmployeeName) )'" $EmployeeId = foreach ($item in $EmployeeName) { $result = ConvertFrom-NameCache -Name $item -Type Employees -Verbose:$false if (-not $result) { Stop-PSFFunction -Message "Employee '$($item)' not found. Unable to query VacationRequests." -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "VacationAbsenceSubTypes", "CacheException" } else { $result } } Write-PSFMessage -Level System -Message "Filtering on EmployeeId '$( [string]::Join("', '", [array]$EmployeeId) )'" } # Parameter DepartmentName if ($DepartmentName) { Write-PSFMessage -Level Verbose -Message "Processing lookup on filtering for Department '$( [string]::Join("'; '", [array]$DepartmentName) )'" $DepartmentId = foreach ($item in $DepartmentName) { $result = ConvertFrom-NameCache -Name $item -Type Departments -Verbose:$false if (-not $result) { Stop-PSFFunction -Message "Department '$($item)' not found. Unable to query VacationRequests." -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "VacationAbsenceSubTypes", "CacheException" } else { $result } } Write-PSFMessage -Level System -Message "Filtering on DepartmentId '$( [string]::Join("', '", [array]$DepartmentId) )'" } # Parameter Type if ($Type) { Write-PSFMessage -Level System -Message "Processing filtering on Type '$( [string]::Join("', '", [array]$Type) )'" $planningType = @() foreach ($absenceType in $Type) { switch ($absenceType) { { $_ -like "Urlaub" } { $planningType += "VACATION" } { $_ -like "Krankheit" } { $planningType += "ILLNESS" } { $_ -like "Abwesenheit*" } { $planningType += "ABSENCE" } { $_ -like "Bereitschaft" } { $planningType += "STAND_BY" } { $_ -like "Überstunden abfeiern" } { $planningType += "OVERTIME" } { $_ -in ("VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME") } { $planningType += $_ } default { Stop-PSFFunction -Message "Unhandled Type '$($absenceType)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "VacationType", "SwitchException" } } } $planningType = $planningType | Sort-Object -Unique Write-PSFMessage -Level Verbose -Message "Filtering on VacationRequestType '$( [string]::Join("', '", [array]$planningType) )'" } # Parameter AbsenceSubType if ($AbsenceSubTypeName) { Write-PSFMessage -Level Verbose -Message "Processing lookup on filtering for AbsenceSubType '$( [string]::Join("', '", [array]$AbsenceSubTypeName) )'" $AbsenceSubTypeId = foreach ($item in $AbsenceSubTypeName) { $result = ConvertFrom-NameCache -Name $item -Type VacationAbsenceSubTypes -Verbose:$false if (-not $result) { Stop-PSFFunction -Message "AbsenceSubType '$($item)' not found. Unable to query VacationRequests." -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "VacationAbsenceSubTypes", "CacheException" } else { $result } } Write-PSFMessage -Level System -Message "Filtering on AbsenceSubTypeId '$( [string]::Join("', '", [array]$AbsenceSubTypeId) )'" } #endregion parameter validation # Prepare body $body = @{} if ($Year) { $body.Add("year", $Year) } if ($Month) { $body.Add("month", $Month) } if ($EmployeeId) { $body.Add("employeeIds", [array]($EmployeeId)) } if ($DepartmentId) { $body.Add("departmentIds", [array]($DepartmentId)) } if ($planningType) { $body.Add("planningTypes", [array]($planningType)) } if ($AbsenceSubTypeId) { $body.Add("planningAdditionalIds", [array]($AbsenceSubTypeId)) } if ($ExcludeVacationRequestId) { $body.Add("excludeVacationRequestIds", [array]($ExcludeVacationRequestId)) } if ($State) { $body.Add("statesOnly", [array]($State)) } if ($CheckPermission) { $body.Add("checkPermissions", $CheckPermission) } if ($AddFrontendValue) { $body.Add("addFrontendValues", $AddFrontendValue) } Write-PSFMessage -Level Debug -Message "Prepared body for API request with parameters: '$( [string]::Join("', '", [array]($body.Keys)) )'" -Data $body -Tag "VacationRequest", "Query" $response = Invoke-TANSSRequest -Type "PUT" -ApiPath $apiPath -Body $body -Token $Token Write-PSFMessage -Level Verbose -Message "Found $( ([array]($response.content.vacationRequests)).count ) request" -Tag "VacationRequest", "Output" Push-DataToCacheRunspace -MetaData $response.meta foreach ($vacationRequest in $response.content.vacationRequests) { Write-PSFMessage -Level Debug -Message "Generating '$($vacationRequest.planningType)' request Id:$($vacationRequest.Id) with status '$($vacationRequest.status)" -Tag "VacationRequest", "Output" [TANSS.Vacation.Request]@{ BaseObject = $vacationRequest Id = $vacationRequest.id } } } Default { Stop-PSFFunction -Message "Unhandled ParameterSet '$($parameterSetName)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "SwitchException", "ParameterSet" } } } end {} } function New-TANSSVacationRequest { <# .Synopsis New-TANSSVacationRequest .DESCRIPTION Create a new vacation/absence request within TANSS for a specified employee on a date period There are various types of "absence": - Vacation - Illness - Absence - Standby - Overtime The command is called with a paramiter called like the absence type to request The type "Absence" can have a subset of additional types. They can be specified by name (Tabcompletion is available), or by a TANSS.Vacation.AbsenceSubType object. The additional absence types can be queried by the command "Get-TANSSVacationAbsenceSubType" .PARAMETER Vacation Switch parameter to command the creation of a vacation request .PARAMETER Illness Switch parameter to command the creation of a Illness record .PARAMETER Absence Switch parameter to command the creation of a absence record .PARAMETER AbsenceSubType TANSS.Vacation.AbsenceSubType object to specify what kind of absence subtype to create .PARAMETER AbsenceSubTypeName The name of the absence subtype to create .PARAMETER Standby Switch parameter to command the creation of a Standby record .PARAMETER Overtime Switch parameter to command the creation of a Overtime record .PARAMETER EmployeeId The ID of the employee to create to request/record for .PARAMETER StartDate The start date .PARAMETER EndDate The end date .PARAMETER HalfDayStart Boolean to specify if the first day is created as a half day (forenoon not in the absence) .PARAMETER HalfDayEnd Boolean to specify if the last day is created as a half day (afternoon not in the absence) .PARAMETER Description Optional description for the request/record .PARAMETER Date The creation of the request/record By default this is the current date. .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> New-TANSSVacationRequest -Illness -EmployeeId 10 -Start "01/02/2023" -End "01/03/2023" Creates an illness record for employee with ID 10 for second of january 2023 to third of january 2023 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Vacation.Request])] Param( [Parameter(ParameterSetName = "Vacation", Mandatory = $true)] [switch] $Vacation, [Parameter(ParameterSetName = "Illness", Mandatory = $true)] [switch] $Illness, [Parameter(ParameterSetName = "Absence", Mandatory = $true)] [Parameter(ParameterSetName = "AbsenceWithAbsenceObject", Mandatory = $true)] [Parameter(ParameterSetName = "AbsenceWithAbsenceName", Mandatory = $true)] [switch] $Absence, [Parameter(ParameterSetName = "AbsenceWithAbsenceObject", Mandatory = $true)] [TANSS.Vacation.AbsenceSubType] $AbsenceSubType, [Parameter(ParameterSetName = "AbsenceWithAbsenceName", Mandatory = $true)] [string] $AbsenceSubTypeName, [Parameter(ParameterSetName = "Standby", Mandatory = $true)] [switch] $Standby, [Parameter(ParameterSetName = "Overtime", Mandatory = $true)] [switch] $Overtime, [int[]] $EmployeeId, [Parameter(Mandatory = $true)] [datetime] $StartDate, [Parameter(Mandatory = $true)] [datetime] $EndDate, [Alias("StartHalfDay")] [bool] $HalfDayStart = $false, [Alias("EndHalfDay")] [bool] $HalfDayEnd = $false, [Alias("Reason", "RequestReason")] [string] $Description, [Alias("RequestDate")] [datetime] $Date = (Get-Date), [TANSS.Connection] $Token ) begin { # Validation - Basic checks if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" -Tag "VacationRequest" #region Validation # Check dates if ($StartDate -gt $EndDate) { Stop-PSFFunction -Message "Specified dates are not valid! Please check dates, StartDate '$($StartDate)' is greater then EndDate '$($EndDate))'" -EnableException $true -Cmdlet $pscmdlet } # Fallback to employeeId from token if no requestorId is set if (-not $EmployeeId) { Write-PSFMessage -Level Verbose -Message "No Employee specified, using current logged in employee '$($Token.UserName)' (Id:$($Token.EmployeeId))" -Tag "VacationRequest", "EmployeeId" $EmployeeId = $Token.EmployeeId } # Find additional AbsenceSubType from specified name if ($parameterSetName -like "AbsenceWithAbsenceName") { Write-PSFMessage -Level System -Message "Gathering TANSS absence type '$($AbsenceSubTypeName)'" -Tag "VacationRequest", "AbsenceSubType", "Lookup" $tmpWhatIfPreference = $WhatIfPreference $WhatIfPreference = $fals $AbsenceSubType = Get-TANSSVacationAbsenceSubType -Name $AbsenceSubTypeName -Token $Token -ErrorAction Ignore $WhatIfPreference = $tmpWhatIfPreference Remove-Variable tmpWhatIfPreference -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false if ($AbsenceSubType) { Write-PSFMessage -Level Verbose -Message "Found AbsenceSubTypeId '$($AbsenceSubType.Id)' for '$($AbsenceSubTypeName)'" } else { Stop-PSFFunction -Message "Unable to find AbsenceSubType '$($AbsenceSubTypeName)'" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "AbsenceSubType" } } # set planningType switch ($parameterSetName) { { $_ -like "Vacation" } { $planningType = "VACATION" } { $_ -like "Illness" } { $planningType = "ILLNESS" } { $_ -like "Absence*" } { $planningType = "ABSENCE" } { $_ -like "Standby" } { $planningType = "STAND_BY" } { $_ -like "Overtime" } { $planningType = "OVERTIME" } Default { Stop-PSFFunction -Message "Unhandled ParameterSetName. Unable to set planningType for VacationRequest. Developers mistake!" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "PlanningType" } } #endregion Validation - checking parameters foreach ($requesterId in $EmployeeId) { $_requestDate = [int][double]::Parse((Get-Date -Date $Date.ToUniversalTime() -UFormat %s)) # gathering absence object $plannedVactionRequest = Request-TANSSVacationRequestObject -EmployeeId $requesterId -Type $planningType -StartDate $StartDate -EndDate $EndDate -Token $Token if(-not $plannedVactionRequest) { continue } Write-PSFMessage -Level Verbose -Message "Adding RequestDate and optional description to VacationRequest object" -Tag "VacationRequest", "VactionRequestObject" $plannedVactionRequest.BaseObject.requestReason = "$($Description)" $plannedVactionRequest.BaseObject.requestDate = $_requestDate if ($AbsenceSubType) { Write-PSFMessage -Level Verbose -Message "Insert additionalAbsenceSubType '$($AbsenceSubType.Name)' to VacationRequest object" -Tag "VacationRequest", "VactionRequestObject", "AbsenceSubType" $plannedVactionRequest.BaseObject.planningAdditionalId = $AbsenceSubType.Id } $days = $plannedVactionRequest.Days if($HalfDayStart) { $days[0].Afternoon = $false } if($HalfDayEnd) { $days[-1].Forenoon = $false } $plannedVactionRequest.Days = $days Remove-Variable -Name days -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false -ErrorAction Ignore -WarningAction Ignore -InformationAction Ignore $body = $plannedVactionRequest.BaseObject | ConvertTo-PSFHashtable # enforce types, due to some strange conversation behaviour sometimes $body.days = [array]$body.days $body.startDate = [int]$body.startDate $body.endDate = [int]$body.endDate $apiPath = Format-ApiPath -Path "api/v1/vacationRequests" $daycount = 0 + ($plannedVactionRequest.days | Measure-Object | Select-Object -ExpandProperty Count) if ($pscmdlet.ShouldProcess("VacationRequest for employeeId '$($RequesterId)' with $($daycount) days on planningType '$($planningType)' on dates '$(Get-Date -Date $StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $EndDate -Format 'yyyy-MM-dd')'", "Add")) { Write-PSFMessage -Level Verbose -Message "Add VacationRequest for employeeId '$($RequesterId)' with $($daycount) days on planningType '$($planningType)' on dates '$(Get-Date -Date $StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $EndDate -Format 'yyyy-MM-dd')'" -Tag "VacationRequest", "VactionRequestObject" # Create the object within TANSS $result = Invoke-TANSSRequest -Type POST -ApiPath $apiPath -Body $body -Token $Token Write-PSFMessage -Level Verbose -Message "$($result.meta.text) - RequestId '$($result.content.id)' with status '$($result.content.status)'" -Tag "VacationRequest", "VactionRequestObject", "VacationRequestResult" # output the result [TANSS.Vacation.Request]@{ BaseObject = $result.content Id = $result.content.id } } } } end { } } function Out-TANSSVacationRequestPdf { <# .Synopsis Out-TANSSVacationRequestPdf .DESCRIPTION Write a PDF for a vacation request from Tanss. This is only available for VacataRequest of Type "vacation" .PARAMETER InputObject TANSS.Vacation.Request object to output pdf file for .PARAMETER Id The Id of the vacation request .PARAMETER Path The path to output the pdf to .PARAMETER PassThru Switch parameter. If specified, the file object will be thrown out to the console .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Out-TANSSVacationRequestPdf Description .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ByID", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [string] $Path, [switch] $PassThru, [TANSS.Connection] $Token ) begin { # Validation - Basic checks if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning # Check path if ($Path) { if($Path.Contains("\")) { # Check if pdf filename is specified if($Path.split("\")[-1] -like "*.pdf") { # assume explicit specified PDF $fileName = $Path.split("\")[-1] $resolved = Resolve-Path -Path $Path.TrimEnd( $fileName ) -ErrorAction Ignore } else { # assume path $resolved = Resolve-Path -Path $Path -ErrorAction Ignore } if($resolved) { $_path = $resolved | Select-Object -ExpandProperty Path if($fileName) { $_path = "$($_path)\$($fileName)" } } else { Stop-PSFFunction -Message "Path '$($Path)' is not valid" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "OutPdf", "PathException" } } else { if($Path -notlike "*.pdf") { Write-PSFMessage -Level Warning -Message "Unusual behaviour, filename for outputfile does not contain '.pdf'" -Tag "VacationRequest", "OutPdf", "FileName" } $fileName = $Path $_path = "$(Resolve-Path -Path ".\" -ErrorAction Ignore | Select-Object -ExpandProperty Path)\$fileName" if(-not $_path) { Stop-PSFFunction -Message "Path '$($Path)' is not valid" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "OutPdf", "PathException" } } } else { $_path = "$(Resolve-Path -Path ".\" | Select-Object -ExpandProperty Path)\" } Write-PSFMessage -Level System -Message "Specified path: $($_path)" -Tag "VacationRequest", "OutPdf" } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" -Tag "VacationRequest", "OutPdf" # If Id is piped in, query vacationRequests from TANSS if ($parameterSetName -like "ById*") { $InputObject = foreach ($requestId in $Id) { Get-TANSSVacationRequest -Id $requestId -Token $Token } } foreach ($vacationRequest in $InputObject) { Write-PSFMessage -Level Verbose -Message "Working on '$($vacationRequest.TypeName)' VacationRequest '$($vacationRequest.Id)' ($($vacationRequest.EmployeeName)) for range '$($vacationRequest.StartDate) - $($vacationRequest.EndDate)'" -Tag "VacationRequest", "OutPdf" if ($vacationRequest.Type -ne "Vacation") { Write-PSFMessage -Level Warning -Message "VacationRequest '$(($vacationRequest.Id))' is not of type 'Vacation'. PDF output only supported for VacationRequest of type 'vacation'" -Tag "VacationRequest", "OutPdf", "Warning" continue } if (-not $fileName) { $name = "urlaubsantrag_ID$($vacationRequest.Id)_$(Get-Date -Date $vacationRequest.StartDate -Format "yyyy-MM-dd")_$(Get-Date -Date $vacationRequest.EndDate -Format "yyyy-MM-dd").pdf" Write-PSFMessage -Level Verbose -Message "No name specified output file. Using filename: $($name)" -Tag "VacationRequest", "OutPdf", "FileName" $_path = Join-Path -Path $_path -ChildPath $name Write-PSFMessage -Level System -Message "Output path is: $($_path)" -Tag "VacationRequest", "OutPdf", "Path" } $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($vacationRequest.Id)/pdf" #$apiPath = "backend/api/v1/vacationRequests/$($vacationRequest.Id)/pdf" $downloadLink = Invoke-TANSSRequest -Type Get -ApiPath $apiPath -Pdf if ($pscmdlet.ShouldProcess("PDF for vacation request '$vacationRequest.Id' from '$($vacationRequest.EmployeeName)' to '$_path'", "Out")) { Write-PSFMessage -Level Verbose -Message "Ouput PDF for vacation request '$vacationRequest.Id' from '$($vacationRequest.EmployeeName)' to '$_path'" -Tag "VacationRequest", "OutPdf" $apiPath = Format-ApiPath -Path $downloadLink.content.url #$apiPath = "backend/$($downloadLink.content.url)" $param = @{ "Uri" = "$($Token.Server)/$($apiPath)" "Headers" = @{ "apiToken" = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Token.AccessToken)) } "Method" = "GET" "ContentType" = 'application/json; charset=UTF-8' "Verbose" = $false "Debug" = $false "ErrorAction" = "Stop" "ErrorVariable" = "invokeError" "OutFile" = $_path } try { Invoke-RestMethod @param } catch { Write-PSFMessage -Level Error -Message "Error on rest call: $($invokeError.ErrorRecord.Exception.Message)" -Tag "VacationRequest", "OutPdf", "RestException" -ErrorRecord $invokeError.ErrorRecord -PSCmdlet $pscmdlet continue } if($PassThru) { Get-Item -Path $_path } } } } end { } } function Remove-TANSSVacationRequest { <# .Synopsis Remove-TANSSVacationRequest .DESCRIPTION Remove a vacation request .PARAMETER InputObject TANSS.Vacation.Request to remove .PARAMETER Id The Id of the VacationRequest record to remove .PARAMETER Force Process the removal quietly. .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-TANSSVacationRequest -Id 10 | Remove-TANSSVacationRequest Remove the VacationRequest Id 10 .EXAMPLE PS C:\> Remove-TANSSVacationRequest -Id 10 -Force Remove the VacationRequest Id 10 without asking for confirmation .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ById", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'High' )] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [switch] $Force, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" # If Id is piped in, query vacationRequests from TANSS if ($parameterSetName -like "ById") { $InputObject = foreach ($requesterId in $Id) { Write-PSFMessage -Level Verbose -Message "Query VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" # Query VacationRequest by ID $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($requesterId)" $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token -Confirm:$false # Output result Write-PSFMessage -Level Verbose -Message "$($response.meta.text): VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" [TANSS.Vacation.Request]@{ BaseObject = $response.content Id = $response.content.id } } } if (-not $InputObject) { Write-PSFMessage -Level Error -Message "No VacationRequests to remove" -Tag "VacationRequest", "Set", "NoData" -PSCmdlet $pscmdlet } else { $processRemoval = $false foreach ($vacationRequest in $InputObject) { # Check on Force parameter, otherwise process shouldprocess if ($Force) { $processRemoval = $true } else { if ($pscmdlet.ShouldProcess("VacationRequestId '$($vacationRequest.Id)' from '$($vacationRequest.EmployeeName)' on '$($vacationRequest.StartDate)-$($vacationRequest.EndDate)'", "Remove")) { $processRemoval = $true } } if ($processRemoval) { Write-PSFMessage -Level Verbose -Message "Remove VacationRequestId '$($vacationRequest.Id)' from '$($vacationRequest.EmployeeName)' on '$($vacationRequest.StartDate)-$($vacationRequest.EndDate)'" -Tag "VacationRequest", "Set", "Remove" # Remove VacationRequest $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($vacationRequest.Id)" $response = Invoke-TANSSRequest -Type DELETE -ApiPath $apiPath -Token $Token -Confirm:$false } } } } end { } } function Request-TANSSVacationRequestObject { <# .Synopsis Request-TANSSVacationRequestObject .DESCRIPTION Retrieve a vacation request object from TANSS. This object can be used to create a new VacationRequest .PARAMETER EmployeeId The ID of the employee to request for .PARAMETER EmployeeName The name of the employee to request for .PARAMETER StartDate The start date .PARAMETER EndDate The end date .PARAMETER Type Name of the request type Values can be tabcompleted, so you don't have to type Available: "Urlaub", "Krankheit", "Abwesenheit", "Bereitschaft", "Überstunden abfeiern", "VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME" .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .EXAMPLE PS C:\> Request-TANSSVacationRequestObject -EmployeeId 10 -Type "Urlaub" -Start "01/02/2023" -End "01/03/2023" Request a object to create a new vacation request in the database for employee with ID 10. The output will be of type and from 2.1.2023 to 03.01.2023 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ApiNative", SupportsShouldProcess = $false, PositionalBinding = $true, ConfirmImpact = 'Low' )] [OutputType([TANSS.Vacation.Request])] Param( [Parameter( ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, ParameterSetName = "ApiNative" )] [int[]] $EmployeeId, [Parameter( ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, ParameterSetName = "UserFriendly", Mandatory = $true )] [string[]] $EmployeeName, [Parameter(Mandatory = $true)] [string] $Type, [Parameter(Mandatory = $true)] [datetime] $StartDate, [Parameter(Mandatory = $true)] [datetime] $EndDate, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning # Parameter Type if ($Type) { Write-PSFMessage -Level System -Message "Processing Type '$($Type)'" -Tag "VacationRequest", "Request", "VacationType" switch ($Type) { { $_ -like "Urlaub" } { $planningType = "VACATION" } { $_ -like "Krankheit" } { $planningType = "ILLNESS" } { $_ -like "Abwesenheit*" } { $planningType = "ABSENCE" } { $_ -like "Bereitschaft" } { $planningType = "STAND_BY" } { $_ -like "Überstunden abfeiern" } { $planningType = "OVERTIME" } { $_ -in ("VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME") } { $planningType = $_ } default { Stop-PSFFunction -Message "Unhandled Type '$($Type)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "Request", "VacationType", "SwitchException" } } Write-PSFMessage -Level System -Message "Using VacationRequestType '$($planningType)'" -Tag "VacationRequest", "Request", "VacationType" } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" -Tag "VacationRequest", "Request" if ($EmployeeName) { Write-PSFMessage -Level System -Message "Convert EmployeeId from EmployeeName" -Tag "VacationRequest", "Request", "EmployeeName" $EmployeeId = @() foreach ($name in $EmployeeName) { Write-PSFMessage -Level System -Message "Working on employee name '$($name)'" -Tag "VacationRequest", "Request", "EmployeeName" $id = ConvertFrom-NameCache -Name $name -Type "Employees" if (-not $id) { Write-PSFMessage -Level Warning -Message "No Id for employee '$($name)' found" -Tag "VacationRequest", "Request", "EmployeeName", "Warning" } else { Write-PSFMessage -Level System -Message "Found id '$($id)' for employee '$($name)'" -Tag "VacationRequest", "Request", "EmployeeName" } $EmployeeId += $id } } # Fallback to employeeId from token if no requestorId is set if (-not $EmployeeId) { Write-PSFMessage -Level Verbose -Message "No Employee specified, using current logged in employee '$($Token.UserName)' (Id:$($Token.EmployeeId))" -Tag "VacationRequest", "Request", "EmployeeId" $EmployeeId = $Token.EmployeeId } foreach ($requesterId in $EmployeeId) { Write-PSFMessage -Level System -Message "Request $planningType vacation object for id '$($id)' on dates '$(Get-Date -Date $StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $EndDate -Format 'yyyy-MM-dd')'" -Tag "VacationRequest", "Request" # gathering absence object $_startDate = [int][double]::Parse((Get-Date -Date $StartDate.Date.ToUniversalTime() -UFormat %s)) $_endDate = [int][double]::Parse((Get-Date -Date $EndDate.Date.ToUniversalTime() -UFormat %s)) $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/properties" $body = @{ "requesterId" = $requesterId "planningType" = $planningType "startDate" = $_startDate "endDate" = $_endDate } $plannedVactionRequest = Invoke-TANSSRequest -Type POST -ApiPath $apiPath -Body $body -Token $Token | Select-Object -ExpandProperty content if ($plannedVactionRequest) { Write-PSFMessage -Level Verbose -Message "Received VacationRequest object with $($plannedVactionRequest.days | Measure-Object | Select-Object -ExpandProperty Count) days on planningType '$($planningType)'" -Tag "VacationRequest", "VactionRequestObject" # output object [TANSS.Vacation.Request]@{ BaseObject = $plannedVactionRequest Id = $plannedVactionRequest.id } } else { Stop-PSFFunction -Message "Unable gathering '$($planningType)' VacationRequest object for employeeId '$($requesterId)' on dates '$(Get-Date -Date $StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $EndDate -Format 'yyyy-MM-dd')' from '$($Token.Server)'" -Cmdlet $pscmdlet } } } end {} } function Set-TANSSVacationEntitlement { <# .Synopsis Set-TANSSVacationEntitlement .DESCRIPTION Modifies yearly entitlements for employees .PARAMETER InputObject TANSS.Vacation.Entitlement object to modify .PARAMETER EmployeeId The id of the employee to modfiy .PARAMETER EmployeeName The name of the employee to modfiy .PARAMETER Year The year to modify .PARAMETER Days Amount of days to set .PARAMETER TransferedDays Amount of days transfered from the last year .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Set-VacationEntitlement -Year 2022 -EmployeeId 2 -Days 30 Set entitlement for employee ID 2 to 30 days in year 2022 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "Default", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Vacation.Entitlement])] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Entitlement[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [int[]] $EmployeeId, [Parameter( ParameterSetName = "ByName", Mandatory = $true, ValueFromPipeline = $true )] [string[]] $EmployeeName, [ValidateNotNullOrEmpty()] [int] $Year = (Get-Date).Year, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [Alias("NumberOfDays")] [int] $Days, [ValidateNotNullOrEmpty()] [Alias("DaysTransfered")] [int] $TransferedDays, [switch] $PassThru, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" -Tag "VacationEntitlement", "Set" if ($parameterSetName -notlike "ByInputObject") { $tempWhatIf = $WhatIfPreference $WhatIfPreference = $false $InputObject = Get-TANSSVacationEntitlement -Year $Year -Token $Token $WhatIfPreference = $tempWhatIf } # Filter on EmployeeName if ($parameterSetName -like "ByName") { $InputObject = foreach ($_employeeName in $EmployeeName) { $InputObject | Where-Object EmployeeName -like $_employeeName } Write-PSFMessage -Level Verbose -Message "Select $(([array]$InputObject).Count) records, by employee name '$([string]::Join("', '", ([array]$EmployeeName)))'" -Tag "VacationEntitlement", "Set", "Filtering" } # Filter on EmployeeId if ($parameterSetName -like "ById") { $InputObject = foreach ($_employeeId in $EmployeeId) { $InputObject | Where-Object EmployeeId -like $_employeeId } Write-PSFMessage -Level Verbose -Message "Select $(([array]$InputObject).Count) records, by employee id '$([string]::Join("', '", ([array]$EmployeeId)))'" -Tag "VacationEntitlement", "Set", "Filtering" } # Process VacationEntitlement modification foreach ($entitlement in $InputObject) { if ($pscmdlet.ShouldProcess("Vacation entitlement for '$($entitlement.EmployeeName)' to $($Days) days in $($Year)", "Set")) { Write-PSFMessage -Level Verbose -Message "Set vacation entitlement for '$($entitlement.EmployeeName)' to $($Days) days in $($Year)" -Tag "VacationEntitlement", "Set" # Prepare request $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/vacationDays" if ($TransferedDays) { $_transferred = $TransferedDays } else { $_transferred = 0 } $body = @{ "employeeId" = $entitlement.employeeId "year" = $entitlement.year "numberOfDays" = $Days "transferred" = $_transferred } # Set entitlement $response = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token # Output result if ($PassThru) { Write-PSFMessage -Level Verbose -Message "$($response.meta.text): Going to output $(([array]($response.content)).count) VacationEntitlement records in year $($Year)" -Tag "VacationEntitlement", "Query" foreach ($newEntitlement in $response.content) { $_baseObject = $entitlement.BaseObject $_baseObject.numberOfDays = $newEntitlement.numberOfDays if ($newEntitlement.transferred) { $_transferred = $newEntitlement.transferred if($_baseObject.TransferedDays) { $_baseObject.TransferedDays = $_transferred } } else { $_transferred = 0 } [TANSS.Vacation.Entitlement]@{ BaseObject = $_baseObject EmployeeId = $newEntitlement.employeeId Year = $newEntitlement.year NumberOfDays = $newEntitlement.numberOfDays TransferedDays = $_transferred } } } } } } end {} } function Set-TANSSVacationRequest { <# .Synopsis Set-TANSSVacationRequest .DESCRIPTION Modfiy a vacation/absence record within TANSS .PARAMETER InputObject TANSS.Vacation.Request object passed in to modify .PARAMETER Id The Id of the VacationRequest within TANSS service .PARAMETER Type Name of the request type Values can be tabcompleted, so you don't have to type Available: "Urlaub", "Krankheit", "Abwesenheit", "Bereitschaft", "Überstunden abfeiern", "VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME" .PARAMETER AbsenceSubType TANSS.Vacation.AbsenceSubType object to set on the absense record .PARAMETER AbsenceSubTypeName For type "Abwesenheit", "ABSENCE" there are subtypes available This one specifies the name of the subtype to set on the absense record Values can be tabcompleted, so you don't have to type .PARAMETER StartDate Starting date for the record to modify .PARAMETER EndDate End date for the record to modify .PARAMETER Description Description to set on the record .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Set-TANSSVacationRequest -Id 123 -Description "new description" Change the description of the VacationRequest 123 to "new description" .EXAMPLE PS C:\> $vacationRequest | Set-TANSSVacationRequest -EndDate "01/31/2023" Set enddate to "01/31/2023" the request in variable $vacationRequest .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Vacation.Request])] Param( [Parameter( ParameterSetName = "ByInputObjectWithSubType", Mandatory = $true, ValueFromPipeline = $true )] [Parameter( ParameterSetName = "ByInputObjectWithSubTypeName", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ByIdWithSubType", Mandatory = $true, ValueFromPipeline = $true )] [Parameter( ParameterSetName = "ByIdWithSubTypeName", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [ValidateNotNullOrEmpty()] [string] $Type, [Parameter(ParameterSetName = "ByInputObjectWithSubType")] [Parameter(ParameterSetName = "ByIdWithSubType")] [ValidateNotNullOrEmpty()] [TANSS.Vacation.AbsenceSubType] $AbsenceSubType, [Parameter( ParameterSetName = "ByInputObjectWithSubTypeName", Mandatory = $true )] [Parameter( ParameterSetName = "ByIdWithSubTypeName", Mandatory = $true )] [ValidateNotNullOrEmpty()] [string] $AbsenceSubTypeName, [ValidateNotNullOrEmpty()] [datetime] $StartDate, [ValidateNotNullOrEmpty()] [datetime] $EndDate, [Alias("Reason", "RequestReason")] [string] $Description, [switch] $PassThru, [TANSS.Connection] $Token ) begin { # Validation - Basic checks if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning # Parameter Type if ($Type) { Write-PSFMessage -Level System -Message "Processing Type '$($Type)'" switch ($Type) { { $_ -like "Urlaub" } { $planningType = "VACATION" } { $_ -like "Krankheit" } { $planningType = "ILLNESS" } { $_ -like "Abwesenheit*" } { $planningType = "ABSENCE" } { $_ -like "Bereitschaft" } { $planningType = "STAND_BY" } { $_ -like "Überstunden abfeiern" } { $planningType = "OVERTIME" } { $_ -in ("VACATION", "ILLNESS", "ABSENCE", "STAND_BY", "OVERTIME") } { $planningType = $_ } default { Stop-PSFFunction -Message "Unhandled Type '$($Type)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "VacationType", "SwitchException" } } Write-PSFMessage -Level System -Message "Using VacationRequestType '$($planningType)'" } } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" -Tag "VacationRequest" #region Validation # Check dates if (($StartDate -and $EndDate) -and ($StartDate -gt $EndDate)) { Stop-PSFFunction -Message "Specified dates are not valid! Please check dates, StartDate '$($StartDate)' is greater then EndDate '$($EndDate))'" -EnableException $true -Cmdlet $pscmdlet } # Find additional AbsenceSubType from specified name if ($parameterSetName -like "*WithSubTypeName") { Write-PSFMessage -Level System -Message "Gathering TANSS absence type '$($AbsenceSubTypeName)'" -Tag "VacationRequest", "AbsenceSubType", "Lookup" $tmpWhatIfPreference = $WhatIfPreference $WhatIfPreference = $fals $AbsenceSubType = Get-TANSSVacationAbsenceSubType -Name $AbsenceSubTypeName -Token $Token -ErrorAction Ignore $WhatIfPreference = $tmpWhatIfPreference Remove-Variable tmpWhatIfPreference -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false if ($AbsenceSubType) { Write-PSFMessage -Level Verbose -Message "Found AbsenceSubTypeId '$($AbsenceSubType.Id)' for '$($AbsenceSubTypeName)'" } else { Stop-PSFFunction -Message "Unable to find AbsenceSubType '$($AbsenceSubTypeName)'" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "AbsenceSubType" } } #endregion Validation - checking parameters # If Id is piped in, query vacationRequests from TANSS if ($parameterSetName -like "ById*") { $InputObject = foreach ($requesterId in $Id) { Write-PSFMessage -Level Verbose -Message "Query VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" # Query VacationRequest by ID $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($requesterId)" $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token -Confirm:$false # Output result Write-PSFMessage -Level Verbose -Message "$($response.meta.text): VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" [TANSS.Vacation.Request]@{ BaseObject = $response.content Id = $response.content.id } } } foreach ($vacationRequest in $InputObject) { Write-PSFMessage -Level Verbose -Message "Working on '$($vacationRequest.TypeName)' VacationRequest '$($vacationRequest.Id)' ($($vacationRequest.EmployeeName)) for range '$($vacationRequest.StartDate) - $($vacationRequest.EndDate)'" -Tag "VacationRequest", "Set" # earlier Startdate should be set --> VacationDay objects have to be added to days property if ($StartDate -and ($StartDate -lt $vacationRequest.StartDate)) { Write-PSFMessage -Level System -Message "StartDate found, need to add $(($vacationRequest.EndDate - $StartDate).Days) days to VacationRequest" -Tag "VacationRequest", "Set", "AddDays" $plannedVactionRequest = Request-TANSSVacationRequestObject -EmployeeId $vacationRequest.BaseObject.requesterId -Type $vacationRequest.BaseObject.planningType -StartDate $StartDate -EndDate $vacationRequest.EndDate -Token $Token if(-not $plannedVactionRequest) { continue } # add days new days to vacation request $vacationRequest.Days = $plannedVactionRequest.Days Write-PSFMessage -Level System -Message "VacationRequest '$($vacationRequest.Id)' is modified with ne Startdate, new range '$($vacationRequest.StartDate) - $($vacationRequest.EndDate)'" -Tag "VacationRequest", "Set", "AddDays" Remove-Variable -Name apiPath, _startDate, body, plannedVactionRequest -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false -ErrorAction:Ignore -WarningAction:Ignore -InformationAction:Ignore } # Later Enddate should be set --> VacationDay objects have to be added to days property if ($EndDate -and ($EndDate -gt $vacationRequest.EndDate)) { Write-PSFMessage -Level System -Message "EndDate found, need to add $(($EndDate - $vacationRequest.EndDate).Days) days to VacationRequest" -Tag "VacationRequest", "Set", "AddDays" # Query addiontial days $plannedVactionRequest = Request-TANSSVacationRequestObject -EmployeeId $vacationRequest.BaseObject.requesterId -Type $vacationRequest.BaseObject.planningType -StartDate $vacationRequest.StartDate -EndDate $EndDate -Token $Token if(-not $plannedVactionRequest) { continue } # add days new days to vacation request $vacationRequest.Days = $plannedVactionRequest.Days Write-PSFMessage -Level System -Message "VacationRequest '$($vacationRequest.Id)' is modified with ne Startdate, new range '$($vacationRequest.StartDate) - $($vacationRequest.EndDate)'" -Tag "VacationRequest", "Set", "AddDays" Remove-Variable -Name apiPath, _endDate, body, plannedVactionRequest -Force -WhatIf:$false -Confirm:$false -Verbose:$false -Debug:$false -ErrorAction:Ignore -WarningAction:Ignore -InformationAction:Ignore } # Later StartDate should be set --> have to be remove days from VacationRequest objects if ($StartDate -and ($StartDate -ne $vacationRequest.StartDate)) { Write-PSFMessage -Level System -Message "StartDate found, need to remove $(($StartDate - $vacationRequest.StartDate).Days) day(s) from VacationRequest '$($vacationRequest.Id)'" -Tag "VacationRequest", "Set", "RemoveDays" $_startDate = [int][double]::Parse((Get-Date -Date $StartDate.Date.ToUniversalTime() -UFormat %s)) $vacationRequest.BaseObject.startDate = $_startDate $vacationRequest.Days = $vacationRequest.Days | Where-Object date -ge $StartDate } # Earlier EndDate should be set --> have to be remove days from VacationRequest objects if ($EndDate -and ($EndDate -ne $vacationRequest.EndDate)) { Write-PSFMessage -Level System -Message "EndDate found, need to remove $(($EndDate - $vacationRequest.EndDate).Days * -1) day(s) from VacationRequest '$($vacationRequest.Id)'" -Tag "VacationRequest", "Set", "RemoveDays" $_endDate = [int][double]::Parse((Get-Date -Date $EndDate.Date.ToUniversalTime() -UFormat %s)) $vacationRequest.BaseObject.endDate = $_endDate $vacationRequest.Days = $vacationRequest.Days | Where-Object date -le $EndDate } # Set Description if ($Description) { Write-PSFMessage -Level System -Message "Description found, going to change description from '$($vacationRequest.Description)' to '$($Description)'" -Tag "VacationRequest", "Set", "RequestDate" $vacationRequest.BaseObject.requestReason = "$($Description)" } # Set type if ($planningType) { Write-PSFMessage -Level System -Message "Type found, going to change Type from '$($vacationRequest.Type)' to '$($planningType)'" -Tag "VacationRequest", "Set", "Type" $vacationRequest.BaseObject.planningType = $planningType # remove additional planning type when change from absence so something else if (($vacationRequest.BaseObject.planningType -notlike "ABSENCE") -and ($vacationRequest.BaseObject.planningAdditionalId -gt 0)) { $vacationRequest.BaseObject.planningAdditionalId = 0 } } # Set AbsenceSubType if ($AbsenceSubType -or $AbsenceSubTypeName) { if (($planningType -like "ABSENCE") -and $AbsenceSubTypeName) { $AbsenceSubType = Get-TANSSVacationAbsenceSubType -Name $AbsenceSubTypeName Write-PSFMessage -Level Verbose -Message "Set additionalAbsenceSubType '$($AbsenceSubType.Name)' to VacationRequest object" -Tag "VacationRequest", "Set", "AbsenceSubType" $vacationRequest.BaseObject.planningAdditionalId = $AbsenceSubType.Id } elseif (($planningType -notlike "ABSENCE") -and ($AbsenceSubType -or $AbsenceSubTypeName)) { Write-PSFMessage -Level Important -Message "AbsenceSubType specified, but not valid '$(if($planningType){"for '$($planningType)'"} else { "without Type"})'! AbsenceSubTypes are only possible with Type 'Abwesenheit'/'ABSENCE'. Setting will be ignored" -Tag "VacationRequest", "AbsenceSubType" } } # Make the change effective within TANSS $body = $vacationRequest.BaseObject | ConvertTo-PSFHashtable $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($vacationRequest.Id)" if ($pscmdlet.ShouldProcess("VacationRequest for employeeId '$($vacationRequest.EmployeeId)' with $($vacationRequest.days | Measure-Object | Select-Object -ExpandProperty Count) days on planningType '$($vacationRequest.Type)' on dates '$(Get-Date -Date $vacationRequest.StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $vacationRequest.EndDate -Format 'yyyy-MM-dd')'", "Set")) { Write-PSFMessage -Level Verbose -Message "Set VacationRequest for employeeId '$($vacationRequest.EmployeeId)' with $($vacationRequest.days | Measure-Object | Select-Object -ExpandProperty Count) days on planningType '$($vacationRequest.Type)' on dates '$(Get-Date -Date $vacationRequest.StartDate -Format 'yyyy-MM-dd')'-'$(Get-Date -Date $vacationRequest.EndDate -Format 'yyyy-MM-dd')'" -Tag "VacationRequest", "Set" # Create the object within TANSS $result = Invoke-TANSSRequest -Type PUT -ApiPath $apiPath -Body $body -Token $Token Write-PSFMessage -Level Verbose -Message "$($result.meta.text) - RequestId '$($result.content.id)' with status '$($result.content.status)'" -Tag "VacationRequest", "VactionRequestObject", "VacationRequestResult" # output the result if ($result -and $PassThru) { [TANSS.Vacation.Request]@{ BaseObject = $result.content Id = $result.content.id } } } } } end { } } function Set-TANSSVacationRequestStatus { <# .Synopsis Set-TANSSVacationRequestStatus .DESCRIPTION Approve or decline a vacation request within TANSS .PARAMETER InputObject TANSS.Vacation.Request object to modify .PARAMETER Id The id of the vacation request to modify .PARAMETER Status Status to set for the request Available values are: "Approve", "Decline" Values can be tabcompleted, so you don't have to type .PARAMETER Token The TANSS.Connection token to access api If not specified, the registered default token from within the module is going to be used .PARAMETER PassThru Outputs the result to the console .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. .PARAMETER Confirm If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. .EXAMPLE PS C:\> Get-TANSSVacationRequest -Id 10 | Set-TANSSVacationRequestStatus -Status "Approve" Approve the VacationRequest Id 10 .EXAMPLE PS C:\> Set-TANSSVacationRequestStatus -Id 10 -Status "Decline" Decline the VacationRequest Id 10 .EXAMPLE PS C:\> $vacationRequests | Set-TANSSVacationRequestStatus -Status "Approve" -PassThru Approve all requests in variable '$vacationrequests' and output the (approved) VacationRequests on the console Assuming, the variable is build on something like: PS C:\>$vacationrequests = Get-TANSSVacationRequest -Year 2022 -Month 8 .NOTES Author: Andreas Bellstedt .LINK https://github.com/AndiBellstedt/PSTANSS #> [CmdletBinding( DefaultParameterSetName = "ById", SupportsShouldProcess = $true, PositionalBinding = $true, ConfirmImpact = 'Medium' )] [OutputType([TANSS.Vacation.Request])] Param( [Parameter( ParameterSetName = "ByInputObject", Mandatory = $true, ValueFromPipeline = $true )] [TANSS.Vacation.Request[]] $InputObject, [Parameter( ParameterSetName = "ById", Mandatory = $true, ValueFromPipeline = $true )] [Alias("RequestId", "VacationRequestId")] [int[]] $Id, [Parameter(Mandatory = $true)] [ValidateSet("Approve", "Decline")] [string] $Status, [switch] $PassThru, [TANSS.Connection] $Token ) begin { if (-not $Token) { $Token = Get-TANSSRegisteredAccessToken } Assert-CacheRunspaceRunning } process { $parameterSetName = $pscmdlet.ParameterSetName Write-PSFMessage -Level Debug -Message "ParameterNameSet: $($parameterSetName)" # If Id is piped in, query vacationRequests from TANSS if ($parameterSetName -like "ById") { $InputObject = foreach ($requesterId in $Id) { Write-PSFMessage -Level Verbose -Message "Query VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" # Query VacationRequest by ID $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($requesterId)" $response = Invoke-TANSSRequest -Type "GET" -ApiPath $apiPath -Token $Token # Output result Write-PSFMessage -Level Verbose -Message "$($response.meta.text): VacationRequestId $($requesterId)" -Tag "VacationRequest", "Query" [TANSS.Vacation.Request]@{ BaseObject = $response.content Id = $response.content.id } } } if (-not $InputObject) { Write-PSFMessage -Level Significant -Message "No VacationRequests found to set status on" -Tag "VacationRequest", "Set", "NoData" } else { switch ($Status) { "Approve" { $Status = "Approve" # Just to be sure with the spelling $body = @{ "status" = "APPROVED" } } "Decline" { $Status = "Decline" # Just to be sure with the spelling $body = @{ "status" = "DECLINED" } } Default { Stop-PSFFunction -Message "Unhandled status '$($Status)', developers mistake" -EnableException $true -Cmdlet $pscmdlet -Tag "VacationRequest", "SwitchException", "ParameterSet" } } foreach ($vacationRequest in $InputObject) { if ($pscmdlet.ShouldProcess("VacationRequestId '$($vacationRequest.Id)' from '$($vacationRequest.EmployeeName)' on '$($vacationRequest.StartDate)-$($vacationRequest.EndDate)'", $Status)) { Write-PSFMessage -Level Verbose -Message "$($Status) VacationRequestId '$($vacationRequest.Id)' from '$($vacationRequest.EmployeeName)' on '$($vacationRequest.StartDate)-$($vacationRequest.EndDate)'" -Tag "VacationRequest", "Set", $Status # Set status on VacationRequest $apiPath = Format-ApiPath -Path "api/v1/vacationRequests/$($vacationRequest.Id)" $response = Invoke-TANSSRequest -Type "PUT" -ApiPath $apiPath -Body $body -Token $Token Write-PSFMessage -Level Verbose -Message "VacationRequestId '$($vacationRequest.Id)' - $($response.meta.text)" -Tag "VacationRequest", "Set" # Output if Passthrough is set if($PassThru) { [TANSS.Vacation.Request]@{ BaseObject = $response.content Id = $response.content.id } } } } } } end { } } <# This is an example configuration file By default, it is enough to have a single one of them, however if you have enough configuration settings to justify having multiple copies of it, feel totally free to split them into multiple files. # Example Configuration Set-PSFConfig -Module 'PSTANSS' -Name 'Example.Setting' -Value 10 -Initialize -Validation 'integer' -Handler { } -Description "Example configuration setting. Your module can then use the setting using 'Get-PSFConfigValue'" #> #region Module configurations Set-PSFConfig -Module 'PSTANSS' -Name 'Import.DoDotSource' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be dotsourced on import. By default, the files of this module are read as string value and invoked, which is faster but worse on debugging." Set-PSFConfig -Module 'PSTANSS' -Name 'Import.IndividualFiles' -Value $false -Initialize -Validation 'bool' -Description "Whether the module files should be imported individually. During the module build, all module code is compiled into few files, which are imported instead by default. Loading the compiled versions is faster, using the individual files is easier for debugging and testing out adjustments." Set-PSFConfig -Module 'PSTANSS' -Name 'API.RestPathPrefix' -Value "backend/" -Initialize -Validation 'string' -Description "Individual URI path for API webservices on TANSS server. HuckIT specifies the rest calls on 'https://api-doc.tanss.de/', but on prod-installations for TANSS, there maybe a prefix in the path of the api rest calls." #endregion Module configurations #region Module variables New-Variable -Name TANSSToken -Scope Script -Visibility Public -Description "Variable for registered token. This is for convinience use with the commands in the module" -Force #endregion Module variables #region Manual Lookup definitions [TANSS.Lookup]::LinkTypes = @{ "0" = "Keine Zuweisung" "1" = "PC" "2" = "Kunde (generell)" "3" = "Mitarbeiter" "4" = "Peripherie" "5" = "Komponente" "6" = "Lizenz" "24" = "Domain" } [TANSS.Lookup]::VacationTypesPredefinedApi = [ordered]@{ "VACATION" = "Urlaub" "ILLNESS" = "Krankheit" "ABSENCE" = "Abwesenheit" "STAND_BY" = "Bereitschaft" "OVERTIME" = "Überstunden abfeiern" } [TANSS.Lookup]::VacationAbsenceSubTypes = @{} #endregion Manual Lookup definitions <# Stored scriptblocks are available in [PsfValidateScript()] attributes. This makes it easier to centrally provide the same scriptblock multiple times, without having to maintain it in separate locations. It also prevents lengthy validation scriptblocks from making your parameter block hard to read. Set-PSFScriptblock -Name 'PSTANSS.ScriptBlockName' -Scriptblock { } #> Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Companies" -ScriptBlock { [TANSS.Lookup]::Companies.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Client" -ScriptBlock { [TANSS.Lookup]::Employees.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Contracts" -ScriptBlock { [TANSS.Lookup]::Contracts.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.CostCenters" -ScriptBlock { [TANSS.Lookup]::CostCenters.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Departments" -ScriptBlock { [TANSS.Lookup]::Departments.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Employees" -ScriptBlock { [TANSS.Lookup]::Employees.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.OrderBys" -ScriptBlock { [TANSS.Lookup]::OrderBys.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Phases" -ScriptBlock { [TANSS.Lookup]::Phases.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Tags" -ScriptBlock { [TANSS.Lookup]::Tags.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.Tickets" -ScriptBlock { [TANSS.Lookup]::Tickets.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.TicketStates" -ScriptBlock { [TANSS.Lookup]::TicketStates.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.TicketTypes" -ScriptBlock { [TANSS.Lookup]::TicketTypes.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.VacationAbsenceSubTypes" -ScriptBlock { [TANSS.Lookup]::VacationAbsenceSubTypes.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.CarNumberPlate" -ScriptBlock { [TANSS.Lookup]::CarNumberplate.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.SupportTypes" -ScriptBlock { [TANSS.Lookup]::SupportTypes.Values } Register-PSFTeppScriptblock -Name "PSTANSS.CacheLookup.NotChargedReasons" -ScriptBlock { [TANSS.Lookup]::NotChargedReasons.Values } <# # Example: Register-PSFTeppScriptblock -Name "PSTANSS.alcohol" -ScriptBlock { 'Beer','Mead','Whiskey','Wine','Vodka','Rum (3y)', 'Rum (5y)', 'Rum (7y)' } #> # VacationRequestTypes Register-PSFTeppScriptblock -Name "PSTANSS.Parameter.GetVacationRequest.Type" -ScriptBlock { @([TANSS.Lookup]::VacationTypesPredefinedApi.Values, [TANSS.Lookup]::VacationTypesPredefinedApi.Keys) } <# # Example: Register-PSFTeppArgumentCompleter -Command Get-Alcohol -Parameter Type -Name PSTANSS.alcohol #> #region Ticket Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Company -Name "PSTANSS.CacheLookup.Companies" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Client -Name "PSTANSS.CacheLookup.Client" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Department -Name "PSTANSS.CacheLookup.Departments" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter EmployeeAssigned -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter EmployeeTicketAdmin -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Phase -Name "PSTANSS.CacheLookup.Phases" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Status -Name "PSTANSS.CacheLookup.TicketStates" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter Type -Name "PSTANSS.CacheLookup.TicketTypes" Register-PSFTeppArgumentCompleter -Command New-TANSSTicket -Parameter OrderBy -Name "PSTANSS.CacheLookup.OrderBys" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Company -Name "PSTANSS.CacheLookup.Companies" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Client -Name "PSTANSS.CacheLookup.Client" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Department -Name "PSTANSS.CacheLookup.Departments" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter EmployeeAssigned -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter EmployeeTicketAdmin -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Phase -Name "PSTANSS.CacheLookup.Phases" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Status -Name "PSTANSS.CacheLookup.TicketStates" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter Type -Name "PSTANSS.CacheLookup.TicketTypes" Register-PSFTeppArgumentCompleter -Command Set-TANSSTicket -Parameter OrderBy -Name "PSTANSS.CacheLookup.OrderBys" #endregion Ticket #region Core Register-PSFTeppArgumentCompleter -Command Find-TANSSObject -Parameter CompanyName -Name "PSTANSS.CacheLookup.Companies" #endregion Core #region Employee Register-PSFTeppArgumentCompleter -Command New-TANSSEmployee -Parameter Department -Name "PSTANSS.CacheLookup.Departments" Register-PSFTeppArgumentCompleter -Command New-TANSSEmployee -Parameter CompanyName -Name "PSTANSS.CacheLookup.Companies" #endregion Employee #region Vacation Register-PSFTeppArgumentCompleter -Command Get-TANSSVacationType -Parameter Name -Name "PSTANSS.CacheLookup.VacationAbsenceSubTypes" Register-PSFTeppArgumentCompleter -Command New-TANSSVacationRequest -Parameter AbsenceSubTypeName -Name "PSTANSS.CacheLookup.VacationAbsenceSubTypes" Register-PSFTeppArgumentCompleter -Command Get-TANSSVacationRequest -Parameter EmployeeName -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command Get-TANSSVacationRequest -Parameter DepartmentName -Name "PSTANSS.CacheLookup.Departments" Register-PSFTeppArgumentCompleter -Command Get-TANSSVacationRequest -Parameter Type -Name "PSTANSS.Parameter.GetVacationRequest.Type" Register-PSFTeppArgumentCompleter -Command Get-TANSSVacationRequest -Parameter AbsenceSubTypeName -Name "PSTANSS.CacheLookup.VacationAbsenceSubTypes" Register-PSFTeppArgumentCompleter -Command Set-TANSSVacationRequest -Parameter Type -Name "PSTANSS.Parameter.GetVacationRequest.Type" Register-PSFTeppArgumentCompleter -Command Set-TANSSVacationRequest -Parameter AbsenceSubTypeName -Name "PSTANSS.CacheLookup.VacationAbsenceSubTypes" Register-PSFTeppArgumentCompleter -Command Request-TANSSVacationRequestObject -Parameter Type -Name "PSTANSS.Parameter.GetVacationRequest.Type" Register-PSFTeppArgumentCompleter -Command Request-TANSSVacationRequestObject -Parameter EmployeeName -Name "PSTANSS.CacheLookup.Employees" Register-PSFTeppArgumentCompleter -Command Set-TANSSVacationEntitlement -Parameter EmployeeName -Name "PSTANSS.CacheLookup.Employees" #endregion Vacation New-PSFLicense -Product 'PSTANSS' -Manufacturer 'Andreas Bellstedt' -ProductVersion $script:ModuleVersion -ProductType Module -Name MIT -Version "1.0.0.0" -Date (Get-Date "2022-07-29") -Text @" Copyright (c) 2022 Andreas Bellstedt Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. "@ $runspaceName = "TANSS.LookupValidation" $ScriptBlock = [System.Management.Automation.ScriptBlock]::Create( (Get-Content "$($script:ModuleRoot)\internal\scripts\Expand-TANSSCacheData.ps1" -Raw) ) if (Get-PSFRunspace -Name $runspaceName) { [TANSS.Cache]::StopValidationRunspace = $true Get-PSFRunspace -Name $runspaceName | Stop-PSFRunspace } Register-PSFRunspace -Name $runspaceName -ScriptBlock $ScriptBlock [TANSS.Cache]::StopValidationRunspace = $false Start-PSFRunspace -Name $runspaceName #endregion Load compiled code |