Populi.psm1

function Add-PAddress {
<#
.SYNOPSIS
  Adds an address to a person or organization.
 
.DESCRIPTION
  Adds address to a person or organization using the given parameters. Returns an address id that can then be used
  with other cmdlets like Update-PAddress | Delete-PAddress. (See output section.)
  Review the parameters for specific requirements and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be adding this address to his/her own profile.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER OrganizationId
  Numeric ID of the organization to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER Street
  e.g. 777 Magnolia Ln
  This parameter is required.
 
.PARAMETER City
  e.g. Moscow
  This parameter is required.
 
.PARAMETER State
  e.g. ID
 
.PARAMETER Postal
  e.g. 83843
 
.PARAMETER Country
  e.g. USA
 
.PARAMETER AddressType (PersonId)
  HOME, WORK, BILLING, SCHOOL, SHIPPING, OTHER
 
.PARAMETER OrgAddressType (OrganizationId)
  MAIN, BILLING, SHIPPING, OTHER
 
.PARAMETER Primary
  Use if you want to mark the email address as primary or not primary. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the email address as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    <Home|Work|Billing|Main|School|Shipping|Other>AddressId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/25/2019
 
.EXAMPLE
  Add-PAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7781234' -PhoneNumber '888-555-1212' -PhoneType SCHOOL
 
.EXAMPLE
  Add-PAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -PhoneNumber '888-555-1212' -OrgPhoneType WORK
#>

[CmdletBinding(DefaultParameterSetName='ByPersonId')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByPersonId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [parameter(ParameterSetName='ByOrganizationId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [parameter(Mandatory)]
      [string]
      $Street,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [parameter(Mandatory)]
      [string]
      $City,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [string]
      $State,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [string]
      $Postal,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [string]
      $Country,

      [Parameter(ParameterSetName='ByPersonId')]
      [ValidateSet("HOME","WORK","BILLING","SCHOOL","SHIPPING","OTHER")]
      [string]
      $AddressType,

      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("WORK","BILLING","SHIPPING","OTHER")]
      [string]
      $OrgAddressType,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddAddressBody = @{
             task = 'addAddress';
             access_key = $PopuliAuthkey;
             street = $Street;
             city = $City;
        }

        Write-Verbose -Message "Set default output object name."
        $AddressTypeId = "OtherAddressId"

        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $AddAddressBody.Add('person_id', $PersonId)
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to request string."
            $AddAddressBody.Add('organization_id', $OrganizationId)
        }
        if ($PSBoundParameters.ContainsKey('State')) {
            Write-Verbose -Message "Adding State $State to request string."
            $AddAddressBody.Add('state', $State)
        }
        if ($PSBoundParameters.ContainsKey('Postal')) {
            Write-Verbose -Message "Adding Postal $Postal to request string."
            $AddAddressBody.Add('postal', $Postal)
        }
        if ($PSBoundParameters.ContainsKey('Country')) {
            Write-Verbose -Message "Adding Country $Country to request string."
            $AddAddressBody.Add('country', $Country)
        }
        if ($PSBoundParameters.ContainsKey('AddressType')) {
            Write-Verbose -Message "Adding AddressType $AddressType to request string."
            $AddAddressBody.Add('type', $AddressType)
            $AddressType = $AddressType.ToLower()
            $AddressType = (Get-Culture).TextInfo.ToTitleCase($AddressType)
            $AddressTypeId = $AddressType + "AddressId"
        }
        if ($PSBoundParameters.ContainsKey('OrgAddressType')) {
            Write-Verbose -Message "Adding OrgAddressType $OrgAddressType to request string."
            $AddAddressBody.Add('type', $OrgAddressType)
            $OrgAddressType = $OrgAddressType.ToLower()
            $OrgAddressType = (Get-Culture).TextInfo.ToTitleCase($OrgAddressType)
            $AddressTypeId = $OrgAddressType + "AddressId"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary to request string."
            $AddAddressBody.Add('primary', $Primary)
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public to request string."
            $AddAddressBody.Add('public', $Public)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddAddressBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AddressId = [pscustomobject] @{
                       $AddressTypeId = $Response.response.id
                    }
                    Write-Output $AddressId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose -Message "Add-PAddress cmdlet finished."
    }

}  #END: Add-PAddress
function Add-PEmailAddress {
<#
.SYNOPSIS
  Adds an email to a person or organization.
 
.DESCRIPTION
  Adds an email address using the given parameters. Review the parameters for specific requirements
  and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be updating an email address on his/her own profile.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER OrganizationId
  Numeric ID of the organization to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER EMailAddress
  e.g. bob@example.com
  This parameter is required.
 
.PARAMETER EmailType (PersonId)
  HOME, WORK, SCHOOL, OTHER.
 
.PARAMETER OrgEmailType (OrganizationId)
  WORK, OTHER.
 
.PARAMETER Primary
  Use if you want to mark the email address as primary or not primary. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the email address as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    EmailId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/02/2019
  Updated: 04/25/2019
 
.EXAMPLE
  Add-PEmailAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7781234' -EmailAddress 'bob@school.edu' -EmailType SCHOOL
 
.EXAMPLE
  Add-PEmailAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '7781234' -EmailAddress 'org@school.edu' -OrgEmailType OTHER
#>

[CmdletBinding(DefaultParameterSetName='ByPersonId')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByPersonId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [parameter(ParameterSetName='ByOrganizationId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [parameter(Mandatory)]
      [mailaddress]
      $EmailAddress,

      [Parameter(ParameterSetName='ByPersonId')]
      [ValidateSet("HOME","WORK","SCHOOL","OTHER")]
      [string]
      $EmailType,

      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("WORK","OTHER")]
      [string]
      $OrgEmailType,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddEmailAddressBody = @{
             task = 'addEmailAddress';
             access_key = $PopuliAuthkey;
             email_address = $EmailAddress;
        }

        Write-Verbose -Message "Set default output object name."
        $EmailTypeId = "OtherEmailId"

        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to to request string."
            $AddEmailAddressBody.Add('person_id', $PersonId)
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to to request string."
            $AddEmailAddressBody.Add('organization_id', $OrganizationId)
        }
        if ($PSBoundParameters.ContainsKey('EmailType')) {
            Write-Verbose -Message "Adding EmailType $EmailType to to request string."
            $AddEmailAddressBody.Add('type', $EmailType)
            $EmailType = $EmailType.ToLower()
            $EmailType = (Get-Culture).TextInfo.ToTitleCase($EmailType)
            $EmailTypeId = $EmailType + "EmailId"
        }
        if ($PSBoundParameters.ContainsKey('OrgEmailType')) {
            Write-Verbose -Message "Adding OrgEmailType $OrgEmailType to to request string."
            $AddEmailAddressBody.Add('type', $OrgEmailType)
            $OrgEmailType = $OrgEmailType.ToLower()
            $OrgEmailType = (Get-Culture).TextInfo.ToTitleCase($OrgEmailType)
            $EmailTypeId = $OrgEmailType + "EmailId"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary to to request string."
            $AddEmailAddressBody.Add('primary', $Primary)
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public to to request string."
            $AddEmailAddressBody.Add('public', $Public)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddEmailAddressBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PEmailAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $EmailId = [pscustomobject] @{
                        $EmailTypeId = $Response.response.id
                    }
                    Write-Output $EmailId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose -Message "Add-PEmailAddress cmdlet finished."
    }

}  #END: Add-PEmailAddress
function Add-PPhoneNumber {
<#
.SYNOPSIS
  Adds a phone number to a person or organization.
 
.DESCRIPTION
  Adds phone number using the given parameters. Returns a Phone id that can then be used
  with other cmdlets like Update-PPhoneNumber | Delete-PPhoneNumber. (See Output section.)
  Review the parameters for specific requirements and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be adding this phone number to his/her own profile.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER OrganizationId
  Numeric ID of the organization to whose profile you are attaching this email address.
  This Parameter is not required. (but either person_id OR organization_id MUST be set)
 
.PARAMETER PhoneNumber
  e.g. 1-800-888-8888
  This parameter is required.
 
.PARAMETER PhoneType (PersonId)
  HOME, WORK, MOBILE, SCHOOL, FAX, OTHER
 
.PARAMETER OrgPhoneType (OrganizationId)
  WORK, FAX, OTHER
 
.PARAMETER Primary
  Use if you want to mark the email address as primary or not primary. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the email address as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    <Home|Work|School|Mobile|Fax|Other>PhoneId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/24/2019
 
.EXAMPLE
  Add-PPhoneNumber -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7781234' -PhoneNumber '888-555-1212' -PhoneType SCHOOL
 
.EXAMPLE
  Add-PPhoneNumber -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -PhoneNumber '888-555-1212' -OrgPhoneType WORK
#>

[CmdletBinding(DefaultParameterSetName='ByPersonId')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByPersonId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [parameter(ParameterSetName='ByOrganizationId',
                 Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [parameter(Mandatory)]
      [string]
      $PhoneNumber,

      [Parameter(ParameterSetName='ByPersonId')]
      [ValidateSet("HOME","WORK","SCHOOL","FAX","OTHER")]
      [string]
      $PhoneType,

      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("WORK","FAX","OTHER")]
      [string]
      $OrgPhoneType,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByPersonId')]
      [Parameter(ParameterSetName='ByOrganizationId')]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddPhoneNumberBody = @{
             task = 'addPhoneNumber';
             access_key = $PopuliAuthkey;
             phone_number = $PhoneNumber;
        }

        Write-Verbose -Message "Set default output object name."
        $PhoneTypeId = "OtherPhoneId"

        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $AddPhoneNumberBody.Add('person_id', $PersonId)
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to request string."
            $AddPhoneNumberBody.Add('organization_id', $OrganizationId)
        }
        if ($PSBoundParameters.ContainsKey('PhoneType')) {
            Write-Verbose -Message "Adding Type $PhoneType to request string."
            $AddPhoneNumberBody.Add('type', $PhoneType)
            $PhoneType = $PhoneType.ToLower()
            $PhoneType = (Get-Culture).TextInfo.ToTitleCase($PhoneType)
            $PhoneTypeId = $PhoneType + "PhoneId"
        }
        if ($PSBoundParameters.ContainsKey('OrgPhoneType')) {
            Write-Verbose -Message "Adding Type $OrgPhoneType to request string."
            $AddPhoneNumberBody.Add('type', $OrgPhoneType)
            $OrgPhoneType = $OrgPhoneType.ToLower()
            $OrgPhoneType = (Get-Culture).TextInfo.ToTitleCase($OrgPhoneType)
            $PhoneTypeId = $OrgPhoneType + "PhoneId"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary to request string."
            $AddPhoneNumberBody.Add('primary', $Primary)
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public to request string."
            $AddPhoneNumberBody.Add('public', $Public)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddPhoneNumberBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PPhoneNumber."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $PhoneId = [pscustomobject] @{
                        $PhoneTypeId = $Response.response.id
                    }
                    Write-Output $PhoneId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose -Message "Add-PPhoneNumber cmdlet finished."
    }

}  #END: Add-PPhoneNumber
function Add-PRole {
<#
.SYNOPSIS
  Adds a role to a person.
 
.DESCRIPTION
  The current user must have the Staff role and permission to add the role (this varies by role... so Academic Admins can add the Registrar role,
  Admissions Admins can add the Admission role, etc).
  See Get-PAvailableRoles to look up all possible roles and their numeric IDs.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person you're interested in.
  This parameter is required.
 
.PARAMETER RoleId
  The numeric ID of the role you want to add. See Get-PRoles cmdlet to find RoleId.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    Result = SUCCESS (or FAILURE)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
 
.EXAMPLE
  Add-PRole -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId 7857760 -RoleId 3
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Add-PRole @PopuliCredentials -PersonId 7857760 -RoleId 3
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory)]
        [int]
        $PersonId,

        [Parameter(Mandatory)]
        [int]
        $RoleId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $AddRoleBody = @{
             task = 'addRole';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
             role_id = $RoleId
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddRoleBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PRole."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AddRole = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $AddRole
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Add-PRole cmdlet finished."
    }

} #END:Add-PRole
function Add-PTag {
<#
.SYNOPSIS
  Adds a tag to a particular person.
 
.DESCRIPTION
  Adds a tag from a particular person using the given parameters. Review the parameters for specific requirements
  and settings. If you pass "tag" and that tag doesn't exist, it will be created. If you pass in a tag_id that doesn't exists, a BAD_PARAMETER error will be thrown.
  The same tag cannot be attached multiple times to the same person - if the person already has this tag, addTag will return SUCCESS and do nothing.
  System tags cannot be assigned by anyone other than Populi... so certain tags like "Expelled" are off-limits. To add these tags, you'll need to take some action
  in Populi - the correct system tags will be added as a byproduct of that action.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person who should be tagged.
  This parameter Required.
 
.PARAMETER TagId
  Numeric ID of the tag. See Get-PTags cmdlet for list of TagId and TagName.
  This parameter is not required (but either tag_id or tag must be set)
 
.PARAMETER TagName
  The actual tag you want to be added (e.g. "Do not call", or "Good reference").
  See Get-PTags cmdlet for list of TagId and TagName.
  This parameter is not required (but either tag_id or tag must be set)
 
.OUTPUTS
  Returns PowerShell objects:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/02/2019
 
.EXAMPLE
  Add-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7857760' -TagId '12345'
 
.EXAMPLE
  Add-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7857760' -TagName "Test"
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Add-PTag @PopuliCredentials -PersonId '7781234' -TagId '12345'
#>

[CmdletBinding(DefaultParameterSetName='ByTagName')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [Parameter(ParameterSetName='ByTagId',
                 Mandatory)]
      [int]
      $TagId,

      [Parameter(ParameterSetName='ByTagName',
                 Mandatory)]
      [string]
      $TagName
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddTagBody = @{
             task = 'addTag';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }
        if ($PSBoundParameters.ContainsKey('TagId')) {
            Write-Verbose -Message "Adding TagId $TagId to request string."
            $AddTagBody.Add('tag_id', $TagId)
        }
        if ($PSBoundParameters.ContainsKey('TagName')) {
            Write-Verbose -Message "Adding TagName $TagName to request string."
            $AddTagBody.Add('tag', $TagName)
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddTagBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PTag."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AddTag = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $AddTag
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose -Message "Add-PTag cmdlet finished."
    }

} #END: Add-PTag
function Add-PTodo {
<#
.SYNOPSIS
  Adds a new todo (the Added By of this new todo will show the currently logged-in user).
 
.DESCRIPTION
  Right now you can only attach todos to people, so the only legitimate value for attached_to_type is PERSON.
  If you attach a todo onto someone's profile (say a lead or student who needs to be called), it will be visible to everyone with the Staff role.
  If you attach a todo to a person, there will be a handy link to jump to their profile when the todo is displayed on your dasboard.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be updating an email address on his/her own profile.
  This parameter is required.
 
.PARAMETER Content
  What the todo should say (e.g. "Remember the milk on the way home from work")
  This parameter is required.
 
.PARAMETER Due
  The due date for this todo (e.g. 2011-06-24)
 
.PARAMETER AssignedTo
  The person responsible for completing this todo. Defaults to the currently logged-in user. When assigning to another user use PersonId.
 
.PARAMETER AttachedToType
  If you'd like to attach this todo onto someone's profile, set this to PERSON.
 
.PARAMETER AttachedTo
  If you'd like to attach this todo onto someone's profile, Use the PersonId (and you MUST have attached_to_type set to PERSON).
 
.OUTPUTS
  Returns PowerShell object:
    Id
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 09/06/2019
 
.EXAMPLE
  Add-PTodo -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -Content "Remember the milk on the way home."
 
.EXAMPLE
  Add-PTodo -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -Content "Remember the milk on the way home." -Due "2019-09-06"
 
.EXAMPLE
  Add-PTodo @populicredentials -Content "Create new student accounts." -Due "2019-09-06" -AttachedToType PERSON -AttachedTo '7857760'
#>

[CmdletBinding()]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [string]
      $Content,

      [parameter(HelpMessage="Enter date in format yyyy-mm-dd")]
      [ValidatePattern("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")]
      [string]
      $Due,

      [parameter()]
      [string]
      $AssignedTo,

      [Parameter()]
      [ValidateSet("PERSON")]
      [string]
      $AttachedToType,

      [Parameter()]
      [int]
      $AttachedTo
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddTodoBody = @{
             task = 'addTodo';
             access_key = $PopuliAuthkey;
             content = $Content;
        }

        if ($PSBoundParameters.ContainsKey('Due')) {
            Write-Verbose -Message "Adding Due Date $Due to request string."
            $AddTodoBody.Add('due', $Due)
        }
        if ($PSBoundParameters.ContainsKey('AssignedTo')) {
            Write-Verbose -Message "Adding AssignedTo $AssignedTo to request string."
            $AddTodoBody.Add('assigned_to', $AssignedTo)
        }
        if ($PSBoundParameters.ContainsKey('AttachedToType')) {
            Write-Verbose -Message "Adding AttachedToType $AttachedToType to request string."
            $AddTodoBody.Add('attached_to_type', $AttachedToType)
        }
        if ($PSBoundParameters.ContainsKey('AttachedTo')) {
            Write-Verbose -Message "Adding AttachedTo $AttachedTo to request string."
            $AddTodoBody.Add('attached_to', $AttachedTo)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddTodoBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PTodo."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $TodoId = [pscustomobject] @{
                        'TodoId' = $Response.response.id
                    }
                    Write-Output $TodoId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose -Message "Add-PTodo cmdlet finished."
    }

}  #END: Add-PTodo
function Block-PUser {
<#
.SYNOPSIS
  Used to block a particular user account.
 
.DESCRIPTION
  Users with the Academic Admin role can block anyone. Users with the Staff role can block anyone except for users with the Academic Admin role.
  The user status of current Account Admins and Billing Contacts can't be edited. You cannot block your user account.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person whose user account will be removed.
  This parameter is required.
 
.PARAMETER Reason
  The reason the user account is being blocked.
 
.OUTPUTS
  Returns PowerShell objects:
    Result = SUCCESS (or FAILURE)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
 
.EXAMPLE
  Block-PUser -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId 7857760 -Reason "No longer attending."
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Block-PUser @PopuliCredentials -PersonId 7857760
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [Parameter()]
        [string]
        $Reason
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $BlockUserBody = @{
             task = 'blockUser';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }
        if ($PSBoundParameters.ContainsKey('Reason')) {
            Write-Verbose -Message "Adding Reason $Reason to request string."
            $BlockUserBody.Add('reason', $Reason)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $BlockUserBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Block-PUser."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $BlockUser = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $BlockUser
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Block-PUser cmdlet finished."
    }

} #END:Block-PUser
function Download-PBackup {
<#
.SYNOPSIS
  Once a backup is ready for download, you can download it (as a ZIP file named backup_YEAR_MO_DY.zip) using this task.
 
.DESCRIPTION
  Unlike most tasks in Populi's API, this function returns the actual binary data of a ZIP file rather than XML.
  By specifying on_complete_url when calling requestBackup, you can have your own web application called as soon as the backup is ready for download.
  Your application can then call downloadBackup to get the ZIP file and encrypt and save it however you'd like.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER BackupId
  The numeric ID of the backup you'd like to download. This value is returned by running the Request-PBackup cmdlet.
  This parameter is required.
 
.PARAMETER Path
  Enter the path to store the backup file. The path will be tested before the backup begins to download. Do not include the filename.
  This will be returned with the downloaded file. Remember to save in a secure location.
  This parameter is required.
 
.OUTPUTS
  Binary zip file data. The HTTP Content-disposition header will include the filename (e.g. backup_YYYY_MO_DY.zip).
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/07/2019
 
.EXAMPLE
  Download-PBackup -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -BackupId 39614 -Path "c:\users\$ENV:USERNAME\Desktop"
 
.EXAMPLE
 #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Download-PBackup @PopuliCredentials -BackupId 39614 -Path $Path
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [string]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $BackupId,

        [Parameter(Mandatory)]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Folder does not exist"
            }
            return $true
        })]
        [string]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $DownloadBackupBody = @{
            task = 'downloadBackup';
            backup_id = $BackupId
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Sending request to Populi."
            $Download = Invoke-WebRequest -Uri $PopuliUri -Method Post -Body $DownloadBackupBody -TimeoutSec 60

                if ($Download.Content.Contains('error')) {
                    Write-Verbose -Message "Error returned from Populi while executing Download-PBackup."
                    $PError = [pscustomobject] @{
                        'ErrorMessage' = $Download.Content
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Creating filename from Download Header."
                    $FileName = $Download.Headers.'Content-disposition'.Substring(22,21)
                    Write-Verbose "Updating the path to include filename."
                    $FilePath = Join-Path -Path $Path -ChildPath $FileName
                    Write-Verbose -Message "Checking if file exists."
                        if (Test-Path $FilePath.trim()) {
                            Write-Warning -Message "$FilePath --> File already exists. File not saved."
                            break
                        }
                        else {
                            Write-Verbose -Message "Writing file $FileName."
                            [System.IO.File]::WriteAllBytes("$FilePath", $Download.content)
                            Write-Verbose -Message "File saved to $FilePath."
                        }
                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }

    } #END:Process

    end {
        Write-Verbose "Download-PBackup cmdlet finished."
    }

} #END:Download-PBackup
function Get-PAcademicTerms {
<#
.SYNOPSIS
  Return term information given the selected parameters.
 
.DESCRIPTION
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference.
 
.PARAMETER StartDate
  Start date of the term you are querying. If you enter a start date the end date is required.
  Date format is yyyy-MM-dd.
 
.PARAMETER EndDate
  End date of the term you are querying. This is required if you enter a start date.
  Date format is yyyy-MM-dd.
 
.PARAMETER DateInTerm
  Enter a date and it will return the term that date is in. Example would be to run a monthly report based on the current term.
  You can use (Get-Date) or enter a date in format yyyy-MM-dd.
 
.PARAMETER TermName
  Search for a term based on full name of a term. Wildcards are allowed. See Examples.
 
.PARAMETER ReturnAll
  Returns all terms in XML format.
 
.OUTPUTS
  Returns PowerShell objects:
    TermId
    Name
    FullName
    StartDate
    EndDate
    Type
    YearId
    StartYear
    EndYear
    NonStandard
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/18/2019
 
.EXAMPLE
  Get-PAcademicTerms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -StartDate 2019-01-07 -EndDate 2019-10-26
 
.EXAMPLE
  Get-Date | Get-PAcademicTerms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789'
  Get-PAcademicTerms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -DateInTerm 2019-01-15
 
.EXAMPLE
  Get-PAcademicTerms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -TermName "2017-2018: Fall Semester"
  Get-PAcademicTerms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -TermName "Fall Semester"
  Get-PAcademicTerms @PopuliCredentials -TermName "2018 *"
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PAcademicTerms @PopuliCredentials -DateInTerm (Get-Date)
#>

[CmdletBinding(DefaultParameterSetName='ByDateInTerm')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(ParameterSetName='ByStartEnd',
                   Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd")]
        [ValidatePattern("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")]
        [String]
        $StartDate,

        [Parameter(ParameterSetName='ByStartEnd',
                   Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd")]
        [ValidatePattern("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")]
        [String]
        $EndDate,

        [Parameter(ParameterSetName='ByDateInTerm',
                   Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd.",
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [DateTime]
        $DateInTerm,

        [Parameter(ParameterSetName='ByTermName',
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [string]
        $TermName,

        [Parameter(ParameterSetName='ByReturnAll')]
        [switch] $ReturnAll
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetAcademicTermsBody = @{
            task = 'getAcademicTerms';
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetAcademicTermsBody -ErrorAction Stop

                if ($Response.error) {
                     Write-Verbose -Message "Error returned from Populi while executing Get-PAcademicTerms."
                     $PError = [pscustomobject] @{
                         'ErrorCode' = $Response.error.code
                         'ErrorMessage' = $Response.error.message
                     }
                     Write-Output $PError
                }
                else {
                    if (($PSBoundParameters.ContainsKey('StartDate')) -and ($PSBoundParameters.ContainsKey('EndDate'))) {
                        Write-Verbose -Message "Return term with dates $StartDate to $EndDate."
                        $Response = $Response.response.academic_term | Where-Object { ($_.start_date -eq $StartDate) -and ($_.end_date -eq $EndDate) }
                    }
                    if ($PSBoundParameters.ContainsKey('DateInTerm')) {
                        Write-Verbose -Message "Return term with date $DateInTerm in term."
                        $DateInTerm.ToString("yyyy-MM-dd") | out-null
                        $Response = $Response.response.academic_term | Where-Object { ($DateInTerm -ge $_.start_date) -and ($DateInTerm -le $_.end_date) }
                    }
                    if ($PSBoundParameters.ContainsKey('TermName')) {
                        Write-Verbose -Message "Return term with name $TermName."
                        $Response = $Response.response.academic_term | Where-Object { ($_.fullname -match $TermName) }
                    }
                    if ($PSBoundParameters.ContainsKey('ReturnAll')) {
                        Write-Verbose -Message "Return all academic terms."
                        $Response = $Response.response.academic_term
                    }

                    Write-Verbose -Message "Return data as PowerShell objects."
                    $Terms = foreach ($Term in $Response) {
                        [pscustomobject] @{
                            'TermId' = $Term.termid
                            'Name' = $Term.name
                            'Fullname' = $Term.fullname
                            'StartDate' = $Term.start_date
                            'EndDate' = $Term.end_date
                            'Type' = $Term.type
                            'YearId' = $Term.yearid
                            'StartYear' = $Term.start_year
                            'EndYear' = $Term.end_year
                            'NonStandard' = $Term.nonstandard
                        }
                    }#END:foreach
                    Write-Output $Terms
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PAcademicTerms cmdlet finished."
    }

} #END:Get-PAcademicTerms
function Get-PAllCustomFields {
<#
.SYNOPSIS
  Returns all custom fields your college has defined.
 
.DESCRIPTION
  You must have the Staff role to call this task.
  You must have the Staff role to access "PERSON" type custom fields.
  You must have the Academic Admin role to access "STUDENT" type custom fields.
  You must have the Academic Admin role to access "TERM_STUDENT" type custom fields.
  You must have the Admissions Admin role to access "ADMISSIONS" type custom fields.
  You must have the Academic Admin or Registrar role to access "CAMPUS_LIFE" type custom fields.
  You must have the Financial Admin role to access "FINANCIAL" type custom fields.
  You must have the Financial Aid role to access "FINANCIAL_AID" type custom fields.
  You must have the Financial Admin role to access "DONATION" type custom fields.
  You must have the Staff role to access "ORGANIZATION" type custom fields.
  Return data InputType can be:
    DATE - e.g. 2010-09-09
    DATE_TIME- e.g. 2010-09-09 19:00:45
    DECIMAL - e.g. 10.88
    CHECKBOX - Allows multiple values to be selected from a list
    FILE - a numeric file_id (e.g. 11111)
    INTEGER - e.g. 101
    RADIO - Select one from a list of a few options
    SELECT - Select one from a list of many options
    TEXT_AREA - Lots of text
    TEXT - Little bit of text
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. (See Description.)
  This parameter is required.
 
.PARAMETER Type
    ALL (default), PERSON, STUDENT, TERM_STUDENT, ADMISSIONS, CAMPUS_LIFE, FINANCIAL, FINANCIAL_AID, DONATION, ORGANIZATION
 
.OUTPUTS
  Returns PowerShell objects:
    CustomFieldId
    Name
    Description
    Type
    InputType
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/04/2019
 
.EXAMPLE
  Get-PAllCustomFields -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789'
 
.EXAMPLE
  Get-PAllCustomFields -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -Type STUDENT
 
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter()]
        [ValidateSet("All","PERSON","STUDENT","TERM_STUDENT","ADMISSIONS","CAMPUS_LIFE","FINANCIAL","FINANCIAL_AID","DONATION","ORGANIZATION")]
        [string]
        $Type
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetAllCustomFieldsBody = @{
             task = 'getAllCustomFields';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('Type')) {
            Write-Verbose -Message "Adding Type $Type to request string."
            $GetAllCustomFieldsBody.Add('type', $Type)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetAllCustomFieldsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PAllCustomFields."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $CustomFields = foreach ($CustomField in $Response.response.custom_field) {
                        [pscustomobject] @{
                        'CustomFieldId' = $CustomField.id
                        'Name' = $CustomField.name
                        'Description' = $CustomField.description
                        'Type' = $CustomField.type
                        'InputType' = $CustomField.input_type
                        }
                    }

                    Write-Output $CustomFields

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PAllCustomFields cmdlet finished."
    }

} #END: Get-PAllCustomFields
function Get-PApplications {
<#
.SYNOPSIS
  Returns applications based on the filter conditions.
 
.DESCRIPTION
  You must have the Admissions role to call this task. The "StartDate" and "EndDate" parameters are required when filtering by the "DateField" parameter.
  There is a limit of 200 results in the response. To return more than 200, use the Offset parameter and make multiple calls.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference.
 
.PARAMETER DateField
  The name of the date field you want to filter by (e.g. APPLIED, DECISION, SUBMITTED, or WITHDRAWN).
 
.PARAMETER StartDate
  The start date used to filter the "DateField" parameter. Required if using DateField.
 
.PARAMETER EndDate
  The end date used to filter the "DateField" parameter. Required if using DateField.
 
.PARAMETER TermId
  The numeric ID of the academic term you're interested in.
 
.PARAMETER ProgramId
  The numeric ID of the program you're interested in.
 
.PARAMETER DegreeId
  The numeric ID of the degree you're interested in.
 
.PARAMETER SpecializationId
  The numeric ID of the specialization you're interested in.
 
.PARAMETER Offset
  The numeric value you want to offset the results by.
 
.OUTPUTS
  Returns PowerShell objects:
    ApplicationId
    LeadId
    LeadActive
    LeadStatus
    PersonId
    FirstName
    PreferredName
    MiddleName
    LastName
    Gender
    Email
    ApplicationTemplateId
    ApplicationTemplateName
    RepresentativeId
    ProgramId
    ProgramName
    DegreeSeeking
    DegreeId
    DegreeAbbreviation
    DegreeName
    SpecializationId
    SpecializationAbbreviation
    SpecializationName
    AcademicTermId
    AcademicTermName
    ExpectedEnrollment
    FullTime
    StartedOn
    SubmittedAt
    DecisionOn
    WithdrawnOn
    SubmittedType
    Provisional
    FeeStatus
    FeeId
    FeeAmount
    FeePayment
    SalesReceiptId
    TransactionId
    ApplicantActivityAt
    NumDaysSinceLastActivity
    StaffActivityAt
    PercentCompleted
    Status
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 07/15/2019
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
 
.EXAMPLE
  Get-PApplications @PopuliCredentials -DateField APPLIED -StartDate 2019-01-01 -EndDate 2019-06-30
 
.EXAMPLE
  Get-PApplications @PopuliCredentials -TermId 223196
 
.EXAMPLE
  Get-PApplications @PopuliCredentials -ProgramId 18081
#>

[CmdletBinding(DefaultParameterSetName='Default')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(ParameterSetName='ByDateField',
                   Mandatory)]
        [ValidateSet("APPLIED","DECISION","SUBMITTED","WITHDRAWN")]
        [String]
        $DateField,

        [Parameter(ParameterSetName='ByDateField',
                   Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd")]
        [ValidatePattern("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")]
        [String]
        $StartDate,

        [Parameter(ParameterSetName='ByDateField',
                   Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd")]
        [ValidatePattern("^\d{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])$")]
        [String]
        $EndDate,

        [Parameter(ParameterSetName='ById')]
        [int]
        $TermId,

        [Parameter(ParameterSetName='ById')]
        [int]
        $ProgramId,

        [Parameter(ParameterSetName='ById')]
        [int]
        $DegreeId,

        [Parameter(ParameterSetName='ById')]
        [int]
        $SpecializationId,

        [Parameter(ParameterSetName='Default')]
        [Parameter(ParameterSetName='ByDateField')]
        [Parameter(ParameterSetName='ById')]
        [int]
        $OffSet
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetApplicationsBody = @{
            task = 'getApplications';
            access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('DateField')) {
            Write-Verbose -Message "Adding DateField $DateField to request string."
            $GetApplicationsBody.Add('date_field', $DateField)
        }
        if ($PSBoundParameters.ContainsKey('StartDate')) {
            Write-Verbose -Message "Adding StartDate $StartDate to request string."
            $GetApplicationsBody.Add('start_date', $StartDate)
        }
        if ($PSBoundParameters.ContainsKey('EndDate')) {
            Write-Verbose -Message "Adding EndDate $EndDate to request string."
            $GetApplicationsBody.Add('end_date', $EndDate)
        }
        if ($PSBoundParameters.ContainsKey('TermId')) {
            Write-Verbose -Message "Adding TermId $TermId to request string."
            $GetApplicationsBody.Add('term_id', $TermId)
        }
        if ($PSBoundParameters.ContainsKey('ProgramId')) {
            Write-Verbose -Message "Adding ProgramId $ProgramId to request string."
            $GetApplicationsBody.Add('program_id', $ProgramId)
        }
        if ($PSBoundParameters.ContainsKey('DegreeId')) {
            Write-Verbose -Message "Adding DegreeId $DegreeId to request string."
            $GetApplicationsBody.Add('degree_id', $DegreeId)
        }
        if ($PSBoundParameters.ContainsKey('SpecializationId')) {
            Write-Verbose -Message "Adding SpecializationId $SpecializationId to request string."
            $GetApplicationsBody.Add('specialization_id', $SpecializationId)
        }
        if ($PSBoundParameters.ContainsKey('OffSet')) {
            Write-Verbose -Message "Adding OffSet $OffSet to to request string."
            $GetApplicationsBody.Add('offset', $OffSet)
        }


        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetApplicationsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PApplications."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Applications = foreach ($Application in $Response.response.application) {
                        [pscustomobject] @{
                            'ApplicationId' = $Application.id
                            'LeadId' = $Application.lead_id
                            'LeadActive' = $Application.lead_active
                            'LeadStatus' = $Application.lead_status
                            'PersonId' = $Application.person_id
                            'FirstName' = $Application.first_name
                            'PreferredName' = $Applicaion.preferred_name
                            'MiddleName' = $Application.middle_name
                            'LastName' = $Application.last_name
                            'Gender' = $Application.gender
                            'Email' = $Application.email
                            'ApplicationTemplateId' = $Application.application_template_id
                            'ApplicationTemplateName' = $Application.application_template_name
                            'RepresentativeId' = $Application.representative_id
                            'ProgramId' = $Application.program_id
                            'ProgramName' = $Application.program_name
                            'DegreeSeeking' = $Application.degree_seeking
                            'DegreeId' = $Application.degree_id
                            'DegreeAbbreviation' = $Application.degree_abbreviation
                            'DegreeName' = $Application.degree_name
                            'SpecializationId' = $Application.specialization_id
                            'SpecializationAbbreviation' = $Application.specialization_abbreviation
                            'SpecializationName' = $Application.specialization_name
                            'AcademicTermId' = $Application.academic_term_id
                            'AcademicTermName' = $Application.academic_term_name
                            'ExpectedEnrollment' = $Application.expected_enrollment
                            'FullTime' = $Application.full_time
                            'StartedOn' = $Application.started_on
                            'SubmittedAt' = $Application.submitted_at
                            'DecisionOn' = $Application.decision_on
                            'WithdrawnOn' = $Application.withdrawn_on
                            'SubmittedType' = $Application.submitted_type
                            'Provisional' = $Application.provisional
                            'FeeStatus' = $Application.fee_status
                            'FeeId' = $Application.fee_id
                            'FeeAmount' = $Application.fee_amount
                            'FeePayment' = $Application.fee_payment
                            'SalesReceiptId' = $Application.sales_receipt_id
                            'TransactionId' = $Application.transaction_id
                            'ApplicantActivityAt' = $Application.applicant_activity_at
                            'NumDaysSinceLastActivity' = $Application.num_days_since_last_activity
                            'StaffActivityAt' = $Application.staff_activity_at
                            'PercentCompleted' = $Application.percent_completed
                            'Status' = $Application.status
                        }
                    }#END:foreach
                    Write-Output $Applications
               }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PApplications cmdlet finished."
    }

} #END:Get-PApplications
function Get-PAuthkey {
<#
.SYNOPSIS
  Returns access key, by sending a HTTPS POST request to https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/.
  All API requests (GET or POST) must include either the access_key as the Authorization header or the parameter access_key.
 
.DESCRIPTION
  Returns access key, by sending a HTTPS POST request (we do not allow GET, since that could result
  in your password being stored in Populi server logs) to https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/.
  If you have more than 15 failed login attempts in an hour, Populi will block your account for security reasons.
  The account will need to be re-enabled by an Admin user in the Populi web interface.
  Never store your API access key in an insecure place. If you have reason to believe your key has been compromised,
  use the Populi interface to change the password of the associated account, then generate a new key.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER Credential
  Enter username and you will be prompted for password on execution of cmdlet.
 
.PARAMETER Path
  Enter the path to store the authkey. Remember to save in a secure location.
 
.OUTPUTS
  Returns PowerShell objects:
    access_key
    account_id
  Optionally a text file with the access key given the path parameter.
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/13/2018
 
.EXAMPLE
  Get-PAuthkey -PopuliUri https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -Credential <populi_username>
  This will open an interactive window and prompt for <populi_password>.
 
.EXAMPLE
  $Credential = New-Object -TypeName System.Management.Automation.PSCredential
  -ArgumentList '<populi_username>',('<populi_password' | ConvertTo-SecureString -AsPlainText -Force)
  Get-PAuthkey -PopuliUri https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -Credential $Credential
 
.EXAMPLE
  Enter a path to save the authkey in a text file.
  Get-PAuthkey -PopuliUri https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -Credential <populi_username> -Path <path>
#>

[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [ValidateNotNull()]
        [System.Management.Automation.PSCredential]
        [System.Management.Automation.Credential()]
        $Credential,

        [Parameter()]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Path does not exist. Please enter a vaild path to store your authkey file. "
            }
            return $true
        })]
        [string]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $UserName = $Credential.UserName
        $Password = $Credential.GetNetworkCredential().Password

        $GetAuthKeyBody = @{
            username = $UserName;
            password = $Password;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetAuthkeyBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PAuthkey."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AccessKey = [pscustomobject] @{
                        'access_key' = $Response.response.access_key
                        'account_id' = $Response.response.account_id
                    }
                    Write-Output $AccessKey

                    if ($PSBoundParameters.ContainsKey('Path')) {
                        Write-Verbose -Message "Creating filename Authkey.txt"
                        $FileName = "Authkey.txt"
                        Write-Verbose "Updating the path to include filename."
                        $FilePath = Join-Path -Path $Path -ChildPath $FileName
                        Write-Verbose -Message "Checking if file exists."
                            if (Test-Path $FilePath.trim()) {
                                Write-Warning -Message "$FilePath --> File already exists. File not saved."
                                break
                            }
                            else {
                                Write-Verbose -Message "Writing file $FileName."
                                $Response.response.access_key | Out-File -FilePath $FilePath
                                Write-Verbose -Message "File saved to $FilePath."
                            }
                    } #END:if

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PAuthkey cmdlet finished."
    }

} #END: Get-PAuthkey
function Get-PAvailableRoles {
<#
.SYNOPSIS
  Returns all the roles in Populi (Student, Staff, Admissions, etc).
 
.DESCRIPTION
  Useful if you'd like to give someone a role but need to know its numeric role_id.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    RoleId
    RoleName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
 
.EXAMPLE
  Get-PAvailableRoles -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  This example uses the ImportExcel module. This will create an excel spreadsheet of all role members of all the roles and saves them in an Excel file.
  Get-PAvailableRoles @PopuliCredentials | Get-PRoleMembers @PopuliCredentials | Export-Excel C:\users\$ENV:USERNAME\Desktop\Example.xlsx
 
.EXAMPLE
  Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PAvailableRoles @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetAvailableRolesBody = @{
             task = 'getAvailableRoles';
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetAvailableRolesBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PAvailableRoles."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Roles = foreach ($Role in $Response.response.role) {
                        Write-Verbose -Message "Converting $($Role.name)"
                        [pscustomobject]@{
                            RoleId = $Role.id
                            RoleName = $Role.name
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Roles
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PAvailableRoles cmdlet finished."
    }

} #END:Get-PAvailableRoles
function Get-PCourseCatalog {
<#
.SYNOPSIS
  Returns courses from your catalog (only active courses are returned by default).
 
.DESCRIPTION
  Useful for automatically syncing your course catalog to your website.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER IncludeRetired
  If set to 1, retired courses will be returned as well.
 
.OUTPUTS
  Returns PowerShell objects:
    CourseId
    CourseName
    Abbrv
    Description
    Credits
    Hours
    Status
    DeptId
    DeptName
    Programs
      ProgramId
      Program
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/12/2019
 
.EXAMPLE
  Get-PCourseCatalog -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PCourseCatalog @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [parameter(ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [ValidateSet("0","1")]
        [int]
        $IncludeRetired = 0
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCourseCatalogBody = @{
             task = 'getCourseCatalog';
             include_retired = $IncludeRetired;
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetCourseCatalogBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseCatalog."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Courses = foreach ($Course in $Response.response.course) {
                        Write-Verbose -Message "Converting $($Course.name)"
                        [pscustomobject]@{
                            CourseId = $Course.courseid
                            CourseName = $Course.name
                            Abbrv = $Course.abbrv
                            Description = $Course.description
                            Credits = $Course.credits
                            Hours = $Course.hours
                            Status = $Course.status
                            DeptId = $Course.deptid
                            DeptName = $Course.dept_name
                            ProgramId = $Course.programs.program.id
                            ProgramName = $Course.programs.program.name
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Courses
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PCourseCatalog cmdlet finished."
    }

} #END: Get-PCourseCatalog
function Get-PCourseInstance {
<#
.SYNOPSIS
  A course instance is created each time a course from the catalog is offered in a particular term.
  If the same catalog course is offered multiple times in the same term, each instance will have a unique section number.
 
.DESCRIPTION
  To get more detail about a course instance see: getCourseInstanceStudents, getCourseInstanceAssignmentGroups, getCourseInstanceFiles, getCourseInstanceLessons,
  and getCourseInstanceMeetings
  <max_enrolled> & <max_auditors> can return an empty string meaning "Unlimited" (as opposed to an integer value which would mean there is a limit).
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference. This parameter is required.
 
.PARAMETER InstanceId
  The numeric ID of the course instance you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    InstanceId
    Name
    Abbrv
    Section
    Credits
    Hours
    AffectsEarnedCredits
    Description
    PassFail
    Finalized
    TermId
    TermName
    AllowAuditorAssignments
    AllowAuditorAttendance
    StartDate
    EndDate
    OpenToStudentsDate
    ClosedToStudentsDate
    MaxEnrolled
    MaxAuditors
    Published
    Books {Hashtable - See examples}
    MeetingTimes
      StartTime
      EndTime
      Room
      Building
      Weekdays
    PrimaryFaculty
      PrimaryFacultyId
      PrimaryFacultyFirstname
      PrimaryFacultyLastName
      PrimaryFacultyPreferredName
      PrimaryFacultyDisplayName
      PrimaryFacultyIsTeachingAssistant
    SecondaryFaculty
      SecondaryFacultyId
      SecondaryFacultyFirstname
      SecondaryFacultyLastName
      SecondaryFacultyPreferredName
      SecondaryFacultyDisplayName
      SecondaryFacultyIsTeachingAssistant
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 03/13/2019
 
.EXAMPLE
  Get-PCourseInstance -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId '8059238'
 
.EXAMPLE
  Get-PTermCourseInstances @populicredentials -TermId '7289900' | Get-PCourseInstance @populicredentials
 
#>

[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $InstanceId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCourseInstanceBody = @{
                task = 'getCourseInstance';
                instance_id = $InstanceId
                access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Requesting data from Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetCourseInstanceBody -ErrorAction Stop

                if ($Response.error) {
                   Write-Verbose -Message "Error returned from Populi while executing Get-PCourseInstance."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."

                    $Course = [ordered]@{
                        'InstanceId' = $Response.response.instanceid
                        'Name' = $Response.response.name
                        'Abbrv' = $Response.response.abbrv
                        'Section' = $Response.response.section
                        'Credits' = $Response.response.credits
                        'Hours' = $Respnse.response.hours
                        'AffectsEarnedCredits' = $Response.response.affects_earned_credits
                        'Description' = $Response.response.description
                        'PassFail' = $Response.response.pass_fail
                        'Finalized' = $Response.response.finalized
                        'TermId' = $Response.response.termid
                        'TermName' = $Response.response.term_name
                        'AllowAuditorAssignments' = $Response.response.allow_auditor_assignments
                        'AllowAuditorAttendance' = $Response.response.allow_auditor_attendance
                        'StartDate' = $Response.response.start_date
                        'EndDate' = $Response.response.end_date
                        'OpenToStudentsDate' = $Response.response.open_to_students_date
                        'ClosedToStudentsDate' = $Response.response.closed_to_students_date
                        'MaxEnrolled' = $Response.response.max_enrolled
                        'MaxAuditors' = $Response.response.max_auditors
                        'Published' = $Response.response.published
                        'Books' = $Response.response.books.book
                    }

                    Write-Verbose -Message "Checking for schedule data."
                    $i = 1
                    foreach ($Item in $Response.response.schedule.meeting_time) {

                        if ($i -eq 1) {
                            Write-Verbose -Message "Adding schedule data to output."
                            $Course.add('StartTime',($Item.start_time))
                            $Course.add('EndTime',($Item.end_time))
                            $Course.add('Room',($Item.room))
                            $Course.add('Building',($Item.building))
                            $Course.add('Weekdays',($Item.weekdays.day))
                            $i++
                        }
                        else {
                            Write-Verbose -Message "Adding schedule data to output."
                            $Course.add('StartTime'+$i,($Item.start_time))
                            $Course.add('EndTime'+$i,($Item.end_time))
                            $Course.add('Room'+$i,($Item.room))
                            $Course.add('Building'+$i,($Item.building))
                            $Course.add('Weekdays'+$i,($Item.weekdays.day))
                            $i++
                        }

                    } #END:foreach:meeting_time

                    Write-Verbose -Message "Checking for faculty data."
                    foreach ($Item in $Response.response.faculty.person) {

                        if (($Item.primary) -eq 1) {
                            Write-Verbose -Message "Adding primary faculty data to output."
                            $Course.add('PrimaryFacultyId',($Item.personid))
                            $Course.add('PrimaryFacultyFirstName',($Item.first))
                            $Course.add('PrimaryFacultyLastName',($Item.last))
                            $Course.add('PrimaryFacultyPreferredName',($Item.preferred))
                            $Course.add('PrimaryFacultyDisplayName',($Item.displayname))
                            $Course.add('PrimaryFacultyIsTeachingAssistant',($Item.is_teaching_assistant))
                        }
                        else {
                            Write-Verbose -Message "Adding secondary faculty data to output."
                            $i = (($Response.response.faculty.person).IndexOf($Item))
                            $Course.add('SecondaryFacultyId'+$i,($Item.personid))
                            $Course.add('SecondaryFacultyFirstName'+$i,($Item.first))
                            $Course.add('SecondaryFacultyLastName'+$i,($Item.last))
                            $Course.add('SecondaryFacultyPreferredName'+$i,($Item.preferred))
                            $Course.add('SecondaryFacultyDisplayName'+$i,($Item.displayname))
                            $Course.add('SecondaryFacultyIsTeachingAssistant'+$i,($Item.is_teaching_assistant))
                        }

                    } #END:foreach:person

                Write-Output $Course
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }

     } #END:Process

     end {
         Write-Verbose -Message "Get-PCourseInstance cmdlet finished."
     }

} #END:Get-PCourseInstance
function Get-PCurrentAcademicTerm {
<#
.SYNOPSIS
  Returns the current academic term.
 
.DESCRIPTION
  Under Academics -> Settings, there is a setting called Default Term. If this is set, then that is what you are going to get for the current term regardless
  of time. Some schools use this to have control over what is considered the "current term" for reports and other things.
  However, by default the setting is set to "automatic". If it's set to automatic, then it will make the best guess for what term is the "current" term for today.
  It will favor standard chronological sequential terms when possible, though if none exists it could return a non-standard term.
  If there is no term of any kind in progress, it will look to the future until it finds one.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    TermId
    Name
    Fullname
    StartDate
    EndDate
    Type
    YearId
    StartYear
    EndYear
    NonStandard
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/06/2018
 
.EXAMPLE
  Get-PCurrentAcademicTerm -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
#>

[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCurrentAcademicTermBody = @{
            task = 'getCurrentAcademicTerm';
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetCurrentAcademicTermBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCurrentAcademicTerm."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Term = [pscustomobject] @{
                        'TermId' = $Response.response.termid
                        'Name' = $Response.response.name
                        'Fullname' = $Response.response.fullname
                        'StartDate' = $Response.response.start_date
                        'EndDate' = $Response.response.end_date
                        'Type' = $Response.response.type
                        'YearId' = $Response.response.yearid
                        'StartYear' = $Response.response.start_year
                        'EndYear' = $Response.response.end_year
                        'NonStandard' = $Response.response.nonstandard
                    }
                    Write-Output $Term
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        } #END:try/catch
    } #END:Process

    end {
        Write-Verbose "Get-PCurrentAcademicTerm cmdlet finished."
    }

} #END:Get-PCurrentAcademicTerm
function Get-PCustomFields {
<#
.SYNOPSIS
  Returns custom fields attached to a particular person or organization.
 
.DESCRIPTION
  You must have the Staff role to call this task.get
  You must have the Staff role to access a person's "PERSON" type custom data.
  You must have the Academic Admin or Registrar role to access a person's "STUDENT" type custom data.
  You must have the Academic Admin role, Registrar role, Academic Auditor role, or be an advisor of the person to access their "TERM_STUDENT" type custom data.
  You must have the Admissions Admin role, Admissions role, Academic Admin role, or Registrar role to access a person's "ADMISSIONS" type custom data.
  You must have the Campus Life role, Academic Admin role, Registrar role, or Financial Admin role to access a person's "CAMPUS_LIFE" type custom data.
  You must have the Financial Admin role, Student Billing role, or Financial Aid role to access a person's "FINANCIAL" or "FINANCIAL_AID" type custom data.
  You must have the Staff role to access an organization's "ORGANIZATION" type custom data.
  For more information about <input_type> see getAllCustomFields
  For RADIO, CHECKBOX, and SELECT input types, notice that a numeric <option_index> is returned in addition to the <value> (this corresponds to the <index> returned by getCustomFieldOptions).
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. (See Description.)
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person you're interested in.
  Not Required. Either PersonId OR OrganizationId MUST be set.
 
.PARAMETER OrganizationId
   The numeric ID of the organization you're interested in.
   Not Required. Either PersonId OR OrganizationId MUST be set.
 
.PARAMETER Type
    ALL (default), PERSON, STUDENT, TERM_STUDENT, ADMISSIONS, CAMPUS_LIFE, FINANCIAL, or FINANCIAL_AID
 
.OUTPUTS
  Returns PowerShell objects:
    CustomFieldId
    Name
    Type
    InputType
    Value
    OptionIndex
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/03/2019
 
.EXAMPLE
  Get-PCustomFields -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7781234'
 
.EXAMPLE
  Get-PCustomFields -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7781234' -Type STUDENT
 
.EXAMPLE
  Get-PCustomFields -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizatonId '7781234'
#>

[CMdletBinding(DefaultParameterSetName='ByPersonId')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [parameter(ParameterSetName='ByPersonId',
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [parameter(ParameterSetName='ByOrganizationId',
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $OrganizationId,

        [parameter(ParameterSetName='ByPersonId')]
        [parameter(ParameterSetName='ByOrganizationId')]
        [ValidateSet("All","PERSON","STUDENT","TERM_STUDENT","ADMISSIONS","CAMPUS_LIFE","FINANCIAL","FINANCIAL_AID")]
        [string]
        $Type

    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCustomFieldsBody = @{
             task = 'getCustomFields';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $GetCustomFieldsBody.Add('person_id', $PersonId)
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to request string."
            $GetCustomFieldsBody.Add('Organization_id', $OrganizationId)
        }
        if ($PSBoundParameters.ContainsKey('Type')) {
            Write-Verbose -Message "Adding Type $Type to request string."
            $GetCustomFieldsBody.Add('type', $Type)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetCustomFieldsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCustomFields."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $CustomFields = foreach ($CustomField in $Response.response.custom_field) {
                    Write-Verbose -Message "Converting $($CustomField.id)"
                        [pscustomobject] @{
                        'CustomFieldId' = $CustomField.id
                        'Name' = $CustomField.name
                        'Type' = $CustomField.type
                        'InputType' = $CustomField.input_type
                        'Value' = $CustomField.value
                        'OptionIndex' = $CustomField.option_index
                        }
                    }

                    Write-Output $CustomFields

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PCustomFields cmdlet finished."
    }

} #END: Get-PCustomFields
function Get-PFees {
<#
.SYNOPSIS
  Returns all information related to fees configured for the institution.
 
.DESCRIPTION
  You must have the Financial Admin, Student Billing, or Financial Aid role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    FeeId
    FeeName
    FeeType
    Status
    Description
    Amount
    MaxAmount
    ReportOn1098T (1=Yes / 0=No)
    ReportOnT2202A (1=Yes / 0=No)
    Refundable (1=Yes / 0=No)
    Condition
    FinaidApplies (1=Yes / 0=No)
    FeeClass
    AccountName
    AccountNumber
    AccountType
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/13/2019
 
.EXAMPLE
  Get-PFees -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetFeesBody = @{
             task = 'getFees';
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetFeesBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PFees."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Fees = foreach ($Fee in $Response.response.fee) {
                        Write-Verbose -Message "Converting $($Fee.name)"
                        [pscustomobject]@{
                            FeeId = $Fee.id
                            FeeName = $Fee.name
                            FeeType = $Fee.type
                            Status = $Fee.status
                            Description = $Fee.description
                            Amount = $Fee.amount
                            MaxAmount = $Fee.max_amount
                            ReportOn1098T = $Fee.report_on_1098t
                            ReportOnT2202A = $Fee.report_on_t2202a
                            Refundable = $Fee.refundable
                            Condition = $Fee.condition
                            FinaidApplies = $Fee.finaid_applies
                            FeeClass = $Fee.fee_class
                            AccountName = $Fee.account_name
                            AccountNumber = $Fee.account_number
                            AccountType = $Fee.account_type
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Fees
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PFees cmdlet finished."
    }

} #END: Get-PFees
function Get-PFinancialAidAwards {
<#
.SYNOPSIS
  Returns all aid awards for a particular aid year (see Get-PFinancialAidYears).
 
.DESCRIPTION
  You must have the Financial Aid, Financial Admin or Student Billing role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER AidYearId
  The numeric ID of an aid year (see Get-PFinancialAidYears)
  This parameter is required.
 
.PARAMETER AwardTypeId
  The numeric ID of an award type (see Get-PFinancialAidAwardTypes).
 
.PARAMETER PersonId
  The numeric ID of a student.
 
.OUTPUTS
  Returns PowerShell objects:
    AwardId
    PersonId
    LastName
    FirstName
    StudentId
    AwardTypeId
    AwardName
    AwardAbbrv
    AwardType
    AwardSource
    Status
    ScheduledAmount
    DisbursedAmount
    NetAmount
    Amount
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/05/2019
 
.EXAMPLE
  # Get the AidAwardYear by first running Get-PFinancialAidYears
  Get-PFinancialAidAwards -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -AidYearId 22
 
.EXAMPLE
  # Run for a specific award year and award type. Run Get-PFinancialAwardTypes to get the AwardTypeId.
  Get-PFinancialAidAwards @PopuliCredencials -AidYearId 22 -AwardTypeId 16923
 
.EXAMPLE
 # Run for a specific award year, award type and person
 Get-PFinancialAidAwards @PopuliCredencials -AidYearId 22 -AwardTypeId 16923 -PersonId 7786500
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $AidYearId,

        [Parameter()]
        [int]
        $AwardTypeId,

        [Parameter()]
        [int]
        $PersonId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetFinancialAidAwardsBody = @{
             task = 'getFinancialAidAwards';
             access_key = $PopuliAuthkey;
             aid_year_id = $AidYearId;
        }
        if ($PSBoundParameters.ContainsKey('AwardTypeId')) {
            Write-Verbose -Message "Adding AwardTypeId $AwardTypeId to request string."
            $GetFinancialAidAwardsBody.Add('award_type_id', $AwardTypeId)
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $GetFinancialAidAwardsBody.Add('person_id', $PersonId)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetFinancialAidAwardsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PFinancialAidAwards."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Awards = foreach ($Award in $Response.response.award){
                        [pscustomobject] @{
                            'AwardId' = $Award.id
                            'PersonId' = $Award.student.id
                            'LastName' = $Award.student.last_name
                            'FirstName' = $Award.student.first_name
                            'StudentId' = $Award.student.student_id
                            'AwardTypeId' = $Award.award_type.id
                            'AwardName' = $Award.award_type.name
                            'AwardAbbrv' = $Award.award_type.abbreviation
                            'AwardType' = $Award.award_type.type
                            'AwardSource' = $Award.award_type.source
                            'Status' = $Award.status
                            'ScheduledAmount' = $Award.scheduled_amount
                            'DisbursedAmount' = $Award.disbursed_amount
                            'NetAmount' = $Award.net_amount
                            'Amount' = $Award.amount
                        }
                    } #END:foreach
                Write-Output $Awards
                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch

    } #END:process

    end {
        Write-Verbose -Message "Get-PFinancialAidAwards cmdlet finished."
    }

} #END: Get-PFinancialAidAwards
function Get-PFinancialAidAwardTypes {
<#
.SYNOPSIS
  Returns all available financial aid award types (both active and retired)
 
.DESCRIPTION
  You must have the Financial Aid, Financial Admin or Student Billing role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    AwardTypeId
    AwardTypeName
    Abbrv
    Type
    Status
    Source
    NeedBased (1=Yes / 0=No)
    ReportOn1098t (1=Yes / 0=No)
    CountAgainstNeed (1=Yes / 0=No)
    OnlyAllowWholeDollarAmounts (1=Yes / 0=No)
    LiabilityAccountId
    LiabilityAccountName
    LiabilityAccountNumber
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/03/2019
 
.EXAMPLE
  Get-PFinancialAidAwardTypes -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PFinancialAidAwardTypes @PopuliCredentials
#>

[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetFinancialAidAwardTypesBody = @{
            task = 'getFinancialAidAwardTypes';
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetFinancialAidAwardTypesBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PFinancialAidAwardTypes."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AwardTypes = foreach ($AwardType in $Response.response.award_type) {
                        [pscustomobject] @{
                            'AwardTypeId' = $AwardType.id
                            'AwardTypeName' = $AwardType.name
                            'Abbrv' = $AwardType.abbrv
                            'Type' = $AwardType.type
                            'Status' = $AwardType.status
                            'Source' = $AwardType.source
                            'NeedBased' = $AwardType.need_based
                            'ReportOn1098t' = $AwardType.report_on_1098t
                            'CountAgainstNeed' = $AwardType.count_against_need
                            'OnlyAllowWholeDollarAmounts' = $AwardType.only_allow_whole_dollar_amounts
                            'LiabilityAccountId' = $AwardType.liability_account.id
                            'LiabilityAccountName' = $AwardType.liability_account.name
                            'LiabilityAccountNumber' = $AwardType.liability_account.number
                        }
                    }
                    Write-Output $AwardTypes
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        } #END:try/catch
    } #END:Process

    end {
        Write-Verbose "Get-PFinancialAidAwardTypes cmdlet finished."
    }

} #END:Get-PFinancialAidAwardTypes
function Get-PFinancialAidDisbursements {
<#
.SYNOPSIS
  Returns all disbursements (whether original, to source, or to student) for a particular aid year (see getFinancialAidYears).
 
.DESCRIPTION
  You must have the Financial Aid, Financial Admin or Student Billing role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Registrar or Academic Admin role to call this task.
  This parameter is required.
 
.PARAMETER AidYearId
  The numeric ID of an aid year (see Get-PFinancialAidYears)
  This parameter is required.
 
.PARAMETER Type
  Possible values: DISBURSEMENT, REFUND_TO_SOURCE, REFUND_TO_STUDENT.
  This parameter is required.
 
.PARAMETER AwardTypeId
  The numeric ID of an award type (see Get-PFinancialAidAwardTypes).
 
.PARAMETER TermID
  The numeric ID of an academic term.
 
.PARAMETER PersonId
  The numeric ID of a student.
 
.OUTPUTS
  Returns PowerShell objects:
    DisbursementId
    AwardId
    Type
    Amount
    ScheduledDate
    StatusDate
    PostedDate
    Status
    AidApplicationId
    AidApplicationStatus
    PersonId
    LastName
    FirstName
    PreferredName
    StudentId
    AwardTypeId
    AwardName
    Abbrv
    TermId
    TermName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/03/2019
 
.EXAMPLE
  #Get Disbursements for an AidAwardYear
  Get-PFinancialAidDisbursements -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -AidYearId 22 -Type DISBURSEMENT
 
.EXAMPLE
  # Run for a specific award year an award type.
  Get-PFinancialAidDisbursements @PopuliCredencials -AidYearId 22 -Type DISBURSEMENT -AwardTypeId 16923
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $AidYearId,

        [Parameter(Mandatory)]
        [ValidateSet("DISBURSEMENT","REFUND_TO_SOURCE","REFUND_TO_STUDENT")]
        [string]
        $Type,

        [Parameter()]
        [int]
        $AwardTypeId,

        [Parameter()]
        [int]
        $TermId,

        [Parameter()]
        [int]
        $PersonId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetFinancialAidDisbursementsBody = @{
             task = 'getFinancialAidDisbursements';
             access_key = $PopuliAuthkey;
             aid_year_id = $AidYearId;
             type = $Type;
        }
        if ($PSBoundParameters.ContainsKey('AwardTypeId')) {
            Write-Verbose -Message "Adding AwardTypeId $AwardTypeId to request string."
            $GetFinancialAidDisbursementsBody.Add('award_type_id', $AwardTypeId)
        }
        if ($PSBoundParameters.ContainsKey('TermId')) {
            Write-Verbose -Message "Adding TermId $TermId to request string."
            $GetFinancialAidDisbursementsBody.Add('academic_term_id', $TermId)
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $GetFinancialAidDisbursementsBody.Add('person_id', $PersonId)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetFinancialAidDisbursementsBody  -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PFinancialAidDisbursements."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Disbursements = foreach ($Disbursement in $Response.response.disbursement){
                        [pscustomobject] @{
                            'DisbursementId' = $Disbursement.id
                            'AwardId' = $Disbursement.award_id
                            'Type' = $Disbursement.type
                            'Amount' = $Disbursement.amount
                            'ScheduledDate' = $Disbursement.scheduled_date
                            'StatusDate' = $Disbursement.status_date
                            'PostedDate' = $Disbursement.posted_date
                            'Status' = $Disbursement.status
                            'AidApplicationId' = $Disbursement.aid_application_id
                            'AidApplicationStatus' = $Disbursement.aid_application_status
                            'PersonId' = $Disbursement.student.id
                            'LastName' = $Disbursement.student.last_name
                            'FirstName' = $Disbursement.student.first_name
                            'PreferredName' = $Disbursement.student.preferred_name
                            'StudentId' = $Disbursement.student.student_id
                            'AwardTypeId' = $Disbursement.award_type.id
                            'AwardName' = $Disbursement.award_type.name
                            'Abbrv' = $Disbursement.award_type.abbreviation
                            'TermId' = $Disbursement.academic_term.id
                            'TermName' = $Disbursement.academic_term.name
                        }
                    } #END:foreach
                Write-Output $Disbursements
                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch

    } #END:process

    end {
        Write-Verbose -Message "Get-PFinancialAidDisbursements cmdlet finished."
    }

} #END: Get-PFinancialAidDisbursements
function Get-PFinancialAidYears {
<#
.SYNOPSIS
  Returns all financial aid years
 
.DESCRIPTION
  Returns all financial aid years - note that these are different than calendar years, and each award must be attached to a financial aid year.
  You must have the Financial Aid, Financial Admin or Student Billing role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    AidYearId
    AidYearName
    StartDate
    EndDate
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/03/2019
 
.EXAMPLE
  Get-PFinancialAidYears -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PFinancialAidYears @PopuliCredentials
#>

[CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetFinancialAidYearsBody = @{
            task = 'getFinancialAidYears';
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetFinancialAidYearsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PFinancialAidYears."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AidYears = foreach ($AidYear in $Response.response.aid_year) {
                        [pscustomobject] @{
                            'AidYearId' = $AidYear.id
                            'AidYearName' = $AidYear.name
                            'StartDate' = $AidYear.start_date
                            'EndDate' = $AidYear.end_date
                        }
                    }
                    Write-Output $AidYears
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        } #END:try/catch
    } #END:Process

    end {
        Write-Verbose "Get-PFinancialAidYears cmdlet finished."
    }

} #END:Get-PFinancialAidYears
function Get-PGradeReport {
<#
.SYNOPSIS
  Returns the grade report for a particular student and term.
 
.DESCRIPTION
  You must have the Academic Admin or Registrar role to call this task.
  The Content-Type HTTP header will indicate MIME type, and the Content-Disposition header will contain the file name.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person you're interested in.
  This parameter is required.
 
.PARAMETER TermId
  The numeric ID of the term you're interested in.
  This parameter is required.
 
.PARAMETER ProgramId
  The numeric ID of the program you're interested in. Default to all programs (program_id 0).
 
.PARAMETER IncludeLockedGrades
  Boolean. Defaults to true.
 
.PARAMETER Path
  Enter the path to store the downloaded file. The path will be tested before the backup begins to download. Do not include the filename.
  This will be returned with the downloaded file. Remember to save in a secure location.
  This parameter is required.
 
.OUTPUTS
  PDF file of grade report for selected PersonId and TermId.
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/28/2019
 
.EXAMPLE
  Get-PPersonLeads -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonID 7857760 -Termid 223196 -Path "c:\test\"
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [string]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [parameter(Mandatory)]
        [int]
        $TermId,

        [parameter()]
        [int]
        $ProgramId,

        [parameter()]
        [ValidateSet("true","false")]
        [string]
        $IncludeLockedGrades,

        [Parameter(Mandatory)]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Path does not exist."
            }
            return $true
        })]
        [string]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetGradeReportBody = @{
            task = 'getGradeReport';
            person_id = $PersonId;
            term_id = $TermId;
            access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('ProgramId')) {
            Write-Verbose -Message "Adding ProgramId $ProgramId to request string."
            $GetGradeReportBody.Add('program_id', $ProgramId)
        }
        if ($PSBoundParameters.ContainsKey('IncludeLockedGrades')) {
            Write-Verbose -Message "Adding IncludeLockedGrades $IncludeLockedGrades to request string."
            $GetGradeReportBody.Add('include_locked_grades', $IncludeLockedGrades)
        }

        try {
            Write-Verbose -Message "Sending request to Populi."
            $Download = Invoke-WebRequest -Uri $PopuliUri -Method Post -Body $GetGradeReportBody -TimeoutSec 60
                if ($Download.Content.Contains('error')) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PGradeReport."
                    $PError = [pscustomobject] @{
                        'ErrorMessage' = $Download.Content
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Getting filename from download content header."
                    $FileName = $Download.Headers.'Content-disposition'.Substring(22)
                    $FileName = $FileName.Substring(0,$FileName.Length-1)
                    Write-Verbose -Message "Filename: $FileName"
                    $FilePath = Join-Path -Path $Path -ChildPath $FileName
                    Write-Verbose -Message "FilePath: $FilePath"

                        if (Test-Path $FilePath.trim()) {
                            Write-Warning -Message "$FilePath --> File already exists."
                            Write-Verbose -Message "$FilePath --> File already exists."
                            break
                        }
                        else {
                            Write-Verbose -Message "Writing file $FileName."
                            [System.IO.File]::WriteAllBytes("$FilePath", $Download.content)
                             Write-Verbose -Message "File saved to $FilePath."
                        }

                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-WebRequest command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }

    } #END:Process

    end {
        Write-Verbose "Get-PGradeReport cmdlet Finished."
    }

} #END:Get-PGradeReport
function Get-PInquiry {
<#
.SYNOPSIS
  Returns a particular admissions inquiry.
 
.DESCRIPTION
  You must have one of these roles to call this task: Admissions, Admissions Admin.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. (See Description.)
  This parameter is required.
 
.PARAMETER InquiryId
  The numeric ID of the inquiry.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    InquiryId
    PersonId
    LeadId
    FirstName
    MiddleName
    LastName
    Email
    Phone
    AddressId
    Subject
    Content
    ProgramId
    DegreeId
    SpecializationId
    AcademicTermId
    CounselorId
    AutoAssignedTo
    Status
    LeadSourceId
    LocalizationId
    AddedOn
    AddedBy
    AddedAt
    DeletedBy
    DeletedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/30/2019
 
.EXAMPLE
  Get-PInquiry -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -InquiryId 13
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $InquiryId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetInquiryBody = @{
             task = 'getInquiry';
             inquiry_id = $InquiryId;
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetInquiryBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PInquiry."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Inquiry = [pscustomobject] @{
                        'InquiryId' = $Response.response.inquiry.id
                        'PersonId' = $Response.response.inquiry.person_id
                        'LeadId' = $Response.response.inquiry.lead_id
                        'FirstName' = $Response.response.inquiry.first_name
                        'MiddleName' = $Response.response.inquiry.middle_name
                        'LastName' = $Response.response.inquiry.last_name
                        'Email' = $Response.response.inquiry.email
                        'Phone' = $Response.response.inquiry.phone
                        'AddressId' = $Response.response.inquiry.address_id
                        'Subject' = $Response.response.inquiry.subject
                        'Content' = $Response.response.inquiry.content
                        'ProgramId' = $Response.response.inquiry.program_id
                        'DegreeId' = $Response.response.inquiry.degree_id
                        'SpecializationId' = $Response.response.inquiry.specialization_id
                        'AcademicTermId' = $Response.response.inquiry.academic_term_id
                        'CounselorId' = $Response.response.inquiry.counselor_id
                        'AutoAssignedTo' = $Response.response.inquiry.auto_assigned_to
                        'Status' = $Response.response.inquiry.status
                        'LeadSourceId' = $Response.response.inquiry.lead_source_id
                        'LocalizationId' = $Response.response.inquiry.localization_id
                        'AddedOn' = $Response.response.inquiry.added_on
                        'AddedBy' = $Response.response.inquiry.added_by
                        'AddedAt' = $Response.response.inquiry.added_at
                        'DeletedBy' = $Response.response.inquiry.deleted_by
                        'DeletedAt' = $Response.response.inquiry.deleted_at
                        }
                    Write-Output $Inquiry

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PInquiry cmdlet finished."
    }

} #END: Get-PInquiry
function Get-PLeadSources {
<#
.SYNOPSIS
  Returns all the lead sources you've set up in the Admissions module.
 
.DESCRIPTION
  You must have the Admissions role to call this task.
  Useful for looking up numeric IDs for passing into setLeadInfo.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. (See Description.)
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    LeadId
    Name
    Type
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 11/06/2019
 
.EXAMPLE
  Get-PLeadSources -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789'
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetLeadSourcesBody = @{
             task = 'getLeadSources';
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetLeadSourcesBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PLeadSources."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $LeadSources = foreach ($LeadSource in $Response.response.lead_source) {
                        [pscustomobject] @{
                        'LeadId' = $LeadSource.id
                        'Name' = $LeadSource.name
                        'Type' = $LeadSource.type
                        }
                    }

                    Write-Output $LeadSources

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PLeadSources cmdlet finished."
    }

} #END: Get-PLeadSources
function Get-PNews {
<#
.SYNOPSIS
  Returns the Populi news feed, ordered most recent to least recent (with pinned articles at the top).
 
.DESCRIPTION
  The content element contains HTML, with embedded media links resolved absolutely (so no additional parsing should be necessary).
  Here is an example to help you access the html in the content section:
  $NewsData = Get-PNews -PopuliUri $PopuliUri -PopuliAuthkey $PopuliAuthkey -Limit 5
  foreach ($Item in $NewsData) {
    $Title = $Item.title
    $Content = $Item.content.'#cdata-section'
  }
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task.
  This parameter is required.
 
.PARAMETER Limit
  The maximim number of articles you'd like returned (defaults to 10).
 
.PARAMETER Offset
  If a limit is specified, you can also specify an offset.
 
.OUTPUTS
  Returns PowerShell objects:
    ArticleId
    Title
    Content
    Pinned
    PinnedUntil
    AddedAt
    AddedBy
    AddedByName
    UpdatedAt
    UpdatedBy
    UpdatedByName
    RoleId
    RoleName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/11/2018
 
.EXAMPLE
  Get-PNews -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -Limit 5
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PNews @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [string]
        $PopuliAuthkey,

        [Parameter()]
        [int]
        $Limit = 10,

        [Parameter()]
        [int]
        $Offset = 0
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetNewsBody = @{
            task = 'getNews';
            limit = $Limit;
            offset = $Offset;
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $getNewsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PNews."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."

                    $Roles = foreach ($Role in $Response.response.article.roles.role) {
                        [pscustomobject] @{
                            'RoleId' = $Role.id
                            'RoleName' = $Role.name
                        }
                    }

                    $GetNews = [pscustomobject] @{
                        'ArticleId' = $Response.response.article.article_id
                        'Title' = $Response.response.article.title
                        'Content' = $Response.response.article.content
                        'Pinned' = $Response.response.article.pinned
                        'PinnedUntil' = $Response.response.article.pinned_until
                        'AddedAt' = $Response.response.article.added_at
                        'AddedBy' = $Response.response.article.added_by
                        'AddedByName' = $Response.response.article.added_by_name
                        'UpdateAt' = $Response.response.article.updated_at
                        'UpdatedBy' = $Response.response.article.updated_by
                        'UpdatedByName' = $REsponse.response.article.updated_by_name
                        'Roles' = $Roles
                    }

                    Write-Output $GetNews
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
     } #END:process

    end {
        Write-Verbose "Get-PNews cmdlet finished."
    }

} #END:Get-PNews
function Get-PPerson {
<#
.SYNOPSIS
  Returns basic profile data about a person: name, age, gender, tags, and contact information (address, phone, email).
 
.DESCRIPTION
  If the person has a profile picture, the <image> element will contain base64 encoded binary data.
  The <image> element won't be returned unless the person has a profile picture set. You can set a path to save the image file,
  see parameters and examples. If multiple school,home, work, other identifiers exist (address, phone, email) then it will
  only return the first one. This was a cmdlet design decision since I think it speaks more to data integrity.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person. This parameter is required.
 
.PARAMETER ReturnImageData
  Boolean (e.g. 1 or 0). Returning binary image data will result in slower response times. Defaults to 0.
 
.PARAMETER Path
  Enter the path to store the image file. The filename will be created using "PersonLastName_PersonFirstName.jpg". It is recommended
  to enter a path if you are returning image data.
 
.OUTPUTS
  Returns PowerShell objects:
    FirstName
    LastName
    MiddleName
    PreferredName
    Prefix
    Suffix
    FormerName
    Gender
    BirthDate
    Citizenship
    Citizenships
      <Hashtable>
    ResidentAlien
    HomeCity
    HomeState
    HomeCountry
    LicensePlate
    IsActiveUser
    Races
      <Hashtable>
    HispanicLatino
    Address
      <Home|Work|Billing|School|Shipping|Other>AddressId
      <Home|Work|Billing|School|Shipping|Other>AddressStreet
      <Home|Work|Billing|School|Shipping|Other>AddressCity
      <Home|Work|Billing|School|Shipping|Other>AddressState
      <Home|Work|Billing|School|Shipping|Other>AddressZip
      <Home|Work|Billing|School|Shipping|Other>AddressCountry
      <Home|Work|Billing|School|Shipping|Other>AddressIsPrimary
    Phone
      <Home|Work|Mobile|School|Fax|Other>Phone
      <Home|Work|Mobile|School|Fax|Other>PhoneId
      <Home|Work|Mobile|School|Fax|Other>PhoneIsPrimary
    Email
      <School|Work|Home|Other>Email
      <School|Work|Home|Other>EmailId
      <School|Work|Home|Other>EmailIsPrimary
    Tags
      <Hashtable>
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/17/2018
  Updated: 03/05/2019
 
.EXAMPLE
  Get-PPerson -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonID '7857760'
 
.EXAMPLE
  7857760 | Get-PPerson @PopuliCredentials
 
.EXAMPLE
  Get-PTaggedPeople @PopuliCredentials -TagName "<ENTER_TAG_NAME> | Get-PPerson @PopuliCredentials -Property FirstName,LastName,SchoolEmail,SchoolPhone
 
.EXAMPLE
  Get-PPerson @PopuliCredentials -PersonId 7781234 -ReturnImageData 1 -Path "<PATH_TO_SAVE_FILE>
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [ValidateSet("0","1")]
        [int]
        $ReturnImageData = 0,

        [Parameter()]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Folder does not exist"
            }
            return $true
        })]
        [string]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetPersonBody = @{
             task = 'getPerson';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
             return_image_data = $ReturnImageData;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetPersonBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PPerson."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."

                    $Citizenships = foreach ($Item in $Response.response.citizenships){
                        [pscustomobject] @{
                            'CitizenshipId' = $Item.citizenship.id
                            'CitizenshipAbbr' = $Item.citizenship.abbr
                        }
                    }

                    $Races = foreach ($Race in $Response.response.races){
                        [pscustomobject] @{
                            'RaceId' = $Race.race.id
                            'RaceName' = $Race.race.name
                        }
                    }

                    $Tags = foreach ($Tag in $Response.response.tags.tag){
                        [pscustomobject] @{
                            'TagId' = $Tag.id
                            'TagName' = $Tag.name
                            'System' = $Tag.system
                        }
                    }

                    $Person = [ordered]@{
                        'FirstName' = $Response.response.first
                        'LastName' = $Response.response.last
                        'MiddleName' = $Response.response.middle_name
                        'PreferredName' = $Response.response.preferred_name
                        'Prefix' = $Response.response.prefix
                        'Suffix' = $Respnse.response.suffix
                        'FormerName' = $Response.response.former_name
                        'Gender' = $Response.response.gender
                        'BirthDate' = $Response.response.birth_date
                        'Citizenship' = $Response.response.citizenship
                        'Citizenships' = $Citizenships
                        'ResidentAlien' = $Response.response.resident_alien
                        'HomeCity' = $Response.response.home_city
                        'HomeState' = $Response.response.home_state
                        'HomeCountry' = $Response.response.home_country
                        'LicensePlate' = $Response.response.license_plate
                        'IsActiveUser' = $Response.response.is_active_user
                        'HispanicLatino' = $Response.response.hispanic_latino
                        'Races' = $Races
                        'Tags' = $Tags
                    }

                    foreach ($Item in $Response.response.email) {
                        $EmailType = ($Item.type).ToLower()
                        $EmailType = (Get-Culture).TextInfo.ToTitleCase($EmailType)
                        $EmailAddress = $EmailType + "Email"

                            if ($Person.Contains($EmailAddress)) {
                                Write-Verbose -Message "$EmailAddress type already exists. $($Item.Address) not added to output."
                                continue
                            }

                        $Person.Add($EmailAddress,($Item.Address))
                        $EmailId = $EmailType + "EmailId"
                        $Person.Add($EmailId,($Item.emailid))
                        $EmailIsPrimary = $EmailType +"EmailIsPrimary"
                        $Person.Add($EmailIsPrimary,($Item.is_primary))
                    }

                    foreach ($Item in $Response.response.phone){
                        $PhoneType = ($Item.type).ToLower()
                        $PhoneType = (Get-Culture).TextInfo.ToTitleCase($PhoneType)
                        $PhoneNumber = $PhoneType + "Phone"

                            if ($Person.Contains($PhoneNumber)) {
                                Write-Verbose -Message "$PhoneNumber type already exists. $($Item.number) not added to output."
                                continue
                            }

                        $Person.Add($PhoneNumber,($Item.number))
                        $PhoneId = $PhoneType + "PhoneId"
                        $Person.Add($PhoneId,($Item.phoneid))
                        $PhoneIsPrimary = $PhoneType +"PhoneIsPrimary"
                        $Person.Add($PhoneIsPrimary,($Item.is_primary))
                    }

                    foreach ($Item in $Response.response.address){
                        $AddressType = ($Item.type).ToLower()
                        $AddressType = (Get-Culture).TextInfo.ToTitleCase($AddressType)
                        $AddressId = $AddressType + "AddressId"

                            if ($Person.Contains($AddressId)) {
                                Write-Verbose -Message "$AddressType type already exists. $($Item.street) not added to output."
                                continue
                            }

                        $Person.Add($AddressId,($Item.addressid))
                        $AddressStreet = $AddressType + "AddressStreet"
                        $Person.Add($AddressStreet,($Item.street))
                        $AddressCity = $AddressType + "AddressCity"
                        $Person.Add($AddressCity,($Item.city))
                        $AddressState = $AddressType + "AddressState"
                        $Person.Add($AddressState,($Item.state))
                        $AddressZip = $AddressType + "AddressZip"
                        $Person.Add($AddressZip,($Item.zip))
                        $AddressCountry = $AddressType + "AddressCountry"
                        $Person.Add($AddressCountry,($Item.country))
                        $AddressIsPrimary = $AddressType +"AddressIsPrimary"
                        $Person.Add($AddressIsPrimary,($Item.is_primary))
                    }

                    [pscustomobject]$Person

                        if ($PSBoundParameters.ContainsKey('Path')) {
                            Write-Verbose -Message "Creating filename using Lastname_Firstname_PersonId.jpg"
                            $FileName = ($Person.LastName) + "_" + ($Person.FirstName) + "_" + ($PersonId) + ".jpg"
                            Write-Verbose "Updating the path to include filename."
                            $FilePath = Join-Path -Path $Path -ChildPath $FileName
                            Write-Verbose -Message "Checking if file exists."
                                if (Test-Path $FilePath.trim()) {
                                    Write-Warning -Message "$FilePath --> File already exists. File not saved."
                                    break
                                }
                                else {
                                    Write-Verbose -Message "Writing file $FileName."
                                    $bytes = [Convert]::FromBase64String($Response.response.image)
                                    [IO.File]::WriteAllBytes($FilePath, $bytes)
                                    Write-Verbose -Message "File saved to $FilePath."
                                }
                        }

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PPerson cmdlet finished."
    }

} #END: Get-PPerson
function Get-PPersonLeads {
<#
.SYNOPSIS
  Returns all leads attached to a person.
 
.DESCRIPTION
  You must have the Admissions, Admissions Admin, Registrar, or Academic Admin role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. (See Description.)
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    LeadId
    FirstName
    PreferredName
    MiddleName
    LastName
    Active
    MostRecent
    AddedOn
    RepresentativeId
    RepresentativeFirstName
    RepresentativePreferredName
    RepresentativeMiddleName
    RepresentativeLastName
    Status
    ProgramId
    ProgramName
    DegreeId
    DegreeName
    SpecializationId
    SpecializationName
    TermId
    TermName
    SourceId
    SourceName
    SourceComment
    EducationLevelId
    EducationLevelName
    DeclinedReasonId
    DeclinedReasonName
    DeclinedReasonComment
    HighSchoolGradDate
    InquiryIds
    ApplicationIds
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/31/2019
 
.EXAMPLE
  Get-PPersonLeads -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonID 7857760
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetPersonLeadsBody = @{
             task = 'getPersonLeads';
             person_id = $PersonId;
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetPersonLeadsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PPersonLeads."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Leads = foreach ($Lead in $Response.response.leads.lead) {
                        [pscustomobject] @{
                            'LeadId' = $Lead.id
                            'FirstName' = $Lead.first_name
                            'PreferredName' = $Lead.preferred_name
                            'MiddleName' = $Lead.middle_name
                            'LastName' = $Lead.last_name
                            'Active' = $Lead.active
                            'MostRecent' = $Lead.most_recent
                            'AddedOn' = $Lead.added_on
                            'RepresentativeId' = $Lead.representative_id
                            'RepresentativeFirstName' = $Lead.representative_first_name
                            'RepresentativePreferredName' = $Lead.representative_preferred_name
                            'RepresentativeMiddleName' = $Lead.representative_middle_name
                            'RepresentativeLastName' = $Lead.representative_last_name
                            'Status' = $Lead.status
                            'ProgramId' = $Lead.program_id
                            'ProgramName' = $Lead.program_name
                            'DegreeId' = $Lead.degree_id
                            'DegreeName' = $Lead.degree_name
                            'SpecializationId' = $Lead.specialization_id
                            'SpecializationName' = $Lead.specialization_name
                            'TermId' = $Lead.academic_term_id
                            'TermName' = $Lead.academic_term_name
                            'SourceId' = $Lead.source_id
                            'SourceName' = $Lead.souce_name
                            'SourceComment' = $Lead.source_comment
                            'EducationLevelId' = $Lead.education_level_id
                            'EducationLevelName' = $Lead.education_level_name
                            'DeclinedReasonId' = $Lead.declined_reason_id
                            'DeclinedReasonName' = $Lead.declined_reason_name
                            'DeclinedReasonComment' = $Lead.declined_reason_comment
                            'HighSchoolGradDate' = $Lead.high_school_grad_date
                            'InquiriyIds' = $Lead.inquiries.inquiry.id
                            'ApplicationIds' = $Lead.applications.application.id
                        }
                    }
                    Write-Output $Leads

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PPersonLeads cmdlet finished."
    }

} #END: Get-PPersonLeads
function Get-PPrograms {
<#
.SYNOPSIS
  Returns information about each program configured at the school.
 
.DESCRIPTION
  You must have one of the following roles to call this task: Academic Admin, Registrar, Academic Auditor, Admissions, Admissions Admin.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting. This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    ProgramId
    ProgramName
    Units
    GraduateLevel
    Status
    Default
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 07/23/2019
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PPrograms @PopuliCredentials
 
.EXAMPLE
  Get-PPrograms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
#>

[CmdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetProgramsBody = @{
            task = 'getPrograms';
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetProgramsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PPrograms."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Programs = foreach ($Program in $Response.response.program) {
                        [pscustomobject] @{
                            'ProgramId' = $Program.id
                            'ProgramName' = $Program.name
                            'Units' = $Program.units
                            'GraduateLevel' = $Program.graduate_level
                            'Status' = $Program.status
                            'Default' = $Program.default
                        }
                    }
                    Write-Output $Programs
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        } #END:try/catch
    } #END:Process

    end {
        Write-Verbose "Get-PPrograms cmdlet finished."
    }

} #END:Get-PPrograms
function Get-PRoleMembers {
<#
.SYNOPSIS
 Returns members of a particular role.
 
.DESCRIPTION
  You must have the Staff role to call this task. There is a limit of 1000 results in the response.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER RoleId
  Numeric ID of the role. Either RoleId OR RoleName MUST be set.
 
.PARAMETER RoleName
  Name of the role. Either RoleId OR RoleName MUST be set.
 
.PARAMETER Status
  Possible values: ACTIVE (default), INACTIVE, and ALL.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonID
    FirstName
    LastName
    Inactive (1=Yes / 0=No)
    UserName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/14/2019
  Updated: 03/06/2019
 
.EXAMPLE
  Get-PRoleMembers @PopuliCredentials -RoleName "Faculty"
 
.EXAMPLE
  Get-PRoleMembers @PopuliCredentials -RoleName "Staff" | Get-PPerson @PopuliCredentials -Property FirstName,LastName,WorkEmail,WorkPhone
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PRoleMembers @PopuliCredentials
#>

[CMdletBinding(DefaultParameterSetName="ByRoleName")]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(ParameterSetName="ByRoleId",
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $RoleId,

        [Parameter(ParameterSetName="ByRoleName",
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [String]
        $RoleName,

        [Parameter(ParameterSetName='ByRoleId')]
        [Parameter(ParameterSetName='ByRoleName')]
        [ValidateSet("ACTIVE","INACTIVE","ALL")]
        [string]
        $Status
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetRoleMembersBody = @{
             task = 'getRoleMembers';
             access_key = $PopuliAuthkey;
        }

        if ($PSBoundParameters.ContainsKey('RoleId')) {
            Write-Verbose -Message "Adding RoleId $RoleId to request string."
            $GetRoleMembersBody.Add('roleID', $RoleId)
        }
        if ($PSBoundParameters.ContainsKey('RoleName')) {
            Write-Verbose -Message "Adding RoleName $RoleName to request string."
            $GetRoleMembersBody.Add('roleName', $RoleName)
        }
        if ($PSBoundParameters.ContainsKey('Status')) {
            Write-Verbose -Message "Adding Status $Status to request string."
            $GetRoleMembersBody.Add('status', $Status)
        }


        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetRoleMembersBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PRoleMembers."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $People = foreach ($Person in $Response.response.person) {
                        Write-Verbose -Message "Converting $($Person.username)"
                        [pscustomobject]@{
                            PersonId = $Person.personID
                            FirstName = $Person.first
                            LastName = $Person.last
                            Inactive = $Person.inactive
                            UserName = $Person.username
                            RoleId = $RoleId
                            RoleName = $RoleName
                        }
                    } #END:foreach

                   Write-Output $People

                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from Invoke-Restmethod or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PRoleMembers cmdlet finished."
    }

} #END:Get-PRoleMembers
function Get-PRoles {
<#
.SYNOPSIS
 Returns all active roles for a particular person (or the current users if no person_id is specified).
 
.DESCRIPTION
  To get a list of all possible roles (not just those attached to this person), see Get-PAvailableRoles
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person whose roles you wish to retrieve. If not specified, the roles for the logged-in user will be returned.
 
.OUTPUTS
  Returns PowerShell objects:
    RoleId
    RoleName
    Inactive (1=Yes / 0=No)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/14/2019
 
.EXAMPLE
  Get-PRoles -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId '7856690'
 
.EXAMPLE
  Search-PPeople @PopuliCredentials -SearchTerm "Test User" -Limit 1 | Get-PRoles @PopuliCredentials
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PRoles @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetRolesBody = @{
             task = 'getRoles';
             access_key = $PopuliAuthkey;
        }

        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $GetRolesBody.Add('person_id', $PersonId)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetRolesBody -ErrorAction Stop

                if ($Response.error) {
                     Write-Verbose -Message "Error returned from Populi while executing Get-PProles."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Roles = foreach ($Role in $Response.response.role) {
                        Write-Verbose -Message "Converting $($Role.name)"
                        [pscustomobject]@{
                            RoleId = $Role.id
                            RoleName = $Role.name
                            Inactive = $Role.inactive
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Roles
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PRoles cmdlet finished."
    }
} #END:Get-PRoles
function Get-PStudentInfo {
<#
.SYNOPSIS
  Returns student information for a particular person.
 
.DESCRIPTION
  If the person has a profile picture, the <image> element will contain base64 encoded binary data.
  The <image> element won't be returned unless the person has a profile picture set. You can set a path to save the image file,
  see parameters and examples.
  An optional <advisors> element is returned for active students.
  An optional <campuses> element is returned if the current user has the Staff role and your school has at least one campus set up.
  <leave_of_absence_start_date> & <leave_of_absence_anticipated_return_date> will only be returned if the <leave_of_absence> value is "1".
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person you're interested in.
  To call this task for anyone other than yourself, you must have the Registrar role, Academic Admin role, or be an advisor of the person.
  If not set, uses the person_id of the currently logged-in user.
 
.PARAMETER ReturnImageData
  Boolean (e.g. 1 or 0). Returning binary image data will result in slower response times. Defaults to 0.
 
.PARAMETER Path
  If requesting ImageData, enter the path to store the image file. The filename will be created using LastName_FirstName_StudentId.jpg.
 
.OUTPUTS
  Returns PowerShell objects:
    StudentId
    FirstName
    LastName
    MiddleName
    PreferredName
    Prefix
    Suffix
    Gender
    BirthDate
    Image
    EntranceTermId
    EntranceTermName
    ExitDate
    ExitReason
    LeaveOfAbsence
    LeaveOfAbsenceStartDate
    LeaveOfAbsenceAnticipatedReturnDate
    Advisors
      <Hashtable>
    Campuses
      <Hashtable>
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/08/2019
 
.EXAMPLE
  Get-PStudentInfo -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId '7857760'
 
.EXAMPLE
  Get-PStudent @PopuliCredentials -PersonId 7781234 -ReturnImageData 1 -Path "<PATH_TO_SAVE_FILE>"
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [parameter(ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [ValidateSet("0","1")]
        [int]
        $ReturnImageData = 0,

        [Parameter()]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Folder does not exist. Please enter a valid path."
            }
            return $true
        })]
        [String]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetStudentInfoBody = @{
             task = 'getStudentInfo';
             access_key = $PopuliAuthkey;
             return_image_data = $ReturnImageData;
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $GetStudentInfoBody.Add('person_id', $PersonId)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetStudentInfoBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PStudentInfo."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."

                    $Advisors = foreach ($Advisor in $Response.response.advisors.advisor){
                        [pscustomobject] @{
                            'PersonId' = $Advisor.person_id
                            'FirstName' = $Advisor.first
                            'LastName' = $Advisor.last
                        }
                    }

                    $Campuses = foreach ($Campus in $Response.response.campuses.campus) {
                        [pscustomobject] @{
                            'CampusId' = $Campus.campus_id
                            'CampusName' = $Campus.name
                            'Status' = $Campus.status
                            'City' = $Campus.city
                            'State' = $Campus.state
                            'Zip' = $Campus.zip
                            'Country' = $Campus.country
                            'IsPrimary' = $Campus.is_primary
                        }
                    }

                    $Student = [pscustomobject] @{
                        'StudentId' = $Response.response.student_id
                        'FirstName' = $Response.response.first
                        'LastName' = $Response.response.last
                        'MiddleName' = $Response.response.middle_name
                        'PreferredName' = $Response.response.preferred_name
                        'Prefix' = $Response.response.prefix
                        'Suffix' = $Response.response.suffix
                        'Gender' = $Response.response.gender
                        'BirthDate' = $Response.response.birth_date
                        'EntranceTermId' = $Response.response.entrance_term_id
                        'EntranceTermName' = $Response.response.entrance_term_name
                        'ExitDate' = $Response.response.exit_date
                        'ExitReason' = $Response.response.exit_reason
                        'LeaveOfAbsence' = $Response.response.leave_of_absence
                        'LeaveOfAbsenceStartDate' = $Response.response.leave_of_absence_start_date
                        'LeaveOfAbsenceAnticipatedReturnDate' = $Response.response.leave_of_absence_anticipated_return_date
                        'Advisors' = $Advisors
                        'Campuses' = $Campuses
                    }

                    Write-Output $Student

                        if ($PSBoundParameters.ContainsKey('Path')) {
                            Write-Verbose -Message "Creating filename using Lastname_Firstname.jpg"
                            $FileName = ($Student.LastName) + "_" + ($Student.FirstName) + "_" + ($Student.StudentId) +  ".jpg"
                            Write-Verbose "Updating the path to include filename."
                            $FilePath = Join-Path -Path $Path -ChildPath $FileName
                            Write-Verbose -Message "Checking if file exists."
                                if (Test-Path $FilePath.trim()) {
                                    Write-Warning -Message "$FilePath --> File already exists. File not saved."
                                    break
                                }
                                else {
                                    Write-Verbose -Message "Writing file $FileName."
                                    $bytes = [Convert]::FromBase64String($Response.response.image)
                                    [IO.File]::WriteAllBytes($FilePath, $bytes)
                                    Write-Verbose -Message "File saved to $FilePath."
                                }
                        }

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PStudentInfo cmdlet finished."
    }

} #END: Get-PStudentInfo
function Get-PTaggedPeople {
<#
.SYNOPSIS
  Returns people tagged with a particular tag.
 
.DESCRIPTION
  You must have the Staff role to call this task. There is a limit of 1000 results in the response.
  The "num_results" attribute (in the <response> element) indicates the total number of possible results (regardless of the limit or the page parameter).
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.PARAMETER TagId
  Numeric ID of the tag. Not required but either TagId OR tagName MUST be set.
 
.PARAMETER TagName
  Name of the tag. Not required but either TagId OR tagName MUST be set.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    FirstName
    LastName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/14/2018
 
.EXAMPLE
  Get-PTaggedPeople -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TagName 'Test'
 
.EXAMPLE
  "Test" | Get-PTaggedPeople -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  Get-PTaggedPeople -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TagId '307358'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTaggedPeople @PopuliCredentials -TagId '307358'
#>

[CMdletBinding(DefaultParameterSetName='ByTagName')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [string]
        $PopuliAuthkey,

        [Parameter(ParameterSetName='ByTagId',
                   Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TagId,

        [Parameter(ParameterSetName='ByTagName',
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName,
                   Mandatory)]
        [string]
        $TagName
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTaggedPeopleBody = @{
             task = 'getTaggedPeople';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('TagId')) {
            Write-Verbose -Message "Adding TagId $TagId to request string."
            $GetTaggedPeopleBody.Add('tagID', $TagId)
        }
        if ($PSBoundParameters.ContainsKey('TagName')) {
            Write-Verbose -Message "Adding TagName $TagName to request string."
            $GetTaggedPeopleBody.Add('tagName', $TagName)
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTaggedPeopleBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTaggedPeople."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $People = foreach ($Person in $Response.response.person) {
                        [pscustomobject] @{
                            'PersonId' = $Person.person_id
                            'FirstName' = $Person.first_name
                            'LastName' = $Person.last_name
                        }
                    }
                    Write-Output $People
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose "Get-PTaggedPeople cmdlet finished."
    }

} #END:Get-PTaggedPeople
function Get-PTags {
<#
.SYNOPSIS
  Returns a list of available tags.
 
.DESCRIPTION
  Returns a list of available tags.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    TagId
    TagName
    System (0 or 1)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/10/2018
 
.EXAMPLE
  Get-PTags -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  #Get TagId, TagName, System based on TagName:
  Get-PTags @PopuliCredentials | Where-Object {$_.tagname -match 'Test'}
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTags @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTagsBody = @{
             task = 'getTags';
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTagsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTags."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Tags = foreach ($Tag in $Response.response.tags.tag) {
                        [pscustomobject] @{
                            'TagId' = $Tag.id
                            'TagName' = $Tag.name
                            'System' = $Tag.system
                        }
                    }
                Write-Output $Tags
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Get-PTags cmdlet finished."
    }

} #END: Get-PTags
function Get-PTermCourseInstances {
<#
.SYNOPSIS
  Returns course instances for a given term (only active course instances are returned by default).
 
.DESCRIPTION
  Returns course instances for a given term (only active course instances are returned by default).
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference. This parameter is required.
 
.PARAMETER TermId
  The numeric ID of the term you're interested in. One method for optaining the term id is running the
  Get-CurrentAcademicTerm cmdlet. For more information check the Populi API reference.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    InstanceId
    CourseId
    Name
    Abbrv
    Section
    PrimaryFacultyId
    PrimaryFacultyName
    Description
    DepartmentId
    DepartmentName
    Credits
    Hours
    DeliveryMethodId
    DeliveryMethodName
    CampusId
    CampusName
    StartDate
    EndDate
    OpenToStudentsDate
    ClosedToStudentsDate
    MaxEnrolled
    MaxAuditors
    Published
    Programs
      ProgramId
      ProgramName
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/06/2018
  Updated: 04/11/2019
 
.EXAMPLE
  Get-PTermCourseInstances -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TermId '7289900'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTermCourseInstance @PopuliCredentials -TermId '162800'
#>

[CmdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TermId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTermCourseInstancesBody = @{
                task = 'getTermCourseInstances';
                term_id = $TermId
                access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Requesting data from Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTermCourseInstancesBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTermCourseInstances."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Courses = foreach ($Course in $Response.response.course_instance) {
                        [pscustomobject] @{
                            'InstanceId' = $Course.instanceid
                            'CourseId' = $Course.courseid
                            'Name' = $Course.name
                            'Abbrv' = $Course.abbrv
                            'Section' = $Course.section
                            'PrimaryFacultyId' = $Course.primary_faculty_id
                            'PrimaryFacultyName' = $Course.primary_faculty_name
                            'Description' = $Course.description
                            'DepartmentId' = $Course.department_id
                            'DepartmentName' = $Course.department_name
                            'Credits' = $Course.credits
                            'Hours' = $Course.hours
                            'DeliveryMethodId' = $Course.delivery_method_id
                            'DeliveryMethodName' = $Course.delivery_method_name
                            'CampusId' = $Course.campus_id
                            'CampusName' = $Course.campus_name
                            'StartDate' = $Course.start_date
                            'EndDate' = $Course.end_date
                            'OpenToStudentsDate' = $Course.open_to_students_date
                            'ClosedToStudentsDate' = $Course.closed_to_students_date
                            'MaxEnrolled' = $Course.max_enrolled
                            'MaxAuditors' = $Course.max_auditors
                            'Published' = $Course.published
                            'ProgramId' = $Course.programs.program.id
                            'ProgramName' = $Course.programs.program.name
                        }
                    } #END:foreach
                Write-Output $Courses
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }

     } #END:Process

     end {
         Write-Verbose -Message "Get-PTermCourseInstances cmdlet finished."
     }

} #END:Get-PTermCourseInstances
function Get-PTermEnrollment {
<#
.SYNOPSIS
  Returns term enrollment for a particular academic term.
 
.DESCRIPTION
  You must have the Academic Admin or Registrar role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference. This parameter is required.
 
.PARAMETER TermId
  The numeric ID of the term you're interested in. One method for optaining the term id is running the
  Get-CurrentAcademicTerm cmdlet. For more information check the Populi API reference.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    AcademicTermId
    InstanceId
    CatalogCourseId
    Status
    Credits
    Hours
    AcademicTermName
    Abbrv
    CourseName
    Section
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/11/2019
 
.EXAMPLE
  Get-PTermEnrollment -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TermId '7289900'
 
.EXAMPLE
  Get-PCurrentAcademicTerm @PopuliCredentials | Get-PTermEnrollment @PopuliCredentials
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTermEnrollment @PopuliCredentials -TermId '162200'
#>

[CmdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TermId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTermEnrollmentBody = @{
                task = 'getTermEnrollment';
                term_id = $TermId
                access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Requesting data from Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTermEnrollmentBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTermEnrollment."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Return data as PowerShell objects."
                    $Enrollments = foreach ($Enrollment in $Response.response.enrollment) {
                        [pscustomobject] @{
                            'PersonId' = $Enrollment.person_id
                            'AcademicTermId' = $Enrollment.academic_term_id
                            'InstanceId' = $Enrollment.instance_id
                            'CatalogCourseId' = $Enrollment.catalog_course_id
                            'Status' = $Enrollment.status
                            'Credits' = $Enrollment.credits
                            'Hours' = $Enrollment.hours
                            'AcademicTermName' = $Enrollment.academic_term_name
                            'Abbrv' = $Enrollment.course_abbrv
                            'CourseName' = $Enrollment.course_name
                            'Section' = $Enrollment.section
                        }
                    } #END:foreach
                Write-Output $Enrollments
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
     } #END:Process

     end {
         Write-Verbose -Message "Get-PTermEnrollment cmdlet finished."
     }

} #END: Get-PTermEnrollment
function Get-PTermStudents {
<#
.SYNOPSIS
  Returns term students.
 
.DESCRIPTION
  If the person has a profile picture, the element will contain base64 encoded binary data. The element won't be returned unless the person has a profile picture set.
  There is a limit of 1000 results in the response. The "num_results" attribute (in the <response> element) indicates the total number of possible results
  (regardless of the limit or the page parameter).
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Registrar or Academic Admin role to call this task.
  This parameter is required.
 
.PARAMETER TermId
  Numeric ID of the term you're interested in. Defaults to the current academic term_id.
 
.PARAMETER ProgramId
  Possible values: ALL (default), NONE, or any numeric program_id.
 
.PARAMETER CampusId
  Possible values: ALL (default), 0 (None), or any numeric campus_id.
 
.PARAMETER ReturnImageData
  Boolean (e.g. 1 or 0). Returning binary image data will result in slower response times. Defaults to 0.
 
.PARAMETER Path
  If ReturnImageData set to 1, enter the path to store the image file. File name will be LastName_FirstName_PersonId.jpg.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    StudentId
    FirstName
    MiddleName
    PreferredName
    UserName
    Prefix
    Suffix
    FormerName
    Gender
    BirthDate
    Image
    ProgramId
    ProgramName
    Standing
    Degree
    FullTime
    UnitsAttempted
    UnitsGranted
    TermGpa
    CumUnitsGranted
    CumGpa
    CumGpaIncludingTransfer
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/03/2019
 
.EXAMPLE
  #Returns all students in the current term
  Get-PTermStudents -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789'
 
.EXAMPLE
  #Pipe a TermId to Get-PTermStudents
  '162800' | Get-PTermStudents @PopuliCred
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTermStudents @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TermId,

        [string]
        $ProgramId,

        [string]
        $CampusId,

        [int]
        $ReturnImageData = 0,

        [Parameter()]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Container) ){
                throw "Folder does not exist"
            }
            return $true
        })]
        [string]
        $Path
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTermStudentsBody = @{
             task = 'getTermStudents';
             access_key = $PopuliAuthkey;
             return_image_data = $ReturnImageData;
        }
        if ($PSBoundParameters.ContainsKey('TermId')) {
            Write-Verbose -Message "Adding TermId $TermId to request string."
            $GetTermStudentsBody.Add('term_id', $TermId)
        }
        if ($PSBoundParameters.ContainsKey('CampusId')) {
            Write-Verbose -Message "Adding CampusId $CampusId to request string."
            $GetTermStudentsBody.Add('campus_id', $CampusId)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTermStudentsBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTermStudents."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Students = foreach ($Student in $Response.response.student){
                        [pscustomobject] @{
                            'PersonId' = $Student.person_id
                            'StudentId' = $Student.student_id
                            'FirstName' = $Student.first
                            'LastName' = $Student.last
                            'MiddleName' = $Student.middle_name
                            'PreferredName' = $Student.preferred_name
                            'UserName' = $Student.username
                            'Prefix' = $Student.prefix
                            'Suffix' =$Student.suffix
                            'FormerName' = $Student.former_name
                            'Gender' = $Student.gender
                            'BirthDate' = $Student.birth_date
                            'ProgramId' = $Student.program_id
                            'ProgramName' = $Student.program_name
                            'Standing' = $Student.standing
                            'Degree' = $Student.standing
                            'FullTime' = $Student.full_time
                            'UnitsAttempted' = $Student.units_attempted
                            'UnitsGranted' = $Student.units_granted
                            'TermGpa' = $Student.term_gpa
                            'CumUnitsGranted' = $Student.cum_units_granted
                            'CumGpa' = $Student.cum_gpa
                            'CumGpaIncludingTransfer' = $Student.cum_gpa_including_transfer
                        }
                    } #END:foreach

                    if ($PSBoundParameters.ContainsKey('Path')) {

                        foreach ($Image in $Response.response.student){
                            Write-Verbose -Message "Creating filename using Lastname_Firstname_PersonId.jpg"
                            $FileName = ($Image.last) + "_" + ($Image.first) + "_" + ($Image.person_id) + ".jpg"
                            Write-Verbose "Updating the path to include filename."
                            $FilePath = Join-Path -Path $Path -ChildPath $FileName
                            Write-Verbose -Message "Checking if file exists."
                                if (Test-Path $FilePath.trim()) {
                                    Write-Warning -Message "$FilePath --> File already exists. File not saved."
                                    break
                                }
                                else {
                                    Write-Verbose -Message "Writing file $FileName."
                                    $bytes = [Convert]::FromBase64String($Image.image)
                                    [IO.File]::WriteAllBytes($FilePath, $bytes)
                                    Write-Verbose -Message "File saved to $FilePath."
                                }
                        }

                    } #END:if

                    Write-Output $Students

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch

    } #END:process

    end {
        Write-Verbose -Message "Get-PTermStudents cmdlet finished."
    }

} #END: Get-PTermStudents
function Get-PTodos {
<#
.SYNOPSIS
  Returns todos for the current user.
 
.DESCRIPTION
  All times are returned in your school's local timezone.
  Right now <attached_to_type> will always be PERSON - in future, you may be able to attach todos to organizations, etc.
  There is a limit of 200 results in the response.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER Completed
  Possible values: NO (default), YES, or BOTH. Whether you'd like to see completed todos, uncompleted todos, or all todos.
 
.OUTPUTS
  Returns PowerShell objects:
    TodoId
    DueDate
    Overdue
    AssignedTo
    AssignedBy
    AttachedTo
    CompletedTime
    AddedTime
    Content
    AssignedToName
    AssignedByName
    AttachedToName
    AttachedToType
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 09/04/2019
 
.EXAMPLE
  Get-PTodos -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PTodos @PopuliCredentials -Completed BOTH
#>

#>
[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter()]
        [ValidateSet("NO","YES","BOTH")]
        [String]
        $Completed
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTodosBody = @{
             task = 'getTodos';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('Completed')) {
            Write-Verbose -Message "Adding Completed $Completed to request string."
            $GetTodosBody.Add('completed', $Completed)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetTodosBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTodos."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Todos = foreach ($Todo in $Response.response.todo) {
                        Write-Verbose -Message "Converting $($todo.todoid)"
                        [pscustomobject]@{
                            TodoId = $Todo.todoid
                            DueDate = $Todo.due_date
                            Overdue = $Todo.overdue
                            AssignedTo = $Todo.assigned_to
                            AssignedBy = $Todo.assigned_by
                            AttachedTo = $Todo.attached_to
                            CompletedTime = $Todo.completed_time
                            AddedTime = $Todo.added_time
                            Content = $Todo.content
                            AssignedToName = $Todo.assigned_to_name
                            AssignedByName = $Todo.assigned_by_name
                            AttachedToName = $Todo.attached_to_name
                            AttachedToType = $Todo.attached_to_type
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Todos
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PTodos cmdlet finished."
    }

} #END: Get-PTodos
function Get-PUpdatedPeople {
<#
.SYNOPSIS
  Returns all people who have had information changed since StartTime.
 
.DESCRIPTION
  This is useful if you want to sync Populi users to a directory service, etc.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  For more information check the Populi API reference. This parameter is required.
 
.PARAMETER StartTime
  Return all people with updated info since this second. Format should be a local timestamp like "2010-11-06 13:27:10".
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    FirstName
    LastName
    PreferredName
    MiddleName
    Prefix
    Suffix
    FormerName
    MaidenName
    Gender
    BirthDate
    Status
    IsActiveUser (returns 1 or 0)
    UserName
    UpdatedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/11/2019
 
.EXAMPLE
  Get-PUpdatedPeople -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -StartTime (Get-Date).AddDays(-1)
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Get-PUpdatedPeople @PopuliCredentials -StartDate (Get-Date)
#>

#>
[CmdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   HelpMessage="Enter date in format yyyy-mm-dd HH:mm:ss.",
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [DateTime]
        $StartTime
    )
    process {
        Write-Verbose -Message "Building request string with parameter data."
        $StartTime.ToString("yyyy-MM-dd HH:mm:ss") | Out-Null
        $GetUpdatedPeopleBody = @{
            task = 'getUpdatedPeople';
            start_time = $StartTime;
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetUpdatedPeopleBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PUpdatedPeople."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $People = foreach ($Person in $Response.response.person) {
                        Write-Verbose -Message "Converting $($Person.id)"
                        [pscustomobject] @{
                            'PersonId' = $Person.id
                            'FirstName' = $Person.first_name
                            'LastName' = $Person.last_name
                            'PreferredName' = $Person.preferred_name
                            'MiddleName' = $Person.middle_name
                            'Prefix' = $Person.prefix
                            'Suffix' = $Person.suffix
                            'FormerName' = $Person.former_name
                            'MaidenName' = $Person.maiden_name
                            'Gender' = $Person.gender
                            'BirthDate' = $Person.birth_date
                            'Status' = $Person.status
                            'IsActiveUser' = $Person.is_active_user
                            'UserName' = $Person.user_name
                            'UpdatedAt' = $Person.updated_at
                        }
                    }#END:foreach
                    Write-Output $People
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PUpdatedPeople cmdlet finished."
    }

} #END: Get-PUpdatedPeople
function Get-PUsers {
<#
.SYNOPSIS
  Returns all users.
 
.DESCRIPTION
  You must have the Staff role to call this task.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    FirstName
    LastName
    UserName
    Blocked (1=Yes / 0=No)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
 
.EXAMPLE
  Get-PUsers -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890'
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetUsersBody = @{
             task = 'getUsers';
             access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $GetUsersBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PUsers."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Users = foreach ($Person in $Response.response.person) {
                        Write-Verbose -Message "Converting $($Person.username)"
                        [pscustomobject]@{
                            PersonId = $Person.person_id
                            FirstName = $Person.first
                            LastName = $Person.last
                            UserName = $Person.username
                            Blocked = $Person.blocked
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Users
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PUsers cmdlet finished."
    }

} #END:Get-PUsers
function Remove-PAddress {
<#
.SYNOPSIS
  Deletes an address.
 
.DESCRIPTION
  The current user must have the Staff role or else be deleting an email address on his/her own profile.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER AddressId
  Numeric ID of the address.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/30/2019
 
.EXAMPLE
  Remove-PAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -AddressId 4567834
#>

[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $AddressId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $DeleteAddressBody = @{
             task = 'deleteAddress';
             access_key = $PopuliAuthkey;
             addressid = $AddressId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will delete the address with AddressId $AddressId", "Delete Address")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $DeleteAddressBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveAddress= [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemoveAddress = "Remove action terminated by user."
            }

            Write-Output $RemoveAddress
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Remove-PAddress cmdlet finished."
    }

} #END:Remove-PAddress
function Remove-PEmailAddress {
<#
.SYNOPSIS
  Deletes an email address.
 
.DESCRIPTION
  The current user must have the Staff role or else be deleting an email address on his/her own profile.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER EmailId
  Numeric ID of the email address.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/30/2019
 
.EXAMPLE
  Remove-PEmailAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -EmailId
#>

[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $EmailId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $DeleteEmailAddressBody = @{
             task = 'deleteEmailAddress';
             access_key = $PopuliAuthkey;
             emailid = $EmailId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will delete the email address with EmailId $EmailId", "Delete Email Address")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $DeleteEmailAddressBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PEmailAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveEmailAddress= [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemoveEmailAddress = "Remove action terminated by user."
            }

            Write-Output $RemoveEmailAddress
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Remove-PEmailAddress cmdlet finished."
    }

} #END:Remove-PEmailAddress
function Remove-PPhoneNumber {
<#
.SYNOPSIS
  Deletes a phone number.
 
.DESCRIPTION
  The current user must have the Staff role or else be deleting an email address on his/her own profile.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PhoneId
  Numeric ID of the phone number.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/30/2019
 
.EXAMPLE
  Remove-PPhoneNumber -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PhoneId 1869988
#>

[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PhoneId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $DeletePhoneNumberBody = @{
             task = 'deletePhoneNumber';
             access_key = $PopuliAuthkey;
             phoneid = $PhoneId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will delete the phone number with PhoneId $PhoneId", "Delete Phone Number")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $DeletePhoneNumberBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PPhoneNumber."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemovePhoneNumber= [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemovePhoneNumber = "Remove action terminated by user."
            }

            Write-Output $RemovePhoneNumber
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Remove-PPhoneNumber cmdlet finished."
    }

} #END:Remove-PPhoneNumber
function Remove-PRole {
<#
.SYNOPSIS
 Removes a role from a person.
 
.DESCRIPTION
  Unfortunately, at this time the Student role cannot be added/removed through the API. The current user must have the Staff role and permission to
  remove the role (this varies by role... so Academic Admins can remove the Registrar role, Admissions Admins can remove the Admission role, etc).
  See Get-PAvailableRoles to look up all possible roles and their numeric IDs.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person you're interested in.
  This parameter is required.
 
.PARAMETER RoleId
  The numeric ID of the role you want to remove.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
  Updated: 04/30/2019
 
.EXAMPLE
  Remove-PRole -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId 7857760 -RoleId 3
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Remove-PRole @PopuliCredentials -PersonId 7857760 -RoleId 3
#>

[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [Parameter(Mandatory)]
        [int]
        $RoleId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $RemoveRoleBody = @{
             task = 'removeRole';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
             role_id = $RoleId
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will remove RoleId $RoleId from PersonId $PersonId", "Remove Role")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $RemoveRoleBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PRole."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveRole = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemoveRole = "Remove action terminated by user."
            }

            Write-Output $RemoveRole
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Remove-PRole cmdlet finished."
    }

} #END: Remove-PRole
function Remove-PTag {
<#
.SYNOPSIS
  Removes a tag from a particular person.
 
.DESCRIPTION
  Removes a tag from a particular person using the given parameters. Review the parameters for specific requirements
  and settings. The tag_id or tag that you pass in must exist in Populi or a BAD_PARAMETER error will be thrown.
  However, this task will return SUCCESS even if the particular person doesn't have the particular tag - Populi will do nothing in that case.
  System tags cannot be removed by anyone other than Populi... so certain tags like "Expelled" are off-limits.
  To remove these tags, you'll need to take some action in Populi - the correct system tags will be removed as a byproduct of that action.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person whose tag should be removed.
  Required.
 
.PARAMETER TagId
  Numeric ID of the tag.
  This parameter is not required (but either TagId or TagName must be set)
 
.PARAMETER TagName
  The actual tag you want to be removed (e.g. "Do not call", or "Good reference").
  This parameter is not required (but either TagId or TagName must be set)
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/02/2019
  Updated: 04/30/2019
 
.EXAMPLE
  Remove-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId 7851234 -Tag "Test"
 
.EXAMPLE
  Remove-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7857760' -TagId '12345'
#>

[CmdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low',
               DefaultParameterSetName='ByTagName')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByTagId')]
      [Parameter(ParameterSetName='ByTagName')]
      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [Parameter(ParameterSetName='ByTagId',
                 Mandatory)]
      [int]
      $TagId,

      [Parameter(ParameterSetName='ByTagName',
                 Mandatory)]
      [string]
      $TagName
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $RemoveTagBody = @{
             task = 'removeTag';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }

        if ($PSBoundParameters.ContainsKey('TagId')) {
            Write-Verbose -Message "Adding TagId $TagId to request string."
            $RemoveTagBody.Add('tag_id', $TagId)
            $ShouldProcessParams += "TagId = $TagId"
        }
        if ($PSBoundParameters.ContainsKey('TagName')) {
            Write-Verbose -Message "Adding TagName $TagName to request string."
            $RemoveTagBody.Add('tag', $TagName)
            $ShouldProcessParams += "TagName = $TagName"
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will remove $ShouldProcessParams from PersonId $PersonId", "Remove Tag")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $RemoveTagBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PTag."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveTag = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemoveTag = "Remove action terminated by user."
            }

            Write-Output $RemoveTag
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch

    } #END:process

    end {
        Write-Verbose "Remove-PTag cmdlet finished."
    }

} #END: Remove-PTag
function Remove-PTodo {
<#
.SYNOPSIS
  Deletes a todo.
 
.DESCRIPTION
  *Remove was used instead of delete since it is the approved verb for powershell commands.
  This function can only be used on todos 1) assigned to the currently logged-in user,
  2) assigned by the currently logged-in user or
  3) public todos attached to somone's profile if the currently logged-in user has the Staff role.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER TodoId
  The numeric ID of the todo you're interested in.
  Use the Get-PTodos or the Add-PTodo cmdlet to get the TodoId.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 09/06/2019
 
