Public/Get-PatientMeasurementRequirements.ps1

<#
    .SYNOPSIS
    Gets the measurement requirements from the eCC salesforce org for patients.

    .DESCRIPTION
    Measurement requirements are determine by examining the planned entries on a patient calendar
    and the current devices assign.

    Any measurements required that do not have devices that support those measurement types are
    the needs.

    .INPUTS
    None. You cannot pipe objects to Get-ObservationsForPatient.

    .OUTPUTS
    An array of PSCustomObject that contain the following members:
        - Patient - the patient object
        - has - array of measurement id that the patient has
        - needs - array of measurement ids that the patient needs
        - preferences - the array of all the preferences

    .PARAMETER Patients
    The patients to retrieve needs. See Get-Patients.

    .PARAMETER Def
    The metric metadata definitions from Get-MetricDefinitions. If not supplied then it will be called.

    .EXAMPLE
    PS> $requirements = Get-PatientMeasurementRequirements -Patients (Get-Patients -SelectCdrIds @("195a2e2a-0d78-4558-935d-1a1c793d8626"))

    .LINK
    Set-Config

    .NOTES
    Assumes config is initialized for org access.
#>

function Get-PatientMeasurementRequirements {

    [CmdletBinding()]
    [OutputType([PSCustomObject[]])]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline)]
        [ValidateNotNull()]
        [PScustomObject[]]
        $Patients,

        [Parameter(Mandatory = $false, Position = 1, ValueFromPipeline)]
        [PSCustomObject]
        $Def
    )

    begin {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Function started"
    }

    end {
        Write-Verbose "[$($MyInvocation.MyCommand.Name)] Complete"
    }

    process {
        Write-Debug "[$($MyInvocation.MyCommand.Name)] PSBoundParameters: $($PSBoundParameters | Out-String)"

        if (-not $PSBoundParameters.ContainsKey('Def')) {
            $Def = Get-MetricDefinitions
        }

        # For performance reasons these query retrieve for all patient and not per patient
        $Devices = Get-SfDevices
        $PlannedEntries = Get-SfPlannedEntries
        $Preferences = Get-SfPatientPreferences

        foreach ($Patient in $Patients) {
            $has = @()
            $Devices | Where-Object { $Patient.sfPatient.Id -eq $_.phecc__Patient__c } | ForEach-Object {
                $model = $_.phecc__Device_Model__c
                $has += $Def.capabilities | Where-Object { $_.phecc__Device_Model__c -eq $model } | Select-Object phecc__Measurement_Type__c -Expand phecc__Measurement_Type__c
            }
            $needs = $PlannedEntries | Where-Object { $Patient.sfPatient.phecc__Permission__c -eq $_.phecc__Permission__c } | Select-Object pecc__Measurement_Type__c -ExpandProperty phecc__Measurement_Type__c | Sort-Object | Get-Unique | Where-Object { $has -notcontains $_ }
            [PSCustomObject]@{
                Patient     = $Patient
                has         = $Def.measurements | Where-Object { $has -contains $_.Id }
                needs       = $Def.measurements | Where-Object { $needs -contains $_.Id }
                preferences = $Preferences | Where-Object { $_.phecc__Patient__c -eq $Patient.sfPatient.Id }
            }
        }
    }
}