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-PCourseOfferingLink {
<#
.SYNOPSIS
  Adds a link to a particular course offering.
 
.DESCRIPTION
  You must have the Academic Admin role, the Registrar role, or be a course teacher to call this task (and the course must not be finalized).
 
.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 CourseOfferingId
  The numeric ID of the course offering you're interested in. ("instanceid"/"instance_id" = "course_offering_id")
  This parameter is required.
 
.PARAMETER Name
  The name of the link.
  This parameter is required.
 
.PARAMETER Url
  The URL for the link.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    LinkId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/18/2019
 
.EXAMPLE
  Add-PCourseOfferingLink -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -CourseOfferingId 9636721 -Name "Google" -Url "https://www.google.com
#>

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

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

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

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

        [Parameter(Mandatory)]
        [uri]
        $Url
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddCourseOfferingLinkBody = @{
             task = 'addCourseOfferingLink';
             access_key = $PopuliAuthkey;
             course_offering_id = $CourseOfferingId;
             name = $Name;
             url = $Url;
        }

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

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

                } #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 "Add-PCourseOfferingLink cmdlet finished."
    }

} #END: Add-PCourseOfferingLink
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-PFieldOfStudy {
<#
.SYNOPSIS
  Adds a field of study to a person.
 
.DESCRIPTION
  You must have the Staff role to call this task.
  Private fields of study are only visible to Faculty/Staff/Advisors.
 
.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 OrganizationId
  The numeric ID of the organization.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person.
  This parameter is required.
 
.PARAMETER Name
  The name of the field of study.
 
.PARAMETER StartDate
  Format should be a date like "2020-09-05".
 
.PARAMETER EndDate
  Format should be a date like "2024-05-07".
 
.PARAMETER IsPrivate
  Boolean. Defaults to the "Make relationships between people and organizations private by default" security setting.
  (1 = Yes, 0 = No)
 
.PARAMETER CanShowOnTranscript
  Boolean. Defaults to true.
  (1 = Yes, 0 = No)
 
.OUTPUTS
  Returns PowerShell object:
    Result = SUCCESS (or FAILURE)
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/27/2020
 
.EXAMPLE
  Add-PFieldOfStudy -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '386' -PersonId '40783'
 
.EXAMPLE
  Add-PFieldOfStudy -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '386' -PersonId '40783' -Name "Example Field Of Study" -StartDate 2020-01-02 -EndDate 2020-05-15 -IsPrivate 0 -CanShowOnTranscript 1
 
#>

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

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

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

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

      [Parameter()]
      [string]
      $Name,

      [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]
      $StartDate,

      [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]
      $EndDate,

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddFieldOfStudyBody = @{
             task = 'addFieldOfStudy';
             access_key = $PopuliAuthkey;
             organization_id = $OrganizationId;
             person_id = $PersonId;
        }
        if ($PSBoundParameters.ContainsKey('Name')) {
            Write-Verbose -Message "Adding Name $Name to request string."
            $AddFieldOfStudyBody.Add('name', $Name)
        }
        if ($PSBoundParameters.ContainsKey('StartDate')) {
            Write-Verbose -Message "Adding Start Date $StartDate to request string."
            $AddFieldOfStudyBody.Add('start_date', $StartDate)
        }
        if ($PSBoundParameters.ContainsKey('EndDate')) {
            Write-Verbose -Message "Adding End Date $EndDate to request string."
            $AddFieldOfStudyBody.Add('end_date', $EndDate)
        }
        if ($PSBoundParameters.ContainsKey('IsPrivate')) {
            Write-Verbose -Message "Adding IsPrivate $IsPrivate to request string."
            $AddFieldOfStudyBody.Add('is_private', $IsPrivate)
        }
        if ($PSBoundParameters.ContainsKey('CanShowOnTranscript')) {
            Write-Verbose -Message "Adding CanShowOnTranscript $CanShowOnTranscript to request string."
            $AddFieldOfStudyBody.Add('can_show_on_transcript', $CanShowOnTranscript)
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-PFieldOfStudy."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $AddFieldOfStudy = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $AddFieldOfStudy
                }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Add-PFieldOfStudy: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        }# END:try/Catch
    } #END:Process

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

}  #END: Add-PFieldOfStudy
function Add-POrganization {
<#
.SYNOPSIS
  Adds a new organization into Populi.
 
.DESCRIPTION
  You must have the Staff role to call this task.
  See Get-POrganizationTypes for "TypeId" options.
  See Add-PPhoneNumber, Add-PEmailAddress, Add-PAddress if you'd like to add contact information to your new organization.
  See Add-PTag if you'd like to tag your new organization.
 
.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 Name
  The name of the organization.
  This parameter is required.
 
.PARAMETER TypeId
  The numeric ID of the type.
 
.OUTPUTS
  Returns PowerShell object:
    OrganizationId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/27/2020
 
.EXAMPLE
  Add-POrganization -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -Name 'Test Organization'
#>

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

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

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

      [parameter()]
      [int]
      $TypeId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddOrganizationBody = @{
             task = 'addOrganization';
             access_key = $PopuliAuthkey;
             name = $Name;
        }
        if ($PSBoundParameters.ContainsKey('TypeId')) {
            Write-Verbose -Message "Adding TypeId $TypeId to request string."
            $AddOrganizationBody.Add('type_id', $TypeId)
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Add-POrganization."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $OrganizationId = [pscustomobject] @{
                       'OrganizationId' = $Response.response.id
                    }
                    Write-Output $OrganizationId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Add-POrganization: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        }# END:try/Catch
    } #END:Process

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

}  #END: Add-POrganization
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 or organization.
 
.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 is not required (but either person_id or organization_id must be set).
 
.PARAMETER OrganizationId
  The numeric ID of the organization that should be tagged.
  This parameter is not required (but either person_id or organization_id must be set).
 
.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
  Updated Date: 04/26/2020
 
.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 "MPRTest"
 
.EXAMPLE
  Add-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -TagId '12345'
 
.EXAMPLE
  Add-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -TagName 'MPRTest'
 
