Skip to content

Commit

Permalink
Add picklist ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT for AC unit chang…
Browse files Browse the repository at this point in the history
…es (#5111)
  • Loading branch information
gigxz authored Feb 5, 2025
1 parent e284a34 commit b0eaa4a
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 21 deletions.
9 changes: 8 additions & 1 deletion drivers/hmis/app/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6656,6 +6656,12 @@ type PickListOption {
}

enum PickListType {
"""
Units available for the given Enrollment at the given project. Includes all
available units at project even if they have a different type from what the
household is currently occupying.
"""
ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT
ALL_SERVICE_CATEGORIES
ALL_SERVICE_TYPES

Expand All @@ -6680,7 +6686,8 @@ enum PickListType {
AVAILABLE_SERVICE_TYPES

"""
Units available for the given household at the given project
Units available for the given Enrollment at the given project. List is limited
to units with the same unit type currently occupied by the household, if any.
"""
AVAILABLE_UNITS_FOR_ENROLLMENT

Expand Down
3 changes: 2 additions & 1 deletion drivers/hmis/app/graphql/types/forms/enums/pick_list_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class Forms::Enums::PickListType < Types::BaseEnum
value 'ALL_UNIT_TYPES', 'All unit types.'
value 'POSSIBLE_UNIT_TYPES_FOR_PROJECT', 'Unit types that are eligible to be added to project'
value 'AVAILABLE_UNIT_TYPES', 'Unit types that have unoccupied units in the specified project'
value 'AVAILABLE_UNITS_FOR_ENROLLMENT', 'Units available for the given household at the given project'
value 'AVAILABLE_UNITS_FOR_ENROLLMENT', 'Units available for the given Enrollment at the given project. List is limited to units with the same unit type currently occupied by the household, if any.'
value 'ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT', 'Units available for the given Enrollment at the given project. Includes all available units at project even if they have a different type from what the household is currently occupying.'
value 'ALL_SERVICE_TYPES'
value 'ALL_SERVICE_CATEGORIES'
value 'CUSTOM_SERVICE_CATEGORIES'
Expand Down
26 changes: 22 additions & 4 deletions drivers/hmis/app/graphql/types/forms/pick_list_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ def self.options_for_type(pick_list_type, user:, project_id: nil, client_id: nil
available_unit_types_for_project(project)
when 'AVAILABLE_UNITS_FOR_ENROLLMENT'
available_units_for_enrollment(project, household_id: household_id)
when 'ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT'
admin_available_units_for_enrollment(project, household_id: household_id)
when 'OPEN_HOH_ENROLLMENTS_FOR_PROJECT'
open_hoh_enrollments_for_project(project, user: user)
when 'ENROLLMENTS_FOR_CLIENT'
Expand Down Expand Up @@ -474,7 +476,7 @@ def self.enrollments_for_client(client, user:)
end
end

def self.available_units_for_enrollment(project, household_id: nil)
def self.admin_available_units_for_enrollment(project, household_id: nil)
return [] unless project

# Eligible units are unoccupied units, PLUS units occupied by household members
Expand All @@ -487,10 +489,8 @@ def self.available_units_for_enrollment(project, household_id: nil)
[]
end

unit_types_assigned_to_household = Hmis::Unit.where(id: hh_units).pluck(:unit_type_id).compact.uniq
eligible_units = Hmis::Unit.where(id: unoccupied_units + hh_units)
# If some household members are assigned to units with unit types, then list should be limited to units of the same type.
eligible_units = eligible_units.where(unit_type_id: unit_types_assigned_to_household) if unit_types_assigned_to_household.any?

eligible_units.preload(:unit_type).
order(:unit_type_id, :id).
map do |unit|
Expand All @@ -504,6 +504,24 @@ def self.available_units_for_enrollment(project, household_id: nil)
end
end

def self.available_units_for_enrollment(project, household_id: nil)
return [] unless project

# use picklist that includes all available units including units of other types
picklist = admin_available_units_for_enrollment(project, household_id: household_id)
return picklist unless household_id # no household, so no need to filter unit types

# drop units that have different types
hh_unit_type_ids = project.enrollments.where(household_id: household_id).map(&:current_unit_type).compact.map(&:id).uniq
return picklist if hh_unit_type_ids.empty? # household doesn't have a unit type, so no need for further filtering

# if the household has a unit type, exclude units that don't match
allowed_unit_type_unit_ids = project.units.where(unit_type_id: hh_unit_type_ids).pluck(:id).to_set
picklist.filter do |option|
option[:code].in?(allowed_unit_type_unit_ids)
end
end

def self.assessment_names_for_project(project)
# It's a little odd to combine the "roles" (eg INTAKE) with the identifiers (eg housing_needs_assessment), but
# we need to do that in order to get the desired behavior. The "Intake" option should show all Intakes,
Expand Down
1 change: 1 addition & 0 deletions drivers/hmis/app/models/hmis/hud/enrollment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Hmis::Hud::Enrollment < Hmis::Hud::Base
has_many :unit_occupancies, class_name: 'Hmis::UnitOccupancy', inverse_of: :enrollment, dependent: :destroy
has_one :active_unit_occupancy, -> { active }, class_name: 'Hmis::UnitOccupancy', inverse_of: :enrollment
has_one :current_unit, through: :active_unit_occupancy, class_name: 'Hmis::Unit', source: :unit
has_one :current_unit_type, through: :current_unit, class_name: 'Hmis::UnitType', source: :unit_type

# Cached chronically homeless at entry
has_one :ch_enrollment, class_name: 'Hmis::ChEnrollment', dependent: :destroy
Expand Down
50 changes: 35 additions & 15 deletions drivers/hmis/spec/requests/hmis/pick_list_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -308,36 +308,56 @@ def picklist_option_codes(project)
end
end

describe 'AVAILABLE_UNITS_FOR_ENROLLMENT' do
describe 'unit picklists' do
let!(:e1) { create :hmis_hud_enrollment, data_source: ds1, project: p1, client: c1 }
let!(:un1) { create :hmis_unit, project: p1 }
let!(:un2) { create :hmis_unit, project: p1 }
let!(:un3) { create :hmis_unit } # in another project
let!(:br1) { create :hmis_unit_type, description: '1 BR' }
let!(:br2) { create :hmis_unit_type, description: '2 BR' }

let!(:un1) { create :hmis_unit, project: p1, unit_type: br1 }
let!(:un2) { create :hmis_unit, project: p1, unit_type: br1 }
let!(:un3) { create :hmis_unit, project: p1, unit_type: br2 }

# cruft: units in other projects
let!(:un4) { create :hmis_unit, unit_type: br1 }
let!(:un5) { create :hmis_unit, unit_type: br2 }
let!(:un6) { create :hmis_unit }

# assign e1 to un1
let!(:uo1) { create :hmis_unit_occupancy, unit: un1, enrollment: e1, start_date: 1.week.ago }

def picklist_option_codes(project, household_id = nil)
def picklist_option_codes(project, picklist: 'AVAILABLE_UNITS_FOR_ENROLLMENT', household_id: nil)
Types::Forms::PickListOption.options_for_type(
'AVAILABLE_UNITS_FOR_ENROLLMENT',
picklist,
user: hmis_user,
project_id: project.id,
household_id: household_id,
).map { |opt| opt[:code] }
end

it 'resolves available units for project' do
expect(picklist_option_codes(p1)).to contain_exactly(un2.id)
end
context 'AVAILABLE_UNITS_FOR_ENROLLMENT' do
it 'resolves available units for project' do
expect(picklist_option_codes(p1)).to contain_exactly(un2.id, un3.id)
end

it 'includes units that are currently occupied by the household, plus other units of the same type' do
result = picklist_option_codes(p1, household_id: e1.household_id)
expect(result).to contain_exactly(un1.id, un2.id)
end

it 'includes units that are currently occupied by the household' do
expect(picklist_option_codes(p1, e1.household_id)).to contain_exactly(un1.id, un2.id)
it 'if household unit doesn\'t have a type, includes all available units' do
un1.update!(unit_type: nil)
expect(picklist_option_codes(p1, household_id: e1.household_id)).to contain_exactly(un1.id, un2.id, un3.id)
end
end

it 'if household is occupied by a unit that has a type, excludes other unit typoes from list' do
un1.unit_type = create(:hmis_unit_type)
un1.save!
expect(picklist_option_codes(p1, e1.household_id)).to contain_exactly(un1.id)
context 'ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT' do
it 'resolves available units for project' do
expect(picklist_option_codes(p1)).to contain_exactly(un2.id, un3.id)
end

it 'includes units with differing unit types' do
expect(picklist_option_codes(p1, picklist: 'ADMIN_AVAILABLE_UNITS_FOR_ENROLLMENT', household_id: e1.household_id)).to contain_exactly(un1.id, un2.id, un3.id)
end
end
end

Expand Down

0 comments on commit b0eaa4a

Please sign in to comment.