public/New-VSAOrganization.ps1
|
function New-VSAOrganization { <# .Synopsis Creates a new organization. .DESCRIPTION Creates a new organization. Takes either persistent or non-persistent connection information. .PARAMETER VSAConnection Specifies existing non-persistent VSAConnection. .PARAMETER URISuffix Specifies the URI suffix if it differs from the default. .PARAMETER OrgId Specifies the numeric ID of the organization. A random ID is generated if not provided. .PARAMETER OrgName Specifies the full organization name. .PARAMETER OrgRef Specifies a unique string to reference the organization. Must be unique, usually a shortened name or acronym. .PARAMETER DefaultDepartmentName Specifies the Default Department Name. Default is 'root'. .PARAMETER DefaultMachineGroupName Specifies the Default Machine Group Name. Default is 'root'. .PARAMETER OrgType Specifies the Organization Type. .PARAMETER ParentOrgId Specifies the Numeric ID of an existing organization that is set as the parent for the new one. .PARAMETER Website Specifies the organization's website. .PARAMETER NoOfEmployees Specifies the number of employees. .PARAMETER AnnualRevenue Specifies the annual revenue. .PARAMETER ContactInfo Specifies a string representation of contact information object. If provided, individual contact fields are extracted. .PARAMETER PreferredContactMethod Specifies the preferred contact method. .PARAMETER PrimaryPhone Specifies the primary phone number. .PARAMETER PrimaryFax Specifies the primary fax number. .PARAMETER PrimaryEmail Specifies the primary email address. .PARAMETER Country Specifies the country. .PARAMETER Street Specifies the street address. .PARAMETER City Specifies the city. .PARAMETER State Specifies the state. .PARAMETER ZipCode Specifies the ZIP code. .PARAMETER PrimaryTextMessagePhone Specifies the primary phone number for text messages. .PARAMETER FieldName Specifies the name of a custom field. .PARAMETER FieldValue Specifies the value of a custom field. .PARAMETER CustomFields Specifies an array of custom fields as string representations. If provided, individual fields are extracted. .PARAMETER Attributes Specifies additional attributes in a string representation. Converted to a hashtable for processing. .PARAMETER ExtendedOutput Indicates whether to return extended output. If specified, returns the OrgId property of the newly created organization; otherwise, returns a boolean result if the operation was successful. .EXAMPLE New-VSAOrganization -VSAConnection $VSAConnection -OrgName 'My Organization' -OrgRef 'myorg' .INPUTS Accepts a piped Organization object. .OUTPUTS Returns True if the creation was successful; returns the OrgId property of the new Organization if the ExtendedOutput switch is specified. .NOTES Version 1.0.0 #> [CmdletBinding(SupportsShouldProcess)] param ( [parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [VSAConnection] $VSAConnection, [parameter(DontShow, Mandatory=$false)] [ValidateNotNullOrEmpty()] [string] $URISuffix = 'api/v1.0/system/orgs', [parameter(DontShow, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if( (-not [string]::IsNullOrEmpty($_)) -and ($_ -notmatch "^\d+$") ) { throw "Non-numeric value" } return $true })] [string] $OrgId, [parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, HelpMessage = "Specify name of the organization.")] [ValidateNotNullOrEmpty()] [string] $OrgName, [parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, HelpMessage = "Unique string to reference the organization. Usually shorten name or acronim.")] [ValidateNotNullOrEmpty()] [string] $OrgRef, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $DefaultDepartmentName = 'root', [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $DefaultMachineGroupName = 'root', [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $OrgType, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if( (-not [string]::IsNullOrEmpty($_)) -and ($_ -notmatch "^\d+$") ) { throw "Non-numeric Id" } return $true })] [string] $ParentOrgId, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $Website, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if( (-not [string]::IsNullOrEmpty($_)) -and ($_ -notmatch "^\d+$") ) { throw "Non-numeric value" } return $true })] [Alias('numEmployees', 'NumberOfEmployees')] [string] $NoOfEmployees, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [ValidateScript({ if( (-not [string]::IsNullOrEmpty($_)) -and ($_ -notmatch "^\d*\.?\d*$") ) { throw "Non-numeric value" } return $true })] [string] $AnnualRevenue, [parameter(DontShow, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] # Accepts a [hashtable]/[pscustomobject] (preferred) or the legacy "{ Key= value; ... }" # string. When supplied, it takes precedence over the discrete contact parameters below. [object] $ContactInfo, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $PreferredContactMethod, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $PrimaryPhone, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $PrimaryFax, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $PrimaryEmail, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $Country, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $Street, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $City, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $State, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $ZipCode, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $PrimaryTextMessagePhone, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $FieldName, [parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true)] [string] $FieldValue, [parameter(DontShow, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] # Each element accepts a [hashtable]/[pscustomobject] (preferred) or the legacy # "{ FieldName= ..; FieldValue= .. }" string. [object[]] $CustomFields = @(), [parameter(DontShow, Mandatory=$false, ValueFromPipelineByPropertyName=$true)] # Accepts a [hashtable]/[pscustomobject] (preferred) or the legacy "{ Key= value; ... }" string. [object] $Attributes, [parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [switch] $ExtendedOutput ) process { # ContactInfo, CustomFields and Attributes are nested structures handled explicitly below via # ConvertTo-VSAHashtable, so they are intentionally NOT populated into the body from the raw # bound parameter here (F-39 kept them out of the naive copy for the same reason). [string[]]$OrganizationFields = @('OrgId', 'OrgName', 'OrgRef', 'DefaultDepartmentName', 'DefaultMachineGroupName', 'OrgType', 'ParentOrgId', 'Website', 'NoOfEmployees', 'AnnualRevenue', 'FieldName', 'FieldValue') [string[]]$ContactInfoFields = @('PreferredContactMethod', 'PrimaryPhone', 'PrimaryFax', 'PrimaryEmail', 'Country', 'Street', 'City', 'State', 'ZipCode', 'PrimaryTextMessagePhone') [string[]]$AllFields = $OrganizationFields + $ContactInfoFields # Build the request body from bound parameters. Values (including those containing commas, # ampersands, quotes, etc.) are preserved exactly, unlike the previous Get-PSCallStack string parsing (F-39). [hashtable]$BodyHT = ConvertTo-VSARequestBody -BoundParameters $PSBoundParameters -Include $AllFields # Add a random OrgId if it doesn't exist $OrgId = $((100..999) | Get-Random).ToString() if ( $BodyHT.ContainsKey('OrgId') ) { $BodyHT['OrgId'] = $OrgId } else { $BodyHT.Add('OrgId', $OrgId) } # Set default values for DefaultDepartmentName and DefaultMachineGroupName if not provided if ($BodyHT.ContainsKey('DefaultDepartmentName')) { if([string]::IsNullOrEmpty($DefaultDepartmentName)) { $BodyHT.DefaultDepartmentName = 'root' } } else { $BodyHT.Add('DefaultDepartmentName', 'root') } if ($BodyHT.ContainsKey('DefaultMachineGroupName')) { if([string]::IsNullOrEmpty($DefaultMachineGroupName)) { $BodyHT.DefaultMachineGroupName = 'root' } } else { $BodyHT.Add('DefaultMachineGroupName', 'root') } # Process Contact Info: a supplied -ContactInfo object (hashtable/pscustomobject/legacy string) # takes precedence; otherwise assemble it from the discrete contact parameters. [hashtable] $ContactInfoHT = @{} if ( $null -ne $ContactInfo ) { $ContactInfoHT = ConvertTo-VSAHashtable $ContactInfo } if ( 0 -eq $ContactInfoHT.Count ) { foreach ($Field in $ContactInfoFields) { if ($BodyHT.ContainsKey($Field)) { $ContactInfoHT[$Field] = $BodyHT[$Field] } } } # The discrete contact fields (and any raw ContactInfo) must never remain at the body top level. $BodyHT.Remove('ContactInfo') foreach ($Field in $ContactInfoFields) { $BodyHT.Remove($Field) } #Remove empty keys foreach ( $key in @($ContactInfoHT.Keys) ) { if ( -not $ContactInfoHT[$key] ) { $ContactInfoHT.Remove($key) } } # Add Contact Info hashtable to Body if it's not empty if (0 -lt $ContactInfoHT.Count) { $BodyHT.Add('ContactInfo', $ContactInfoHT) } #region Process Custom Fields $CFArrayList = New-Object System.Collections.ArrayList if ( 0 -lt $CustomFields.Count ) { Foreach ( $CustomField in $CustomFields ) { [hashtable]$FieldHT = ConvertTo-VSAHashtable $CustomField if ( 0 -lt $FieldHT.Count ) { [void]$CFArrayList.Add($FieldHT) } } } if ( ( -not [string]::IsNullOrWhiteSpace($FieldName)) -and ( -not [string]::IsNullOrWhiteSpace($FieldValue)) ) { [hashtable]$FieldHT = @{ FieldName = $FieldName; FieldValue = $FieldValue } [void]$CFArrayList.Add($FieldHT) } $BodyHT.Remove('CustomFields') if ( 0 -lt $CFArrayList.Count ) { $BodyHT.Add('CustomFields', $($CFArrayList.ToArray()) ) } #endregion Process Custom Fields #region Process Attributes $BodyHT.Remove('Attributes') if ( $null -ne $Attributes ) { [hashtable] $AttributesHT = ConvertTo-VSAHashtable $Attributes if ( 0 -lt $AttributesHT.Count ) { $BodyHT.Add('Attributes', $AttributesHT ) } } #endregion Process Attributes #Check if the Parent Organization exists if ( -not [string]::IsNullOrEmpty($ParentOrgId) ) { Write-Debug "New-VSAOrganization. Check if the Parent Organization exists" $ParentOrg = try { Get-VSAOrganization -VSAConnection $VSAConnection -OrgID $ParentOrgId } catch {$null} if ( [string]::IsNullOrEmpty($ParentOrg) ) { Write-Warning "Could not find the Parent Organization by the ParentOrgId provided '$ParentOrgId' for '$OrgName'." } } else { $BodyHT.Remove("ParentOrgId") } return Invoke-VSAWriteRequest -Body $BodyHT -Method POST -URISuffix $URISuffix ` -VSAConnection $VSAConnection -ExtendedOutput:$ExtendedOutput } } New-Alias -Name Add-VSAOrganization -Value New-VSAOrganization New-Alias -Name New-VSAOrg -Value New-VSAOrganization Export-ModuleMember -Function New-VSAOrganization -Alias Add-VSAOrganization, New-VSAOrg |