.EXAMPLE
  Remove-PTodo -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TodoId '15940549'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Remove-PTodo @PopuliCredentials -TodoId '15940549'
#>


[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TodoId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $RemoveTodoBody = @{
             task = 'deleteTodo';
             access_key = $PopuliAuthkey;
             todo_id = $TodoId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will remove $ShouldProcessParams from Todo $TodoId", "Remove Todo")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $RemoveTodoBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PTodo."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveTodo = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }

                }
            }
            else {
                $RemoveTodo = "Remove action terminated by user."
            }

            Write-Output $RemoveTodo
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Remove-PTodo cmdlet finished."
    }

} #END: Remove-PTodo
function Remove-PUser {
<#
.SYNOPSIS
  Removes the user account from a person.
 
.DESCRIPTION
  Users with the Academic Admin role can remove any user account. Users with the Staff role can remove any user account except for users with
  the Academic Admin role. The user status of current Account Admins and Billing Contacts can't be edited.
  You cannot remove your user account.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person whose user account will be removed.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
  Updated: 04/30/2019
 
.EXAMPLE
  Remove-PUser -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId 7857760
#>

[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $RemoveUserBody = @{
             task = 'removeUser';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will remove the user account from PersonId $PersonId", "Remove User")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $RemoveUserBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Remove-PUser."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $RemoveUser = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }
            else {
                $RemoveUser = "Remove action terminated by user."
            }

            Write-Output $RemoveUser
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Remove-PUser cmdlet finished."
    }

} #END:Remove-PUser
function Request-PBackup {
<#
.SYNOPSIS
  Requests a backup of your Populi data, delivered as a ZIP file in CSV format.
  You can be notified by email when it's ready for download, or have an HTTP request made to another web application.
 
.DESCRIPTION
  The <BackupId> returned is the ID of the backup request (the same ID that will be passed to on_complete_url).
  See downloadBackup to download the backup after it's completed.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER OnCompleteEmail
  Where to send the "Backup Ready for Download" email.
 
.PARAMETER OnCompleteUrl
  If set, when the backup is ready for download we'll make an HTTP request to this URL, including the backup_id as a POST variable.
 
.OUTPUTS
  Returns PowerShell objects:
    BackupId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/07/2019
 
.EXAMPLE
  Request-PBackup -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -OnCompleteEmail "mtest@school.com"
 
.EXAMPLE
 #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Request-PBackup @PopuliCredentials
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [string]
        $PopuliAuthkey,

        [Parameter()]
        [mailaddress]
        $OnCompleteEmail,

        [Parameter()]
        [uri]
        $OnCompleteUrl
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $RequestBackupBody = @{
            task = 'requestBackup';
            access_key = $PopuliAuthkey;
        }

        if ($PSBoundParameters.ContainsKey('OnCompleteEmail')) {
            Write-Verbose -Message "Adding OnCompleteEmail $OnCompleteEmail to request string."
            $RequestBackupBody.Add('on_complete_email', $OnCompleteEmail)
        }
        if ($PSBoundParameters.ContainsKey('OnCompleteUrl')) {
            Write-Verbose -Message "Adding OnCompleteUrl $OnCompleteUrl to request string."
            $RequestBackupBody.Add('on_complete_url', $OnCompleteUrl)
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $RequestBackupBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Request-PBackup."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Backup = [pscustomobject] @{
                        'BackupId' = $Response.response.id
                    }
                    Write-Output $Backup
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose "Request-PBackup cmdlet finished."
    }

} #END:Request-PBackup
function Search-PPeople {
<#
.SYNOPSIS
  Looks up people by name, email, phone number, etc.
 
.DESCRIPTION
  Looks up people by name, email, phone number, etc. Metaphone matching is used to try to correct misspellings... so you can accidentally search
  for "Mervin Smith" and hopefully get Marvin Smith returned.
  Use Get-PPerson cmdlet to look up more detailed information about one of your search results.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.PARAMETER SearchTerm
  e.g. "Joe McStudent" or "208-111-2222" or "joe@mcstudent.edu"
  This parameter is required.
 
.PARAMETER Limit
  The maximum number of matches you'd like returned - defaults to 5.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    FirstName
    LastName
    MiddleName
    PreferredName
    IsUser (Returns 0 or 1)
    PrimaryEmail
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/07/2019
 
.EXAMPLE
  Search-PPeople -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -SearchTerm "Matthew Test"
 
.EXAMPLE
 #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Search-PPeople @PopuliCredentials -SearchTerm "Matthew Test" -Limit 1
#>

[CMdletBinding()]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Position=1,
                   Mandatory)]
        [string]
        $PopuliAuthkey,

        [parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [string]
        $SearchTerm,

        [int]
        $Limit = 5
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $SearchPeopleBody = @{
            task = 'searchPeople';
            search_term = $SearchTerm
            limit = $Limit;
            access_key = $PopuliAuthkey;
        }

        try {
            Write-Verbose -Message "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $SearchPeopleBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Search-PPeople."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $People = foreach ($Person in $Response.response.person) {
                        Write-Verbose -Message "Converting $($Person.id)"
                        [pscustomobject] @{
                            'PersonId' = $Person.id
                            'FirstName' = $Person.first_name
                            'LastName' = $Person.last_name
                            'MiddleName' = $Person.middle_name
                            'PreferredName' = $Person.preferred_name
                            'IsUser'= $Person.is_user
                            'PrimaryEmail' = $Person.primary_email
                        }
                    }
                    Write-Output $People
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }

     } #END:Process

     end {
         Write-Verbose -Message "Search-PPeople cmdlet finished."
     }

} #END: Search-PPeople
function Set-PTodoCompleted {
<#
.SYNOPSIS
  Marks a todo completed or not completed.
 
.DESCRIPTION
  This function can only be used on todos assigned to the currently logged-in user.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER TodoId
  The numeric ID of the todo you're interested in.
  Use the Get-PTodos or the Add-PTodo cmdlet to return the TodoId.
  This parameter is required.
 
.PARAMETER Completed
  Possible values: 1 (default) or 0. Whether the todo should be marked completed.
  1 = Completed / 0 = Not Completed
 
.OUTPUTS
  Returns PowerShell objects:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 09/04/2019
 
.EXAMPLE
  Set-PTodoCompleted -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -TodoId '15940549'
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Set-PTodoCompleted @PopuliCredentials -TodoId '15940549' -Completed 1
#>


[CMdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low')]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TodoId,

        [Parameter()]
        [ValidateSet("1","0")]
        [int]
        $Completed

    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $SetTodoCompletedBody = @{
             task = 'setTodoCompleted';
             access_key = $PopuliAuthkey;
             todo_id = $TodoId;
        }
        if ($PSBoundParameters.ContainsKey('Completed')) {
            Write-Verbose -Message "Adding Completed $Completed to to request string."
            $SetTodoCompletedBody.Add('completed', $Completed)
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will set Todo with Id $TodoId as completed", "Set-TodoCompleted")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $SetTodoCompletedBody -ErrorAction Stop

                if ($Response.error) {
                     Write-Verbose -Message "Error returned from Populi while executing Set-PTodoCompleted."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $SetTodoCompleted = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }
            }

            else {
                $SetTodoCompleted = "Set-PTodoCompleted was terminated by user."
            }

            Write-Output $SetTodoCompleted

        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
         Write-Verbose -Message "Set-PTodoCompleted cmdlet finished."
    }

} #END: Set-PTodoCompleted
function Unblock-PUser {
<#
.SYNOPSIS
  Used to unblock a particular user account.
 
.DESCRIPTION
  Users with the Academic Admin role can unblock anyone. Users with the Staff role can unblock anyone except for users with the Academic Admin role.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  This parameter is required.
 
.PARAMETER PersonId
  Numeric ID of the person whose user account will be unblocked.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    Result = SUCCESS (or FAILURE)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/15/2019
 
.EXAMPLE
  Unblock-PUser -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -PersonId 7857760
 
.EXAMPLE
  #Store your Populi Credentials in a hash table:
  $PopuliCredentials = @{
  PopuliURI = https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/
  PopuliAuthkey = '1ReallyLongAlphaNumericSequence'
  }
  Unblock-PUser @PopuliCredentials -PersonId 7857760
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [Parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $UnblockUserBody = @{
             task = 'unblockUser';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $UnblockUserBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Unblock-PUser."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $UnblockUser = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $UnblockUser
                }
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:process

    end {
        Write-Verbose "Unblock-PUser cmdlet finished."
    }

} #END:Unblock-PUser
function Update-PAddress {
<#
.SYNOPSIS
  Updates an address.
 
.DESCRIPTION
  Updates an address using the given parameters. Review the parameters for specific requirements
  and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be updating an email address on his/her own profile.
  This parameter is required.
 
.PARAMETER AddressId
  Numeric ID of the address. Required.
 
.PARAMETER Street
  e.g. 777 Magnolia Ln
 
.PARAMETER City
  e.g. Moscow
 
.PARAMETER State
  e.g. ID
 
.PARAMETER Postal
  e.g. 83843
 
.PARAMETER Country
  e.g. USA
 
.PARAMETER AddressType (Person AddressId)
  HOME, WORK, BILLING, SCHOOL, SHIPPING OTHER.
 
.PARAMETER OrgAddressType (Organization AddressId)
  MAIN, BILLING, SHIPPING, OTHER.
 
.PARAMETER Primary
  Use if you want to mark the email address as primary or not primary. e.g. 1 or 0
 
.PARAMETER Old
  Use if you want to mark the email address as old or not old. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the email address as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/30/2019
 
.EXAMPLE
  #Update address with a person address id.
  Update-PAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -AddressId '7781234' -Address '123 Main St.' -AddressType BILLING
 
.EXAMPLE
  #Update address with an organizational address id.
  Update-PAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -AddressId '2265253' -OrgAddressType BILLING
#>

[CmdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low',
               DefaultParameterSetName='ByAddressType')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $AddressId,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [string]
      $Street,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [string]
      $City,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [string]
      $State,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [string]
      $Postal,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [string]
      $Country,


      [Parameter(ParameterSetName='ByAddressType')]
      [ValidateSet("HOME","WORK","BILLING","SCHOOL","SHIPPING","OTHER")]
      [string]
      $AddressType,

      [Parameter(ParameterSetName='ByOrgAddressType')]
      [ValidateSet("MAIN","BILLING","SHIPPING","OTHER")]
      [string]
      $OrgAddressType,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [ValidateSet("1","0")]
      [int]
      $Old,

      [Parameter(ParameterSetName='ByAddressType')]
      [Parameter(ParameterSetName='ByOrgAddressType')]
      [Parameter()]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $UpdateAddressBody = @{
             task = 'updateAddress';
             access_key = $PopuliAuthkey;
             addressid = $AddressId;
        }
        if ($PSBoundParameters.ContainsKey('Street')) {
            Write-Verbose -Message "Adding Street $Street to request string."
            $UpdateAddressBody.Add('street', $Street)
            $ShouldProcessParams += "street = $Street"
        }
        if ($PSBoundParameters.ContainsKey('City')) {
            Write-Verbose -Message "Adding City $City to request string."
            $UpdateAddressBody.Add('city', $City)
            $ShouldProcessParams += ", city = $City"
        }
        if ($PSBoundParameters.ContainsKey('State')) {
            Write-Verbose -Message "Adding State $State to request string."
            $UpdateAddressBody.Add('state', $State)
            $ShouldProcessParams += ", state = $State"
        }
        if ($PSBoundParameters.ContainsKey('Postal')) {
            Write-Verbose -Message "Adding Postal $Postal to request string."
            $UpdateAddressBody.Add('postal', $Postal)
            $ShouldProcessParams += ", postal = $Postal"
        }
        if ($PSBoundParameters.ContainsKey('Country')) {
            Write-Verbose -Message "Adding Country $Country to request string."
            $UpdateAddressBody.Add('country', $Country)
            $ShouldProcessParams += ", country = $Country"
        }
        if ($PSBoundParameters.ContainsKey('AddressType')) {
            Write-Verbose -Message "Adding Type $AddressType to request string."
            $UpdateAddressBody.Add('type', $AddressType)
            $ShouldProcessParams += ", AddressType = $AddressType"
        }
        if ($PSBoundParameters.ContainsKey('OrgAddressType')) {
            Write-Verbose -Message "Adding OrgAddressType $OrgAddressType to request string."
            $UpdateAddressBody.Add('type', $OrgAddressType)
            $ShouldProcessParams += ", OrgAddressType = $OrgAddressType"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary to request string."
            $UpdateAddressBody.Add('primary', $Primary)
            $ShouldProcessParams += ", Primary = $Primary"
        }
        if ($PSBoundParameters.ContainsKey('Old')) {
            Write-Verbose -Message "Adding old $Old to request string."
            $UpdateAddressBody.Add('old', $Old)
            $ShouldProcessParams += ", Old = $Old"
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public to request string."
            $UpdateAddressBody.Add('public', $Public)
            $ShouldProcessParams += ", Public = $Public"
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will update address id $AddressId with parameters $ShouldProcessParams", "Update Address")) {
                Write-Verbose "Sending request to Populi ..."
                $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $UpdateAddressBody -ErrorAction Stop

                if ($Response.error) {
                   Write-Verbose -Message "Error returned from Populi while executing Update-PAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Return result as PowerShell objects."
                    $UpdateAddress = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }

            }
            else {
                $UpdateAddress = "Update action terminated by user."
            }

            Write-Output $UpdateAddress
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose "Update-PAddress cmdlet finished."
    }

} #END: Update-PAddress
function Update-PEmailAddress {
<#
.SYNOPSIS
  Updates an email address.
 
.DESCRIPTION
  Updates an email address using the given parameters. Review the parameters for specific requirements and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be updating an email address on his/her own profile.
  This parameter is required.
 
.PARAMETER EmailId
  Numeric ID of the email address. Required.
 
.PARAMETER EMailAddress
  e.g. bob@example.com
 
.PARAMETER EmailType (Person EmailId)
  HOME, WORK, SCHOOL, OTHER.
 
.PARAMETER OrgEmailType (Organization EmailId)
  WORK, OTHER.
 
.PARAMETER Primary
  Use if you want to mark the email address as primary or not primary. e.g. 1 or 0
 
.PARAMETER Old
  Use if you want to mark the email address as old or not old. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the email address as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/17/2018
  Updated: 11/06/2019
 
.EXAMPLE
  #Update email address with a person email id.
  Update-PEmailAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -EmailId '7781234' -EmailAddress 'bob@school.edu' -EmailType SCHOOL
 
.EXAMPLE
  #Update email address with an organizational email id.
  Update-PEmailAddress -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -EmailId '2265253' -EmailAddress 'org@school.edu' -OrgEmailType WORK
#>

[CmdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low',
               DefaultParameterSetName='ByEmailType')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByEmailType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $EmailId,

      [Parameter(ParameterSetName='ByEmailType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter()]
      [mailaddress]
      $EmailAddress,

      [Parameter(ParameterSetName='ByEmailType')]
      [ValidateSet("HOME","WORK","SCHOOL","OTHER")]
      [string]
      $EmailType,

      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("WORK","OTHER")]
      [string]
      $OrgEmailType,

      [Parameter(ParameterSetName='ByEmailType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByEmailType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("1","0")]
      [int]
      $Old,

      [Parameter(ParameterSetName='ByEmailType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter()]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose "Building request string with parameter data.."
        $UpdateEmailAddressBody = @{
             task = 'updateEmailAddress';
             access_key = $PopuliAuthkey;
             emailid = $EmailId;
        }
        if ($PSBoundParameters.ContainsKey('EmailAddress')) {
            Write-Verbose -Message "Adding EmailAddress $EmailAddress to request string."
            $UpdateEmailAddressBody.Add('email_address', $EmailAddress)
            $ShouldProcessParams += "EmailAddress = $EmailAddress"
        }
        if ($PSBoundParameters.ContainsKey('EmailType')) {
            Write-Verbose -Message "Adding Type $Type to request string."
            $UpdateEmailAddressBody.Add('type', $EmailType)
            $ShouldProcessParams += ", EmailType = $EmailType"
        }
        if ($PSBoundParameters.ContainsKey('OrgEmailType')) {
            Write-Verbose -Message "Adding OrgEmailType $OrgEmailType to request string."
            $UpdateEmailAddressBody.Add('type', $OrgEmailType)
            $ShouldProcessParams += ", OrgEmailType = $OrgEmailType"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary to request string."
            $UpdateEmailAddressBody.Add('primary', $Primary)
            $ShouldProcessParams += ", Primary = $Primary"
        }
        if ($PSBoundParameters.ContainsKey('Old')) {
            Write-Verbose -Message "Adding old $Old to request string."
            $UpdateEmailAddressBody.Add('old', $Old)
            $ShouldProcessParams += ", Old = $Old"
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public to request string."
            $UpdateEmailAddressBody.Add('public', $Public)
            $ShouldProcessParams += ", Public = $Public"
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will update email address id $EmailId with parameters $ShouldProcessParams", "Update Email Address")) {
                Write-Verbose "Sending request to Populi ..."
                $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $UpdateEmailAddressBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Update-PEmailAddress."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $UpdateEmailAddress = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }

            }
            else {
                $UpdateEmailAddress = "Update action terminated by user."
            }

            Write-Output $UpdateEmailAddress
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose "Update-PEmailAddress cmdlet finished."
    }

} #END: Update-PEmailAddress
function Update-PPhoneNumber {
<#
.SYNOPSIS
  Updates a phone number.
 
.DESCRIPTION
  Updates a phone number using the given parameters. Review the parameters for specific requirements
  and settings.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  The current user must have the Staff role or else be updating an email address on his/her own profile.
  This parameter is required.
 
.PARAMETER PhoneId
  Numeric ID of the phone number.
  This parameter is required.
 
.PARAMETER PhoneNumber
  e.g. 1-800-888-8888
 
.PARAMETER PhoneType (Person PhoneId)
  HOME, WORK, MOBILE, SCHOOL, FAX, OTHER.
 
.PARAMETER OrgPhoneType (Organization PhoneId)
  WORK, FAX, OTHER.
 
.PARAMETER Primary
  Use if you want to mark the phone number as primary or not primary. e.g. 1 or 0
 
.PARAMETER Old
  Use if you want to mark the phone number as old or not old. e.g. 1 or 0
 
.PARAMETER Public
  Use if you want to mark the phone number as public or not public. e.g. 1 or 0
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/25/2019
 
.EXAMPLE
  #Update phone number with a person phone id.
  Update-PPhoneNumber -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PhoneId '7781234' -PhoneNumber '1-800-888-8888' -PhoneType SCHOOL
 
.EXAMPLE
  #Update phone number with an organizational phone id.
  Update-PPhoneNumber -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PhoneId '2261234' -PhoneNumber '1-800-888-8888' -PhoneType FAX
#>

[CmdletBinding(SupportsShouldProcess,
               ConfirmImpact='Low',
               DefaultParameterSetName='ByPhoneType')]
    param (
      [Parameter(Position=0,
                 Mandatory)]
      [string]
      $PopuliUri,

      [Parameter(Position=1,
                 Mandatory)]
      [string]
      $PopuliAuthkey,

      [Parameter(ParameterSetName='ByPhoneType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter(Mandatory,
                 ValueFromPipeline,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PhoneId,

      [Parameter(ParameterSetName='ByPhoneType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter()]
      [string]
      $PhoneNumber,

      [Parameter(ParameterSetName='ByPhoneType')]
      [ValidateSet("HOME","WORK","MOBILE","SCHOOL","FAX","OTHER")]
      [string]
      $PhoneType,

      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("WORK","FAX","OTHER")]
      [string]
      $OrgPhoneType,

      [Parameter(ParameterSetName='ByPhoneType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("1","0")]
      [int]
      $Primary,

      [Parameter(ParameterSetName='ByPhoneType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [ValidateSet("1","0")]
      [int]
      $Old,

      [Parameter(ParameterSetName='ByPhoneType')]
      [Parameter(ParameterSetName='ByOrganizationType')]
      [Parameter()]
      [ValidateSet("1","0")]
      [int]
      $Public
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $UpdatePhoneNumberBody = @{
             task = 'updatePhoneNumber';
             access_key = $PopuliAuthkey;
             phoneid = $PhoneId;
        }
        if ($PSBoundParameters.ContainsKey('PhoneNumber')) {
            Write-Verbose -Message "Adding Phone Number $PhoneNumber to request string."
            $UpdatePhoneNumberBody.Add('phone_number', $PhoneNumber)
            $ShouldProcessParams += "PhoneNumber = $PhoneNumber"
        }
        if ($PSBoundParameters.ContainsKey('PhoneType')) {
            Write-Verbose -Message "Adding PhoneType $PhoneType to request string."
            $UpdatePhoneNumberBody.Add('type', $PhoneType)
            $ShouldProcessParams += ", PhoneType = $PhoneType"
        }
        if ($PSBoundParameters.ContainsKey('OrgPhoneType')) {
            Write-Verbose -Message "Adding OrgPhoneType $OrgPhoneType request string."
            $UpdatePhoneNumberBody.Add('type', $OrgPhoneType)
            $ShouldProcessParams += ", OrgPhoneType = $OrgPhoneType"
        }
        if ($PSBoundParameters.ContainsKey('Primary')) {
            Write-Verbose -Message "Adding Primary $Primary request string."
            $UpdatePhoneNumberBody.Add('primary', $Primary)
            $ShouldProcessParams += ", Primary = $Primary"
        }
        if ($PSBoundParameters.ContainsKey('Old')) {
            Write-Verbose -Message "Adding old $Old request string."
            $UpdatePhoneNumberBody.Add('old', $Old)
            $ShouldProcessParams += ", Old = $Old"
        }
        if ($PSBoundParameters.ContainsKey('Public')) {
            Write-Verbose -Message "Adding Public $Public request string."
            $UpdatePhoneNumberBody.Add('public', $Public)
            $ShouldProcessParams += ", Public = $Public"
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will update phone number id $PhoneId with parameters $ShouldProcessParams", "Update Phone Number")) {
                Write-Verbose "Sending request to Populi ..."
                $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $UpdatePhoneNumberBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PAllCustomFields."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $UpdatePhoneNumber = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                }

            }
            else {
                $UpdatePhoneNumber = "Update action terminated by user."
            }

            Write-Output $UpdatePhoneNumber
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }# END:try/Catch
    } #END:Process

    end {
        Write-Verbose "UPdate-PPhoneNumber cmdlet finished."
    }

} #END: Update-PPhoneNumber
function Upload-PFile {
<#
.SYNOPSIS
  Uploads a file for a particular person.
 
.DESCRIPTION
  You must have the Staff role to call this task.
  Returns the FileId on success.
  The RoleIds parameter will not be used for custom info fields.
  If no role_ids are passed in we will default to the user's "Default activity feed visibility" setting.
  If you pass in CustomFieldId you will not need to call Set-PCustomField, we will set the field for you.
 
.PARAMETER PopuliUri
  Set to the correct URL for your college (i.e. https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/).
  This parameter is required.
 
.PARAMETER PopuliAuthKey
  The authentication key with necessary permissions for the data you are requesting.
  You must have the Staff role to call this task. This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person.
  This parameter is required.
 
.PARAMETER Filepath
  Path of file to be uploaded. Enter the full path, inculding the filename.
  This parameter is required.
 
.PARAMETER CustomFieldId
  If passed in, the file will be uploaded to the given custom info field.
  You can get the CustomFieldId you want by running Get-PAllCustomField or Get-PCustomFields.
 
.PARAMETER TermId
  The numeric ID of the term you're interested in.
  (Must be set for TERM_STUDENT custom fields.)
 
.PARAMETER RoleIds
  An array of role IDs - the file will be visible to people with these role IDs.
 
.OUTPUTS
  Returns PowerShell objects:
    FileId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 10/03/2019
 
.EXAMPLE
  Upload-PFile @populicredentials -PersonId '7857760' -FilePath "c:\test\test.pdf"
 
.EXAMPLE
  Upload-PFile @populicredentials -PersonId '7857760' -FilePath "c:\test\test.pdf" -CustomFieldId '189607'
#>

[CMdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]
        $PopuliUri,

        [Parameter(Mandatory)]
        [String]
        $PopuliAuthkey,

        [parameter(Mandatory,
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $PersonId,

        [Parameter(Mandatory)]
        [ValidateScript({
            if(-Not ($_ | Test-Path -PathType Leaf)) {
                throw "File and/or folder does not exist. The Path argument must include the file to be uploaded."
            }
            return $True
        })]
        [string]
        $FilePath,

        [Parameter()]
        [int]
        $CustomFieldId,

        [Parameter()]
        [int]
        $TermId,

        [Parameter()]
        [int]
        $RoleIds
    )

    process {
        Write-Verbose -Message "Extracting FileName from FilePath parameter."
        $FileName = (Split-Path -Path $FilePath -Leaf)
        $LF = "`r`n"
        Write-Verbose -Message "Reading file ..."
        $ReadFile = [System.IO.File]::ReadAllBytes($FilePath)
        Write-Verbose -Message "Encoding file ..."
        $Enc = [System.Text.Encoding]::GetEncoding("iso-8859-1")
        $FileEnc = $Enc.GetString($ReadFile)
        $Boundary = [System.Guid]::NewGuid().ToString()

        Write-Verbose -Message "Building multipart/form-data for request string."
        $UploadFileBody =
            "--$Boundary$LF" +
            "Content-Disposition: form-data; name=`"file`"; filename=`"$FileName`"$LF" +
            "Content-Type: 'multipart/form-data'$LF$LF" +
            "$FileEnc$LF" +

            "--$Boundary$LF" +
            "Content-Disposition: form-data; name=`"access_key`"$LF" +
            "Content-Type: 'multipart/form-data'$LF$LF" +
            "$PopuliAuthkey$LF" +

            "--$Boundary$LF" +
            "Content-Disposition: form-data; name=`"task`"$LF" +
            "Content-Type: 'multipart/form-data'$LF$LF" +
            "uploadFile$LF" +

            "--$Boundary$LF" +
            "Content-Disposition: form-data; name=`"person_id`"$LF" +
            "Content-Type: 'multipart/form-data'$LF$LF" +
            "$PersonId$LF"
        Write-Verbose -Message "Adding data to request string."
        switch($PSBoundParameters.Keys) {
        'CustomFieldId' {$UploadFileBody +=
                          ("--$Boundary$LF" +
                           "Content-Disposition: form-data; name=`"custom_field_id`"$LF" +
                           "Content-Type: 'multipart/form-data'$LF$LF" +
                           "$CustomFieldId$LF")}
        'TermId'        {$UploadFileBody +=
                          ("--$Boundary$LF" +
                           "Content-Disposition: form-data; name=`"term_id`"$LF" +
                           "Content-Type: 'multipart/form-data'$LF$LF" +
                           "$TermId$LF")}
        'RoleIds'       {$UploadFileBody +=
                          ("--$Boundary$LF" +
                           "Content-Disposition: form-data; name=`"role_ids`"$LF" +
                           "Content-Type: 'multipart/form-data'$LF$LF" +
                           "$RoleIds")}
         }

         $UploadFileBody += "--$Boundary--$LF"

         try {
             Write-Verbose "Sending request to Populi ..."
             $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -ContentType "multipart/form-data; boundary=`"$Boundary`"" -Body $UploadFileBody -ErrorAction Stop

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Upload-PFile."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $UploadFile = [pscustomobject] @{
                        'FileId' = $Response.response.result
                    }

                    Write-Output $UploadFile

                } #END:else
        }
        catch {
            Write-Verbose -Message "Error returned from the Invoke-RestMethod command or while processing output."
            Write-Warning "ERROR: $($_.Exception.GetType().FullName)"
        }
    } #END:process

    end {
        Write-Verbose -Message "Upload-PFile cmdlet finished."
    }

} #END: Upload-PFile