#>

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

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

      [Parameter(ParameterSetName='ByPersonIdTagId')]
      [Parameter(ParameterSetName='ByPersonIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [Parameter(ParameterSetName='ByOrgIdTagId')]
      [Parameter(ParameterSetName='ByOrgIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

      [Parameter(ParameterSetName='ByPersonIdTagId')]
      [Parameter(ParameterSetName='ByOrgIdTagId',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $TagId,

      [Parameter(ParameterSetName='ByPersonIdTagName')]
      [Parameter(ParameterSetName='ByOrgIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [string]
      $TagName
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddTagBody = @{
             task = 'addTag';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $AddTagBody.Add('person_id', $PersonId)
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to request string."
            $AddTagBody.Add('organization_id', $OrganizationId)
        }
        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 Add-PTransferCredit {
<#
.SYNOPSIS
  Adds a transfer credit to a person.
 
.DESCRIPTION
  You must have the Admissions Admin, Admissions, Academic Admin, or Registrar role to call this task.
  Transfer Institutions will automatically be created.
  applies_to_all_programs = true will automatically apply the transfer credit to the student's program(s).
  To enter program grade information see addTransferCreditProgram.
  effective_date is the date after which the transfer credit may be counted as a retake.
  Defaults to the "Transfer Credit Default Effective Date" academic setting.
 
.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 OrganizationId
  The numeric ID of the organization.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person.
  This parameter is required.
 
.PARAMETER CourseNumber
  This parameter is required.
 
.PARAMETER CourseName
  This parameter is required.
 
.PARAMETER Credits
  This parameter is not required (but either credits, hours, clinical_hours, or attendance_hours must be set).
 
.PARAMETER Hours
  This parameter is not required (but either credits, hours, clinical_hours, or attendance_hours must be set).
 
.PARAMETER ClinicalHours
  This parameter is not required (but either credits, hours, clinical_hours, or attendance_hours must be set).
 
.PARAMETER AttendanceHours
  This parameter is not required (but either credits, hours, clinical_hours, or attendance_hours must be set).
 
.PARAMETER FulfillsProgramRequirements
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER PassAffectsGpa
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER FailAffectsGpa
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER PassFailPassAffectsGpa
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER PassFailFailAffectsGpa
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER AffectsStanding
  Defaults to Yes. (1 = Yes, 0 = No)
 
.PARAMETER CatalogCourseId
  The numeric ID of the catalog course.
  This parameter is not required (but either catalog_course_id or course_group_id must be set).
 
.PARAMETER CourseGroupId
  The numeric ID of the course group.
  This parameter is not required (but either catalog_course_id or course_group_id must be set).
 
.PARAMETER Description
  Test field to enter a short description about the transfer credit.
 
.PARAMETER Status
  PENDING (default), ACCEPTED, or REJECTED
  This parameter is not required (you must have the Academic Admin or Registrar role to set a transfer credit to APPROVED or REJECTED).
 
.PARAMETER EffectiveDate
  Format should be a date like "2020-09-05".
  May only be set when status is APPROVED.
 
.PARAMETER AppliesToAllPrograms
  Defaults to Yes. (1 = Yes, 0 = No)
  If it equals true the transfer credit will automatically apply to the student�s program(s).
  Similar to the process of adding a transfer credit from the GUI, you can select Programs: ALL, which will attach the transfer credit
  to each of the students program's (in the event they have more than one).
  Note that the transfer credit > program won�t get a grade, but it will apply to the student�s program(s).
  To enter program grade info see Add-PTransferCreditProgram. If you have grade information for a transfer credit you should pass in
  applies_to_all_programs=0 and use Add-PTransferCreditProgram.
 
.OUTPUTS
  Returns PowerShell object:
    TransferCreditId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/27/2020
 
.EXAMPLE
  Add-PTransferCredit @PopuliCredentials -OrganizationalId 386 -PersonId 40783 -CourseNumber "CS100" -CourseName "Intro To Computers" -Credits 3 -CatalogCourseId 4045
#>

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

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

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

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

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [string]
      $CourseNumber,

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [string]
      $CourseName,

      [Parameter()]
      [int]
      $Credits,

      [Parameter()]
      [int]
      $Hours,

      [Parameter()]
      [int]
      $ClinicalHours,

      [Parameter()]
      [int]
      $AttendanceHours,

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

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

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

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

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

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

      [Parameter()]
      [int]
      $CatalogCourseId,

      [Parameter()]
      [int]
      $CourseGroupId,

      [Parameter()]
      [string]
      $Description,

      [Parameter()]
      [ValidateSet("PENDING","APPROVED","REJECTED")]
      [string]
      $Status,

      [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]
      $EffectiveDate,

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddTransferCreditBody = @{
             task = 'addTransferCredit';
             access_key = $PopuliAuthkey;
             organization_id = $OrganizationId;
             person_id = $PersonId;
             course_number = $CourseNumber;
             course_name = $CourseName;
        }
        if ($PSBoundParameters.ContainsKey('Credits')) {
            Write-Verbose -Message "Adding Credits $Credits to request string."
            $AddTransferCreditBody.Add('credits', $Credits)
        }
        if ($PSBoundParameters.ContainsKey('Hours')) {
            Write-Verbose -Message "Adding Hours $Hours to request string."
            $AddTransferCreditBody.Add('hours', $Hours)
        }
        if ($PSBoundParameters.ContainsKey('ClinicalHours')) {
            Write-Verbose -Message "Adding ClinicalHours $ClinicalHours to request string."
            $AddTransferCreditBody.Add('clinical_hours', $ClinicalHours)
        }
        if ($PSBoundParameters.ContainsKey('AttendanceHours')) {
            Write-Verbose -Message "Adding AttendanceHours $AttendanceHours to request string."
            $AddTransferCreditBody.Add('attendance_hours', $AttendanceHours)
        }
        if ($PSBoundParameters.ContainsKey('FulfillsProgramRequirements')) {
            Write-Verbose -Message "Adding FulfillsProgramRequirements $FulfillsProgramRequirements to request string."
            $AddTransferCreditBody.Add('fulfills_program_requirements', $FulfillsProgramRequirements)
        }
        if ($PSBoundParameters.ContainsKey('PassAffectsGpa')) {
            Write-Verbose -Message "Adding PassAffectsGpa $PassAffectsGpa to request string."
            $AddTransferCreditBody.Add('pass_affects_gpa', $PassAffectsGpa)
        }
        if ($PSBoundParameters.ContainsKey('FailAffectsGpa')) {
            Write-Verbose -Message "Adding FailAffectsGpa $FailAffectsGpa to request string."
            $AddTransferCreditBody.Add('fail_affects_gpa', $FailAffectsGpa)
        }
        if ($PSBoundParameters.ContainsKey('PassFailPassAffectsGpa')) {
            Write-Verbose -Message "Adding PassFailPassAffectsGpa $PassFailPassAffectsGpa to request string."
            $AddTransferCreditBody.Add('pass_fail_pass_affects_gpa', $PassFailPassAffectsGpa)
        }
        if ($PSBoundParameters.ContainsKey('PassFailFailAffectsGpa')) {
            Write-Verbose -Message "Adding PassFailFailAffectsGpa $PassFailfailAffectsGpa to request string."
            $AddTransferCreditBody.Add('pass_fail_fail_affects_gpa', $PassFailFailAffectsGpa)
        }
        if ($PSBoundParameters.ContainsKey('AffectsStanding')) {
            Write-Verbose -Message "Adding AffectsStanding $AffectsStanding to request string."
            $AddTransferCreditBody.Add('affects_standing', $AffectsStanding)
        }
        if ($PSBoundParameters.ContainsKey('CatalogCourseId')) {
            Write-Verbose -Message "Adding CatalogCourseId $CatalogCourseId to request string."
            $AddTransferCreditBody.Add('catalog_course_id', $CatalogCourseId)
        }
        if ($PSBoundParameters.ContainsKey('CourseGroupId')) {
            Write-Verbose -Message "Adding CourseGroupId $CourseGroupId to request string."
            $AddTransferCreditBody.Add('course_group_id', $CourseGroupId)
        }
        if ($PSBoundParameters.ContainsKey('Description')) {
            Write-Verbose -Message "Adding Description $Description to request string."
            $AddTransferCreditBody.Add('description', $Description)
        }
        if ($PSBoundParameters.ContainsKey('Status')) {
            Write-Verbose -Message "Adding Status $Status to request string."
            $AddTransferCreditBody.Add('status', $Status)
        }
        if ($PSBoundParameters.ContainsKey('EffectiveDate')) {
            Write-Verbose -Message "Adding EffectiveDate $EffectiveDate to request string."
            $AddTransferCreditBody.Add('effective_date', $EffectiveDate)
        }
        if ($PSBoundParameters.ContainsKey('AppliesToAllPrograms')) {
            Write-Verbose -Message "Adding AppliesToAllPrograms $AppliesToAllPrograms to request string."
            $AddTransferCreditBody.Add('applies_to_all_programs', $AppliesToAllPrograms)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddTransferCreditBody -ErrorAction Stop
                if ($Response.error) {
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Verbose -Message "Error returned from Populi while executing Add-PTransferCredit: $($PError)"
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $TransferCreditId = [pscustomobject] @{
                        'TransferCreditId' = $Response.response.id
                    }
                    Write-Output $TransferCreditId
                }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Add-PTransferCredit: $($_.ErrorDetails.Message)"
            Write-Warning $($_.ErrorDetails.Message)
        }# END:try/Catch
    } #END:Process

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

}  #END: Add-PTransferCredit
function Add-PTransferCreditProgram {
<#
.SYNOPSIS
  Adds a program to a transfer credit.
 
.DESCRIPTION
  You must have the Admissions Admin, Admissions, 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.
  This parameter is required.
 
.PARAMETER TransferCreditId
  The numeric ID of the transfer credit you're interested in.
  The TransferCreditId is returned from Add-PTransferCredit cmdlet.
  This parameter is required.
 
.PARAMETER ProgramId
  The numeric ID of the program you're interested in.
  This parameter is required.
 
.PARAMETER Grade
  Mixed. Use Get-PTransferCreditProgramGradeOptions to get a list of values.
 
.PARAMETER PassFail
  Whether or not this the grade is a pass/fail grade. Defaults to false.
  Not required (but must be passed in if the grade parameter is numeric).
  (1 = Yes, 0 = No)
 
.PARAMETER ShowOnTranscript
  Boolean. Defaults to true. Whether or not the transfer credit should show up on the transcript. Only used when the transfer credit's status = APPROVED.
  (1 = Yes, 0 = No)
 
.PARAMETER IsTransferStudent
  Whether or not the student is considered a transfer student in the particular program. Only used when the transfer credit's status = APPROVED.
  (1 = Yes, 0 = No)
 
.OUTPUTS
  Returns PowerShell object:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/27/2020
 
.EXAMPLE
  Add-PTransferCreditProgram -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -TransferCreditId 3746 -ProgramId 1783
 
.EXAMPLE
  Add-PTransferCreditProgram -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -TransferCreditId 3746 -ProgramId 1783 -Grade "A" -PassFail 0
 
#>

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

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

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $TransferCreditId,

      [Parameter(Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $ProgramId,

      [Parameter()]
      [string]
      $Grade,

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $AddTransferCreditProgramBody = @{
             task = 'addTransferCreditProgram';
             access_key = $PopuliAuthkey;
             transfer_credit_id = $TransferCreditId;
             program_id = $ProgramId;
        }
        if ($PSBoundParameters.ContainsKey('Grade')) {
            Write-Verbose -Message "Adding Grade $Grade to request string."
            $AddTransferCreditProgramBody.Add('grade', $Grade)
        }
        if ($PSBoundParameters.ContainsKey('PassFail')) {
            Write-Verbose -Message "Adding PassFail $PassFail to request string."
            $AddTransferCreditProgramBody.Add('pass_fail', $PassFail)
        }
        if ($PSBoundParameters.ContainsKey('ShowOnTranscript')) {
            Write-Verbose -Message "Adding ShowOnTranscript $ShowOnTranscript to request string."
            $AddTransferCreditProgramBody.Add('show_on_transcript', $ShowOnTranscript)
        }
        if ($PSBoundParameters.ContainsKey('IsTransferStudent')) {
            Write-Verbose -Message "Adding IsTransferStudent $IsTransferStudent to request string."
            $AddTransferCreditProgramBody.Add('is_transfer_student', $IsTransferStudent)
        }

        try {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $AddTransferCreditProgramBody -ErrorAction Stop
                if ($Response.error) {
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Verbose -Message "Error returned from Populi while executing Add-PTransferCreditProgram: $($PError)"
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Result = [pscustomobject] @{
                        'Result' = $Response.response.result
                    }
                    Write-Output $Result
                }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Add-PTransferCreditProgram: $($_.ErrorDetails.Message)"
            Write-Warning $($_.ErrorDetails.Message)
        }# END:try/Catch

    } #END:Process

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

}  #END: Add-PTransferCreditProgram
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"
#>

[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. Please enter a valid path."
            }
            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 -ErrorAction Stop

                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-PAcademicYears {
<#
.SYNOPSIS
  Returns all academic year IDs, as well as calendar years associated with each.
 
.DESCRIPTION
 
.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.
 
.OUTPUTS
  Returns PowerShell objects:
    YearId
    StartYear
    EndYear
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/23/2019
 
.EXAMPLE
  Get-PAcademicYears -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."
        $GetAcademicYearsBody = @{
                task = 'getAcademicYears';
                access_key = $PopuliAuthkey;
        }

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

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

                    $Years = foreach ($Year in $Response.response.academic_year) {
                        [pscustomobject]@{
                            YearId = $Year.yearid
                            StartYear = $Year.start_year
                            EndYear = $Year.end_year
                        }
                    } #END:foreach

                    Write-Output $Years

                } #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-PAcademicYears cmdlet finished."
     }

} #END:Get-PAcademicYears
function Get-PAidApplication {
<#
.SYNOPSIS
  Returns a particular financial aid application (each student can have one per aid year).
 
.DESCRIPTION
  You must have one of these roles to call this task: Financial Aid, Student Billing, or Financial Admin.
  See Get-PFinancialAidDisbursments cmdlet for AidApplicationId
 
.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 AidApplicationId
  The numeric ID of the aid application.
  See Get-PFinancialAidDisbursments cmdlet for AidApplicationId.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    AidApplicationId
    StudentId
    AidYearId
    AidYearName
    AssignedToId
    AssignedToName
    Dependency
    StudentAidClassId
    StudentAidClassName
    ProgramMonths
    Enrollment
    YearCOA
    ProgramCOA
    YearEFC
    ProgramEFC
    StudentAGI
    ParentsAGI
    AutoZeroEFC
    FisapTotalIncome
    LegalResidenceState
    Need
    Housing
    Status
    Verification
    VerificationStatus
    VerificationGroup
    VerificationExemptReason
    AddedById
    AddedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/23/2019
 
.EXAMPLE
  Get-PAidApplication -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -AidApplicationId
 
.EXAMPLE
   Get-PFinancialAidDisbursements @PopuliCredentials -AidYearId 44 -Type DISBURSEMENT | Select-Object -Property AidApplicationId | Get-PAidApplication @PopuliCredentials
#>

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetAidApplicationBody = @{
                task = 'getAidApplication';
                aid_application_id = $AidApplicationId
                access_key = $PopuliAuthkey;
        }

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

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

                    $AidApplication = foreach ($Application in $Response.response.aid_application) {
                        [pscustomobject]@{
                            AidApplicationId = $Application.id
                            StudentId = $Application.student_id
                            AidYearId = $Application.aid_year_id
                            AidYearName = $Application.aid_year_name
                            AssignedToId = $Application.assigned_to_id
                            AssignedToName = $Application.assigned_to_name
                            Dependency = $Application.dependency
                            StudentAidClassId = $Application.student_aid_class_id
                            StudentAidClassName = $Application.student_aid_class_name
                            ProgramMonths = $Application.program_months
                            Enrollment = $Application.enrollment
                            YearCOA = $Application.year_coa
                            ProgramCOA = $Application.program_coa
                            YearEFC = $Application.year_efc
                            ProgramEFC = $Application.program_efc
                            StudentAGI = $Application.student_agi
                            ParentsAGI = $Application.parents_agi
                            AutoZeroEFC = $Application.auto_zero_efc
                            FisapTotalIncome = $Application.fisap_total_income
                            LegalResidenceState = $Application.legal_residence_state
                            Need = $Application.need
                            Housing = $Application.housing
                            Status = $Application.status
                            Verification = $Application.verification
                            VerificationStatus = $Application.verification_status
                            VerificationGroup = $Application.verification_group
                            VerificationExemptReason = $Application.verification_exempt_reason
                            AddedById = $Application.added_by_id
                            AddedAt = $Application.added_at
                        }
                    } #END:foreach

                    Write-Output $AidApplication

                } #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-PAidApplication cmdlet finished."
     }

} #END:Get-PAidApplication
function Get-PAidApplicationForStudentAidYear {
<#
.SYNOPSIS
  Returns a particular financial aid application (each student can have one per aid year).
 
.DESCRIPTION
  You must have one of these roles to call this task: Financial Aid, Student Billing, or Financial Admin.
  See Get-PFinancialAidYears cmdlet for AidYearId
 
.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 StudentId
  The numeric ID of the student. (StudentId and PersonId are different identifiers.)
  This parameter is required.
 
.PARAMETER AidYearId
  The numeric ID of the aid year.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    AidApplicationId
    StudentId
    AidYearId
    AidYearName
    AssignedToId
    AssignedToName
    Dependency
    StudentAidClassId
    StudentAidClassName
    ProgramMonths
    Enrollment
    YearCOA
    ProgramCOA
    YearEFC
    ProgramEFC
    StudentAGI
    ParentsAGI
    AutoZeroEFC
    FisapTotalIncome
    LegalResidenceState
    Need
    Housing
    Status
    Verification
    VerificationStatus
    VerificationGroup
    VerificationExemptReason
    AddedById
    AddedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/24/2019
 
.EXAMPLE
  Get-PAidApplicationForStudentAidYear -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -StudentId 2017000043 -AidYearId 44
#>

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

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetAidApplicationForStudentAidYearBody = @{
                task = 'getAidApplicationForStudentAidYear';
                student_id = $StudentId;
                aid_year_id = $AidYearId;
                access_key = $PopuliAuthkey;
        }

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

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

                    $AidApplication = foreach ($Application in $Response.response.aid_application) {
                        [pscustomobject]@{
                            AidApplicationId = $Application.id
                            StudentId = $Application.student_id
                            AidYearId = $Application.aid_year_id
                            AidYearName = $Application.aid_year_name
                            AssignedToId = $Application.assigned_to_id
                            AssignedToName = $Application.assigned_to_name
                            Dependency = $Application.dependency
                            StudentAidClassId = $Application.student_aid_class_id
                            StudentAidClassName = $Application.student_aid_class_name
                            ProgramMonths = $Application.program_months
                            Enrollment = $Application.enrollment
                            YearCOA = $Application.year_coa
                            ProgramCOA = $Application.program_coa
                            YearEFC = $Application.year_efc
                            ProgramEFC = $Application.program_efc
                            StudentAGI = $Application.student_agi
                            ParentsAGI = $Application.parents_agi
                            AutoZeroEFC = $Application.auto_zero_efc
                            FisapTotalIncome = $Application.fisap_total_income
                            LegalResidenceState = $Application.legal_residence_state
                            Need = $Application.need
                            Housing = $Application.housing
                            Status = $Application.status
                            Verification = $Application.verification
                            VerificationStatus = $Application.verification_status
                            VerificationGroup = $Application.verification_group
                            VerificationExemptReason = $Application.verification_exempt_reason
                            AddedById = $Application.added_by_id
                            AddedAt = $Application.added_at
                        }
                    } #END:foreach

                    Write-Output $AidApplication

                } #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-PAidApplicationForStudentAidYear cmdlet finished."
     }

} #END:Get-PAidApplicationForStudentAidYear
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 Status
  Possible values: IN_PROGRESS, SUBMITTED, PENDING_DECISION, ACCEPTED, DECLINED, WITHDRAWN, DEFERRED, or WAITLISTED.
 
.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 LeadActive
  Boolean. 1 or 0.
 
.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
    TermId
    TermName
    ExpectedEnrollment
    FullTime
    StartedOn
    SubmittedAt
    DecisionOn
    WithdrawnOn
    AppliedDate
    SubmittedDate
    DecisionDate
    WithdrawnDate
    SubmittedType
    Provisional
    ProvisionalComment
    FeeStatus
    FeeId
    FeeAmount
    FeePayment
    SalesReceiptId
    TransactionId
    ApplicantActivityAt
    NumDaysSinceLastActivity
    StaffActivityAt
    PercentCompleted
    Status
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 07/15/2019
  Updated: 01/29/2020
 
.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='ByStatus')]
    param (
        [Parameter(Position=0,
                   Mandatory)]
        [string]
        $PopuliUri,

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

        [Parameter(ParameterSetName='ByStatus')]
        [ValidateSet("IN_PROGRESS","SUBMITTED","PENDING_DECISION","ACCEPTED","DECLINED","WITHDRAWN","DEFERRED","WAITLISTED")]
        [string]
        $Status,

        [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='ByStatus')]
        [Parameter(ParameterSetName='ByDateField',
                   ValueFromPipeline,
                   ValueFromPipelineByPropertyName)]
        [int]
        $TermId,

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

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

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

        [Parameter(ParameterSetName='ByStatus')]
        [Parameter(ParameterSetName='ByDateField')]
        [ValidateSet("1","0")]
        [int]
        $LeadActive,

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetApplicationsBody = @{
            task = 'getApplications';
            access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('Status')) {
            Write-Verbose -Message "Adding Status $Status to request string."
            $GetApplicationsBody.Add('status', $Status)
        }
        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('LeadActive')) {
            Write-Verbose -Message "Adding LeadActive $LeadActive to request string."
            $GetApplicationsBody.Add('lead_active', $LeadActive)
        }
        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
                            'TermId' = $Application.term_id
                            'TermName' = $Application.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
                            'AppliedDate' = $Application.applied_date
                            'SubmittedDate' = $Application.submitted_date
                            'DecisionDate' = $Application.decision_date
                            'WithdrawnDate' = $Application.withdrawn_date
                            'SubmittedType' = $Application.submitted_type
                            'Provisional' = $Application.provisional
                            'ProvisionalComment' = $Application.provisional_comment
                            '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' = [int]$Application.num_days_since_last_activity
                            'StaffActivityAt' = $Application.staff_activity_at
                            'PercentCompleted' = $Application.percent_completed
                            'Status' = $Application.status
                        }
                    }#END:foreach
                    Write-Verbose -Message "Getting total number of results. Will only return 200."
                    $NumResults = [pscustomobject] @{
                        'num_results' = $Response.response.num_results
                    }
                    $Applications += $NumResults
                    Write-Output $Applications
               }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Add-PApplications: $($_.ErrorDetails.Message)"
            Write-Warning $($_.ErrorDetails.Message)
        }
    } #END:process

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

} #END:Get-PApplications
function Get-PAssignmentComments {
<#
.SYNOPSIS
  Returns assignment comments for a particular assignment and person.
 
.DESCRIPTION
  You must have the Academic Admin role, the Registrar role, or be a course Faculty member 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 AssignmentId
  Numeric ID of the assignment.
  This parameter is required.
 
.PARAMETER PersonId
 
.OUTPUTS
  Returns PowerShell objects:
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/07/2020
 
.EXAMPLE
  Get-PAssignmentComments -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -AssignmentId 21213169 -PersonId 13080374
#>

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

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

        [Parameter(Mandatory,
                   ValueFromPipelineByPropertyName)]
        [int]
        $AssignmentId,

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

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

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PAssignmentComments."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                } #END:if
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Comments = foreach ($Comment in $Response.response.comment) {
                        [pscustomobject] @{
                            'CommentId' = $Comment.id
                            'Comment' = $Comment.comment
                            'FileId' = $Comment.file_id
                            'FileName' = $Comment.file_name
                            'Internal' = $Comment.internal
                            'AddedAt' = $Comment.added_at
                            'AddedById' = $Comment.added_by_id
                            'AddedByName' = $Comment.added_by_name
                        }
                    }#END:foreach

                    Write-Output $Comments

                } #END:else

        } #END:try
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Get-PAssignmentComments: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        }

     } #END:Process

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

} #END:Get-PAssignmentComments
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-PCourseGroups {
<#
.SYNOPSIS
  Returns a list of course groups.
 
.DESCRIPTION
 
.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
  You must have the Academic Admin, Registrar, or Academic Auditor role to call this task.
  For more information check the Populi API reference.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    CourseGroupId
    Abbreviation
    Name
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/28/2019
 
.EXAMPLE
  Get-PCourseGroups -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."
        $GetCourseGroupsBody = @{
                task = 'getCourseGroups';
                access_key = $PopuliAuthkey;
        }

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

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

                    $Groups = foreach ($Group in $Response.response.course_groups.course_group) {
                        [pscustomobject]@{
                            GroupId = $Group.id
                            Abbrv = $Group.abbreviation
                            Name = $Group.name
                        }
                    }

                    Write-Output $Groups

                } #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-PCourseGroups cmdlet finished."
     }

} #END:Get-PCourseGroups
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-PCourseInstanceAssignmentGroups {
<#
.SYNOPSIS
  Returns information about each assignment group.
 
.DESCRIPTION
  Assignment groups are worth a fixed percentage of the course (e.g. Quizzes are worth 10% of each student's final grade),
  and you can then add as many assignments within the Quizzes group as you like, or even add new assignments to the group
  part-way through the term, and be guaranteed that the value of all those assignments together will still equal 10% of
  the course.
  Even if no assignment groups are set up, a default assignment group of "Other" with a <groupid> of 0 will always be returned
  (and worth 100% of the course).
 
.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:
    GroupId
    Name
    WeightPercent
    ExtraCredit
    DropLowest
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/23/2019
 
.EXAMPLE
  Get-PCourseInstanceAssignmentGroups -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070
#>

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

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

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

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

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

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

                    $Groups = foreach ($Group in $Response.response.assignment_group) {
                        [pscustomobject]@{
                            GroupId = $Group.groupid
                            Name = $Group.name
                            WeightPercent = $Group.weight_percent
                            ExtraCredit = $Group.extra_credit
                            DropLowest = $Group.drop_lowest
                        }
                    } #END:foreach

                    Write-Output $Groups

                } #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-PCourseInstanceAssignmentGroups cmdlet finished."
     }

} #END:Get-PCourseInstanceAssignmentGroups
function Get-PCourseInstanceAssignments {
<#
.SYNOPSIS
  Returns information about each assignment in a course - including which Assignment Group it belongs to.
 
.DESCRIPTION
  Every assignment is attached to an Assignment Group - even if it's only the default "Other" group (which has a groupid of 0).
  The "student_info" data will only be returned if you have the Academic Admin role, the Registrar role, or you are a course Faculty member.
 
.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:
    AssignmentId
    Name
    Points
    Type
    PercentOfCourse
    GroupId
    GroupName
    ExtraCredit
    Description
    DiscussionId
    VisibleToStudentsBeforeDue
    TimeDue
    StartWindow
    EndWindow
    TimeLimit
    RetakePolicy
    Retakes
    Proctored
    TestSubmitFeedback
    TestEndFeedback
    PersonId
    StudentId
    FirstName
    LastName
    PreferredName
    SubmitAssignmentData
    AssignmentSubmittedAt
    Grade
    LetterGrade
    GradeAddedAt
    GradeAddedById
    GradeUpdatedAt
    GradeUpdatedById
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/18/2019
 
.EXAMPLE
  Get-PCourseInstanceAssignments -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070
 
.EXAMPLE
  Get-PCourseInstanceAssignments @PopuliCredentials -InstanceId 9054956 | Select-Object -Property AssignmentId,Name,StudentId,Grade,LetterGrade
#>

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

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

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

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

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

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

                    $Data = [System.Collections.ArrayList]@()

                    foreach ($A in $Response.response.assignment) {
                        $AssignmentId = $A.assignmentid
                        $Name = $A.name
                        $Points = $A.points
                        $Type = $A.type
                        $PercentOfCourse = $A.percent_of_course
                        $GroupId = $A.groupid
                        $GroupName = $A.group_name
                        $ExtraCredit = $A.extra_credit
                        $Description = $A.description
                        $DiscussionId = $A.discussion_id
                        $VisibleToStudentsBeforeDue = $Assignment.visible_to_students_before_due
                        $TimeDue = $A.time_due
                        $StartWindow = $A.start_window
                        $EndWindow = $A.end_window
                        $TimeLimit = $A.time_limit
                        $RetakePolicy = $A.retake_policy
                        $Retakes = $A.retakes
                        $Proctored = $A.proctored
                        $TestSubmitFeedback = $A.test_submit_feedback
                        $TestEndFeedback = $A.test_end_feedback

                        ForEach ($Student in $A.student_info) {
                            $Object = [pscustomobject]@{
                                    AssignmentId = $AssignmentId
                                    Name = $Name
                                    Points = $Points
                                    Type = $Type
                                    PercentOfCourse = $PercentOfCourse
                                    GroupId = $GroupId
                                    GroupName = $GroupName
                                    ExtraCredit = $ExtraCredit
                                    Description = $Description
                                    DiscussionId = $DiscussionId
                                    VisibleToStudentsBeforeDue = $VisibleToStudentsBeforeDue
                                    TimeDue = $TimeDue
                                    StartWindow = $StartWindow
                                    EndWindow = $EndWindow
                                    TimeLimit = $TimeLimit
                                    RetakePolicy = $RetakePolicy
                                    Retakes = $Retakes
                                    Proctored = $Proctored
                                    TestSubmitFeedback = $TestSubmitFeedback
                                    TestEndFeedback = $TestEndFeedback
                                    PersonId = $Student.person_id
                                    StudentId = $Student.student_id
                                    FirstName = $Student.first_name
                                    LastName = $Student.last_name
                                    PreferredName = $Student.preferred_name
                                    SubmittedAssignmentData = $Student.submitted_assignment_data
                                    AssignmentSubmittedAt = $Student.assignment_submitted_at
                                    Grade = $Student.grade
                                    LetterGrade = $Student.letter_grade
                                    GradeAddedAt = $Student.grade_added_at
                                    GradeAddedById = $Student.grade_added_by_id
                                    GradeUpdatedAt = $Student.grade_updated_at
                                    GradeUpdateById = $Student.grade_updated_by_id
                                } #END:pscustomobject

                            [void]$Data.Add($Object)

                            } #END:foreach:Student

                    } #END:foreach:A

                    Write-Output $Data

                } #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-PCourseInstanceAssignments cmdlet finished."
     }

} #END:Get-PCourseInstanceAssignments
function Get-PCourseInstanceFiles {
<#
.SYNOPSIS
  Returns the files attached to a course instance.
 
.DESCRIPTION
  See Download-PFile for more information on usage of cmdlet.
 
.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:
    FileId
    Name
    ContentType
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/23/2019
 
.EXAMPLE
  Get-PCourseInstanceFiles -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070
#>

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

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

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

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

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

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

                    $Files = foreach ($File in $Response.response.file) {
                        [pscustomobject]@{
                            FileId = $File.file_id
                            Name = $File.name
                            ContentType = $File.content_type
                        }
                    } #END:foreach

                    Write-Output $Files

                } #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-PCourseInstanceFiles cmdlet finished."
     }

} #END:Get-PCourseInstanceFiles
function Get-PCourseInstanceLessons {
<#
.SYNOPSIS
  Returns the lessons attached to a course instance.
 
.DESCRIPTION
  See Get-PLessonContent to get the HTML content of each lesson.
 
.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:
    LessonId
    Name
    AvailableAt
    IsAvailable
    NumDiscussions
    NumNewPosts
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/19/2019
 
.EXAMPLE
  Get-PCourseInstanceLessons -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9054956
#>

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

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

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

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

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseInstanceLessons."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                } #END:if
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Lessons = foreach ($Lesson in $Response.response.lesson) {
                        [pscustomobject]@{
                            'LessonId' = $Lesson.lessonid
                            'Name' = $Lesson.name
                            'AvailableAt' = $Lesson.available_at
                            'IsAvailable' = $Lesson.is_available
                            'NumDiscussions' = $Lesson.num_discussions
                            'NumNewPosts' = $Lesson.num_new_posts
                        }
                    } #END:foreach
                } #END:else

            Write-Output $Lessons

        } #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-PCourseInstanceLessons cmdlet finished."
     }

} #END:Get-PCourseInstanceLessons
function Get-PCourseInstanceMeetingAttendance {
<#
.SYNOPSIS
  Gets attendance for a course instance meeting.
 
.DESCRIPTION
 
.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.
 
.PARAMETER MeetingId
  The numeric ID of the meeting.
  See Get-PCourseInstanceMeetings cmdlet on obtaining this parameter.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    Status
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/28/2019
 
.EXAMPLE
  Get-PCourseInstanceMeetingAttendance -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070 -MeetingId 13445977
#>

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

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCourseInstanceMeetingAttendanceBody = @{
                task = 'getCourseInstanceMeetingAttendance';
                instanceID = $InstanceId;
                meetingID = $MeetingId;
                access_key = $PopuliAuthkey;
        }

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

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

                    $Attendees = foreach ($Attendee in $Response.response.attendee) {
                        [pscustomobject]@{
                            PersonId = $Attendee.personid
                            Status = $Attendee.status
                        }

                    } #END:foreach

                    Write-Output $Attendees

                } #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-PCourseInstanceMeetingAttendance cmdlet finished."
     }

} #END:Get-PCourseInstanceMeetingAttendance
function Get-PCourseInstanceMeetings {
<#
.SYNOPSIS
  Returns the meetings attached to a course instance.
 
.DESCRIPTION
  If meetingid is 0 then no attendance has been taken for that meeting time.
 
.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:
    MeetingId
    RoomId
    RoomName
    StartDate
    EndDate
    CountsTowardAttendanceHours
    CountsTowardClinicalHours
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/28/2019
 
.EXAMPLE
  Get-PCourseInstanceMeetings -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070
#>

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

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

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

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

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

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

                    $Meetings = foreach ($Meeting in $Response.response.meeting) {
                        [pscustomobject]@{
                            MeetingId = $Meeting.meetingid
                            RoomId = $Meeting.roomid
                            RoomName = $Meeting.room_name
                            Start = $Meeting.start
                            End = $Meeting.end
                            CountsTowardAttendanceHours = $Meeting.counts_toward_attendance_hours
                            CountsTowardClinicalHours = $Meeting.counts_toward_clinical_hours
                        }

                    } #END:foreach

                    Write-Output $Meetings

                } #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-PCourseInstanceMeetings cmdlet finished."
     }

} #END:Get-PCourseInstanceMeetings
function Get-PCourseInstanceStudent {
<#
.SYNOPSIS
  Returns a single student from a course instance.
 
.DESCRIPTION
  Possible values for the Status object are: ENROLLED, AUDITOR, WITHDRAWN, or INCOMPLETE.
  Note that there are some additional elements returned if the student is ENROLLED: grade, letter_grade, and attendance
  (both grade and attendance are percentages: so 97 mean 97%).
  The StartDate object represents the day the student started his or her current status...
  so if Jerry enrolled in the course on April 1 but then switched to auditing on May 16, his Status would be AUDITOR
  and his StartDate would be May 16.
 
.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.
 
.PARAMETER PersonId
  The numeric ID of the student you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    Status
    FirstName
    LastName
    PreferredName
    StartDate
    Grade
    LetterGrade
    Attendance
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/24/2019
 
.EXAMPLE
  Get-PCourseInstanceStudent -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070 -PersonId 7758860
#>

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

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

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

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

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

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseInstanceStudent."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                } #END:if
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Student = [pscustomobject]@{
                        Status = $Response.response.status
                        FirstName = $Response.response.first
                        LastName = $Response.response.last
                        PreferredName = $Response.response.preferred
                        StartDate = $Response.response.start_date
                        Grade = $Response.response.grade
                        LetterGrade = $Response.response.letter_grade
                        Attendance = $Response.response.attendance
                    } #END:pscustomobject

                    Write-Output $Student

                } #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-PCourseInstanceStudent cmdlet finished."
     }

} #END:Get-PCourseInstanceStudent
function Get-PCourseInstanceStudentAttendance {
<#
.SYNOPSIS
  Gets attendance for all course instance meetings for a particular student.
 
.DESCRIPTION
  You must have edit access to the specified course instance 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 InstanceId
  The numeric ID of the course instance you're interested in.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the student you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    MeetingId
    Start
    End
    Summary
    Status
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/24/2019
 
.EXAMPLE
  Get-PCourseInstanceStudentAttendance -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070 -PersonId 7758860
#>

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

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

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

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

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

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseInstanceStudentAttendance."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                } #END:if
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Attendance = foreach ($Meeting in $Response.response.attendee) {
                        [pscustomobject]@{
                            PersonId = $PersonId
                            MeetingId = $Meeting.meetingid
                            Start = $Meeting.start
                            End = $Meeting.end
                            Summary = $Meeting.summary
                            Status = $Meeting.status
                        } #END:pscustomobject
                    } #END:foreach

                    Write-Output $Attendance

                } #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-PCourseInstanceStudentAttendance cmdlet finished."
     }

} #END:Get-PCourseInstanceStudentAttendance
function Get-PCourseInstanceStudents {
<#
.SYNOPSIS
  Returns all students enrolled, auditing, incomoplete, or withdrawn in a course instance.
 
.DESCRIPTION
  Possible values for the Status object are: ENROLLED, AUDITOR, WITHDRAWN, or INCOMPLETE.
  Note that there are some additional elements returned if the student is ENROLLED: grade, letter_grade, and attendance
  (both grade and attendance are percentages: so 97 mean 97%).
  The StartDate object represents the day the student started his or her current status...
  so if Jerry enrolled in the course on April 1 but then switched to auditing on May 16, his Status would be AUDITOR
  and his StartDate would be May 16.
 
.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:
    Status
    PersonId
    FirstName
    LastName
    PreferredName
    StartDate
    Grade
    LetterGrade
    Attendance
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/24/2019
 
.EXAMPLE
  Get-PCourseInstanceStudents -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -InstanceId 9055070
#>

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

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

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

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

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseInstanceStudents."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                } #END:if
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Students = foreach ($Student in $Response.response.courseinstance_student) {
                        [pscustomobject]@{
                            Status = $Student.status
                            PersonId = $Student.personid
                            FirstName = $Student.first
                            LastName = $Student.last
                            PreferredName = $Student.preferred
                            StartDate = $Student.start_date
                            Grade = $Student.grade
                            LetterGrade = $Student.letter_grade
                            Attendance = $Student.attendance
                        } #END:pscustomobject
                    } #END:foreach

                    Write-Output $Students

                } #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-PCourseInstanceStudents cmdlet finished."
     }

} #END:Get-PCourseInstanceStudents
function Get-PCourseOfferingLinks {
<#
.SYNOPSIS
  Returns links attached to a particular course offering.
 
.DESCRIPTION
 
.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 CourseOfferingId
  The numeric ID of the course offering you're interested in. ("instanceid"/"instance_id" = "course_offering_id")
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    LinkId
    Name
    Url
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/10/2019
 
.EXAMPLE
  Get-PCourseOfferingLinks -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -CourseInstanceId 9636721
#>

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetCourseOfferingLinksBody = @{
             task = 'getCourseOfferingLinks';
             access_key = $PopuliAuthkey;
             course_offering_id = $CourseOfferingId;
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PCourseOfferingLinks."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Links = foreach ($Link in $Response.response.links.link) {
                        Write-Verbose -Message "Converting $($Link.name)"
                        [pscustomobject]@{
                            LinkId = $Link.id
                            Name = $Link.name
                            Url = $Link.url
                        } #END:pscustomobject
                    } #END:foreach

                    Write-Output $Links

                } #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-PCourseOfferingLinks cmdlet finished."
    }

} #END: Get-PCourseOfferingLinks
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-PDataSlicerReports {
<#
.SYNOPSIS
 Returns a list of data slicer reports available for use.
 
.DESCRIPTION
  You must have the Academic Admin, Academic Auditor, or Registrar role to call this task.
  The ReportId of a data slicer report may be used to download it via the API using the Get-PDataSlicerReport cmdlet.
 
.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:
    ReportId
    ReportName
    AddedBy
    AddedByName
    AddedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 01/17/2020
 
.EXAMPLE
  Get-PDataSlicerReports -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."
        $GetDataSlicerReportsBody = @{
             task = 'getDataSlicerReports';
             access_key = $PopuliAuthkey;
        }

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

                if ($Response.error) {
                     Write-Verbose -Message "Error returned from Populi while executing Get-PDataSlicerReports."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Reports = foreach ($Report in $Response.response.report) {
                        Write-Verbose -Message "Converting $($Report.name)"
                        [pscustomobject]@{
                            ReportId = $Report.id
                            ReportName = $Report.name
                            AddedBy = $Report.added_by
                            AddedByName = $Report.added_by_name
                            AddedAt = $Report.added_at
                        } #END:pscustomobject
                    } #END:foreach
                    Write-Output $Reports
                } #END:else
        } #END:try
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Get-PDataSlicerReports: $($_.ErrorDetails.Message)"
            Write-Warning $($_.ErrorDetails.Message)
        }
    } #END:process

    end {
         Write-Verbose -Message "Get-PDataSlicerReports cmdlet finished."
    }
} #END:Get-PDataSlicerReports
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 file download begins.
  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-PGradeReport -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-PInquiries {
<#
.SYNOPSIS
  Returns all admissions inquiries matching the specified criteria.
 
.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.
  For more information check the Populi API reference.
  This parameter is required.
 
.PARAMETER StartDate
  The start date after which inquiries were received.
 
.PARAMETER EndDate
  The end date before which inquiries were received.
 
.PARAMETER Status
  The current status of the inquiries (e.g. WAITING_ON_US, WAITING_ON_THEM, CLOSED).
 
.PARAMETER ProgramId
  The numeric ID of the academic program associated with the inquiries.
 
.PARAMETER RepresentativeId
  The numeric ID of the representative associated with the inquiries.
 
.OUTPUTS
  Returns PowerShell objects:
    InquiryId
    PersonId
    LeadId
    FirstName
    MiddleName
    LastName
    Email
    Phone
    AddressId
    Subject
    Content
    ProgramId
    DegreeId
    SpecializationId
    AcademicTermId
    RepresentativeId
    AutoAssignedTo
    Status
    LeadSourceId
    LocalizationId
    AddedOn
    AddedBy
    AddedAt
    DeletedBy
    DeletedAt
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/24/2020
 
.EXAMPLE
#>

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

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

        [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]
        $StartDate,

        [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]
        $EndDate,

        [Parameter()]
        [ValidateSet("WAITING_ON_US","WAITING_ON_THEM","CLOSED")]
        [string]
        $Status,

        [Parameter()]
        [int]
        $ProgramId,

        [Parameter()]
        [int]
        $RepresentativeId
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetInquiriesBody = @{
            task = 'getInquiries';
            access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('StartDate')) {
            Write-Verbose -Message "Adding StartDate $StartDate to request string."
            $GetInquiriesBody.Add('start_date', $StartDate)
        }
        if ($PSBoundParameters.ContainsKey('EndDate')) {
            Write-Verbose -Message "Adding EndDate $EndDate to request string."
            $GetInquiriesBody.Add('end_date', $EndDate)
        }
        if ($PSBoundParameters.ContainsKey('Status')) {
            Write-Verbose -Message "Adding Status $Status to request string."
            $GetInquiriesBody.Add('status', $Status)
        }
        if ($PSBoundParameters.ContainsKey('ProgramId')) {
            Write-Verbose -Message "Adding ProgramId $ProgramId to request string."
            $GetInquiriesBody.Add('program_id', $ProgramId)
        }
        if ($PSBoundParameters.ContainsKey('RepresentativeId')) {
            Write-Verbose -Message "Adding RepresentativeId $RepresentativeId to request string."
            $GetInquiriesBody.Add('representative_id', $RepresentativeId)
        }

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

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

                    Write-Output $Inquiries
               }
        }
        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-PInquiries cmdlet finished."
    }

} #END:Get-PInquiries
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-POrganizationTypes {
<#
.SYNOPSIS
  Returns organization types.
 
.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:
    TypeId
    Name
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/26/2020
 
.EXAMPLE
  Get-POrganizationTypes -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."
        $GetOrganizationTypesBody = @{
            task = 'getOrganizationTypes';
            access_key = $PopuliAuthkey;
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-POrganizationTypes."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Types = foreach ($Type in $Response.response.type) {
                        [pscustomobject] @{
                        'TypeId' = $Type.id
                        'Name' = $Type.name
                        }
                    }
                    Write-Output $Types
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Get-POrganizationTypes: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        } #END:try/catch
    } #END:Process

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

} #END:Get-POrganizationTypes
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,

        [parameter()]
        [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,

        [Parameter()]
        [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-PStudentPrograms {
<#
.SYNOPSIS
  Returns the programs, degrees, and specializations for a particular student.
 
.DESCRIPTION
 
 
.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 Academic Admin or Registrar role to call this task.
  This parameter is required.
 
.PARAMETER PersonId
  The numeric ID of the person you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    Id
    ProgramId
    ProgramName
    StartedOn
    Inactive
    ExitDate
    ExitReason
    EntranceTermId
    EntranceTermName
    PreviousEducationLevelId
    PreviousEducationLevelName
    IsTransferStudent
    DegreeId
    DegreeStudentId
    Abbrv
    DegreeName
    DegreeStatus
    ActiveDate
    InactiveDate
    GraduationDate
    GraduationDegree
    CatalogYearId
    CatalogStartYear
    CatalogEndYear
    AnticipatedCompletionDate
    SpecializationId
    SpecializationName
    Type
    SpecializationStatus
    GrantedDate
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 02/25/2020
 
.EXAMPLE
  Get-PStudentPrograms -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId 7857760
#>

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

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

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

    process {
        Write-Verbose -Message "Building table with parameter data."
        $GetStudentProgramsBody = @{
             task = 'getStudentPrograms';
             access_key = $PopuliAuthkey;
             person_id = $PersonId;
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi."
                    $ErrorCode = $Response.error.code
                    $ErrorMessage = $Response.error.message
                    Write-Warning "$ErrorCode $ErrorMessage"
                }
                else {
                    Write-Verbose -Message "Return data as PowerShell objects."
                    $Data = [System.Collections.ArrayList]@()

                    foreach ($Program in $Response.response.programs) {
                        $Id = $Program.program.id
                        $ProgramId = $Program.program.program_id
                        $ProgramName = $Program.program.name
                        $StartedOn = $Program.program.started_on
                        $Inactive = $Program.program.inactive
                        $ExitDate = $Program.program.exit_date
                        $ExitReason = $Program.program.exit_reason
                        $EntranceTerm = $Program.program.entrance_term_id
                        $EntranceTermName = $Program.program.entrance_term_name
                        $PreviousEducationLevelId = $Program.program.previous_education_level_id
                        $PreviousEducationLevelName = $Program.program.previous_education_level_name
                        $IsTransferStudent = $Program.program.is_transfer_student

                        foreach ($Degree in $Program.program.degrees.degree){
                            $Object = [pscustomobject] @{
                                Id = $Id
                                ProgramId = $ProgramId
                                ProgramName = $ProgramName
                                StartedOn = $StartedOn
                                Inactive = $Inactive
                                ExitDate = $ExitDate
                                ExitReason = $ExitReason
                                EntranceTerm = $EntranceTerm
                                EntranceTermName = $EntranceTermName
                                PreviousEducationLevelId = $PreviousEducationLevelId
                                PreviousEducationLevelName = $PreviousEducationLevelName
                                IsTransferStudent = $IsTransferStudent
                                DegreeId = $Degree.degree_id
                                DegreeStudentId = $Degree.degree_student_id
                                Abbrv = $Degree.abbrv
                                DegreeName = $Degree.name
                                DegreeStatus = $Degree.status
                                ActiveDate = $Degree.active_date
                                InactiveDate = $Degree.inactive_date
                                GraduationDate = $Degree.graduation_date
                                GraduateDegree = $Degree.graduation_degree
                                CatalogYearId = $Degree.catalog_year_id
                                CatalogStartYear = $Degree.catalog_start_year
                                CatalogEndYear = $Degree.catalog_end_year
                                AnticipatedCompletionDate = $Degree.anticipated_completion_date
                                SpecializationId = $Degree.specializations.specialization.specialization_id
                                SpecializationName = $Degree.specializations.specialization.name
                                Type = $Degree.specializations.specialization.type
                                SpecializationStatus = $Degree.specializations.specialization.status
                                GrantedDate = $Degree.specializations.specialization.granted_date
                            }
                            [void]$Data.Add($Object)
                       } #END:foreach:Degree

                    } #END:foreach:Program

                Write-Output $Data

                } #END:else

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

    } #END:process

    end {
        Write-Verbose -Message "Finished."
    }

} #END: Get-PStudentPrograms
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-PTransferCreditProgramGradeOptions {
<#
.SYNOPSIS
  Returns transfer credit program grade options.
 
.DESCRIPTION
  You must have the Admissions Admin, Admissions, 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.
  This parameter is required.
 
.PARAMETER ProgramId
  The numeric ID of the program you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    GradeScale
      Value
      Label
    PassFailGradeScale
      Value
      Label
    Other
      Value
      Label
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/26/2020
 
.EXAMPLE
  Get-PTransferCreditProgramGradeOptions -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -ProgramId 18075
#>

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetTransferCreditProgramGradeOptionsBody = @{
            task = 'getTransferCreditProgramGradeOptions';
            access_key = $PopuliAuthkey;
            program_id = $ProgramId;
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PTransferCreditProgramGradeOptions."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $GradeScale = foreach ($Option in $Response.response.grade_scale.option) {
                        [pscustomobject] @{
                        'Value' = $Option.value
                        'Label' = $Option.label
                        }
                    }
                    $PassFailGradeScale = foreach ($Option in $Response.response.pass_fail_grade_scale.option){
                        [pscustomobject] @{
                        'Value' = $Option.value
                        'Label' = $Option.label
                        }
                    }
                    Write-Output $GradeScale
                    Write-Output $PassFailGradeScale
                } #END:if/else
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Get-PTransferCreditProgramGradeOptions: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        } #END:try/catch
    } #END:Process

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

} #END:Get-PTransferCreditProgramGradeOptions
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-PUpdatedEnrollment {
<#
.SYNOPSIS
  Returns updated enrollment for a particular time.
 
.DESCRIPTION
  You must have the Academic Admin or Registrar 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.
  For more information check the Populi API reference. This parameter is required.
 
.PARAMETER StartDate
  Format should be a date like "2010-11-06".
  This parameter is required.
 
.PARAMETER Offset
  The numeric value you want to offset the results by.
 
.OUTPUTS
  Returns PowerShell objects:
    PersonId
    TermId
    InstanceId
    CatalogCourseId
    Status
    StatusDate
    Credits
    Hours
    Finalized
    FirstName
    LastName
    MiddleName
    PreferredName
    AcademicTermName
    CourseAbbr
    CourseName
    Section
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/24/2019
 
.EXAMPLE
  Get-PUpdatedEnrollment -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -StartDate "2019-12-01"
#>

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

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

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

        [Parameter()]
        [int]
        $Offset
    )
    process {
        Write-Verbose -Message "Building request string with parameter data."
        $GetUpdatedEnrollmentBody = @{
            task = 'getUpdatedEnrollment';
            start_date = $StartDate;
            access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('Offset')) {
            Write-Verbose -Message "Adding Offset $Offset to request string."
            $GetUpdatedEnrollmentBody.Add('offset', $Offset)
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Get-PUpdatedEnrollment."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Enrollments = foreach ($Enrollment in $Response.response.enrollment) {
                        Write-Verbose -Message "Converting $($Enrollment.person_id)"
                        [pscustomobject] @{
                            'PersonId' = $Enrollment.person_id
                            'TermId' = $Enrollment.term_id
                            'InstanceId' = $Enrollment.instance_id
                            'CatalogCourseId' = $Enrollment.catalog_course_id
                            'Status' = $Enrollment.status
                            'StatusDate' = $Enrollment.status_date
                            'Credits' = $Enrollment.credits
                            'Hours' = $Enrollment.hours
                            'Finalized' = $Enrollment.finalized
                            'FirstName' = $Enrollment.person_first_name
                            'LastName' = $Enrollment.person_last_name
                            'MiddleName' = $Enrollment.person_middle_name
                            'PreferredName' = $Enrollment.person_preferred_name
                            'AcademicTermName' = $Enrollment.academic_term_name
                            'CourseAbbrv' = $Enrollment.course_abbrv
                            'CourseName' = $Enrollment.course_name
                            'Section' = $Enrollment.section
                        } #END:pscustomobject
                    }#END:foreach

                    Write-Output $Enrollments

                } #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-PUpdatedEnrollment cmdlet finished."
    }

} #END: Get-PUpdatedEnrollment
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-PCourseOfferingLink {
<#
.SYNOPSIS
  Deletes a link attached to a particular course offering.
 
.DESCRIPTION
  You must have the Academic Admin role, the Registrar role, or be a course teacher to call this task (and the course must not be finalized).
 
.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 CourseOfferingId
  The numeric ID of the course offering you're interested in. ("instanceid"/"instance_id" = "course_offering_id")
  This parameter is required.
 
.PARAMETER LinkId
  The numeric ID of the link you're interested in.
  This parameter is required.
 
.OUTPUTS
  Returns PowerShell objects:
    SUCCESS or FAILURE
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/18/2019
 
.EXAMPLE
  Remove-PCourseOfferingLink -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -CourseOfferingId 9636721 -LinkId 6269053
#>

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

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

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

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

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $DeleteCourseOfferingLinkBody = @{
             task = 'deleteCourseOfferingLink';
             access_key = $PopuliAuthkey;
             course_offering_id = $CourseOfferingId;
             link_id = $LinkId;
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will delete the link with LinkId $LinkId in the Course with InstanceId $CourseOfferingId", "Delete Link")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $DeleteCourseOfferingLinkBody -ErrorAction Stop

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

            Write-Output $RemoveLink

        } #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 "Remove-PCourseOfferingLink cmdlet finished."
    }

} #END: Add-PCourseOfferingLink
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.
  This parameter is not required (but either PersonId or OrganizationId must be set).
 
