Skip to content

Commit

Permalink
Merge branch 'release-151' into martha/5752-join-hh
Browse files Browse the repository at this point in the history
  • Loading branch information
martha committed Feb 6, 2025
2 parents f2e9e4f + 0f2a2cb commit 128e6b3
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 30 deletions.
3 changes: 2 additions & 1 deletion app/models/concerns/cas_client_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ def cas_assessment_collected_at
:additional_homeless_nights_unsheltered,
:calculated_homeless_nights_sheltered,
:calculated_homeless_nights_unsheltered,
:total_homeless_nights_sheltered
:total_homeless_nights_sheltered,
:psh_required
end
end
108 changes: 102 additions & 6 deletions app/models/grda_warehouse/cas_project_client_calculator/boston.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ def value_for_cas_project_client(client:, column:)
end
end

def handles_days_homeless?
true
end

def unrelated_columns
[
:vispdat_score,
Expand Down Expand Up @@ -61,7 +65,7 @@ def unrelated_columns
cas_assessment_collected_at: 'Date the assessment was collected', # note this is really just assessment_collected_at
majority_sheltered: 'Most recent current living situation was sheltered',
assessment_score_for_cas: 'Days homeless in the past 3 years for pathways, score for transfer assessments',
tie_breaker_date: 'Date pathways was collected, or Financial Assistance End Date for transfer assessments',
tie_breaker_date: 'Date pathways was collected for Pathways 2023, First Date Homeless for Pathways 2024, or Financial Assistance End Date for Transfer Assessments',
financial_assistance_end_date: 'Latest Date Eligible for Financial Assistance response from the most recent pathways assessment',
assessor_first_name: 'First name of the user who completed the most recent pathways assessment',
assessor_last_name: 'Last name of the user who completed the most recent pathways assessment',
Expand All @@ -73,6 +77,7 @@ def unrelated_columns
days_homeless_for_vispdat_prioritization: 'Unused',
hiv_positive: 'HIV/AIDS response from the most recent pathways assessment',
meth_production_conviction: 'Meth production response from the most recent pathways assessment',
lifetime_sex_offender: 'Registered sex offender (level 1,2,3) - lifetime registration (SORI)',
requires_wheelchair_accessibility: 'Does the client need a wheelchair accessible unit response from the most recent pathways assessment',
income_maximization_assistance_requested: 'Did the client request income maximization services response from the most recent pathways assessment',
sro_ok: 'Is the client ok with an SRO response from the most recent pathways assessment',
Expand All @@ -94,7 +99,6 @@ def unrelated_columns
hiv_positive: 'c_housing_HIV',
income_maximization_assistance_requested: 'c_interest_income_max',
sro_ok: 'c_singleadult_sro',
evicted: 'c_pathways_barrier_eviction',
rrh_desired: 'c_interested_rrh',
housing_barrier: 'c_pathways_barriers_yn',
}.freeze
Expand Down Expand Up @@ -143,6 +147,13 @@ def unrelated_columns
:calculated_homeless_nights_unsheltered,
:total_homeless_nights_sheltered,
:total_homeless_nights_unsheltered,
:date_of_first_service,
:psh_required,
:meth_production_conviction,
:lifetime_sex_offender,
:evicted,
:days_homeless,
:hmis_days_homeless_all_time,
]
end
# memoize :pathways_questions
Expand Down Expand Up @@ -186,6 +197,23 @@ def most_recent_transfer_assessment_for_destination(client)
nil
end

private def lifetime_sex_offender(client)
most_recent_pathways_or_transfer(client).
question_matching_requirement('c_transfer_barrier_SORI', '1').present?
end

private def evicted(client)
evicted = most_recent_pathways_or_transfer(client).question_matching_requirement('c_pathways_barrier_meth', '1').present?
return true if evicted

evicted = most_recent_pathways_or_transfer(client).
question_matching_requirement('c_transfer_barrier_PHAterm', '1').present?
return true if evicted

# Otherwise unknown
nil
end

private def service_need(client)
need = most_recent_pathways_or_transfer(client).question_matching_requirement('c_pathways_service_indicators', '1').present?
return true if need
Expand Down Expand Up @@ -321,6 +349,18 @@ def days_homeless_in_last_three_years_cached(client)
pre_calculated_days
end

# Overrides the usual calculation for first date homeless if available
# If the question doesn't exist on the assessment or is empty, use the usual definition
private def date_of_first_service(client)
field_name = 'c_pathways_first_date_homeless'
answer = most_recent_pathways_or_transfer(client).
question_matching_requirement(field_name)&.AssessmentAnswer

return client.date_of_first_service if answer.blank?

answer.to_date
end

# If a client has more than 548 self-reported days (combination of sheltered and unsheltered)
# and does not have a verification uploaded, count unsheltered days first, then count sheltered days UP TO 548.
# If the self reported days are verified, use the provided amounts.
Expand Down Expand Up @@ -396,12 +436,46 @@ def total_homeless_nights_sheltered(client)
question_matching_requirement('c_pathways_nights_sheltered_warehouse_added_total')&.AssessmentAnswer.to_i || 0
end

