diff --git a/app/controllers/schemes_controller.rb b/app/controllers/schemes_controller.rb index 83bff5542..d9dccab5d 100644 --- a/app/controllers/schemes_controller.rb +++ b/app/controllers/schemes_controller.rb @@ -14,6 +14,11 @@ class SchemesController < ApplicationController @total_count = all_schemes.size end + def show + @scheme = Scheme.find_by(id: params[:id]) + render_not_found and return unless (current_user.organisation == @scheme.organisation) || current_user.support? + end + private def search_term diff --git a/app/helpers/navigation_items_helper.rb b/app/helpers/navigation_items_helper.rb index c0b55c674..369428053 100644 --- a/app/helpers/navigation_items_helper.rb +++ b/app/helpers/navigation_items_helper.rb @@ -41,23 +41,23 @@ private end def users_current?(path) - path == "/users" + path == "/users" || path.include?("/users/") end def supported_housing_current?(path) - path == "/supported-housing" + path == "/supported-housing" || path.include?("/supported-housing/") end def organisations_current?(path) - path == "/organisations" || subnav_users_path?(path) || subnav_logs_path?(path) || subnav_details_path?(path) || subnav_supported_housing_path?(path) + path == "/organisations" || path.include?("/organisations/") end def subnav_supported_housing_path?(path) - path.include?("/organisations") && path.include?("/supported-housing") + path.include?("/organisations") && path.include?("/supported-housing") || path.include?("/supported-housing/") end def subnav_users_path?(path) - path.include?("/organisations") && path.include?("/users") + (path.include?("/organisations") && path.include?("/users")) || path.include?("/users/") end def subnav_logs_path?(path) diff --git a/app/helpers/tab_nav_helper.rb b/app/helpers/tab_nav_helper.rb index 1157b83e6..bb163ddd8 100644 --- a/app/helpers/tab_nav_helper.rb +++ b/app/helpers/tab_nav_helper.rb @@ -6,6 +6,11 @@ module TabNavHelper [govuk_link_to(link_text, user), "User #{user.email}"].join("\n") end + def scheme_cell(scheme) + link_text = scheme.service_name.presence + [govuk_link_to(link_text, scheme), "Scheme #{scheme.primary_client_group_display}"].join("\n") + end + def org_cell(user) role = "#{user.role.to_s.humanize}" [user.organisation.name, role].join("\n") diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 7f6ec337e..096706018 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -4,4 +4,104 @@ class Scheme < ApplicationRecord scope :search_by_code, ->(code) { where("code ILIKE ?", "%#{code}%") } scope :search_by_service_name, ->(name) { where("service_name ILIKE ?", "%#{name}%") } scope :search_by, ->(param) { search_by_code(param).or(search_by_service_name(param)) } + + SCHEME_TYPE = { + 0 => "Missings", + 4 => "Foyer", + 5 => "Direct Access Hostel", + 6 => "Other Supported Housing", + 7 => "Housing for older people", + }.freeze + + PRIMARY_CLIENT_GROUP = { + "O" => "Homeless families with support needs", + "H" => "Offenders & people at risk of offending", + "M" => "Older people with support needs", + "L" => "People at risk of domestic violence", + "A" => "People with a physical or sensory disability", + "G" => "People with alcohol problems", + "F" => "People with drug problems", + "B" => "People with HIV or AIDS", + "D" => "People with learning disabilities", + "E" => "People with mental health problems", + "I" => "Refugees (permanent)", + "S" => "Rough sleepers", + "N" => "Single homeless people with support needs", + "R" => "Teenage parents", + "Q" => "Young people at risk", + "P" => "Young people leaving care", + "X" => "Missing", + }.freeze + + SUPPORT_TYPE = { + 0 => "Missing", + 1 => "Resettlement Support", + 2 => "Low levels of support", + 3 => "Medium levels of support", + 4 => "High levels of care and support", + 5 => "Nursing care services to a care home", + 6 => "Floating Support", + }.freeze + + INTENDED_STAY = { + "M" => "Medium stay", + "P" => "Permanent", + "S" => "Short Stay", + "V" => "Very short stay", + "X" => "Missing", + }.freeze + + REGISTERED_UNDER_CARE_ACT = { + 0 => "No", + 1 => "Yes – part registered as a care home", + }.freeze + + SENSITIVE = { + 0 => "No", + 1 => "Yes", + }.freeze + + def display_attributes + [ + { name: "Service code", value: code }, + { name: "Name", value: service_name }, + { name: "Confidential information", value: sensitive_display }, + { name: "Managing agent", value: organisation.name }, + { name: "Type of service", value: scheme_type_display }, + { name: "Registered under Care Standards Act 2000", value: registered_under_care_act_display }, + { name: "Total number of units", value: total_units }, + { name: "Primary client group", value: primary_client_group_display }, + { name: "Secondary client group", value: secondary_client_group_display }, + { name: "Level of support given", value: support_type_display }, + { name: "Intended length of stay", value: intended_stay_display }, + ] + end + + def scheme_type_display + SCHEME_TYPE[scheme_type] + end + + def sensitive_display + SENSITIVE[sensitive] + end + + def registered_under_care_act_display + REGISTERED_UNDER_CARE_ACT[registered_under_care_act] + end + + def primary_client_group_display + PRIMARY_CLIENT_GROUP[primary_client_group] + end + + def secondary_client_group_display + PRIMARY_CLIENT_GROUP[secondary_client_group] + end + + def support_type_display + SUPPORT_TYPE[support_type] + end + + def intended_stay_display + INTENDED_STAY[intended_stay] + end end diff --git a/app/views/schemes/_scheme_list.html.erb b/app/views/schemes/_scheme_list.html.erb index 002a215b4..8d6ef7a72 100644 --- a/app/views/schemes/_scheme_list.html.erb +++ b/app/views/schemes/_scheme_list.html.erb @@ -29,7 +29,7 @@ <%= table.body do |body| %> <%= body.row do |row| %> <% row.cell(text: scheme.code) %> - <% row.cell(text: scheme.service_name) %> + <% row.cell(text: simple_format(scheme_cell(scheme), { class: "govuk-!-font-weight-bold" }, wrapper_tag: "div")) %> <% row.cell(text: scheme.organisation.name) %> <% row.cell(text: scheme.created_at.to_formatted_s(:govuk_date)) %> <% end %> diff --git a/app/views/schemes/show.html.erb b/app/views/schemes/show.html.erb new file mode 100644 index 000000000..bb883d0e9 --- /dev/null +++ b/app/views/schemes/show.html.erb @@ -0,0 +1,17 @@ +<% title = @scheme.service_name %> +<% content_for :title, title %> + +<%= render partial: "organisations/headings", locals: { main: @scheme.service_name, sub: nil } %> + +
+
+ <%= govuk_summary_list do |summary_list| %> + <% @scheme.display_attributes.each do |attr| %> + <%= summary_list.row do |row| %> + <% row.key { attr[:name].to_s.humanize } %> + <% row.value { details_html(attr) } %> + <% end %> + <% end %> + <% end %> +
+
diff --git a/config/routes.rb b/config/routes.rb index c7b3df36e..3e4492127 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -35,7 +35,7 @@ Rails.application.routes.draw do get "edit/password", to: "users#edit_password" end - resources :schemes, path: "/supported-housing", only: [:index] + resources :schemes, path: "/supported-housing", only: %i[index show] resources :users do member do diff --git a/db/migrate/20220613094847_add_missing_attributes_to_scheme.rb b/db/migrate/20220613094847_add_missing_attributes_to_scheme.rb new file mode 100644 index 000000000..ca0121d3d --- /dev/null +++ b/db/migrate/20220613094847_add_missing_attributes_to_scheme.rb @@ -0,0 +1,14 @@ +class AddMissingAttributesToScheme < ActiveRecord::Migration[7.0] + def change + change_table :schemes, bulk: true do |t| + t.string :primary_client_group + t.string :secondary_client_group + t.integer :sensitive + t.integer :total_units + t.integer :scheme_type + t.integer :registered_under_care_act + t.integer :support_type + t.string :intended_stay + end + end +end diff --git a/db/schema.rb b/db/schema.rb index cd132897d..6a4e5f2ea 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: 2022_06_08_144156) do +ActiveRecord::Schema[7.0].define(version: 2022_06_13_094847) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -283,6 +283,14 @@ ActiveRecord::Schema[7.0].define(version: 2022_06_08_144156) do t.bigint "organisation_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "primary_client_group" + t.string "secondary_client_group" + t.integer "sensitive" + t.integer "total_units" + t.integer "scheme_type" + t.integer "registered_under_care_act" + t.integer "support_type" + t.string "intended_stay" t.index ["organisation_id"], name: "index_schemes_on_organisation_id" end diff --git a/db/seeds.rb b/db/seeds.rb index 356e020b4..ad1fc1ac4 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -73,6 +73,14 @@ unless Rails.env.test? Scheme.create!( code: "S878", service_name: "Beulahside Care", + sensitive: 0, + registered_under_care_act: 0, + support_type: 1, + scheme_type: 4, + total_units: 5, + intended_stay: "M", + primary_client_group: "O", + secondary_client_group: "H", organisation: org, created_at: Time.zone.now, ) @@ -80,6 +88,14 @@ unless Rails.env.test? Scheme.create!( code: "S312", service_name: "Abdullahview Point", + sensitive: 0, + registered_under_care_act: 1, + support_type: 1, + scheme_type: 5, + total_units: 2, + intended_stay: "S", + primary_client_group: "D", + secondary_client_group: "E", organisation: org, created_at: Time.zone.now, ) @@ -87,6 +103,14 @@ unless Rails.env.test? Scheme.create!( code: "7XYZ", service_name: "Caspermouth Center", + sensitive: 1, + registered_under_care_act: 1, + support_type: 4, + scheme_type: 7, + total_units: 7, + intended_stay: "X", + primary_client_group: "G", + secondary_client_group: "R", organisation: dummy_org, created_at: Time.zone.now, ) diff --git a/spec/factories/scheme.rb b/spec/factories/scheme.rb index 8d15032fe..6c3537146 100644 --- a/spec/factories/scheme.rb +++ b/spec/factories/scheme.rb @@ -2,6 +2,14 @@ FactoryBot.define do factory :scheme do code { Faker::Name.initials(number: 4) } service_name { Faker::Name.name_with_middle } + sensitive { Faker::Number.within(range: 0..1) } + registered_under_care_act { Faker::Number.within(range: 0..1) } + support_type { Faker::Number.within(range: 0..6) } + scheme_type { 0 } + total_units { Faker::Number.number(digits: 2) } + intended_stay { %w[M P S V X].sample } + primary_client_group { %w[O H M L A G F B D E I S N R Q P X].sample } + secondary_client_group { %w[O H M L A G F B D E I S N R Q P X].sample } organisation created_at { Time.zone.now } end diff --git a/spec/features/schemes_spec.rb b/spec/features/schemes_spec.rb index b1fe131fe..f772a24c8 100644 --- a/spec/features/schemes_spec.rb +++ b/spec/features/schemes_spec.rb @@ -2,7 +2,7 @@ require "rails_helper" RSpec.describe "Supported housing scheme Features" do context "when viewing list of schemes" do - context "when I am signed as a support user in there are schemes in the database" do + context "when I am signed as a support user and there are schemes in the database" do let(:user) { FactoryBot.create(:user, :support, last_sign_in_at: Time.zone.now) } let!(:schemes) { FactoryBot.create_list(:scheme, 5) } let!(:scheme_to_search) { FactoryBot.create(:scheme) } @@ -75,4 +75,61 @@ RSpec.describe "Supported housing scheme Features" do end end end + + context "when viewing individual scheme" do + context "when I am signed as a support user and there are schemes in the database" do + let(:user) { FactoryBot.create(:user, :support, last_sign_in_at: Time.zone.now) } + let!(:schemes) { FactoryBot.create_list(:scheme, 5) } + let(:notify_client) { instance_double(Notifications::Client) } + let(:confirmation_token) { "MCDH5y6Km-U7CFPgAMVS" } + let(:devise_notify_mailer) { DeviseNotifyMailer.new } + let(:otp) { "999111" } + + before do + allow(DeviseNotifyMailer).to receive(:new).and_return(devise_notify_mailer) + allow(devise_notify_mailer).to receive(:notify_client).and_return(notify_client) + allow(Devise).to receive(:friendly_token).and_return(confirmation_token) + allow(notify_client).to receive(:send_email).and_return(true) + allow(SecureRandom).to receive(:random_number).and_return(otp) + visit("/logs") + fill_in("user[email]", with: user.email) + fill_in("user[password]", with: user.password) + click_button("Sign in") + fill_in("code", with: otp) + click_button("Submit") + end + + context "when I visit supported housing page" do + before do + visit("supported-housing") + end + + it "shows list of links to schemes" do + schemes.each do |scheme| + expect(page).to have_link(scheme.service_name) + expect(page).to have_content(scheme.primary_client_group_display) + end + end + + context "when I click to see individual scheme" do + before do + click_link(schemes.first.service_name) + end + + it "shows me details about the selected scheme" do + expect(page).to have_content(schemes.first.code) + expect(page).to have_content(schemes.first.service_name) + expect(page).to have_content(schemes.first.sensitive_display) + expect(page).to have_content(schemes.first.scheme_type_display) + expect(page).to have_content(schemes.first.registered_under_care_act_display) + expect(page).to have_content(schemes.first.total_units) + expect(page).to have_content(schemes.first.primary_client_group_display) + expect(page).to have_content(schemes.first.secondary_client_group_display) + expect(page).to have_content(schemes.first.support_type_display) + expect(page).to have_content(schemes.first.intended_stay_display) + end + end + end + end + end end diff --git a/spec/helpers/navigation_items_helper_spec.rb b/spec/helpers/navigation_items_helper_spec.rb index 8aa02eb82..52ad582c5 100644 --- a/spec/helpers/navigation_items_helper_spec.rb +++ b/spec/helpers/navigation_items_helper_spec.rb @@ -67,6 +67,36 @@ RSpec.describe NavigationItemsHelper do expect(primary_items("/account", current_user)).to eq(expected_navigation_items) end end + + context "when the user is on the individual user's page" do + let(:expected_navigation_items) do + [ + NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false), + NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false), + NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", true), + NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, false), + ] + end + + it "returns navigation items with the users item set as current" do + expect(primary_items("/users/1", current_user)).to eq(expected_navigation_items) + end + end + + context "when the user is on the individual scheme's page" do + let(:expected_navigation_items) do + [ + NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false), + NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", true), + NavigationItemsHelper::NavigationItem.new("Users", "/organisations/#{current_user.organisation.id}/users", false), + NavigationItemsHelper::NavigationItem.new("About your organisation", organisation_path, false), + ] + end + + it "returns navigation items with supported housing item set as current" do + expect(primary_items("/supported-housing/1", current_user)).to eq(expected_navigation_items) + end + end end context "when the user is a support user" do @@ -132,6 +162,36 @@ RSpec.describe NavigationItemsHelper do end end + context "when the user is on the individual user's page" do + let(:expected_navigation_items) do + [ + NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false), + NavigationItemsHelper::NavigationItem.new("Users", "/users", true), + NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false), + NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", false), + ] + end + + it "returns navigation items with the users item set as current" do + expect(primary_items("/users/1", current_user)).to eq(expected_navigation_items) + end + end + + context "when the user is on the individual scheme's page" do + let(:expected_navigation_items) do + [ + NavigationItemsHelper::NavigationItem.new("Organisations", "/organisations", false), + NavigationItemsHelper::NavigationItem.new("Users", "/users", false), + NavigationItemsHelper::NavigationItem.new("Logs", "/logs", false), + NavigationItemsHelper::NavigationItem.new("Supported housing", "/supported-housing", true), + ] + end + + it "returns navigation items with supported housing item set as current" do + expect(primary_items("/supported-housing/1", current_user)).to eq(expected_navigation_items) + end + end + context "when the user is on the specific organisation's page" do context "when the user is on organisation logs page" do let(:required_sub_path) { "logs" } diff --git a/spec/helpers/tab_nav_helper_spec.rb b/spec/helpers/tab_nav_helper_spec.rb index b59bb5d05..ba2dd3174 100644 --- a/spec/helpers/tab_nav_helper_spec.rb +++ b/spec/helpers/tab_nav_helper_spec.rb @@ -3,6 +3,7 @@ require "rails_helper" RSpec.describe TabNavHelper do let(:organisation) { FactoryBot.create(:organisation) } let(:user) { FactoryBot.build(:user, organisation:) } + let(:scheme) { FactoryBot.build(:scheme) } describe "#user_cell" do it "returns user link and email separated by a newline character" do @@ -18,6 +19,13 @@ RSpec.describe TabNavHelper do end end + describe "#scheme_cell" do + it "returns the scheme link service name and primary user group separated by a newline character" do + expected_html = "#{scheme.service_name}\nScheme #{scheme.primary_client_group_display}" + expect(scheme_cell(scheme)).to match(expected_html) + end + end + describe "#tab_items" do context "when user is a data_coordinator" do let(:user) { FactoryBot.build(:user, :data_coordinator, organisation:) } diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb index 13e612c46..4d5c248d5 100644 --- a/spec/requests/schemes_controller_spec.rb +++ b/spec/requests/schemes_controller_spec.rb @@ -160,4 +160,90 @@ RSpec.describe SchemesController, type: :request do end end end + + describe "#show" do + let(:specific_scheme) { schemes.first } + + context "when not signed in" do + it "redirects to the sign in page" do + get "/supported-housing/#{specific_scheme.id}" + expect(response).to redirect_to("/account/sign-in") + end + end + + context "when signed in as a data provider user" do + let(:user) { FactoryBot.create(:user) } + + before do + sign_in user + get "/supported-housing/#{specific_scheme.id}" + end + + it "returns 401 unauthorized" do + request + expect(response).to have_http_status(:unauthorized) + end + end + + context "when signed in as a data coordinator user" do + let(:user) { FactoryBot.create(:user, :data_coordinator) } + let!(:specific_scheme) { FactoryBot.create(:scheme, organisation: user.organisation) } + + before do + sign_in user + end + + it "has page heading" do + get "/supported-housing/#{specific_scheme.id}" + expect(page).to have_content(specific_scheme.code) + expect(page).to have_content(specific_scheme.service_name) + expect(page).to have_content(specific_scheme.organisation.name) + expect(page).to have_content(specific_scheme.sensitive_display) + expect(page).to have_content(specific_scheme.code) + expect(page).to have_content(specific_scheme.service_name) + expect(page).to have_content(specific_scheme.sensitive_display) + expect(page).to have_content(specific_scheme.scheme_type_display) + expect(page).to have_content(specific_scheme.registered_under_care_act_display) + expect(page).to have_content(specific_scheme.total_units) + expect(page).to have_content(specific_scheme.primary_client_group_display) + expect(page).to have_content(specific_scheme.secondary_client_group_display) + expect(page).to have_content(specific_scheme.support_type_display) + expect(page).to have_content(specific_scheme.intended_stay_display) + end + + context "when coordinator attempts to see scheme belogning to a different organisation" do + let!(:specific_scheme) { FactoryBot.create(:scheme) } + + it "returns 404 not found" do + get "/supported-housing/#{specific_scheme.id}" + expect(response).to have_http_status(:not_found) + end + end + end + + context "when signed in as a support user" do + before do + allow(user).to receive(:need_two_factor_authentication?).and_return(false) + sign_in user + get "/supported-housing/#{specific_scheme.id}" + end + + it "has page heading" do + expect(page).to have_content(specific_scheme.code) + expect(page).to have_content(specific_scheme.service_name) + expect(page).to have_content(specific_scheme.organisation.name) + expect(page).to have_content(specific_scheme.sensitive_display) + expect(page).to have_content(specific_scheme.code) + expect(page).to have_content(specific_scheme.service_name) + expect(page).to have_content(specific_scheme.sensitive_display) + expect(page).to have_content(specific_scheme.scheme_type_display) + expect(page).to have_content(specific_scheme.registered_under_care_act_display) + expect(page).to have_content(specific_scheme.total_units) + expect(page).to have_content(specific_scheme.primary_client_group_display) + expect(page).to have_content(specific_scheme.secondary_client_group_display) + expect(page).to have_content(specific_scheme.support_type_display) + expect(page).to have_content(specific_scheme.intended_stay_display) + end + end + end end