.PARAMETER OrganizationId
  The numeric ID of the organization whose tag should be removed.
  This parameter is not required (but either PersonId or OrganizationId must be set).
 
.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 7857760 -Tag "MPRTest"
 
.EXAMPLE
  Remove-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -PersonId '7857760' -TagId '12345'
 
.EXAMPLE
  Remove-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -TagId '12345'
 
.EXAMPLE
  Remove-PTag -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '123456789' -OrganizationId '2669162' -TagName 'MPRTest'
 
#>

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

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

      [Parameter(ParameterSetName='ByPersonIdTagId')]
      [Parameter(ParameterSetName='ByPersonIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $PersonId,

      [Parameter(ParameterSetName='ByOrgIdTagId')]
      [Parameter(ParameterSetName='ByOrgIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $OrganizationId,

      [Parameter(ParameterSetName='ByPersonIdTagId')]
      [Parameter(ParameterSetName='ByOrgIdTagId',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [int]
      $TagId,

      [Parameter(ParameterSetName='ByPersonIdTagName')]
      [Parameter(ParameterSetName='ByOrgIdTagName',
                 Mandatory,
                 ValueFromPipelineByPropertyName)]
      [string]
      $TagName
    )

    process {
        Write-Verbose "Building request string with parameter data."
        $RemoveTagBody = @{
             task = 'removeTag';
             access_key = $PopuliAuthkey;
        }
        if ($PSBoundParameters.ContainsKey('PersonId')) {
            Write-Verbose -Message "Adding PersonId $PersonId to request string."
            $RemoveTagBody.Add('person_id', $PersonId)
            $ShouldProcessParams += "PersonId = $PersonId"
        }
        if ($PSBoundParameters.ContainsKey('OrganizationId')) {
            Write-Verbose -Message "Adding OrganizationId $OrganizationId to request string."
            $RemoveTagBody.Add('organization_id', $OrganizationId)
            $ShouldProcessParams += "OrganizationId = $OrganizationId"
        }
        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", "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-POrganizations {
<#
.SYNOPSIS
  Looks up organizations by name & location.
 
.DESCRIPTION
  You must have the Staff role to call this task.
  Use Get-POrganization 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. "College of Nursing" or "Chicago, IL".
  This parameter is required.
 
.PARAMETER Limit
  The maximum number of matches you'd like returned - defaults to 5, maximum is 50.
 
.OUTPUTS
  Returns PowerShell objects:
    OrganizationId
    Name
    LastName
    TypeId
    TypeName
    Address
    Type
    AddressId
    Street
    City
    State
    Zip
    Country
    IsPrimary
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 04/26/2020
 
.EXAMPLE
  Search-POrganizations -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -SearchTerm "Methodist"
#>

[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."
        $SearchOrganizationsBody = @{
            task = 'searchOrganizations';
            access_key = $PopuliAuthkey;
            search_term = $SearchTerm
            limit = $Limit;
        }

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

                if ($Response.error) {
                    Write-Verbose -Message "Error returned from Populi while executing Search-POrganizations."
                    $PError = [pscustomobject] @{
                        'ErrorCode' = $Response.error.code
                        'ErrorMessage' = $Response.error.message
                    }
                    Write-Output $PError
                }
                else {
                    Write-Verbose -Message "Formatting data as PowerShell objects."
                    $Organizations = foreach ($Organization in $Response.response.organization) {
                        Write-Verbose -Message "Converting $($Organization.id)"
                        [pscustomobject] @{
                            'OrganizationId' = $Organization.id
                            'Name' = $Organization.name
                            'TypeId' = $Organization.type_id
                            'TypeName' = $Organization.type_name
                            'Type' = $Organization.address.type
                            'AddressId' = $Organization.address.addressid
                            'Street' = $Organization.address.street
                            'City' = $Organization.address.city
                            'State' = $Organization.address.state
                            'Zip' = $Organization.address.zip
                            'Country' = $Organization.address.country
                            'IsPrimary' = $Organization.address.is_primary
                        }
                    }
                    Write-Output $Organizations
                }
        }
        catch {
            Write-Verbose -Message "Error returned from Populi while executing Search-POrganizations: $($_.ErrorDetails.Message)"
            Write-Warning "ERROR: $($_.ErrorDetails.Message)"
        }

     } #END:Process

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

} #END:Search-POrganizations

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-PCourseOfferingLink {
<#
.SYNOPSIS
  Updates a link attached to a particular course offering.
 
.DESCRIPTION
  You must have the Academic Admin role, the Registrar role, or be a course teacher to call this task (and the course must not be finalized).
 
.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 CourseOfferingId
  The numeric ID of the course offering you're interested in. ("instanceid"/"instance_id" = "course_offering_id")
  This parameter is required.
 
.PARAMETER LinkId
  The numeric ID of the link you're interested in.
  This parameter is required.
 
.PARAMETER Name
  The name of the link.
 
.PARAMETER Url
  The URL for the link.
 
.OUTPUTS
  Returns PowerShell objects:
    LinkId
 
.NOTES
  Author: Matthew Rehm
  Creation Date: 12/18/2019
 
.EXAMPLE
  Update-PCourseOfferingLink -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -CourseOfferingId 9636721 -LinkId 6269053 -Name "Google" -Url "https://www.google.com
 
.EXAMPLE
  Update-PCourseOfferingLink -PopuliUri 'https://<YOUR_SUBDOMAIN_HERE>.populiweb.com/api/ -PopuliAuthkey '1234567890' -CourseOfferingId 9636721 -LinkId 6269053 -Name "Google Search"
#>

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

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

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

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

        [Parameter()]
        [string]
        $Name,

        [Parameter()]
        [uri]
        $Url
    )

    process {
        Write-Verbose -Message "Building request string with parameter data."
        $UpdateCourseOfferingLinkBody = @{
             task = 'updateCourseOfferingLink';
             access_key = $PopuliAuthkey;
             course_offering_id = $CourseOfferingId;
             link_id = $LinkId;
        }
        if ($PSBoundParameters.ContainsKey('Name')) {
            Write-Verbose -Message "Adding Name $Name to request string."
            $UpdateCourseOfferingLinkBody.Add('name', $Name)
            $ShouldProcessParams += "Name = $Name"
        }
        if ($PSBoundParameters.ContainsKey('Url')) {
            Write-Verbose -Message "Adding URL $Url to request string."
            $UpdateCourseOfferingLinkBody.Add('url', $Url)
            $ShouldProcessParams += "URL = $Url"
        }

        try {
            if ($PSCmdlet.ShouldProcess("This action will update the link with LinkId $LinkId in the Course with InstanceId $CourseOfferingId with parameters $ShouldProcessParams", "Update Link")) {
            Write-Verbose "Sending request to Populi ..."
            $Response = Invoke-RestMethod -Uri $PopuliUri -Method Post -Body $UpdateCourseOfferingLinkBody -ErrorAction Stop

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

            Write-Output $UpdateLink

        } #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 "Update-PCourseOfferingLink cmdlet finished."
    }

} #END: Update-PCourseOfferingLink
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