From 37ec38278e9f4a3793f0efef2239b41cf3f45303 Mon Sep 17 00:00:00 2001 From: Elliot Anders Date: Tue, 6 Aug 2024 10:10:54 -0400 Subject: [PATCH 1/2] Bundler update; move audit ignore list to file --- .bundler-audit.yml | 6 ++++++ .github/workflows/asset_compilation.yml | 2 +- .github/workflows/build_images.yml | 2 +- .github/workflows/ci.yml | 2 +- Gemfile.lock | 2 +- docker/app/Dockerfile | 2 +- docker/docker-compose.yml | 2 +- 7 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 .bundler-audit.yml diff --git a/.bundler-audit.yml b/.bundler-audit.yml new file mode 100644 index 000000000..6cb0809ab --- /dev/null +++ b/.bundler-audit.yml @@ -0,0 +1,6 @@ +--- +ignore: + - CVE-2019-16676 + - CVE-2017-1002201 + - CVE-2024-26143 + - CVE-2024-6531 diff --git a/.github/workflows/asset_compilation.yml b/.github/workflows/asset_compilation.yml index 70773aa90..8774353c4 100644 --- a/.github/workflows/asset_compilation.yml +++ b/.github/workflows/asset_compilation.yml @@ -79,7 +79,7 @@ jobs: echo "postgres:5432:*:postgres:postgres" > ~/.pgpass chmod 600 ~/.pgpass - gem install bundler --version=2.4.14 + gem install bundler --version=2.5.17 # According to https://www.jessesquires.com/blog/2021/08/23/caching-bundler-on-github-actions/ # this is fragile and failure prone, but the step they recommend using instead (ruby/ruby-setup) diff --git a/.github/workflows/build_images.yml b/.github/workflows/build_images.yml index 93e375eb9..d7f1e1f5a 100644 --- a/.github/workflows/build_images.yml +++ b/.github/workflows/build_images.yml @@ -37,7 +37,7 @@ jobs: target: prod-build build-args: | BUILD_TAG=3.1.6-alpine3.20 - BUNDLER_VERSION=2.4.13 + BUNDLER_VERSION=2.5.17 USER_ID=1000 GROUP_ID=1000 tags: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fd813bdc..40fec87fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -77,7 +77,7 @@ jobs: - name: Run bundle-audit run: | - bundle exec bundle-audit check --update --ignore CVE-2019-16676 CVE-2017-1002201 CVE-2024-26143 + bundle exec bundle-audit check --update - name: Run brakeman run: | bundle exec brakeman -q --no-pager --except PermitAttributes,Render diff --git a/Gemfile.lock b/Gemfile.lock index 07fb4b1f4..31c27d05d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -877,4 +877,4 @@ DEPENDENCIES yabeda-rails BUNDLED WITH - 2.4.13 + 2.5.17 diff --git a/docker/app/Dockerfile b/docker/app/Dockerfile index 46ebe5645..bf33f9939 100644 --- a/docker/app/Dockerfile +++ b/docker/app/Dockerfile @@ -24,7 +24,7 @@ ARG BUILD_TAG FROM ruby:${BUILD_TAG} AS base ARG USER_ID=10000 ARG GROUP_ID=10000 -ARG BUNDLER_VERSION=2.4.13 +ARG BUNDLER_VERSION=2.5.17 LABEL "app"=open-path-cas LABEL "ruby-version"=3.1.6 diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index ee196b180..53a5f7208 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -11,7 +11,7 @@ x-app: &app PG_MAJOR: '12' NODE_MAJOR: '12' YARN_VERSION: '1.17.3' - BUNDLER_VERSION: '2.4.14' + BUNDLER_VERSION: '2.5.17' USER_ID: ${USER_ID:-10000} GROUP_ID: ${GROUP_ID:-10000} environment: &env From 666438749d4ad91508dd62162eae6bf05f6b4220 Mon Sep 17 00:00:00 2001 From: Dave G <149399758+dtgreiner@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:47:23 -0400 Subject: [PATCH 2/2] Dg/boston_psh_route_13-962 (#835) * Route 13 initial commit - route, decisions, notifications included - additional cleanup will be needed around forms and notifications * rubocop * cleanup file and class names * additional cleanup on success route decisions * clean up missing notifications * move notification text into route folder, clean up decline reason, & include cori hearing outcome response * require SSP/HSP contacts & capture voucher issue date on accept referral step * clean up translations * QA suggestions * Use standard method definition --------- Co-authored-by: Elliot Anders --- app/controllers/programs_controller.rb | 1 + app/controllers/sub_programs_controller.rb | 122 +++++++-------- app/mailers/notifications_mailer.rb | 1 + app/mailers/route_thirteen_mailer_methods.rb | 145 ++++++++++++++++++ app/models/client_opportunity_match.rb | 3 + .../route_thirteen_cancel_reasons.rb | 44 ++++++ .../route_thirteen_decline_reasons.rb | 25 +++ .../concerns/route_thirteen_decisions.rb | 25 +++ .../route_thirteen_cancel_reasons.rb | 13 ++ .../route_thirteen_decline_reasons.rb | 13 ++ .../thirteen/thirteen_accept_referral.rb | 109 +++++++++++++ .../thirteen_accept_referral_decline.rb | 94 ++++++++++++ .../thirteen/thirteen_client_match.rb | 101 ++++++++++++ .../thirteen/thirteen_client_review.rb | 103 +++++++++++++ .../thirteen_client_review_decline.rb | 100 ++++++++++++ .../thirteen_confirm_match_success.rb | 85 ++++++++++ .../thirteen/thirteen_hearing_outcome.rb | 106 +++++++++++++ .../thirteen_hearing_outcome_decline.rb | 94 ++++++++++++ .../thirteen/thirteen_hearing_scheduled.rb | 106 +++++++++++++ .../thirteen_hearing_scheduled_decline.rb | 94 ++++++++++++ .../thirteen/thirteen_hsa_review.rb | 97 ++++++++++++ .../thirteen/thirteen_hsa_review_decline.rb | 94 ++++++++++++ .../thirteen_match_acknowledgement.rb | 87 +++++++++++ app/models/match_routes/base.rb | 1 + app/models/match_routes/thirteen.rb | 102 ++++++++++++ .../thirteen_accept_referral_decline.rb | 27 ++++ .../thirteen/thirteen_accept_referral_hsa.rb | 27 ++++ .../thirteen/thirteen_accept_referral_hsp.rb | 27 ++++ ...thirteen_accept_referral_shelter_agency.rb | 27 ++++ .../thirteen/thirteen_accept_referral_ssp.rb | 27 ++++ .../thirteen/thirteen_client_match.rb | 27 ++++ .../thirteen_client_review_decline.rb | 27 ++++ .../thirteen_client_review_dnd_staff.rb | 27 ++++ .../thirteen/thirteen_client_review_hsa.rb | 27 ++++ .../thirteen_client_review_shelter_agency.rb | 27 ++++ ...hirteen_confirm_match_success_dnd_staff.rb | 27 ++++ .../thirteen_confirm_match_success_hsa.rb | 27 ++++ ...en_confirm_match_success_shelter_agency.rb | 27 ++++ .../thirteen_hearing_outcome_decline.rb | 27 ++++ .../thirteen_hearing_outcome_dnd_staff.rb | 27 ++++ .../thirteen/thirteen_hearing_outcome_hsa.rb | 27 ++++ ...thirteen_hearing_outcome_shelter_agency.rb | 27 ++++ .../thirteen_hearing_scheduled_decline.rb | 27 ++++ .../thirteen_hearing_scheduled_dnd_staff.rb | 27 ++++ .../thirteen_hearing_scheduled_hsa.rb | 27 ++++ ...irteen_hearing_scheduled_shelter_agency.rb | 27 ++++ .../thirteen/thirteen_hsa_review_decline.rb | 27 ++++ .../thirteen/thirteen_hsa_review_dnd_staff.rb | 27 ++++ .../thirteen/thirteen_hsa_review_hsa.rb | 27 ++++ .../thirteen_hsa_review_shelter_agency.rb | 27 ++++ .../thirteen_match_acknowledgement_hsa.rb | 27 ++++ ...en_match_acknowledgement_shelter_agency.rb | 27 ++++ app/models/translation.rb | 7 + .../match_decisions/_cancel_actions.haml | 4 +- .../thirteen/_accept_referral.haml | 18 +++ .../thirteen/_accept_referral_decline.haml | 24 +++ .../thirteen/_client_match.haml | 29 ++++ .../thirteen/_client_review.haml | 17 ++ .../thirteen/_client_review_decline.haml | 24 +++ .../thirteen/_confirm_match_success.haml | 19 +++ .../thirteen/_hearing_outcome.haml | 65 ++++++++ .../thirteen/_hearing_outcome_decline.haml | 24 +++ .../thirteen/_hearing_scheduled.haml | 56 +++++++ .../thirteen/_hearing_scheduled_decline.haml | 24 +++ .../match_decisions/thirteen/_hsa_review.haml | 17 ++ .../thirteen/_hsa_review_decline.haml | 24 +++ .../thirteen/_match_acknowledgement.haml | 34 ++++ .../thirteen_accept_referral_decline.haml | 19 +++ .../thirteen_accept_referral_hsa.text.haml | 17 ++ .../thirteen_accept_referral_hsp.text.haml | 17 ++ ...n_accept_referral_shelter_agency.text.haml | 17 ++ .../thirteen_accept_referral_ssp.text.haml | 17 ++ .../thirteen/thirteen_client_match.text.haml | 17 ++ .../thirteen_client_review_decline.haml | 19 +++ ...thirteen_client_review_dnd_staff.text.haml | 19 +++ .../thirteen_client_review_hsa.text.haml | 17 ++ ...een_client_review_shelter_agency.text.haml | 17 ++ ..._confirm_match_success_dnd_staff.text.haml | 17 ++ ...irteen_confirm_match_success_hsa.text.haml | 14 ++ ...irm_match_success_shelter_agency.text.haml | 14 ++ .../thirteen_hearing_outcome_decline.haml | 19 +++ ...irteen_hearing_outcome_dnd_staff.text.haml | 17 ++ .../thirteen_hearing_outcome_hsa.text.haml | 17 ++ ...n_hearing_outcome_shelter_agency.text.haml | 17 ++ .../thirteen_hearing_scheduled_decline.haml | 19 +++ ...teen_hearing_scheduled_dnd_staff.text.haml | 19 +++ .../thirteen_hearing_scheduled_hsa.text.haml | 17 ++ ...hearing_scheduled_shelter_agency.text.haml | 19 +++ .../thirteen/thirteen_hsa_review_decline.haml | 19 +++ .../thirteen_hsa_review_dnd_staff.text.haml | 17 ++ .../thirteen_hsa_review_hsa.text.haml | 17 ++ ...irteen_hsa_review_shelter_agency.text.haml | 17 ++ ...irteen_match_acknowledgement_hsa.text.haml | 22 +++ ...h_acknowledgement_shelter_agency.text.haml | 22 +++ app/views/programs/_form.html.haml | 2 + app/views/sub_programs/_form.html.haml | 2 + ..._hearing_required_column_to_sub_program.rb | 5 + ...earing_outcome_recorded_totch_decisions.rb | 5 + db/schema.rb | 4 +- 99 files changed, 3313 insertions(+), 64 deletions(-) create mode 100644 app/mailers/route_thirteen_mailer_methods.rb create mode 100644 app/models/concerns/match_decisions/route_thirteen_cancel_reasons.rb create mode 100644 app/models/concerns/match_decisions/route_thirteen_decline_reasons.rb create mode 100644 app/models/concerns/route_thirteen_decisions.rb create mode 100644 app/models/match_decision_reasons/route_thirteen_cancel_reasons.rb create mode 100644 app/models/match_decision_reasons/route_thirteen_decline_reasons.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_accept_referral.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_accept_referral_decline.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_client_match.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_client_review.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_client_review_decline.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_confirm_match_success.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hearing_outcome.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hearing_outcome_decline.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hearing_scheduled.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hearing_scheduled_decline.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hsa_review.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_hsa_review_decline.rb create mode 100644 app/models/match_decisions/thirteen/thirteen_match_acknowledgement.rb create mode 100644 app/models/match_routes/thirteen.rb create mode 100644 app/models/notifications/thirteen/thirteen_accept_referral_decline.rb create mode 100644 app/models/notifications/thirteen/thirteen_accept_referral_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_accept_referral_hsp.rb create mode 100644 app/models/notifications/thirteen/thirteen_accept_referral_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_accept_referral_ssp.rb create mode 100644 app/models/notifications/thirteen/thirteen_client_match.rb create mode 100644 app/models/notifications/thirteen/thirteen_client_review_decline.rb create mode 100644 app/models/notifications/thirteen/thirteen_client_review_dnd_staff.rb create mode 100644 app/models/notifications/thirteen/thirteen_client_review_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_client_review_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_confirm_match_success_dnd_staff.rb create mode 100644 app/models/notifications/thirteen/thirteen_confirm_match_success_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_confirm_match_success_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_outcome_decline.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_outcome_dnd_staff.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_outcome_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_outcome_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_scheduled_decline.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_scheduled_dnd_staff.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_scheduled_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_hearing_scheduled_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_hsa_review_decline.rb create mode 100644 app/models/notifications/thirteen/thirteen_hsa_review_dnd_staff.rb create mode 100644 app/models/notifications/thirteen/thirteen_hsa_review_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_hsa_review_shelter_agency.rb create mode 100644 app/models/notifications/thirteen/thirteen_match_acknowledgement_hsa.rb create mode 100644 app/models/notifications/thirteen/thirteen_match_acknowledgement_shelter_agency.rb create mode 100644 app/views/match_decisions/thirteen/_accept_referral.haml create mode 100644 app/views/match_decisions/thirteen/_accept_referral_decline.haml create mode 100644 app/views/match_decisions/thirteen/_client_match.haml create mode 100644 app/views/match_decisions/thirteen/_client_review.haml create mode 100644 app/views/match_decisions/thirteen/_client_review_decline.haml create mode 100644 app/views/match_decisions/thirteen/_confirm_match_success.haml create mode 100644 app/views/match_decisions/thirteen/_hearing_outcome.haml create mode 100644 app/views/match_decisions/thirteen/_hearing_outcome_decline.haml create mode 100644 app/views/match_decisions/thirteen/_hearing_scheduled.haml create mode 100644 app/views/match_decisions/thirteen/_hearing_scheduled_decline.haml create mode 100644 app/views/match_decisions/thirteen/_hsa_review.haml create mode 100644 app/views/match_decisions/thirteen/_hsa_review_decline.haml create mode 100644 app/views/match_decisions/thirteen/_match_acknowledgement.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_accept_referral_decline.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsp.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_accept_referral_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_accept_referral_ssp.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_client_match.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_client_review_decline.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_client_review_dnd_staff.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_client_review_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_client_review_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_dnd_staff.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_decline.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_dnd_staff.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_decline.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_dnd_staff.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hsa_review_decline.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hsa_review_dnd_staff.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hsa_review_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_hsa_review_shelter_agency.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_hsa.text.haml create mode 100644 app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_shelter_agency.text.haml create mode 100644 db/migrate/20240731130949_add_cori_hearing_required_column_to_sub_program.rb create mode 100644 db/migrate/20240805133313_add_core_hearing_outcome_recorded_totch_decisions.rb diff --git a/app/controllers/programs_controller.rb b/app/controllers/programs_controller.rb index 8e9b562d8..6e1bd4081 100644 --- a/app/controllers/programs_controller.rb +++ b/app/controllers/programs_controller.rb @@ -100,6 +100,7 @@ def create :confidential, :eligibility_requirement_notes, :weighting_rules_active, + :cori_hearing_required, ], service_ids: [], requirements_attributes: [ diff --git a/app/controllers/sub_programs_controller.rb b/app/controllers/sub_programs_controller.rb index 9eb728175..0f2fe2c0a 100644 --- a/app/controllers/sub_programs_controller.rb +++ b/app/controllers/sub_programs_controller.rb @@ -15,7 +15,7 @@ class SubProgramsController < ApplicationController def new program = Program.find(params[:program_id]) program_type = program.match_route.default_program_type - @subprogram = SubProgram.new({program_type: program_type, program: program}) + @subprogram = SubProgram.new({ program_type: program_type, program: program }) end def edit @@ -26,30 +26,30 @@ def create @subprogram = SubProgram.new @subprogram.assign_attributes sub_program_params @subprogram.program = @program - prevent_incorrect_building() + prevent_incorrect_building if @subprogram.save redirect_to action: :index, controller: :programs flash[:notice] = "#{@subprogram.program.name} created." else - flash[:error] = "Please review the form problems below." + flash[:error] = 'Please review the form problems below.' render :new end end def update @subprogram.assign_attributes(sub_program_params) - prevent_incorrect_building() + prevent_incorrect_building if @subprogram.save @subprogram.file_tags.destroy_all if file_tag_params.any? && Warehouse::Base.enabled? - tags = Warehouse::Tag.where(id:file_tag_params).map do |tag| + Warehouse::Tag.where(id: file_tag_params).map do |tag| @subprogram.file_tags.create(tag_id: tag.id, name: tag.name) end end redirect_to action: :edit flash[:notice] = "Program \"#{@subprogram.program.name}\" updated." else - flash[:error] = "Please review the form problems below." + flash[:error] = 'Please review the form problems below.' render :new end end @@ -68,69 +68,69 @@ def close end private - # Only allow a trusted parameter "white list" through. - def sub_program_params - params.require(:sub_program). - permit( - :id, - :name, - :voucher_count, - :subgrantee_id, # Service provider - :sub_contractor_id, - :program_type, - :building_id, - :hsa_id, - :confidential, - :event, - :eligibility_requirement_notes, - :weighting_rules_active, - ) - end - def file_tag_params - params.require(:sub_program)[:file_tag_ids]. - map(&:presence).compact.map(&:to_i) || [] - end + # Only allow a trusted parameter "white list" through. + def sub_program_params + params.require(:sub_program). + permit( + :id, + :name, + :voucher_count, + :subgrantee_id, # Service provider + :sub_contractor_id, + :program_type, + :building_id, + :hsa_id, + :confidential, + :event, + :eligibility_requirement_notes, + :weighting_rules_active, + :cori_hearing_required, + ) + end - def check_edit_permission! - not_authorized! unless can_edit_programs? || (can_edit_assigned_programs? && @subprogram&.editable_by?(current_user)) - end + def file_tag_params + params.require(:sub_program)[:file_tag_ids]. + map(&:presence).compact.map(&:to_i) || [] + end - def program_scope - if can_view_programs? - return Program.all - elsif can_view_assigned_programs? - return Program.visible_by(current_user) - else - Program.none - end + def check_edit_permission! + not_authorized! unless can_edit_programs? || (can_edit_assigned_programs? && @subprogram&.editable_by?(current_user)) + end + + def program_scope + if can_view_programs? + return Program.all + elsif can_view_assigned_programs? + return Program.visible_by(current_user) + else + Program.none end + end - def sub_program_scope - if can_view_programs? - return SubProgram.all - elsif can_view_assigned_programs? - return SubProgram.visible_by(current_user) - else - SubProgram.none - end + def sub_program_scope + if can_view_programs? + return SubProgram.all + elsif can_view_assigned_programs? + return SubProgram.visible_by(current_user) + else + SubProgram.none end + end - # Use callbacks to share common setup or constraints between actions. + # Use callbacks to share common setup or constraints between actions. - def set_program - @program = program_scope.find_by(id: params[:program_id]) - end + def set_program + @program = program_scope.find_by(id: params[:program_id]) + end - def set_sub_program - @subprogram = sub_program_scope.find_by(id: params[:id]) - check_edit_permission! - end + def set_sub_program + @subprogram = sub_program_scope.find_by(id: params[:id]) + check_edit_permission! + end - def prevent_incorrect_building - # make sure we unset the building if we shouldn't have one. - unless @subprogram.has_buildings? - @subprogram.building_id = nil - end - end + def prevent_incorrect_building + # make sure we unset the building if we shouldn't have one. + @subprogram.building_id = nil unless @subprogram.has_buildings? + end end diff --git a/app/mailers/notifications_mailer.rb b/app/mailers/notifications_mailer.rb index d817d8159..8fd36c970 100644 --- a/app/mailers/notifications_mailer.rb +++ b/app/mailers/notifications_mailer.rb @@ -21,6 +21,7 @@ class NotificationsMailer < DatabaseMailer include RouteTenMailerMethods include RouteElevenMailerMethods include RouteTwelveMailerMethods + include RouteThirteenMailerMethods def match_recommendation_dnd_staff(notification = nil) setup_instance_variables(notification) diff --git a/app/mailers/route_thirteen_mailer_methods.rb b/app/mailers/route_thirteen_mailer_methods.rb new file mode 100644 index 000000000..2b12ff0d5 --- /dev/null +++ b/app/mailers/route_thirteen_mailer_methods.rb @@ -0,0 +1,145 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module RouteThirteenMailerMethods + extend ActiveSupport::Concern + included do + def thirteen_client_match(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'New Housing Recommendation - Requires Your Action') + end + + def thirteen_match_acknowledgement_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'New Housing Recommendation - Requires Your Action') + end + + def thirteen_match_acknowledgement_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'New Housing Recommendation') + end + + def thirteen_client_review_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Acknowledged - Requires Your Action') + end + + def thirteen_client_review_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Acknowledged') + end + + def thirteen_client_review_dnd_staff(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Acknowledged') + end + + def thirteen_client_review_decline(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Declined by #{Translation.translate('Shelter Agency Thirteen')} - Requires Your Action") + end + + def thirteen_hearing_scheduled_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Accepted by #{Translation.translate('Shelter Agency Thirteen')}") + end + + def thirteen_hearing_scheduled_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Accepted by #{Translation.translate('Shelter Agency Thirteen')} - Requires Your Action") + end + + def thirteen_hearing_scheduled_dnd_staff(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Accepted by #{Translation.translate('Shelter Agency Thirteen')}") + end + + def thirteen_hearing_scheduled_decline(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Declined by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_hearing_outcome_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Review Scheduled by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_hearing_outcome_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Review Scheduled by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_hearing_outcome_dnd_staff(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Review Scheduled by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_hearing_outcome_decline(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Declined by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_hsa_review_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_hsa_review_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_hsa_review_dnd_staff(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_hsa_review_decline(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Declined by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_accept_referral_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_accept_referral_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_accept_referral_ssp(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_accept_referral_hsp(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Ready for Review by #{Translation.translate('HSA Thirteen')}") + end + + def thirteen_accept_referral_decline(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: "Match Declined by #{Translation.translate('HSA Thirteen')} - Requires Your Action") + end + + def thirteen_confirm_match_success_shelter_agency(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Success Confirmed') + end + + def thirteen_confirm_match_success_hsa(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Success Confirmed') + end + + def thirteen_confirm_match_success_dnd_staff(notification = nil) + setup_instance_variables(notification) + mail(to: @contact.email, subject: 'Match Success Confirmed') + end + end +end diff --git a/app/models/client_opportunity_match.rb b/app/models/client_opportunity_match.rb index a1d306e69..98e4091fd 100644 --- a/app/models/client_opportunity_match.rb +++ b/app/models/client_opportunity_match.rb @@ -89,6 +89,9 @@ def self.model_name # Match Route 12 include RouteTwelveDecisions + # Match Route 13 + include RouteThirteenDecisions + has_many :referral_events, class_name: 'Warehouse::ReferralEvent', foreign_key: 'client_opportunity_match_id' has_one :active_referral_event, -> { where(referral_result: nil) }, class_name: 'Warehouse::ReferralEvent', foreign_key: 'client_opportunity_match_id' diff --git a/app/models/concerns/match_decisions/route_thirteen_cancel_reasons.rb b/app/models/concerns/match_decisions/route_thirteen_cancel_reasons.rb new file mode 100644 index 000000000..92d5bf4f0 --- /dev/null +++ b/app/models/concerns/match_decisions/route_thirteen_cancel_reasons.rb @@ -0,0 +1,44 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions + module RouteThirteenCancelReasons + extend ActiveSupport::Concern + + def pre_hsa_decision? + [ + 'MatchDecisions::Thirteen::ThirteenClientMatch', + 'MatchDecisions::Thirteen::ThirteenMatchAcknowledgement', + ].include?(type) + end + + def match_success_decision? + type == 'MatchDecisions::Thirteen::ThirteenConfirmMatchSuccess' + end + + def step_cancel_reasons + [].tap do |reasons| + reasons << 'Incarcerated' + reasons << 'Institutionalized' + reasons << 'In Treatment/Recovery Center' + reasons << 'Match expired' unless pre_hsa_decision? || match_success_decision? + reasons << 'Client has declined match' unless pre_hsa_decision? + reasons << 'Client has disengaged' unless pre_hsa_decision? + reasons << 'Client has disappeared' unless pre_hsa_decision? + reasons << 'CORI' unless pre_hsa_decision? + reasons << 'SORI' unless pre_hsa_decision? + reasons << 'Vacancy should not have been entered' + reasons << 'Client received another housing opportunity' + reasons << 'Client no longer eligible for match' unless match_success_decision? + reasons << 'Client deceased' + reasons << 'Vacancy filled by other client' unless pre_hsa_decision? || match_success_decision? + reasons << 'Health and Safety' unless match_success_decision? + reasons << 'Do not allow other matches for this vacancy' unless match_success_decision? + reasons << 'Other' + end + end + end +end diff --git a/app/models/concerns/match_decisions/route_thirteen_decline_reasons.rb b/app/models/concerns/match_decisions/route_thirteen_decline_reasons.rb new file mode 100644 index 000000000..fbbab0df9 --- /dev/null +++ b/app/models/concerns/match_decisions/route_thirteen_decline_reasons.rb @@ -0,0 +1,25 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions + module RouteThirteenDeclineReasons + extend ActiveSupport::Concern + + def step_decline_reasons(_contact) + [ + 'Client has another housing option', + 'Does not agree to services', + 'Unwilling to live in that neighborhood', + 'Unwilling to live in SRO', + 'Does not want housing at this time', + 'Unsafe environment for this person', + 'Client refused unit (non-SRO)', + 'Client refused voucher', + 'Other', + ] + end + end +end diff --git a/app/models/concerns/route_thirteen_decisions.rb b/app/models/concerns/route_thirteen_decisions.rb new file mode 100644 index 000000000..23582ee73 --- /dev/null +++ b/app/models/concerns/route_thirteen_decisions.rb @@ -0,0 +1,25 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module RouteThirteenDecisions + extend ActiveSupport::Concern + + included do + has_decision :thirteen_client_match, decision_class_name: 'MatchDecisions::Thirteen::ThirteenClientMatch', notification_class_name: 'Notifications::Thirteen::ThirteenClientMatch' + has_decision :thirteen_match_acknowledgement, decision_class_name: 'MatchDecisions::Thirteen::ThirteenMatchAcknowledgement', notification_class_name: 'Notifications::Thirteen::ThirteenMatchAcknowledgementShelterAgency' + has_decision :thirteen_client_review, decision_class_name: 'MatchDecisions::Thirteen::ThirteenClientReview', notification_class_name: 'Notifications::Thirteen::ThirteenClientReviewShelterAgency' + has_decision :thirteen_client_review_decline, decision_class_name: 'MatchDecisions::Thirteen::ThirteenClientReviewDecline', notification_class_name: 'Notifications::Thirteen::ThirteenClientReviewDecline' + has_decision :thirteen_hearing_scheduled, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHearingScheduled', notification_class_name: 'Notifications::Thirteen::ThirteenHearingScheduledHsa' + has_decision :thirteen_hearing_scheduled_decline, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHearingScheduledDecline', notification_class_name: 'Notifications::Thirteen::ThirteenHearingScheduledDecline' + has_decision :thirteen_hearing_outcome, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHearingOutcome', notification_class_name: 'Notifications::Thirteen::ThirteenHearingOutcomeHsa' + has_decision :thirteen_hearing_outcome_decline, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHearingOutcomeDecline', notification_class_name: 'Notifications::Thirteen::ThirteenHearingOutcomeDecline' + has_decision :thirteen_hsa_review, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHsaReview', notification_class_name: 'Notifications::Thirteen::ThirteenHsaReviewHsa' + has_decision :thirteen_hsa_review_decline, decision_class_name: 'MatchDecisions::Thirteen::ThirteenHsaReviewDecline', notification_class_name: 'Notifications::Thirteen::ThirteenHsaReviewDecline' + has_decision :thirteen_accept_referral, decision_class_name: 'MatchDecisions::Thirteen::ThirteenAcceptReferral', notification_class_name: 'Notifications::Thirteen::ThirteenAcceptReferralHsa' + has_decision :thirteen_accept_referral_decline, decision_class_name: 'MatchDecisions::Thirteen::ThirteenAcceptReferralDecline', notification_class_name: 'Notifications::Thirteen::ThirteenAcceptReferralDecline' + has_decision :thirteen_confirm_match_success, decision_class_name: 'MatchDecisions::Thirteen::ThirteenConfirmMatchSuccess', notification_class_name: 'Notifications::Thirteen::ThirteenConfirmMatchSuccessDndStaff' + end +end diff --git a/app/models/match_decision_reasons/route_thirteen_cancel_reasons.rb b/app/models/match_decision_reasons/route_thirteen_cancel_reasons.rb new file mode 100644 index 000000000..e79c9f2ac --- /dev/null +++ b/app/models/match_decision_reasons/route_thirteen_cancel_reasons.rb @@ -0,0 +1,13 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisionReasons + class RouteThirteenCancelReasons < Base + def title + "#{Translation.translate('Route Thirteen')} Cancel" + end + end +end diff --git a/app/models/match_decision_reasons/route_thirteen_decline_reasons.rb b/app/models/match_decision_reasons/route_thirteen_decline_reasons.rb new file mode 100644 index 000000000..8df45e398 --- /dev/null +++ b/app/models/match_decision_reasons/route_thirteen_decline_reasons.rb @@ -0,0 +1,13 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisionReasons + class RouteThirteenDeclineReasons < Base + def title + "#{Translation.translate('Route Thirteen')} Decline" + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_accept_referral.rb b/app/models/match_decisions/thirteen/thirteen_accept_referral.rb new file mode 100644 index 000000000..73254dbd1 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_accept_referral.rb @@ -0,0 +1,109 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenAcceptReferral < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenCancelReasons + include MatchDecisions::RouteThirteenDeclineReasons + + validate :ensure_required_contacts_present_on_accept + validate :ensure_required_contacts_present_on_accept + + def to_partial_path + 'match_decisions/thirteen/accept_referral' + end + + def step_name + 'Accept Referral' + end + + def actor_type + Translation.translate('HSA Thirteen') + end + + def contact_actor_type + :housing_subsidy_admin_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenAcceptReferralShelterAgency + m << Notifications::Thirteen::ThirteenAcceptReferralHsa + m << Notifications::Thirteen::ThirteenAcceptReferralSsp + m << Notifications::Thirteen::ThirteenAcceptReferralHsp + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + declined: 'Declined', + back: 'Pending', + } + end + + def permitted_params + super + [:date_voucher_issued] + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('HSA Thirteen')} assigned match" + when :accepted then "Referral Accepted by #{Translation.translate('HSA Thirteen')}." + when :canceled then canceled_status_label + when :declined then 'Match Declined' + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + missing_contacts << "a #{Translation.translate('Stabilization Service Providers Thirteen')} Contact" if save_will_accept? && match.ssp_contacts.none? + missing_contacts << "a #{Translation.translate('Housing Search Provider Thirteen')} Contact" if save_will_accept? && match.hsp_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def date_voucher_issued_present_if_status_complete + errors.add :date_voucher_issued, 'must be filled in' if status == 'accepted' && date_voucher_issued.blank? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def accepted + @decision.next_step.initialize_decision! + end + + def declined + Notifications::MatchDeclined.create_for_match! match + match.thirteen_accept_referral_decline_decision.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_accept_referral_decline.rb b/app/models/match_decisions/thirteen/thirteen_accept_referral_decline.rb new file mode 100644 index 000000000..1aca3154e --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_accept_referral_decline.rb @@ -0,0 +1,94 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenAcceptReferralDecline < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenDeclineReasons + include MatchDecisions::RouteThirteenCancelReasons + + def to_partial_path + 'match_decisions/thirteen/hsa_review_decline' + end + + def step_name + "#{Translation.translate('CoC Thirteen')} Accept Referral Decline" + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenAcceptReferralDecline + end + end + + def statuses + { + pending: 'Pending', + decline_overridden: 'Decline Overridden', + decline_overridden_returned: 'Decline Overridden, Returned', + decline_confirmed: 'Decline Confirmed', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm #{Translation.translate('HSA Thirteen')} decline" + when :decline_overridden then "#{Translation.translate('HSA Thirteen')} Decline overridden by #{Translation.translate('CoC Thirteen')}. Match proceeding to #{Translation.translate('CoC Thirteen')}" + when :decline_overridden_returned then "#{Translation.translate('HSA Thirteen')} overridden by #{Translation.translate('CoC Thirteen')}. Match returned to the #{Translation.translate('HSA Thirteen')}" + when :decline_confirmed then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: :pending + send_notifications_for_step if send_notifications + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def decline_overridden + match.thirteen_accept_referral_decision.update(status: :skipped) + match.thirteen_confirm_match_success_decision.initialize_decision! + end + + def decline_overridden_returned + # Re-initialize the previous decision + match.thirteen_accept_referral_decision.initialize_decision! + @decision.uninitialize_decision! + end + + def decline_confirmed + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + + def editable? + super && saved_status !~ /decline_overridden|decline_overridden_returned|decline_confirmed/ + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_client_match.rb b/app/models/match_decisions/thirteen/thirteen_client_match.rb new file mode 100644 index 000000000..405506f4b --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_client_match.rb @@ -0,0 +1,101 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenClientMatch < ::MatchDecisions::Base + include MatchDecisions::RouteThirteenCancelReasons + + validate :ensure_required_contacts_present_on_accept + + def to_partial_path + 'match_decisions/thirteen/client_match' + end + + def step_name + 'Client Match' + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenClientMatch + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + expiration_update: 'Pending', + } + end + + def permitted_params + super + [:prevent_matching_until, :shelter_expiration] + end + + def label_for_status status + case status.to_sym + when :pending, :expiration_update then "#{Translation.translate('CoC Thirteen')} assigned match" + when :accepted then "Match accepted by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + # Override default behavior + def record_action_event! contact: d + if status == 'expiration_update' + # Make note of the new expiration + else + decision_action_events.create! match: match, contact: contact, action: status, note: note + end + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def expiration_update + end + + def accepted + @decision.next_step.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_client_review.rb b/app/models/match_decisions/thirteen/thirteen_client_review.rb new file mode 100644 index 000000000..932398d4d --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_client_review.rb @@ -0,0 +1,103 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenClientReview < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenCancelReasons + include MatchDecisions::RouteThirteenDeclineReasons + + validate :ensure_required_contacts_present_on_accept + + def to_partial_path + 'match_decisions/thirteen/client_review' + end + + def step_name + 'Client Review' + end + + def actor_type + Translation.translate('Shelter Agency Thirteen') + end + + def contact_actor_type + :shelter_agency_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenClientReviewShelterAgency + m << Notifications::Thirteen::ThirteenClientReviewHsa + m << Notifications::Thirteen::ThirteenClientReviewDndStaff + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + declined: 'Declined', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('Shelter Agency Thirteen')} assigned match" + when :accepted then "Match accepted by #{Translation.translate('Shelter Agency Thirteen')}." + when :canceled then canceled_status_label + when :declined then 'Match Declined' + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def accepted + if match.sub_program.cori_hearing_required? + @decision.next_step.initialize_decision! + else + match.thirteen_hearing_scheduled_decision.update(status: :skipped) + match.thirteen_hearing_outcome_decision.update(status: :skipped) + match.thirteen_hsa_review_decision.initialize_decision! + end + end + + def declined + Notifications::MatchDeclined.create_for_match! match + match.thirteen_client_review_decline_decision.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_client_review_decline.rb b/app/models/match_decisions/thirteen/thirteen_client_review_decline.rb new file mode 100644 index 000000000..13885077b --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_client_review_decline.rb @@ -0,0 +1,100 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenClientReviewDecline < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenDeclineReasons + include MatchDecisions::RouteThirteenCancelReasons + + def to_partial_path + 'match_decisions/thirteen/client_review_decline' + end + + def step_name + "#{Translation.translate('CoC Thirteen')} Client Review Decline" + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenClientReviewDecline + end + end + + def statuses + { + pending: 'Pending', + decline_overridden: 'Decline Overridden', + decline_overridden_returned: 'Decline Overridden, Returned', + decline_confirmed: 'Decline Confirmed', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm #{Translation.translate('Shelter Agency Thirteen')} decline" + when :decline_overridden then "#{Translation.translate('Shelter Agency Thirteen')} Decline overridden by #{Translation.translate('CoC Thirteen')}. Match proceeding to #{Translation.translate('CoC Thirteen')}" + when :decline_overridden_returned then "#{Translation.translate('Shelter Agency Thirteen')} overridden by #{Translation.translate('CoC Thirteen')}. Match returned to the #{Translation.translate('Shelter Agency Thirteen')}" + when :decline_confirmed then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: :pending + send_notifications_for_step if send_notifications + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def decline_overridden + match.thirteen_client_review_decision.update(status: :skipped) + if match.sub_program.cori_hearing_required? + match.thirteen_hearing_scheduled_decision.initialize_decision! + else + match.thirteen_hearing_scheduled_decision.update(status: :skipped) + match.thirteen_hearing_outcome_decision.update(status: :skipped) + match.thirteen_hsa_review_decision.initialize_decision! + end + end + + def decline_overridden_returned + # Re-initialize the previous decision + match.thirteen_client_review_decision.initialize_decision! + @decision.uninitialize_decision! + end + + def decline_confirmed + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + + def editable? + super && saved_status !~ /decline_overridden|decline_overridden_returned|decline_confirmed/ + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_confirm_match_success.rb b/app/models/match_decisions/thirteen/thirteen_confirm_match_success.rb new file mode 100644 index 000000000..737c9375f --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_confirm_match_success.rb @@ -0,0 +1,85 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenConfirmMatchSuccess < ::MatchDecisions::Base + include MatchDecisions::RouteEightCancelReasons + + def statuses + { + pending: 'Pending', + confirmed: 'Confirmed', + rejected: 'Rejected', + canceled: 'Canceled', # added to support cancellations caused by other match success + back: 'Pending', + } + end + + def to_partial_path + 'match_decisions/thirteen/confirm_match_success' + end + + def label + label_for_status status + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm match success" + when :confirmed then "#{Translation.translate('CoC Thirteen')} confirms match success" + when :rejected then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then 'Match canceled' + when :back then backup_status_label + end + end + + def step_name + Translation.translate('Confirm Match Success') + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + nil + end + + def editable? + super && status !~ /confirmed|rejected/ + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenConfirmMatchSuccessHsa + m << Notifications::Thirteen::ThirteenConfirmMatchSuccessShelterAgency + m << Notifications::Thirteen::ThirteenConfirmMatchSuccessDndStaff + end + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def confirmed + Notifications::MatchSuccessConfirmed.create_for_match! match + match.succeeded!(user: user) + end + + def rejected + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hearing_outcome.rb b/app/models/match_decisions/thirteen/thirteen_hearing_outcome.rb new file mode 100644 index 000000000..40e799973 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hearing_outcome.rb @@ -0,0 +1,106 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHearingOutcome < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenCancelReasons + include MatchDecisions::RouteThirteenDeclineReasons + + validate :ensure_required_contacts_present_on_accept + validate :criminal_hearing_outcome_has_been_recorded + + def to_partial_path + 'match_decisions/thirteen/hearing_outcome' + end + + def step_name + 'Hearing Outcome' + end + + def actor_type + Translation.translate('HSA Thirteen') + end + + def contact_actor_type + :housing_subsidy_admin_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHearingOutcomeShelterAgency + m << Notifications::Thirteen::ThirteenHearingOutcomeHsa + m << Notifications::Thirteen::ThirteenHearingOutcomeDndStaff + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + declined: 'Declined', + back: 'Pending', + } + end + + def permitted_params + super + [:criminal_hearing_outcome_recorded] + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('HSA Thirteen')} assigned match" + when :accepted then "Hearing Outcome Added by #{Translation.translate('HSA Thirteen')}." + when :canceled then canceled_status_label + when :declined then 'Match Declined' + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + private def criminal_hearing_outcome_has_been_recorded + errors.add :criminal_hearing_outcome_recorded, 'must be checked' if save_will_accept? && criminal_hearing_outcome_recorded.blank? + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def accepted + @decision.next_step.initialize_decision! + end + + def declined + Notifications::MatchDeclined.create_for_match! match + match.thirteen_hearing_outcome_decline_decision.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hearing_outcome_decline.rb b/app/models/match_decisions/thirteen/thirteen_hearing_outcome_decline.rb new file mode 100644 index 000000000..570213e53 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hearing_outcome_decline.rb @@ -0,0 +1,94 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHearingOutcomeDecline < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenDeclineReasons + include MatchDecisions::RouteThirteenCancelReasons + + def to_partial_path + 'match_decisions/thirteen/hearing_outcome_decline' + end + + def step_name + "#{Translation.translate('CoC Thirteen')} Hearing Outcome Decline" + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHearingOutcomeDecline + end + end + + def statuses + { + pending: 'Pending', + decline_overridden: 'Decline Overridden', + decline_overridden_returned: 'Decline Overridden, Returned', + decline_confirmed: 'Decline Confirmed', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm #{Translation.translate('HSA Thirteen')} decline" + when :decline_overridden then "#{Translation.translate('HSA Thirteen')} Decline overridden by #{Translation.translate('CoC Thirteen')}. Match proceeding to #{Translation.translate('CoC Thirteen')}" + when :decline_overridden_returned then "#{Translation.translate('HSA Thirteen')} overridden by #{Translation.translate('CoC Thirteen')}. Match returned to the #{Translation.translate('HSA Thirteen')}" + when :decline_confirmed then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: :pending + send_notifications_for_step if send_notifications + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def decline_overridden + match.thirteen_hearing_outcome_decision.update(status: :skipped) + match.thirteen_hsa_review_decision.initialize_decision! + end + + def decline_overridden_returned + # Re-initialize the previous decision + match.thirteen_hearing_outcome_decision.initialize_decision! + @decision.uninitialize_decision! + end + + def decline_confirmed + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + + def editable? + super && saved_status !~ /decline_overridden|decline_overridden_returned|decline_confirmed/ + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hearing_scheduled.rb b/app/models/match_decisions/thirteen/thirteen_hearing_scheduled.rb new file mode 100644 index 000000000..79b2b1eb3 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hearing_scheduled.rb @@ -0,0 +1,106 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHearingScheduled < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenCancelReasons + include MatchDecisions::RouteThirteenDeclineReasons + + validate :ensure_required_contacts_present_on_accept + validate :criminal_hearing_date_present + + def to_partial_path + 'match_decisions/thirteen/hearing_scheduled' + end + + def step_name + 'Hearing Scheduled' + end + + def actor_type + Translation.translate('HSA Thirteen') + end + + def contact_actor_type + :housing_subsidy_admin_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHearingScheduledShelterAgency + m << Notifications::Thirteen::ThirteenHearingScheduledHsa + m << Notifications::Thirteen::ThirteenHearingScheduledDndStaff + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + declined: 'Declined', + back: 'Pending', + } + end + + def permitted_params + super + [:criminal_hearing_date] + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('HSA Thirteen')} assigned match" + when :accepted then "Hearing Scheduled by #{Translation.translate('HSA Thirteen')}." + when :canceled then canceled_status_label + when :declined then 'Match Declined' + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def criminal_hearing_date_present + errors.add :criminal_hearing_date, 'must be filled in' if save_will_accept? && criminal_hearing_date.blank? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def accepted + @decision.next_step.initialize_decision! + end + + def declined + Notifications::MatchDeclined.create_for_match! match + match.thirteen_hearing_scheduled_decline_decision.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hearing_scheduled_decline.rb b/app/models/match_decisions/thirteen/thirteen_hearing_scheduled_decline.rb new file mode 100644 index 000000000..e54d3feb0 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hearing_scheduled_decline.rb @@ -0,0 +1,94 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHearingScheduledDecline < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenDeclineReasons + include MatchDecisions::RouteThirteenCancelReasons + + def to_partial_path + 'match_decisions/thirteen/hearing_scheduled_decline' + end + + def step_name + "#{Translation.translate('CoC Thirteen')} Hearing Schedule Decline" + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHearingScheduledDecline + end + end + + def statuses + { + pending: 'Pending', + decline_overridden: 'Decline Overridden', + decline_overridden_returned: 'Decline Overridden, Returned', + decline_confirmed: 'Decline Confirmed', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm #{Translation.translate('HSA Thirteen')} decline" + when :decline_overridden then "#{Translation.translate('HSA Thirteen')} Decline overridden by #{Translation.translate('CoC Thirteen')}. Match proceeding to #{Translation.translate('CoC Thirteen')}" + when :decline_overridden_returned then "#{Translation.translate('HSA Thirteen')} overridden by #{Translation.translate('CoC Thirteen')}. Match returned to the #{Translation.translate('HSA Thirteen')}" + when :decline_confirmed then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: :pending + send_notifications_for_step if send_notifications + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def decline_overridden + match.thirteen_hearing_scheuled_decision.update(status: :skipped) + match.thirteen_hearing_outcome_decision.initialize_decision! + end + + def decline_overridden_returned + # Re-initialize the previous decision + match.thirteen_hearing_scheuled_decision.initialize_decision! + @decision.uninitialize_decision! + end + + def decline_confirmed + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + + def editable? + super && saved_status !~ /decline_overridden|decline_overridden_returned|decline_confirmed/ + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hsa_review.rb b/app/models/match_decisions/thirteen/thirteen_hsa_review.rb new file mode 100644 index 000000000..767fe2ca9 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hsa_review.rb @@ -0,0 +1,97 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHsaReview < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenCancelReasons + include MatchDecisions::RouteThirteenDeclineReasons + + validate :ensure_required_contacts_present_on_accept + + def to_partial_path + 'match_decisions/thirteen/hsa_review' + end + + def step_name + "#{Translation.translate('HSA Thirteen')} Review" + end + + def actor_type + Translation.translate('HSA Thirteen') + end + + def contact_actor_type + :housing_subsidy_admin_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHsaReviewShelterAgency + m << Notifications::Thirteen::ThirteenHsaReviewHsa + m << Notifications::Thirteen::ThirteenHsaReviewDndStaff + end + end + + def statuses + { + pending: 'Pending', + accepted: 'Accepted', + canceled: 'Canceled', + declined: 'Declined', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('HSA Thirteen')} assigned match" + when :accepted then "Match Reeviewed by #{Translation.translate('HSA Thirteen')}." + when :canceled then canceled_status_label + when :declined then 'Match Declined' + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'accepted' + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def accepted + @decision.next_step.initialize_decision! + end + + def declined + Notifications::MatchDeclined.create_for_match! match + match.thirteen_hsa_review_decline_decision.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_hsa_review_decline.rb b/app/models/match_decisions/thirteen/thirteen_hsa_review_decline.rb new file mode 100644 index 000000000..f26ef2f39 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_hsa_review_decline.rb @@ -0,0 +1,94 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenHsaReviewDecline < ::MatchDecisions::Base + include MatchDecisions::AcceptsDeclineReason + include MatchDecisions::RouteThirteenDeclineReasons + include MatchDecisions::RouteThirteenCancelReasons + + def to_partial_path + 'match_decisions/thirteen/hsa_review_decline' + end + + def step_name + "#{Translation.translate('CoC Thirteen')} HSA Review Decline" + end + + def actor_type + Translation.translate('CoC Thirteen') + end + + def contact_actor_type + :dnd_staff_contacts + end + + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenHsaReviewDecline + end + end + + def statuses + { + pending: 'Pending', + decline_overridden: 'Decline Overridden', + decline_overridden_returned: 'Decline Overridden, Returned', + decline_confirmed: 'Decline Confirmed', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('CoC Thirteen')} to confirm #{Translation.translate('HSA Thirteen')} decline" + when :decline_overridden then "#{Translation.translate('HSA Thirteen')} Decline overridden by #{Translation.translate('CoC Thirteen')}. Match proceeding to #{Translation.translate('CoC Thirteen')}" + when :decline_overridden_returned then "#{Translation.translate('HSA Thirteen')} overridden by #{Translation.translate('CoC Thirteen')}. Match returned to the #{Translation.translate('HSA Thirteen')}" + when :decline_confirmed then "Match rejected by #{Translation.translate('CoC Thirteen')}" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: :pending + send_notifications_for_step if send_notifications + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def decline_overridden + match.thirteen_hsa_review_decision.update(status: :skipped) + match.thirteen_accept_referral_decision.initialize_decision! + end + + def decline_overridden_returned + # Re-initialize the previous decision + match.thirteen_hsa_review_decision.initialize_decision! + @decision.uninitialize_decision! + end + + def decline_confirmed + Notifications::MatchRejected.create_for_match! match + match.rejected! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + + def editable? + super && saved_status !~ /decline_overridden|decline_overridden_returned|decline_confirmed/ + end + end +end diff --git a/app/models/match_decisions/thirteen/thirteen_match_acknowledgement.rb b/app/models/match_decisions/thirteen/thirteen_match_acknowledgement.rb new file mode 100644 index 000000000..500b5d786 --- /dev/null +++ b/app/models/match_decisions/thirteen/thirteen_match_acknowledgement.rb @@ -0,0 +1,87 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchDecisions::Thirteen + class ThirteenMatchAcknowledgement < ::MatchDecisions::Base + include MatchDecisions::RouteThirteenCancelReasons + + validate :ensure_required_contacts_present_on_accept + + def to_partial_path + 'match_decisions/thirteen/match_acknowledgement' + end + + def step_name + 'Match Acknowledged' + end + + def actor_type + Translation.translate('Shelter Agency Thirteen') + end + + def contact_actor_type + :shelter_agency_contacts + end + + # Notifications to send when this step is initiated + def notifications_for_this_step + @notifications_for_this_step ||= [].tap do |m| + m << Notifications::Thirteen::ThirteenMatchAcknowledgementShelterAgency + m << Notifications::Thirteen::ThirteenMatchAcknowledgementHsa + end + end + + def statuses + { + pending: 'Pending', + acknowledged: 'Acknowledged', + canceled: 'Canceled', + back: 'Pending', + } + end + + def label_for_status status + case status.to_sym + when :pending then "#{Translation.translate('Shelter Agency Thirteen')} assigned match" + when :acknowledged then "Match acknowledged by #{Translation.translate('Shelter Agency Thirteen')}. In review" + when :canceled then canceled_status_label + when :back then backup_status_label + end + end + + def initialize_decision! send_notifications: true + super(send_notifications: send_notifications) + update status: 'pending' + send_notifications_for_step if send_notifications + end + + private def ensure_required_contacts_present_on_accept + missing_contacts = [] + missing_contacts << "a #{Translation.translate('Shelter Agency Thirteen')} Contact" if save_will_accept? && match.shelter_agency_contacts.none? + + errors.add :match_contacts, "needs #{missing_contacts.to_sentence}" if missing_contacts.any? + end + + private def save_will_accept? + saved_status == 'pending' && status == 'acknowledged' + end + + class StatusCallbacks < StatusCallbacks + def pending + end + + def acknowledged + @decision.next_step.initialize_decision! + end + + def canceled + Notifications::MatchCanceled.create_for_match! match + match.canceled! + end + end + private_constant :StatusCallbacks + end +end diff --git a/app/models/match_routes/base.rb b/app/models/match_routes/base.rb index cca121435..9759e8127 100644 --- a/app/models/match_routes/base.rb +++ b/app/models/match_routes/base.rb @@ -44,6 +44,7 @@ def self.all_routes MatchRoutes::Ten, MatchRoutes::Eleven, MatchRoutes::Twelve, + MatchRoutes::Thirteen, ] end diff --git a/app/models/match_routes/thirteen.rb b/app/models/match_routes/thirteen.rb new file mode 100644 index 000000000..af51e63db --- /dev/null +++ b/app/models/match_routes/thirteen.rb @@ -0,0 +1,102 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module MatchRoutes + class Thirteen < Base + def title + Translation.translate('Match Route Thirteen') + end + + def self.available_sub_types_for_search + match_steps_for_reporting.keys + end + + def self.match_steps + { + 'MatchDecisions::Thirteen::ThirteenClientMatch' => 1, + 'MatchDecisions::Thirteen::ThirteenMatchAcknowledgement' => 2, + 'MatchDecisions::Thirteen::ThirteenClientReview' => 3, + 'MatchDecisions::Thirteen::ThirteenHearingScheduled' => 4, + 'MatchDecisions::Thirteen::ThirteenHearingOutcome' => 5, + 'MatchDecisions::Thirteen::ThirteenHsaReview' => 6, + 'MatchDecisions::Thirteen::ThirteenAcceptReferral' => 7, + 'MatchDecisions::Thirteen::ThirteenConfirmMatchSuccess' => 8, + } + end + + def self.match_steps_for_reporting + { + 'MatchDecisions::Thirteen::ThirteenClientMatch' => 1, + 'MatchDecisions::Thirteen::ThirteenMatchAcknowledgement' => 2, + 'MatchDecisions::Thirteen::ThirteenClientReview' => 3, + 'MatchDecisions::Thirteen::ThirteenClientReviewDecline' => 4, + 'MatchDecisions::Thirteen::ThirteenHearingScheduled' => 5, + 'MatchDecisions::Thirteen::ThirteenHearingScheduledDecline' => 6, + 'MatchDecisions::Thirteen::ThirteenHearingOutcome' => 7, + 'MatchDecisions::Thirteen::ThirteenHearingOutcomeDecline' => 8, + 'MatchDecisions::Thirteen::ThirteenHsaReview' => 9, + 'MatchDecisions::Thirteen::ThirteenHsaReviewDecline' => 10, + 'MatchDecisions::Thirteen::ThirteenAcceptReferral' => 11, + 'MatchDecisions::Thirteen::ThirteenAcceptReferralDecline' => 12, + 'MatchDecisions::Thirteen::ThirteenConfirmMatchSuccess' => 13, + } + end + + def required_contact_types + [ + 'shelter_agency_contacts', + 'housing_subsidy_admin_contacts', + 'ssp_contacts', + 'hsp_contacts', + 'dnd_staff_contacts', + ] + end + + def contact_label_for(contact_type) + case contact_type + when :shelter_agency_contacts + Translation.translate('Shelter Agency Thirteen') + when :housing_subsidy_admin_contacts + Translation.translate('HSA Thirteen') + when :ssp_contacts + Translation.translate('Stabilization Service Providers Thirteen') + when :hsp_contacts + Translation.translate('Housing Search Provider Thirteen') + when :dnd_staff_contacts + Translation.translate('CoC Thirteen') + else + super + end + end + + def initial_decision + :thirteen_client_match_decision + end + + def success_decision + :thirteen_confirm_match_success_decision + end + + def initial_contacts_for_match + :dnd_staff_contacts + end + + def status_declined?(match) + [ + match.thirteen_client_review_decision&.status == 'declined' && + match.thirteen_client_review_decision_dnd_staff_decision&.status != 'decline_overridden', + match.thirteen_hearing_scheduled_decision&.status == 'declined' && + match.thirteen_hearing_scheduled_decision_dnd_staff_decision&.status != 'decline_overridden', + match.thirteen_hearing_outcome_decision&.status == 'declined' && + match.thirteen_hearing_outcome_decision_dnd_staff_decision&.status != 'decline_overridden', + match.thirteen_hsa_review_decision&.status == 'declined' && + match.thirteen_hsa_review_decision_dnd_staff_decision&.status != 'decline_overridden', + match.thirteen_accept_referral_decision&.status == 'declined' && + match.thirteen_accept_referral_decision_dnd_staff_decision&.status != 'decline_overridden', + ].any? + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_accept_referral_decline.rb b/app/models/notifications/thirteen/thirteen_accept_referral_decline.rb new file mode 100644 index 000000000..c256253ff --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_accept_referral_decline.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenAcceptReferralDecline < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_accept_referral_decline_dnd_staff_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of #{Translation.translate('HSA Thirteen')} decline. Confirmation pending." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_accept_referral_hsa.rb b/app/models/notifications/thirteen/thirteen_accept_referral_hsa.rb new file mode 100644 index 000000000..41c6b7875 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_accept_referral_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenAcceptReferralHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_accept_referral_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of match update - pending #{Translation.translate('HSA Thirteen')} accepting referral." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_accept_referral_hsp.rb b/app/models/notifications/thirteen/thirteen_accept_referral_hsp.rb new file mode 100644 index 000000000..76ee140b0 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_accept_referral_hsp.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenAcceptReferralHsp < ::Notifications::Base + def self.create_for_match! match + match.hsp_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_accept_referral_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of match update - pending #{Translation.translate('HSA Thirteen')} accepting referral." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_accept_referral_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_accept_referral_shelter_agency.rb new file mode 100644 index 000000000..d0aa0ae89 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_accept_referral_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenAcceptReferralShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_accept_referral_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of match update - pending #{Translation.translate('HSA Thirteen')} accepting referral." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_accept_referral_ssp.rb b/app/models/notifications/thirteen/thirteen_accept_referral_ssp.rb new file mode 100644 index 000000000..9bc4606eb --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_accept_referral_ssp.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenAcceptReferralSsp < ::Notifications::Base + def self.create_for_match! match + match.ssp_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_accept_referral_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of match update - pending #{Translation.translate('HSA Thirteen')} accepting referral." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_client_match.rb b/app/models/notifications/thirteen/thirteen_client_match.rb new file mode 100644 index 000000000..82e522e8c --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_client_match.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenClientMatch < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_client_match_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_client_review_decline.rb b/app/models/notifications/thirteen/thirteen_client_review_decline.rb new file mode 100644 index 000000000..15ee481eb --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_client_review_decline.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenClientReviewDecline < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_client_review_decline_dnd_staff_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of #{Translation.translate('Shelter Agency Thirteen')} decline. Confirmation pending." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_client_review_dnd_staff.rb b/app/models/notifications/thirteen/thirteen_client_review_dnd_staff.rb new file mode 100644 index 000000000..ee504d21c --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_client_review_dnd_staff.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenClientReviewDndStaff < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_client_review_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of acknowledged match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_client_review_hsa.rb b/app/models/notifications/thirteen/thirteen_client_review_hsa.rb new file mode 100644 index 000000000..db73fec95 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_client_review_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenClientReviewHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_client_review_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of acknowledged match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_client_review_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_client_review_shelter_agency.rb new file mode 100644 index 000000000..f4e5f3d9a --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_client_review_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenClientReviewShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_client_review_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of acknowledged match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_confirm_match_success_dnd_staff.rb b/app/models/notifications/thirteen/thirteen_confirm_match_success_dnd_staff.rb new file mode 100644 index 000000000..136d88a3c --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_confirm_match_success_dnd_staff.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenConfirmMatchSuccessDndStaff < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of referral acceptance." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_confirm_match_success_hsa.rb b/app/models/notifications/thirteen/thirteen_confirm_match_success_hsa.rb new file mode 100644 index 000000000..e920fd91b --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_confirm_match_success_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenConfirmMatchSuccessHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of referral acceptance." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_confirm_match_success_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_confirm_match_success_shelter_agency.rb new file mode 100644 index 000000000..40ea35ee7 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_confirm_match_success_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenConfirmMatchSuccessShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of referral acceptance." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_outcome_decline.rb b/app/models/notifications/thirteen/thirteen_hearing_outcome_decline.rb new file mode 100644 index 000000000..4460cf0f2 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_outcome_decline.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingOutcomedDecline < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.hearing_outcome_decline_dnd_staff_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of #{Translation.translate('HSA Thirteen')} decline. Confirmation pending." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_outcome_dnd_staff.rb b/app/models/notifications/thirteen/thirteen_hearing_outcome_dnd_staff.rb new file mode 100644 index 000000000..2441c42cc --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_outcome_dnd_staff.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingOutcomeDndStaff < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_outcome_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of scheduled hearing." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_outcome_hsa.rb b/app/models/notifications/thirteen/thirteen_hearing_outcome_hsa.rb new file mode 100644 index 000000000..669d474fc --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_outcome_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingOutcomeHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_outcome_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified to submit hearing outcome." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_outcome_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_hearing_outcome_shelter_agency.rb new file mode 100644 index 000000000..515752c26 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_outcome_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingOutcomeShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_outcome_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of scheduled hearing." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_scheduled_decline.rb b/app/models/notifications/thirteen/thirteen_hearing_scheduled_decline.rb new file mode 100644 index 000000000..8d20bffac --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_scheduled_decline.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingScheduledDecline < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.hearing_scheduled_decline_dnd_staff_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of #{Translation.translate('HSA Thirteen')} decline. Confirmation pending." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_scheduled_dnd_staff.rb b/app/models/notifications/thirteen/thirteen_hearing_scheduled_dnd_staff.rb new file mode 100644 index 000000000..097234ca2 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_scheduled_dnd_staff.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingScheduledDndStaff < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_scheduled_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of pending #{Translation.translate('CORI hearing')} review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_scheduled_hsa.rb b/app/models/notifications/thirteen/thirteen_hearing_scheduled_hsa.rb new file mode 100644 index 000000000..7ae0d67ef --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_scheduled_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingScheduledHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_scheduled_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified to schedule CORI review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hearing_scheduled_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_hearing_scheduled_shelter_agency.rb new file mode 100644 index 000000000..df66a3e63 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hearing_scheduled_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHearingScheduledShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hearing_scheduled_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of pending CORI review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hsa_review_decline.rb b/app/models/notifications/thirteen/thirteen_hsa_review_decline.rb new file mode 100644 index 000000000..b58ca49de --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hsa_review_decline.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHsaReviewDecline < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.hsa_review_decline_dnd_staff_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of #{Translation.translate('HSA Thirteen')} decline. Confirmation pending." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hsa_review_dnd_staff.rb b/app/models/notifications/thirteen/thirteen_hsa_review_dnd_staff.rb new file mode 100644 index 000000000..767a56175 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hsa_review_dnd_staff.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHsaReviewDndStaff < ::Notifications::Base + def self.create_for_match! match + match.dnd_staff_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('CoC Thirteen')} notified of pending #{Translation.translate('HSA Thirteen')} review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hsa_review_hsa.rb b/app/models/notifications/thirteen/thirteen_hsa_review_hsa.rb new file mode 100644 index 000000000..876e5ad96 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hsa_review_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHsaReviewHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified to submit their review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_hsa_review_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_hsa_review_shelter_agency.rb new file mode 100644 index 000000000..00aff2f54 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_hsa_review_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenHsaReviewShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_hsa_review_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of pending #{Translation.translate('HSA Thirteen')} review." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_match_acknowledgement_hsa.rb b/app/models/notifications/thirteen/thirteen_match_acknowledgement_hsa.rb new file mode 100644 index 000000000..a71fa53ca --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_match_acknowledgement_hsa.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenMatchAcknowledgementHsa < ::Notifications::Base + def self.create_for_match! match + match.housing_subsidy_admin_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_match_acknowledgement_decision + end + + def event_label + "#{Translation.translate('HSA Thirteen')} notified of match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/notifications/thirteen/thirteen_match_acknowledgement_shelter_agency.rb b/app/models/notifications/thirteen/thirteen_match_acknowledgement_shelter_agency.rb new file mode 100644 index 000000000..d4d9d0d95 --- /dev/null +++ b/app/models/notifications/thirteen/thirteen_match_acknowledgement_shelter_agency.rb @@ -0,0 +1,27 @@ +### +# Copyright 2016 - 2024 Green River Data Analysis, LLC +# +# License detail: https://github.com/greenriver/boston-cas/blob/production/LICENSE.md +### + +module Notifications::Thirteen + class ThirteenMatchAcknowledgementShelterAgency < ::Notifications::Base + def self.create_for_match! match + match.shelter_agency_contacts.each do |contact| + create! match: match, recipient: contact + end + end + + def decision + match.thirteen_match_acknowledgement_decision + end + + def event_label + "#{Translation.translate('Shelter Agency Thirteen')} notified of match." + end + + def to_partial_path + "notifications/thirteen/#{notification_type}" + end + end +end diff --git a/app/models/translation.rb b/app/models/translation.rb index cafded986..202600c87 100644 --- a/app/models/translation.rb +++ b/app/models/translation.rb @@ -92,8 +92,10 @@ def self.known_translations 'CoC Six', 'CoC Eleven', 'CoC Twelve', + 'CoC Thirteen', 'Confirm Match Success', 'Confirm Match Success Six', + 'CORI hearing', 'Criminal Background Hearing', 'Criminal Background Hearing Scheduled', 'CSPECH Eligible', @@ -142,6 +144,7 @@ def self.known_translations 'Housing Search Provider Eight', 'Housing Search Provider Eleven', 'Housing Search Provider Nine', + 'Housing Search Provider Thirteen', 'Housing Search Providers', 'Housing Search Worker', 'housing subsidy administrator', @@ -157,6 +160,7 @@ def self.known_translations 'HSA Eight', 'HSA Eleven', 'HSA Twelve', + 'HSA Thirteen', 'HSA Complete Match', 'HSA Complete Match Six', 'HSA Nine', @@ -188,6 +192,7 @@ def self.known_translations 'Match Route Six', 'Match Route Ten', 'Match Route Twelve', + 'Match Route Thirteen', 'match shelter agency agreement modal', 'Match status update', 'Meth Production Conviction', @@ -243,6 +248,7 @@ def self.known_translations 'Shelter Agency Nine', 'Shelter Agency Six', 'Shelter Agency Twelve', + 'Shelter Agency Thirteen', 'shelter case manager', 'Should this tag be added to anyone with an assessment score?', 'SSP', @@ -254,6 +260,7 @@ def self.known_translations 'Stabilization Service Providers', 'Stabilization Services Provider', 'Stabilization Service Providers Eleven', + 'Stabilization Service Providers Thirteen', 'Staff Decline', 'Strengths', 'Submit Client Application', diff --git a/app/views/match_decisions/_cancel_actions.haml b/app/views/match_decisions/_cancel_actions.haml index a541ec65e..2980eb332 100644 --- a/app/views/match_decisions/_cancel_actions.haml +++ b/app/views/match_decisions/_cancel_actions.haml @@ -4,14 +4,14 @@ = render 'match_decisions/cancel_tab', active_tab: 'active' = render 'match_decisions/shelter_decline_tab' = render 'match_decisions/park_tab' - = render 'match_decisions/backup_tab' + = render 'match_decisions/backup_tab' unless @decision.previous_step.nil? .o-choose__content .tab-content - cancel_data = {submit_param_name: 'decision[status]', submit_param_value: 'canceled'} = render 'match_decisions/cancel_tab_content', form: form, cancel_data: cancel_data, active_tab: 'active' = render 'match_decisions/shelter_decline_content', form: form, cancel_data: cancel_data = render 'match_decisions/park_tab_content', form: form, cancel_data: cancel_data - = render 'match_decisions/backup_tab_content', form: form, cancel_data: cancel_data + = render 'match_decisions/backup_tab_content', form: form, cancel_data: cancel_data unless @decision.previous_step.nil? = content_for :page_js do :javascript diff --git a/app/views/match_decisions/thirteen/_accept_referral.haml b/app/views/match_decisions/thirteen/_accept_referral.haml new file mode 100644 index 000000000..8953ffedb --- /dev/null +++ b/app/views/match_decisions/thirteen/_accept_referral.haml @@ -0,0 +1,18 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-choose.o-choose--flush.o-choose--flush-top + .o-choose__choice{class: [('o-choose__choice--disabled' if !@decision.editable?)]} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Accept Match + .o-choose__content + = form.input :date_voucher_issued, label: 'Date voucher issued', as: :date_picker, disabled: !@decision.editable? + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + %p + %i.icon-info + If the match is accepted, all involved parties will be notified. + + = render 'match_decisions/continue_button', text: 'Accept Match', icon: 'checkmark', button_attributes: { class: 'btn btn-success jAccept', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) } + = render 'match_decisions/decline_and_cancel_backup_actions', form: form, action_message: "If the match is declined, the #{Translation.translate('CoC Thirteen')} will be informed of the decision." diff --git a/app/views/match_decisions/thirteen/_accept_referral_decline.haml b/app/views/match_decisions/thirteen/_accept_referral_decline.haml new file mode 100644 index 000000000..052f1ef15 --- /dev/null +++ b/app/views/match_decisions/thirteen/_accept_referral_decline.haml @@ -0,0 +1,24 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + - if can_reject_matches? + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--park + %h3 Park Client + .o-choose__content + = render 'match_decisions/park_client', form: form + .o-choose__choice{ class: ('o-choose__choice--100' unless can_reject_matches?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--reject + %h3 Review Decline + .o-choose__content + = render 'match_decisions/decline_overrides', form: form diff --git a/app/views/match_decisions/thirteen/_client_match.haml b/app/views/match_decisions/thirteen/_client_match.haml new file mode 100644 index 000000000..daf26c806 --- /dev/null +++ b/app/views/match_decisions/thirteen/_client_match.haml @@ -0,0 +1,29 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + = render 'match_decisions/shelter_agency_expiration', form: form + - if ! @match.shelter_expiration? || @match.shelter_expiration >= Date.current || can_reject_matches? + .o-pre-choose + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Accept Match + .o-choose__content + - if has_unit? + %p + Please confirm the client's building and unit. + .form-inputs + .building-and-unit + = form.input :building_id, collection: Building.all, selected: default_building_id , label: 'Building', disabled: !@decision.editable?, input_html: {class: 'building', notification_id: notification_id} + = form.input :unit_id, collection: candidate_units, selected: default_unit_id, label: 'Unit', disabled: !@decision.editable?, + input_html: {class: 'unit', data: {dependent: true, url: '/buildings/:id/available_move_in_units.json', 'value-method' => :id, 'label-method' => :name, default_parent_id: default_building_id, default_value: default_unit_id, default_label: default_unit_name}} + %p + %i.icon-info + If accepted, all involved parties will be notified. + + = form.submit 'Accept Match', class: 'btn btn-success jAccept', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) + + = render 'match_decisions/cancel_actions', form: form \ No newline at end of file diff --git a/app/views/match_decisions/thirteen/_client_review.haml b/app/views/match_decisions/thirteen/_client_review.haml new file mode 100644 index 000000000..4a9903836 --- /dev/null +++ b/app/views/match_decisions/thirteen/_client_review.haml @@ -0,0 +1,17 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-choose.o-choose--flush.o-choose--flush-top + .o-choose__choice{class: [('o-choose__choice--disabled' if !@decision.editable?)]} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Accept Match + .o-choose__content + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + %p + %i.icon-info + If the match is accepted, all involved parties will be notified. + + = render 'match_decisions/continue_button', text: 'Accept Match', icon: 'checkmark', button_attributes: { class: 'btn btn-success jAccept', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) } + = render 'match_decisions/decline_and_cancel_backup_actions', form: form, action_message: "If the match is declined, the #{Translation.translate('CoC Thirteen')} will be informed of the decision." diff --git a/app/views/match_decisions/thirteen/_client_review_decline.haml b/app/views/match_decisions/thirteen/_client_review_decline.haml new file mode 100644 index 000000000..052f1ef15 --- /dev/null +++ b/app/views/match_decisions/thirteen/_client_review_decline.haml @@ -0,0 +1,24 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + - if can_reject_matches? + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--park + %h3 Park Client + .o-choose__content + = render 'match_decisions/park_client', form: form + .o-choose__choice{ class: ('o-choose__choice--100' unless can_reject_matches?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--reject + %h3 Review Decline + .o-choose__content + = render 'match_decisions/decline_overrides', form: form diff --git a/app/views/match_decisions/thirteen/_confirm_match_success.haml b/app/views/match_decisions/thirteen/_confirm_match_success.haml new file mode 100644 index 000000000..031433b25 --- /dev/null +++ b/app/views/match_decisions/thirteen/_confirm_match_success.haml @@ -0,0 +1,19 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: !(@decision.editable?)} + .o-choose.o-choose--flush + .o-choose__choice{class: ('o-choose__choice--disabled' if !@decision.editable?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Confirm Match + .o-choose__content + %p Confirming match success will complete the match and remove the client and voucher/unit from future matching. + -# = form.submit 'Confirm Match Success', class: 'btn btn-success', data: {submit_param_name: 'decision[status]', submit_param_value: 'confirmed'}, disabled: !(@decision.editable?) + = render 'match_decisions/continue_button', text: 'Confirm Match Success', icon: 'checkmark', button_attributes: { class: 'btn btn-success', data: {submit_param_name: 'decision[status]', submit_param_value: 'confirmed'}, disabled: !(@decision.editable?) } + = render 'match_decisions/reject_actions', form: form diff --git a/app/views/match_decisions/thirteen/_hearing_outcome.haml b/app/views/match_decisions/thirteen/_hearing_outcome.haml new file mode 100644 index 000000000..325c814f9 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hearing_outcome.haml @@ -0,0 +1,65 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-choose.o-choose--flush.o-choose--flush-top + - if @decision.accessible_by?(current_contact) + .o-choose__choice{class: [('o-choose__choice--disabled' if !@decision.editable?), ( 'o-choose__choice--100' unless can_reject_matches?)]} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Continue Match + .o-choose__content + - if @match.match_route.show_hearing_date + %p + - hearing_date = @match.thirteen_hearing_scheduled_decision.criminal_hearing_date + - if hearing_date.present? + = "Please note: #{Translation.translate('a hearing has been schedule for')}" + %strong + = "#{hearing_date.to_s}." + = form.input :criminal_hearing_outcome_recorded, as: :boolean, required: true, inline_label: "#{Translation.translate('The outcome of the hearing has been recorded')}" + -#= form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .jScheduled.d-none + %label(for="decision_criminal_hearing_date")= "Hearing Outcome" + .row.form-group + .col-md-6 + = form.input :criminal_hearing_date, as: :string, label: false, disabled: !@decision.editable?, input_html: {class: :date_time_picker, style: 'width: 15em;'} + + = render 'match_decisions/continue_button', text: 'Continue Match', icon: 'checkmark', button_attributes: { class: 'btn btn-success jSubmit', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) } + = render 'match_decisions/decline_and_cancel_backup_actions', form: form, action_message: "If the match is declined, the #{Translation.translate('CoC Thirteen')} will be informed of the decision." + += content_for :page_js do + :javascript + $('.date_time_picker').datetimepicker({ + sideBySide: true, + stepping: 15, + format: "MMM D, YYYY h:mm a", + icons: { + time: "icon icon-clock", + date: "icon icon-calendar", + up: "icon icon-arrow-up", + down: "icon icon-arrow-down" + } + }); + + function update_button_states() { + var prevent_matching_present = $('#decision_prevent_matching_until').val() != '' + if(prevent_matching_present) { + $('.jSubmit').attr('disabled', 'disabled'); + $('.jCancel').removeAttr('disabled'); + } else { + $('.jSubmit').removeAttr('disabled'); + + } + } + + $('#decision_prevent_matching_until').on("change", update_button_states); + $('#decision_prevent_matching_until').trigger('change'); + + $('.jSelections input').on('change', function(){ + var action = 'addClass' + if ($(this).val() === 'scheduled') { + action = 'removeClass' + } + $('.jScheduled')[action]('d-none') + }); + $('.jSelections input:checked').trigger('change'); diff --git a/app/views/match_decisions/thirteen/_hearing_outcome_decline.haml b/app/views/match_decisions/thirteen/_hearing_outcome_decline.haml new file mode 100644 index 000000000..052f1ef15 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hearing_outcome_decline.haml @@ -0,0 +1,24 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + - if can_reject_matches? + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--park + %h3 Park Client + .o-choose__content + = render 'match_decisions/park_client', form: form + .o-choose__choice{ class: ('o-choose__choice--100' unless can_reject_matches?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--reject + %h3 Review Decline + .o-choose__content + = render 'match_decisions/decline_overrides', form: form diff --git a/app/views/match_decisions/thirteen/_hearing_scheduled.haml b/app/views/match_decisions/thirteen/_hearing_scheduled.haml new file mode 100644 index 000000000..b824fa0d2 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hearing_scheduled.haml @@ -0,0 +1,56 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-choose.o-choose--flush.o-choose--flush-top + - if @decision.accessible_by?(current_contact) + .o-choose__choice{class: [('o-choose__choice--disabled' if !@decision.editable?), ( 'o-choose__choice--100' unless can_reject_matches?)]} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Continue Match + .o-choose__content + .jScheduled + %label(for="decision_criminal_hearing_date")= Translation.translate('Date and time of criminal background hearing') + .row.form-group + .col-md-6 + = form.input :criminal_hearing_date, as: :string, label: false, disabled: !@decision.editable?, input_html: {class: :date_time_picker, style: 'width: 15em;'} + + = render 'match_decisions/continue_button', text: 'Continue Match', icon: 'checkmark', button_attributes: { class: 'btn btn-success jSubmit', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) } + = render 'match_decisions/decline_and_cancel_backup_actions', form: form, action_message: "If the match is declined, the #{Translation.translate('CoC Thirteen')} will be informed of the decision." + += content_for :page_js do + :javascript + $('.date_time_picker').datetimepicker({ + sideBySide: true, + stepping: 15, + format: "MMM D, YYYY h:mm a", + icons: { + time: "icon icon-clock", + date: "icon icon-calendar", + up: "icon icon-arrow-up", + down: "icon icon-arrow-down" + } + }); + + function update_button_states() { + var prevent_matching_present = $('#decision_prevent_matching_until').val() != '' + if(prevent_matching_present) { + $('.jSubmit').attr('disabled', 'disabled'); + $('.jCancel').removeAttr('disabled'); + } else { + $('.jSubmit').removeAttr('disabled'); + + } + } + + $('#decision_prevent_matching_until').on("change", update_button_states); + $('#decision_prevent_matching_until').trigger('change'); + + $('.jSelections input').on('change', function(){ + var action = 'addClass' + if ($(this).val() === 'scheduled') { + action = 'removeClass' + } + $('.jScheduled')[action]('d-none') + }); + $('.jSelections input:checked').trigger('change'); diff --git a/app/views/match_decisions/thirteen/_hearing_scheduled_decline.haml b/app/views/match_decisions/thirteen/_hearing_scheduled_decline.haml new file mode 100644 index 000000000..052f1ef15 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hearing_scheduled_decline.haml @@ -0,0 +1,24 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + - if can_reject_matches? + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--park + %h3 Park Client + .o-choose__content + = render 'match_decisions/park_client', form: form + .o-choose__choice{ class: ('o-choose__choice--100' unless can_reject_matches?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--reject + %h3 Review Decline + .o-choose__content + = render 'match_decisions/decline_overrides', form: form diff --git a/app/views/match_decisions/thirteen/_hsa_review.haml b/app/views/match_decisions/thirteen/_hsa_review.haml new file mode 100644 index 000000000..4a9903836 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hsa_review.haml @@ -0,0 +1,17 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-choose.o-choose--flush.o-choose--flush-top + .o-choose__choice{class: [('o-choose__choice--disabled' if !@decision.editable?)]} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Accept Match + .o-choose__content + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + %p + %i.icon-info + If the match is accepted, all involved parties will be notified. + + = render 'match_decisions/continue_button', text: 'Accept Match', icon: 'checkmark', button_attributes: { class: 'btn btn-success jAccept', data: {submit_param_name: 'decision[status]', submit_param_value: 'accepted'}, disabled: (!@decision.editable?) } + = render 'match_decisions/decline_and_cancel_backup_actions', form: form, action_message: "If the match is declined, the #{Translation.translate('CoC Thirteen')} will be informed of the decision." diff --git a/app/views/match_decisions/thirteen/_hsa_review_decline.haml b/app/views/match_decisions/thirteen/_hsa_review_decline.haml new file mode 100644 index 000000000..052f1ef15 --- /dev/null +++ b/app/views/match_decisions/thirteen/_hsa_review_decline.haml @@ -0,0 +1,24 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + .o-pre-choose + .form-inputs + .row + .col-md-6 + = form.input :note, as: :text, input_html: {rows: 4, disabled: (!@decision.editable?)} + .o-choose.o-choose--flush + - if can_reject_matches? + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--park + %h3 Park Client + .o-choose__content + = render 'match_decisions/park_client', form: form + .o-choose__choice{ class: ('o-choose__choice--100' unless can_reject_matches?)} + %header + .o-choose__title + .c-choice-icon.c-choice-icon--reject + %h3 Review Decline + .o-choose__content + = render 'match_decisions/decline_overrides', form: form diff --git a/app/views/match_decisions/thirteen/_match_acknowledgement.haml b/app/views/match_decisions/thirteen/_match_acknowledgement.haml new file mode 100644 index 000000000..b43bc6264 --- /dev/null +++ b/app/views/match_decisions/thirteen/_match_acknowledgement.haml @@ -0,0 +1,34 @@ +.match-decision.c-card.c-card--flush.card--block + .c-card__content + = simple_form_for @decision, url: access_context.match_decision_path(@match, @decision) do |form| + = render 'match_decisions/shelter_agency_expiration', form: form + - if ! @match.shelter_expiration? || @match.shelter_expiration >= Date.current || can_reject_matches? + .o-choose.o-choose--flush + .o-choose__choice + %header + .o-choose__title + .c-choice-icon.c-choice-icon--confirm.mr-4 + %h3 Acknowledge Match + .o-choose__content + - if @decision.status.to_s.in?(['pending', 'expiration_update']) + %div{data: {acknowledge_href: access_context.match_decision_acknowledgment_path(@match, @decision)}} + = render 'match_decisions/continue_button', text: 'Acknowledge Receipt of Match Details', icon: 'checkmark', button_attributes: { class: 'btn btn-success', data: {submit_param_name: 'decision[status]', submit_param_value: 'acknowledged'}, disabled: !(@decision.editable?) } + - if can_reject_matches? + .o-choose__choice + %header.jMatchHeader + %ul.o-choose__nav.nav.jMatchActionNav + = render 'match_decisions/cancel_tab', active_tab: 'active' + = render 'match_decisions/park_tab' + = render 'match_decisions/backup_tab' + .o-choose__content + .tab-content + - cancel_data = {submit_param_name: 'decision[status]', submit_param_value: 'canceled'} + = render 'match_decisions/cancel_tab_content', form: form, cancel_data: cancel_data, active_tab: 'active' + = render 'match_decisions/park_tab_content', form: form, cancel_data: cancel_data + = render 'match_decisions/backup_tab_content', form: form + + = content_for :page_js do + :javascript + new App.Matches.ActionNav('.jMatchHeader') + + = render 'match_decisions/cancel_and_park_js' diff --git a/app/views/notifications_mailer/thirteen/thirteen_accept_referral_decline.haml b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_decline.haml new file mode 100644 index 000000000..1d3653c47 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_decline.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ += "A #{Translation.translate('HSA Thirteen')} has declined a housing match." +\ += "The match now requires #{Translation.translate('CoC Thirteen')} confirmation to fully close it and make the voucher or unit and client available for future matching." +\ +Please review details here and take action: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsa.text.haml new file mode 100644 index 000000000..cd24c9dca --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsa.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The review by #{Translation.translate('HSA Thirteen')} has been completed - it is now ready for your action. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsp.text.haml b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsp.text.haml new file mode 100644 index 000000000..dd867d4b6 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_hsp.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The review by #{Translation.translate('HSA Thirteen')} has been completed. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_accept_referral_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_shelter_agency.text.haml new file mode 100644 index 000000000..dd867d4b6 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_shelter_agency.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The review by #{Translation.translate('HSA Thirteen')} has been completed. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_accept_referral_ssp.text.haml b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_ssp.text.haml new file mode 100644 index 000000000..dd867d4b6 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_accept_referral_ssp.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The review by #{Translation.translate('HSA Thirteen')} has been completed. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_client_match.text.haml b/app/views/notifications_mailer/thirteen/thirteen_client_match.text.haml new file mode 100644 index 000000000..623af3aef --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_client_match.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +#{Translation.translate('CoC Twelve')} has sent a match for the client below, and it is now ready for your action. +View details here: +\ +#{notification_match_decision_url @notification, @match, @decision} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' \ No newline at end of file diff --git a/app/views/notifications_mailer/thirteen/thirteen_client_review_decline.haml b/app/views/notifications_mailer/thirteen/thirteen_client_review_decline.haml new file mode 100644 index 000000000..7ca674f5c --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_client_review_decline.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ += "A #{Translation.translate('Shelter Agency Thirteen')} has declined a housing match." +\ += "The match now requires #{Translation.translate('CoC Thirteen')} confirmation to fully close it and make the voucher or unit and client available for future matching." +\ +Please review details here and take action: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_client_review_dnd_staff.text.haml b/app/views/notifications_mailer/thirteen/thirteen_client_review_dnd_staff.text.haml new file mode 100644 index 000000000..de2a43f95 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_client_review_dnd_staff.text.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ +The match is has been accepted by the #{Translation.translate('Shelter Agency Thirteen')} contacts and is currently pending action by #{Translation.translate('HSA Thirteen')}. +\ +#{Translation.translate('HSA Thirteen')} has been notified to schedule a #{Translation.translate('CORI hearing')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_client_review_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_client_review_hsa.text.haml new file mode 100644 index 000000000..31261057f --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_client_review_hsa.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The match is has been acknowledged by the #{Translation.translate('Shelter Agency Thirteen')} contacts and is currently in review. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_client_review_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_client_review_shelter_agency.text.haml new file mode 100644 index 000000000..c72a22ee5 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_client_review_shelter_agency.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ += "#{Translation.translate('Shelter Agency Thirteen')} has acknowledged a match for the client below, and it is now ready for your action." +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_dnd_staff.text.haml b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_dnd_staff.text.haml new file mode 100644 index 000000000..1e14afccb --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_dnd_staff.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, + += "The match now requires final approval from #{Translation.translate('CoC Thirteen')} staff to complete." +\ +Please review the details of the match and note final approval here: +#{notification_match_decision_url @notification, @match, @decision} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_hsa.text.haml new file mode 100644 index 000000000..07ef6ceb8 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_hsa.text.haml @@ -0,0 +1,14 @@ +Hello #{@contact.full_name}, + += "The match now requires final approval from #{Translation.translate('CoC Thirteen')} staff to complete." +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_shelter_agency.text.haml new file mode 100644 index 000000000..07ef6ceb8 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_confirm_match_success_shelter_agency.text.haml @@ -0,0 +1,14 @@ +Hello #{@contact.full_name}, + += "The match now requires final approval from #{Translation.translate('CoC Thirteen')} staff to complete." +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_decline.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_decline.haml new file mode 100644 index 000000000..1d3653c47 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_decline.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ += "A #{Translation.translate('HSA Thirteen')} has declined a housing match." +\ += "The match now requires #{Translation.translate('CoC Thirteen')} confirmation to fully close it and make the voucher or unit and client available for future matching." +\ +Please review details here and take action: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_dnd_staff.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_dnd_staff.text.haml new file mode 100644 index 000000000..bff95cbd9 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_dnd_staff.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +#{Translation.translate('HSA Thirteen')} has schedule a CORI hearing. The match is pending the outcome of this hearing being entered by #{Translation.translate('HSA Thirteen')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_hsa.text.haml new file mode 100644 index 000000000..c50122aa3 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_hsa.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The #{Translation.translate('CORI hearing')} for this match has been scheduled by #{Translation.translate('Shelter Agency Thirteen')} contacts and is currently pending the outcome of this hearing being entered by #{Translation.translate('Shelter Agency Thirteen')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_shelter_agency.text.haml new file mode 100644 index 000000000..823460755 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_outcome_shelter_agency.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +#{Translation.translate('HSA Thirteen')} has schedule a #{Translation.translate('CORI hearing')}. The match is pending the outcome of this hearing being entered by #{Translation.translate('HSA Thirteen')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_decline.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_decline.haml new file mode 100644 index 000000000..1d3653c47 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_decline.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ += "A #{Translation.translate('HSA Thirteen')} has declined a housing match." +\ += "The match now requires #{Translation.translate('CoC Thirteen')} confirmation to fully close it and make the voucher or unit and client available for future matching." +\ +Please review details here and take action: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_dnd_staff.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_dnd_staff.text.haml new file mode 100644 index 000000000..de2a43f95 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_dnd_staff.text.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ +The match is has been accepted by the #{Translation.translate('Shelter Agency Thirteen')} contacts and is currently pending action by #{Translation.translate('HSA Thirteen')}. +\ +#{Translation.translate('HSA Thirteen')} has been notified to schedule a #{Translation.translate('CORI hearing')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_hsa.text.haml new file mode 100644 index 000000000..c1635de4a --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_hsa.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The match is has been accepted by the #{Translation.translate('Shelter Agency Thirteen')} contacts and it is now ready for your action. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_shelter_agency.text.haml new file mode 100644 index 000000000..de2a43f95 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hearing_scheduled_shelter_agency.text.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ +The match is has been accepted by the #{Translation.translate('Shelter Agency Thirteen')} contacts and is currently pending action by #{Translation.translate('HSA Thirteen')}. +\ +#{Translation.translate('HSA Thirteen')} has been notified to schedule a #{Translation.translate('CORI hearing')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hsa_review_decline.haml b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_decline.haml new file mode 100644 index 000000000..1d3653c47 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_decline.haml @@ -0,0 +1,19 @@ +Hello #{@contact.full_name}, +\ += "A #{Translation.translate('HSA Thirteen')} has declined a housing match." +\ += "The match now requires #{Translation.translate('CoC Thirteen')} confirmation to fully close it and make the voucher or unit and client available for future matching." +\ +Please review details here and take action: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hsa_review_dnd_staff.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_dnd_staff.text.haml new file mode 100644 index 000000000..84dcb28e2 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_dnd_staff.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The match is pending the review by #{Translation.translate('HSA Thirteen')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hsa_review_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_hsa.text.haml new file mode 100644 index 000000000..db73bb730 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_hsa.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The match is pending the review by #{Translation.translate('HSA Thirteen')} - it is now ready for your action. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_hsa_review_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_shelter_agency.text.haml new file mode 100644 index 000000000..84dcb28e2 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_hsa_review_shelter_agency.text.haml @@ -0,0 +1,17 @@ +Hello #{@contact.full_name}, +\ +The match is pending the review by #{Translation.translate('HSA Thirteen')}. +\ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_hsa.text.haml b/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_hsa.text.haml new file mode 100644 index 000000000..9f70167b0 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_hsa.text.haml @@ -0,0 +1,22 @@ +Hello #{@contact.full_name}, +\ +The CAS has generated a new match recommendation. +\ +The match is pending acknowledgement by the #{Translation.translate('Shelter Agency Thirteen')} contacts. +\ +- if @match.shelter_expiration.present? + = "#{Translation.translate('Shelter Agency Thirteen')} must acknowledge the match by #{@match.shelter_expiration}." + \ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_shelter_agency.text.haml b/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_shelter_agency.text.haml new file mode 100644 index 000000000..a8b6d3194 --- /dev/null +++ b/app/views/notifications_mailer/thirteen/thirteen_match_acknowledgement_shelter_agency.text.haml @@ -0,0 +1,22 @@ +Hello #{@contact.full_name}, +\ +The CAS has generated a new match recommendation. +\ +Please acknowledge receipt of this match and review the associated #{Translation.translate('HSA Thirteen')} contacts. +\ +- if @match.shelter_expiration.present? + = "#{Translation.translate('Shelter Agency Thirteen')} must acknowledge the match by #{@match.shelter_expiration}." + \ +Please review details: +#{notification_match_url @notification, @match} +\ += render 'client_details' +\ += render 'location_details' +\ += render 'program_details' +\ +\ +\ +\ += render 'email_footer' diff --git a/app/views/programs/_form.html.haml b/app/views/programs/_form.html.haml index 3e48fa735..4446ae326 100644 --- a/app/views/programs/_form.html.haml +++ b/app/views/programs/_form.html.haml @@ -10,6 +10,8 @@ = sp.input :name .form-group.form-group__indented-02 = sp.input :confidential, label: 'Is this a confidential sub-program?', hint: 'Anyone in a match involving a confidential program will have their name hidden on lists of matches by default.' + .form-group.form-group__indented-02 + = sp.input :cori_hearing_required, label: "Requires #{Translation.translate('CORI hearing')}", hint: "This sub-program requires a #{Translation.translate('CORI hearing')} review for any clients matched in #{Translation.translate('Route Thirteen')}" .form-group.form-group__indented-02 = sp.association :housing_subsidy_administrator, label: "#{Translation.translate('Housing Subsidy Administrator')}" .form-group.form-group__indented-02 diff --git a/app/views/sub_programs/_form.html.haml b/app/views/sub_programs/_form.html.haml index 83e616f81..0345a4531 100644 --- a/app/views/sub_programs/_form.html.haml +++ b/app/views/sub_programs/_form.html.haml @@ -12,6 +12,7 @@ %p This sub-program belongs to a confidential program. Client names will be hidden when shown in lists of matches by default. - else = f.input :confidential, label: 'Is this a confidential sub-program?', hint: 'Anyone in a match involving a confidential program will have their name hidden on lists of matches by default.' + = f.input :cori_hearing_required, label: "Requires #{Translation.translate('CORI hearing')}", hint: "This sub-program requires a #{Translation.translate('CORI hearing')} review for any clients matched in #{Translation.translate('Route Thirteen')}" = f.association :housing_subsidy_administrator, label: "#{Translation.translate('Housing Subsidy Administrator')}", as: :select2 = f.association :service_provider, label: 'Service Provider', as: :select2 = f.association :sub_contractor, label: 'Sub-Contractor', as: :select2 @@ -30,6 +31,7 @@ = f.association :file_tags, collection: FileTag.available_tags, selected: @subprogram.file_tags.map(&:tag_id), label: 'Files types from the warehouse to display on matches that involve this sub-program', hint: "These files will be linked from any match involving a client with a #{Translation.translate('full release')} on file.", as: :select2, input_html: { multiple: :multiple } = f.input :event, label: 'Coordinated Entry Event Type', hint: 'When matches are made, coordinated entry events are created for reporting to HUD, which type of event should matches involving this program create?', collection: @subprogram.class.available_event_types.invert, as: :select2 + .col-sm-6.text-right.mb-4 - if @subprogram.persisted? && can_edit_programs? && @subprogram.vouchers.available.empty? && ! @subprogram.closed? = link_to close_program_sub_program_path(@program, @subprogram), class: 'btn btn-danger ml-sm-6', data: {confirm: 'Are you sure you want to close this sub-program?'} do diff --git a/db/migrate/20240731130949_add_cori_hearing_required_column_to_sub_program.rb b/db/migrate/20240731130949_add_cori_hearing_required_column_to_sub_program.rb new file mode 100644 index 000000000..95192cb51 --- /dev/null +++ b/db/migrate/20240731130949_add_cori_hearing_required_column_to_sub_program.rb @@ -0,0 +1,5 @@ +class AddCoriHearingRequiredColumnToSubProgram < ActiveRecord::Migration[7.0] + def change + add_column :sub_programs, :cori_hearing_required, :boolean + end +end diff --git a/db/migrate/20240805133313_add_core_hearing_outcome_recorded_totch_decisions.rb b/db/migrate/20240805133313_add_core_hearing_outcome_recorded_totch_decisions.rb new file mode 100644 index 000000000..db114072f --- /dev/null +++ b/db/migrate/20240805133313_add_core_hearing_outcome_recorded_totch_decisions.rb @@ -0,0 +1,5 @@ +class AddCoreHearingOutcomeRecordedTotchDecisions < ActiveRecord::Migration[7.0] + def change + add_column :match_decisions, :criminal_hearing_outcome_recorded, :boolean + end +end diff --git a/db/schema.rb b/db/schema.rb index f3a5d3ed9..eb851595f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2024_08_05_131951) do +ActiveRecord::Schema[7.0].define(version: 2024_08_05_133313) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -661,6 +661,7 @@ t.boolean "include_note_in_email" t.datetime "date_voucher_issued", precision: nil t.string "manager" + t.boolean "criminal_hearing_outcome_recorded" t.index ["administrative_cancel_reason_id"], name: "index_match_decisions_on_administrative_cancel_reason_id" t.index ["decline_reason_id"], name: "index_match_decisions_on_decline_reason_id" t.index ["match_id"], name: "index_match_decisions_on_match_id" @@ -1675,6 +1676,7 @@ t.boolean "closed", default: false t.integer "event" t.boolean "weighting_rules_active", default: true + t.boolean "cori_hearing_required" t.index ["building_id"], name: "index_sub_programs_on_building_id" t.index ["deleted_at"], name: "index_sub_programs_on_deleted_at" t.index ["program_id"], name: "index_sub_programs_on_program_id"