# all-time days homeless
def days_homeless(client)
overall_nights_homeless(client)
end

# this seems to be calculated many different ways
def hmis_days_homeless_all_time(client)
overall_nights_homeless(client)
end

private def overall_nights_homeless(client)
most_recent_pathways_or_transfer(client).
question_matching_requirement('c_new_boston_homeless_nights_total')&.AssessmentAnswer.to_i ||
client.days_homeless
end

private def default_shelter_agency_contacts(client)
contact_emails = client.client_contacts.shelter_agency_contacts.where.not(email: nil).pluck(:email)
contact_emails << client.source_assessments.max_by(&:assessment_date)&.user&.user_email
contact_emails.compact.uniq
end

# 0 = No PSH
# 1 = PSH required
# 2 = Either
# Default to either if we don't have an answer
# CAS uses `yes`, `no`, `maybe` strings
private def psh_required(client)
value = most_recent_pathways_or_transfer(client).
question_matching_requirement('c_rrh_transfer_needs_subsidized_housing_resource')&.AssessmentAnswer.to_i || 2
case value
when 0
'no'
when 1
'yes'
else
'maybe'
end
end

private def contact_info_for_rrh_assessment(client)
client.client_contacts.case_managers.map(&:full_address).join("\n\n")
end
Expand All @@ -419,6 +493,7 @@ def total_homeless_nights_sheltered(client)
1 => 'IdentifiedPathwaysVersionThreePathways',
2 => 'IdentifiedPathwaysVersionThreeTransfer',
3 => 'IdentifiedPathwaysVersionFourPathways',
4 => 'IdentifiedPathwaysVersionFourTransfer',
}[value.to_i] || 'IdentifiedClientAssessment'
end

Expand Down Expand Up @@ -447,21 +522,42 @@ def total_homeless_nights_sheltered(client)
question_matching_requirement('c_latest_date_financial_assistance_eligibility_rrh')&.AssessmentAnswer
end

# For 2024/2025 score calculations are:
# Individual Pathways Assessment: days homeless in the past 3 years, prefer Pathways answer clamped to 1,096, use
# days in the past three years from the warehouse if not available.
# Family Pathways Assessment: overall days homeless (all time), prefer Pathways answer, use client.days_homeless if
# not available.
# Transfer Assessment: use assessment score.
private def assessment_score_for_cas(client)
case cas_assessment_name(client)
when 'IdentifiedPathwaysVersionThreePathways', 'IdentifiedPathwaysVersionFourPathways'
days_homeless_in_last_three_years_cached(client)
when 'IdentifiedPathwaysVersionThreeTransfer'
if most_recent_pathways_or_transfer(client).family_pathways_2024?
# Family
overall_days_homeless(client)
else
# Individual
days_homeless_in_last_three_years_cached(client)
end

# all time homeless days (no cap on total, but self-report limited to 548 if no verification)
# Also need a mechanism to identify family Pathways assessments/AssessmentQuestions
when 'IdentifiedPathwaysVersionThreeTransfer', 'IdentifiedPathwaysVersionFourTransfer'
assessment_score(client)
end
end

# Various tie-breaker dates used for prioritization in CAS when all else is equal
# For Pathways V3, use the date the assessment was collected
# For the V3 Transfer assessment, use the financial assistance end date
# For Pathways V4, use the first date of homelessness
private def tie_breaker_date(client)
case cas_assessment_name(client)
when 'IdentifiedPathwaysVersionThreePathways', 'IdentifiedPathwaysVersionFourPathways'
when 'IdentifiedPathwaysVersionThreePathways'
cas_assessment_collected_at(client)
when 'IdentifiedPathwaysVersionThreeTransfer'
when 'IdentifiedPathwaysVersionThreeTransfer', 'IdentifiedPathwaysVersionFourTransfer'
financial_assistance_end_date(client)
when 'IdentifiedPathwaysVersionFourPathways'
date_of_first_service(client)
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ def value_for_cas_project_client(client:, column:)
client.send(column)
end

# Defer calculation of `days_homeless` to PushClientsToCas
def handles_days_homeless?
false
end

def description_for_column(column)
custom_descriptions[column].presence || GrdaWarehouse::Hud::Client.cas_columns_data.dig(column, :description)
end
Expand Down
8 changes: 8 additions & 0 deletions app/models/grda_warehouse/hud/assessment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ class Assessment < Base
where(AssessmentID: GrdaWarehouse::Hud::AssessmentQuestion.transfer.select(:AssessmentID))
end

scope :family_pathways, -> do
where(AssessmentID: GrdaWarehouse::Hud::AssessmentQuestion.family_pathways.select(:AssessmentID))
end

def answer(question)
assessment_questions.find_by(assessment_question: question.to_s)&.assessment_answer
end
Expand Down Expand Up @@ -105,5 +109,9 @@ def name
def pathways?
assessment_questions.any?(&:pathways?)
end

def family_pathways_2024?
name == 'Family Pathways 2024'
end
end
end
38 changes: 32 additions & 6 deletions app/models/grda_warehouse/hud/assessment_question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,18 @@ class AssessmentQuestion < Base
pathways_or_rrh.
joins(:lookup).
merge(GrdaWarehouse::AssessmentAnswerLookup.where(response_text: pathways_titles))

# Temporary solution until we have the c_housing_assessment_name question in the 2024 pathways assessment
# where(AssessmentQuestion: [:c_housing_assessment_name, :c_pathways_barriers_yn])
end

scope :transfer, -> do
pathways_or_rrh.
joins(:lookup).
merge(GrdaWarehouse::AssessmentAnswerLookup.where(response_text: 'RRH-PSH Transfer'))
merge(GrdaWarehouse::AssessmentAnswerLookup.where(response_text: transfer_titles))
end

scope :family_pathways, -> do
pathways_or_rrh.
joins(:lookup).
merge(GrdaWarehouse::AssessmentAnswerLookup.where(response_text: family_pathways_titles))
end

# NOTE: you probably want to join/preload :lookup
Expand All @@ -71,8 +74,6 @@ def default_response_text(answer)
end

def pathways?
# FIXME: this is temporary until we have a more permanent solution
# self.AssessmentQuestion.to_s == 'c_pathways_barriers_yn'
self.AssessmentQuestion.to_s == 'c_housing_assessment_name' && human_readable.in?(self.class.pathways_titles)
end

Expand All @@ -83,6 +84,19 @@ def self.pathways_titles
]
end

def self.transfer_titles
[
'RRH-PSH Transfer',
'RRH-PSH Transfer 2024',
]
end

def self.family_pathways_titles
[
'Family Pathways 2024',
]
end

private def pathways_question?
assessment_question == 'c_housing_assessment_name'
end
Expand All @@ -91,11 +105,17 @@ def assessment_name
return 'Pathways 2024' if pathways_2024?
return 'Pathways 2021' if pathways_2021?
return 'RRH-PSH Transfer' if transfer_2021?
return 'RRH-PSH Transfer 2024' if transfer_2024?
return 'Family Pathways 2024' if family_pathways_2024?

# unknown from assessment questions
nil
end

def family_pathways_2024?
lookup&.response_text == 'Family Pathways 2024'
end

def pathways_2024?
return nil unless pathways_question?

Expand All @@ -113,5 +133,11 @@ def transfer_2021?

lookup&.response_text == 'RRH-PSH Transfer'
end

def transfer_2024?
return nil unless pathways_question?

lookup&.response_text == 'RRH-PSH Transfer 2024'
end
end
end
8 changes: 4 additions & 4 deletions app/models/grda_warehouse/hud/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1357,7 +1357,7 @@ def email
return source_clients.map(&:email).reject(&:blank?).first if destination?

# Look for value from OP HMIS
value = most_recent_email_hmis if HmisEnforcement.hmis_enabled?
value = most_recent_email_hmis if HmisEnforcement.hmis_enabled? && data_source&.hmis?
# Look for value from other HMIS integrations
value ||= hmis_client_response['Email'] if hmis_client_response.present?
value ||= hmis_client.processed_fields['email'] if hmis_client&.processed_fields
Expand All @@ -1368,7 +1368,7 @@ def home_phone
# Fetch the data from the source clients if we are a destination client
return source_clients.map(&:home_phone).reject(&:blank?).first if destination?

value = most_recent_home_phone_hmis if HmisEnforcement.hmis_enabled?
value = most_recent_home_phone_hmis if HmisEnforcement.hmis_enabled? && data_source&.hmis?
value ||= hmis_client_response['HomePhone'] if hmis_client_response.present?
value
end
Expand All @@ -1377,7 +1377,7 @@ def cell_phone
# Fetch the data from the source clients if we are a destination client
return source_clients.map(&:cell_phone).reject(&:blank?).first if destination?

value = most_recent_cell_or_other_phone_hmis if HmisEnforcement.hmis_enabled?
value = most_recent_cell_or_other_phone_hmis if HmisEnforcement.hmis_enabled? && data_source&.hmis?
value ||= hmis_client_response['CellPhone'] if hmis_client_response.present?
value ||= hmis_client.processed_fields['phone'] if hmis_client&.processed_fields
value
Expand All @@ -1387,7 +1387,7 @@ def work_phone
# Fetch the data from the source clients if we are a destination client
return source_clients.map(&:work_phone).reject(&:blank?).first if destination?

value = most_recent_work_or_school_phone_hmis if HmisEnforcement.hmis_enabled?
value = most_recent_work_or_school_phone_hmis if HmisEnforcement.hmis_enabled? && data_source&.hmis?
return value if value
return unless hmis_client_response.present?

Expand Down
Loading

0 comments on commit 128e6b3

Please sign in to comment.