diff --git a/app/models/case_log.rb b/app/models/case_log.rb index a98296bb2..2cceb4a8a 100644 --- a/app/models/case_log.rb +++ b/app/models/case_log.rb @@ -567,7 +567,6 @@ private def reset_derived_questions dependent_questions = { waityear: [{ key: :renewal, value: 0 }], - homeless: [{ key: :renewal, value: 0 }], referral: [{ key: :renewal, value: 0 }], underoccupation_benefitcap: [{ key: :renewal, value: 0 }], wchair: [{ key: :needstype, value: 1 }], @@ -693,30 +692,6 @@ private end end - def get_housingneeds - return 1 if has_housingneeds? - return 2 if no_housingneeds? - return 3 if unknown_housingneeds? - end - - def has_housingneeds? - if [housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f].any?(1) - 1 - end - end - - def no_housingneeds? - if housingneeds_g == 1 - 1 - end - end - - def unknown_housingneeds? - if housingneeds_h == 1 - 1 - end - end - def all_fields_completed? subsection_statuses = form.subsections.map { |subsection| subsection.status(self) }.uniq subsection_statuses == [:completed] @@ -754,4 +729,32 @@ private def upcase_and_remove_whitespace(string) string.present? ? string.upcase.gsub(/\s+/, "") : string end + + def fully_wheelchair_accessible? + housingneeds_type.present? && housingneeds_type.zero? + end + + def essential_wheelchair_access? + housingneeds_type == 1 + end + + def level_access_housing? + housingneeds_type == 2 + end + + def other_housingneeds? + housingneeds_other == 1 + end + + def has_housingneeds? + housingneeds == 1 + end + + def no_housingneeds? + housingneeds == 2 + end + + def unknown_housingneeds? + housingneeds == 3 + end end diff --git a/app/models/derived_variables/case_log_variables.rb b/app/models/derived_variables/case_log_variables.rb index 3bf227b6f..5f5e06766 100644 --- a/app/models/derived_variables/case_log_variables.rb +++ b/app/models/derived_variables/case_log_variables.rb @@ -43,10 +43,8 @@ module DerivedVariables::CaseLogVariables self.has_benefits = get_has_benefits self.tshortfall_known = 0 if tshortfall self.nocharge = household_charge&.zero? ? 1 : 0 - self.housingneeds = get_housingneeds if is_renewal? self.underoccupation_benefitcap = 2 if collection_start_year == 2021 - self.homeless = 1 self.referral = 0 self.waityear = 2 if is_general_needs? @@ -70,6 +68,8 @@ module DerivedVariables::CaseLogVariables self.voiddate = startdate end end + + set_housingneeds_fields if housingneeds? end private @@ -186,4 +186,23 @@ private self.location = scheme.locations.first end end + + def set_housingneeds_fields + self.housingneeds_a = fully_wheelchair_accessible? ? 1 : 0 + self.housingneeds_b = essential_wheelchair_access? ? 1 : 0 + self.housingneeds_c = level_access_housing? ? 1 : 0 + self.housingneeds_f = other_housingneeds? ? 1 : 0 + set_housingneeds_values_to_zero unless has_housingneeds? + self.housingneeds_g = no_housingneeds? ? 1 : 0 + self.housingneeds_h = unknown_housingneeds? ? 1 : 0 + end + + def set_housingneeds_values_to_zero + self.housingneeds_a = 0 + self.housingneeds_b = 0 + self.housingneeds_c = 0 + self.housingneeds_f = 0 + self.housingneeds_g = 0 + self.housingneeds_h = 0 + end end diff --git a/app/models/scheme.rb b/app/models/scheme.rb index 45f09d4a5..b52f7539c 100644 --- a/app/models/scheme.rb +++ b/app/models/scheme.rb @@ -112,7 +112,7 @@ class Scheme < ApplicationRecord def check_details_attributes [ - { name: "Service code", value: id_to_display, id: "id" }, + { name: "Scheme code", value: id_to_display, id: "id" }, { name: "Name", value: service_name, id: "service_name" }, { name: "Confidential information", value: sensitive, id: "sensitive" }, { name: "Type of scheme", value: scheme_type, id: "scheme_type" }, diff --git a/app/models/validations/household_validations.rb b/app/models/validations/household_validations.rb index 48b862ab3..7053d3571 100644 --- a/app/models/validations/household_validations.rb +++ b/app/models/validations/household_validations.rb @@ -54,16 +54,6 @@ module Validations::HouseholdValidations validate_person_age_matches_economic_status(record, 1) end - def validate_accessibility_requirements(record) - all_options = [record.housingneeds_a, record.housingneeds_b, record.housingneeds_c, record.housingneeds_f, record.housingneeds_g, record.housingneeds_h] - if all_options.count(1) > 1 - mobility_accessibility_options = [record.housingneeds_a, record.housingneeds_b, record.housingneeds_c] - unless all_options.count(1) == 2 && record.housingneeds_f == 1 && mobility_accessibility_options.any? { |x| x == 1 } - record.errors.add :accessibility_requirements, I18n.t("validations.household.housingneeds_a.one_or_two_choices") - end - end - end - def validate_condition_effects(record) all_options = [record.illness_type_1, record.illness_type_2, record.illness_type_3, record.illness_type_4, record.illness_type_5, record.illness_type_6, record.illness_type_7, record.illness_type_8, record.illness_type_9, record.illness_type_10] if all_options.count(1) >= 1 && household_no_illness?(record) diff --git a/app/services/archive_storage_service.rb b/app/services/archive_storage_service.rb deleted file mode 100644 index 92875d86a..000000000 --- a/app/services/archive_storage_service.rb +++ /dev/null @@ -1,24 +0,0 @@ -class ArchiveStorageService < StorageService - MAX_SIZE = 50 * (1024**2) # 50MiB - - def initialize(archive_io) - super() - @archive = Zip::File.open_buffer(archive_io) - end - - def list_files(folder) - @archive.glob(File.join(folder, "*.*")) - .map(&:name) - end - - def folder_present?(folder) - !list_files(folder).empty? - end - - def get_file_io(file_name) - entry = @archive.get_entry(file_name) - raise "File too large to be extracted" if entry.size > MAX_SIZE - - entry.get_input_stream - end -end diff --git a/app/services/configuration/configuration_service.rb b/app/services/configuration/configuration_service.rb new file mode 100644 index 000000000..07617a807 --- /dev/null +++ b/app/services/configuration/configuration_service.rb @@ -0,0 +1,54 @@ +module Configuration + class ConfigurationService + attr_reader :s3_buckets, :redis_uris + + def initialize(logger = Rails.logger) + @logger = logger + @config = read_config + @s3_buckets = read_s3_buckets + @redis_uris = read_redis_uris + end + + def s3_config_present? + config_present? && @config.key?(:"aws-s3-bucket") + end + + def redis_config_present? + config_present? && @config.key?(:redis) + end + + private + + def config_present? + raise NotImplementedError + end + + def read_config + raise NotImplementedError + end + + def read_s3_buckets + return {} unless s3_config_present? + + s3_buckets = {} + @config[:"aws-s3-bucket"].each do |bucket_config| + if bucket_config.key?(:instance_name) + s3_buckets[bucket_config[:instance_name].to_sym] = bucket_config + end + end + s3_buckets + end + + def read_redis_uris + return {} unless redis_config_present? + + redis_uris = {} + @config[:redis].each do |redis_config| + if redis_config.key?(:instance_name) + redis_uris[redis_config[:instance_name].to_sym] = redis_config.dig(:credentials, :uri) + end + end + redis_uris + end + end +end diff --git a/app/services/configuration/env_configuration_service.rb b/app/services/configuration/env_configuration_service.rb new file mode 100644 index 000000000..077f425b4 --- /dev/null +++ b/app/services/configuration/env_configuration_service.rb @@ -0,0 +1,37 @@ +module Configuration + class EnvConfigurationService < ConfigurationService + private + + def config_present? + !ENV["S3_CONFIG"].nil? || !ENV["REDIS_CONFIG"].nil? + end + + def read_config + unless config_present? + @logger.warn("Could not find S3_CONFIG or REDIS_CONFIG in the environment variables!") + return {} + end + + config = {} + assign_config(config, :"aws-s3-bucket", "S3_CONFIG") + assign_config(config, :redis, "REDIS_CONFIG") + config + end + + def assign_config(config, symbol, env_variable) + config_hash = parse_json_config(env_variable) + config[symbol] = config_hash unless config_hash.empty? + end + + def parse_json_config(env_variable_name) + if ENV[env_variable_name].present? + begin + return JSON.parse(ENV[env_variable_name], { symbolize_names: true }) + rescue StandardError + @logger.warn("Could not parse #{env_variable_name}!") + end + end + {} + end + end +end diff --git a/app/services/configuration/paas_configuration_service.rb b/app/services/configuration/paas_configuration_service.rb new file mode 100644 index 000000000..b9f2a3226 --- /dev/null +++ b/app/services/configuration/paas_configuration_service.rb @@ -0,0 +1,23 @@ +module Configuration + class PaasConfigurationService < ConfigurationService + private + + def config_present? + !ENV["VCAP_SERVICES"].nil? + end + + def read_config + unless config_present? + @logger.warn("Could not find VCAP_SERVICES in the environment variables!") + return {} + end + + begin + JSON.parse(ENV["VCAP_SERVICES"], { symbolize_names: true }) + rescue StandardError + @logger.warn("Could not parse VCAP_SERVICES!") + {} + end + end + end +end diff --git a/app/services/imports/case_logs_import_service.rb b/app/services/imports/case_logs_import_service.rb index a0d75c0bb..8cd84c946 100644 --- a/app/services/imports/case_logs_import_service.rb +++ b/app/services/imports/case_logs_import_service.rb @@ -107,6 +107,13 @@ module Imports %w[a b c f g h].each do |letter| attributes["housingneeds_#{letter}"] = housing_needs(xml_doc, letter) end + attributes["housingneeds"] = 1 if [attributes["housingneeds_a"], attributes["housingneeds_b"], attributes["housingneeds_c"], attributes["housingneeds_f"]].any? { |housingneed| housingneed == 1 } + attributes["housingneeds"] = 2 if attributes["housingneeds_g"] == 1 + attributes["housingneeds"] = 3 if attributes["housingneeds_h"] == 1 + attributes["housingneeds_type"] = 0 if attributes["housingneeds_a"] == 1 + attributes["housingneeds_type"] = 1 if attributes["housingneeds_b"] == 1 + attributes["housingneeds_type"] = 2 if attributes["housingneeds_c"] == 1 + attributes["housingneeds_other"] = attributes["housingneeds_f"] == 1 ? 1 : 0 attributes["illness"] = unsafe_string_as_integer(xml_doc, "Q10ia") (1..10).each do |index| @@ -275,7 +282,7 @@ module Imports end def fields_not_present_in_softwire_data - %w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check] + %w[majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check housingneeds_type housingneeds_other] end def check_status_completed(case_log, previous_status) diff --git a/app/services/paas_configuration_service.rb b/app/services/paas_configuration_service.rb deleted file mode 100644 index 008b4d2ab..000000000 --- a/app/services/paas_configuration_service.rb +++ /dev/null @@ -1,62 +0,0 @@ -class PaasConfigurationService - attr_reader :s3_buckets, :redis_uris - - def initialize(logger = Rails.logger) - @logger = logger - @paas_config = read_pass_config - @s3_buckets = read_s3_buckets - @redis_uris = read_redis_uris - end - - def config_present? - !ENV["VCAP_SERVICES"].nil? - end - - def s3_config_present? - config_present? && @paas_config.key?(:"aws-s3-bucket") - end - - def redis_config_present? - config_present? && @paas_config.key?(:redis) - end - -private - - def read_pass_config - unless config_present? - @logger.warn("Could not find VCAP_SERVICES in the environment!") - return {} - end - - begin - JSON.parse(ENV["VCAP_SERVICES"], { symbolize_names: true }) - rescue StandardError - @logger.warn("Could not parse VCAP_SERVICES!") - {} - end - end - - def read_s3_buckets - return {} unless s3_config_present? - - s3_buckets = {} - @paas_config[:"aws-s3-bucket"].each do |bucket_config| - if bucket_config.key?(:instance_name) - s3_buckets[bucket_config[:instance_name].to_sym] = bucket_config - end - end - s3_buckets - end - - def read_redis_uris - return {} unless redis_config_present? - - redis_uris = {} - @paas_config[:redis].each do |redis_config| - if redis_config.key?(:instance_name) - redis_uris[redis_config[:instance_name].to_sym] = redis_config.dig(:credentials, :uri) - end - end - redis_uris - end -end diff --git a/app/services/s3_storage_service.rb b/app/services/s3_storage_service.rb deleted file mode 100644 index 15cbee3d0..000000000 --- a/app/services/s3_storage_service.rb +++ /dev/null @@ -1,78 +0,0 @@ -class S3StorageService < StorageService - attr_reader :configuration - - def initialize(paas_config_service, paas_instance_name) - super() - @paas_config_service = paas_config_service - @paas_instance_name = (paas_instance_name || "").to_sym - @configuration = create_configuration - @client = create_client - end - - def list_files(folder) - @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder) - .flat_map { |response| response.contents.map(&:key) } - end - - def folder_present?(folder) - response = @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder, max_keys: 1) - response.key_count == 1 - end - - def get_file_io(file_name) - @client.get_object(bucket: @configuration.bucket_name, key: file_name) - .body - end - - def write_file(file_name, data) - @client.put_object( - body: data, - bucket: @configuration.bucket_name, - key: file_name, - ) - end - -private - - def create_configuration - unless @paas_config_service.config_present? - raise "No PaaS configuration present" - end - unless @paas_config_service.s3_buckets.key?(@paas_instance_name) - raise "#{@paas_instance_name} instance name could not be found" - end - - bucket_config = @paas_config_service.s3_buckets[@paas_instance_name] - StorageConfiguration.new(bucket_config[:credentials]) - end - - def create_client - credentials = - Aws::Credentials.new( - @configuration.access_key_id, - @configuration.secret_access_key, - ) - Aws::S3::Client.new( - region: @configuration.region, - credentials:, - ) - end -end - -class StorageConfiguration - attr_reader :access_key_id, :secret_access_key, :bucket_name, :region - - def initialize(credentials) - @access_key_id = credentials[:aws_access_key_id] - @secret_access_key = credentials[:aws_secret_access_key] - @bucket_name = credentials[:bucket_name] - @region = credentials[:aws_region] - end - - def ==(other) - @access_key_id == other.access_key_id && - @secret_access_key == other.secret_access_key && - @bucket_name == other.bucket_name && - @region == other.region - end -end diff --git a/app/services/storage/archive_service.rb b/app/services/storage/archive_service.rb new file mode 100644 index 000000000..dcf3e8d75 --- /dev/null +++ b/app/services/storage/archive_service.rb @@ -0,0 +1,26 @@ +module Storage + class ArchiveService < StorageService + MAX_SIZE = 50 * (1024**2) # 50MiB + + def initialize(archive_io) + super() + @archive = Zip::File.open_buffer(archive_io) + end + + def list_files(folder) + @archive.glob(File.join(folder, "*.*")) + .map(&:name) + end + + def folder_present?(folder) + !list_files(folder).empty? + end + + def get_file_io(file_name) + entry = @archive.get_entry(file_name) + raise "File too large to be extracted" if entry.size > MAX_SIZE + + entry.get_input_stream + end + end +end diff --git a/app/services/storage/s3_service.rb b/app/services/storage/s3_service.rb new file mode 100644 index 000000000..aee76398d --- /dev/null +++ b/app/services/storage/s3_service.rb @@ -0,0 +1,80 @@ +module Storage + class S3Service < StorageService + attr_reader :configuration + + def initialize(config_service, paas_instance_name) + super() + @config_service = config_service + @instance_name = (paas_instance_name || "").to_sym + @configuration = create_configuration + @client = create_client + end + + def list_files(folder) + @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder) + .flat_map { |response| response.contents.map(&:key) } + end + + def folder_present?(folder) + response = @client.list_objects_v2(bucket: @configuration.bucket_name, prefix: folder, max_keys: 1) + response.key_count == 1 + end + + def get_file_io(file_name) + @client.get_object(bucket: @configuration.bucket_name, key: file_name) + .body + end + + def write_file(file_name, data) + @client.put_object( + body: data, + bucket: @configuration.bucket_name, + key: file_name, + ) + end + + private + + def create_configuration + unless @config_service.s3_config_present? + raise "No S3 bucket is present in the PaaS configuration" + end + unless @config_service.s3_buckets.key?(@instance_name) + raise "#{@instance_name} instance name could not be found" + end + + bucket_config = @config_service.s3_buckets[@instance_name] + StorageConfiguration.new(bucket_config[:credentials]) + end + + def create_client + credentials = + Aws::Credentials.new( + @configuration.access_key_id, + @configuration.secret_access_key, + ) + Aws::S3::Client.new( + region: @configuration.region, + credentials:, + ) + end + end + + class StorageConfiguration + attr_reader :access_key_id, :secret_access_key, :bucket_name, :region + + def initialize(credentials) + @access_key_id = credentials[:aws_access_key_id] + @secret_access_key = credentials[:aws_secret_access_key] + @bucket_name = credentials[:bucket_name] + @region = credentials[:aws_region] + end + + def ==(other) + @access_key_id == other.access_key_id && + @secret_access_key == other.secret_access_key && + @bucket_name == other.bucket_name && + @region == other.region + end + end +end diff --git a/app/services/storage/storage_service.rb b/app/services/storage/storage_service.rb new file mode 100644 index 000000000..afb3d4a58 --- /dev/null +++ b/app/services/storage/storage_service.rb @@ -0,0 +1,19 @@ +module Storage + class StorageService + def list_files(_folder) + raise NotImplementedError + end + + def folder_present?(_folder) + raise NotImplementedError + end + + def get_file_io(_file_name) + raise NotImplementedError + end + + def write_file(_file_name, _data) + raise NotImplementedError + end + end +end diff --git a/app/services/storage_service.rb b/app/services/storage_service.rb deleted file mode 100644 index 0135a92a1..000000000 --- a/app/services/storage_service.rb +++ /dev/null @@ -1,17 +0,0 @@ -class StorageService - def list_files(_folder) - raise NotImplementedError - end - - def folder_present?(_folder) - raise NotImplementedError - end - - def get_file_io(_file_name) - raise NotImplementedError - end - - def write_file(_file_name, _data) - raise NotImplementedError - end -end diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json index e2e0f0131..1ffbc1228 100644 --- a/config/forms/2021_2022.json +++ b/config/forms/2021_2022.json @@ -790,7 +790,7 @@ } ] }, - "header": "Are you sure the time between these dates is correct?", + "header": "Are you sure the property has been vacant for this long?", "type": "interruption_screen", "answer_options": { "0": { @@ -919,7 +919,7 @@ } ] }, - "header": "Are you sure the time between these dates is correct?", + "header": "Are you sure the property has been vacant for this long?", "type": "interruption_screen", "answer_options": { "0": { @@ -1242,7 +1242,7 @@ "description": "", "questions": { "age1_known": { - "check_answers_card_number": 1, + "check_answers_card_number": 1, "header": "Do you know the lead tenant’s age?", "hint_text": "The ’lead’ or ’main’ tenant is the person in the household who does the most paid work. If several people do the same paid work, the lead tenant is whoever is the oldest.", "type": "radio", @@ -5667,40 +5667,79 @@ } } }, - "access_needs": { + "access_needs_exist": { "header": "", "description": "", "questions": { - "accessibility_requirements": { + "housingneeds": { "header": "Does anybody in the household have any disabled access needs?", "hint_text": "", - "type": "checkbox", - "check_answer_label": "Anybody in household with disabled access needs", + "type": "radio", + "check_answer_label": "Anybody with disabled access needs", "answer_options": { - "housingneeds_a": { + "1": { + "value": "Yes" + }, + "2": { + "value": "No" + }, + "divider": { + "value": true + }, + "3": { + "value": "Don’t know" + } + } + } + } + }, + "type_of_access_needs": { + "header": "Disabled access needs", + "description": "", + "questions": { + "housingneeds_type": { + "header": "What type of access need do they have?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Disabled access needs", + "answer_options": { + "0": { "value": "Fully wheelchair accessible housing" }, - "housingneeds_b": { + "1": { "value": "Wheelchair access to essential rooms" }, - "housingneeds_c": { + "2": { "value": "Level access housing" }, - "housingneeds_f": { - "value": "Other disabled access needs" - }, "divider": { "value": true }, - "housingneeds_g": { - "value": "No disabled access needs" + "3": { + "value": "None of the above" + } + } + }, + "housingneeds_other": { + "header": "Do they have any other access needs?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Other disabled access needs", + "answer_options": { + "1": { + "value": "Yes" }, - "housingneeds_h": { - "value": "Don’t know" + "0": { + "value": "No" } } } - } + }, + "depends_on": [ + { + "housingneeds": 1 + } + ] }, "health_conditions": { "header": "", @@ -6209,12 +6248,7 @@ } } } - }, - "depends_on": [ - { - "renewal": 0 - } - ] + } }, "previous_postcode": { "header": "", diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json index 0102d5587..9f3df73e1 100644 --- a/config/forms/2022_2023.json +++ b/config/forms/2022_2023.json @@ -790,7 +790,7 @@ } ] }, - "header": "Are you sure the time between these dates is correct?", + "header": "Are you sure the property has been vacant for this long?", "type": "interruption_screen", "answer_options": { "0": { @@ -919,7 +919,7 @@ } ] }, - "header": "Are you sure the time between these dates is correct?", + "header": "Are you sure the property has been vacant for this long?", "type": "interruption_screen", "answer_options": { "0": { @@ -1277,7 +1277,7 @@ "description": "", "questions": { "age1_known": { - "check_answers_card_number": 1, + "check_answers_card_number": 1, "header": "Do you know the lead tenant’s age?", "hint_text": "The ’lead’ or ’main’ tenant is the person in the household who does the most paid work. If several people do the same paid work, the lead tenant is whoever is the oldest.", "type": "radio", @@ -5669,40 +5669,79 @@ } } }, - "access_needs": { + "access_needs_exist": { "header": "", "description": "", "questions": { - "accessibility_requirements": { + "housingneeds": { "header": "Does anybody in the household have any disabled access needs?", "hint_text": "", - "type": "checkbox", - "check_answer_label": "Anybody in household with disabled access needs", + "type": "radio", + "check_answer_label": "Anybody with disabled access needs", "answer_options": { - "housingneeds_a": { + "1": { + "value": "Yes" + }, + "2": { + "value": "No" + }, + "divider": { + "value": true + }, + "3": { + "value": "Don’t know" + } + } + } + } + }, + "type_of_access_needs": { + "header": "Disabled access needs", + "description": "", + "questions": { + "housingneeds_type": { + "header": "What type of access need do they have?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Disabled access needs", + "answer_options": { + "0": { "value": "Fully wheelchair accessible housing" }, - "housingneeds_b": { + "1": { "value": "Wheelchair access to essential rooms" }, - "housingneeds_c": { + "2": { "value": "Level access housing" }, - "housingneeds_f": { - "value": "Other disabled access needs" - }, "divider": { "value": true }, - "housingneeds_g": { - "value": "No disabled access needs" + "3": { + "value": "None of the above" + } + } + }, + "housingneeds_other": { + "header": "Do they have any other access needs?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Other disabled access needs", + "answer_options": { + "1": { + "value": "Yes" }, - "housingneeds_h": { - "value": "Don’t know" + "0": { + "value": "No" } } } - } + }, + "depends_on": [ + { + "housingneeds": 1 + } + ] }, "health_conditions": { "header": "", @@ -6168,12 +6207,7 @@ } } } - }, - "depends_on": [ - { - "renewal": 0 - } - ] + } }, "previous_postcode": { "header": "", diff --git a/config/initializers/rack_attack.rb b/config/initializers/rack_attack.rb index e130adc50..3bfcff86b 100644 --- a/config/initializers/rack_attack.rb +++ b/config/initializers/rack_attack.rb @@ -1,10 +1,11 @@ -require "paas_configuration_service" +require "configuration/configuration_service" +require "configuration/paas_configuration_service" if Rails.env.development? || Rails.env.test? Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new Rack::Attack.enabled = false else - redis_url = PaasConfigurationService.new.redis_uris[:"dluhc-core-#{Rails.env}-redis-rate-limit"] + redis_url = Configuration::PaasConfigurationService.new.redis_uris[:"dluhc-core-#{Rails.env}-redis-rate-limit"] Rack::Attack.cache.store = ActiveSupport::Cache::RedisCacheStore.new(url: redis_url) end diff --git a/config/locales/en.yml b/config/locales/en.yml index 107558f3c..c6403408c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -124,8 +124,8 @@ en: not_first_let: "Major repairs date must not be completed if the tenancy is a first let" ten_years_before_tenancy_start: "Enter a major repairs completion date that is no more than 10 years before the tenancy start date" void_date: - ten_years_before_tenancy_start: "Enter a void date must no more than 10 years before the tenancy start date" - before_tenancy_start: "Enter a void date must that is before the tenancy start date" + ten_years_before_tenancy_start: "Enter a void date no more than 10 years before the tenancy start date" + before_tenancy_start: "Enter a void date that is before the tenancy start date" after_mrcdate: "Void date must be before the major repairs date if provided" offered: relet_number: "Enter a number between 0 and 20 for the amount of times the property has been re-let" diff --git a/db/migrate/20220809100723_add_accessibility_requirements_fields.rb b/db/migrate/20220809100723_add_accessibility_requirements_fields.rb new file mode 100644 index 000000000..636a7e0ec --- /dev/null +++ b/db/migrate/20220809100723_add_accessibility_requirements_fields.rb @@ -0,0 +1,8 @@ +class AddAccessibilityRequirementsFields < ActiveRecord::Migration[7.0] + def change + change_table :case_logs, bulk: true do |t| + t.column :housingneeds_type, :integer + t.column :housingneeds_other, :integer + end + end +end diff --git a/docs/infrastructure.md b/docs/infrastructure.md index 9c3d1c8d7..5246c701c 100644 --- a/docs/infrastructure.md +++ b/docs/infrastructure.md @@ -4,6 +4,49 @@ nav_order: 5 # Infrastructure +## Configuration + +On [GOV.UK PaaS](https://www.cloud.service.gov.uk/), service credentials are appended to the environment variable `VCAP_SERVICES` when services [are bound](https://docs.cloud.service.gov.uk/deploying_services/s3/#bind-an-aws-s3-bucket-to-your-app) to an application. +Such services include datastores and S3 buckets. + +Our application uses S3 and Redis clients and supports two different ways of parsing their configuration: +* Via the environment variable `VCAP_SERVICES` using the `PaasConfigurationService` class +* Via the environment variables `S3_CONFIG` and `REDIS_CONFIG` using the `EnvConfigurationService` class + +`S3_CONFIG` and `REDIS_CONFIG` are populated using a similar structure than `VCAP_SERVICES`: + +S3_CONFIG: +```json +[ + { + "instance_name": "bucket_1", + "credentials": { + "aws_access_key_id": "123", + "aws_secret_access_key": "456", + "aws_region": "eu-west-1", + "bucket_name": "my-bucket" + } + } +] +``` + +REDIS_CONFIG: +```json +[ + { + "instance_name": "redis_1", + "credentials": { + "uri": "redis_uri" + } + } +] +``` + +In order to switch from using [GOV.UK PaaS](https://www.cloud.service.gov.uk/) provided services to external ones, instances of `PaasConfigurationService` need to be replaced by `EnvConfigurationService`. +This assumes that `S3_CONFIG` or/and `REDIS_CONFIG` are available. + +Please check `full_import.rake` and `rack_attack.rb` for examples of how the configuration is used. + ## Deployment This application is running on [GOV.UK PaaS](https://www.cloud.service.gov.uk/). To deploy you need to: diff --git a/lib/tasks/data_export.rake b/lib/tasks/data_export.rake index cf669f488..fb7af1466 100644 --- a/lib/tasks/data_export.rake +++ b/lib/tasks/data_export.rake @@ -4,7 +4,7 @@ namespace :core do format = args[:format] full_update = args[:full_update].present? && args[:full_update] == "true" - storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["EXPORT_PAAS_INSTANCE"]) + storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["EXPORT_PAAS_INSTANCE"]) export_service = Exports::CaseLogExportService.new(storage_service) if format.present? && format == "CSV" diff --git a/lib/tasks/data_import.rake b/lib/tasks/data_import.rake index 738fbceb5..b8baac256 100644 --- a/lib/tasks/data_import.rake +++ b/lib/tasks/data_import.rake @@ -5,7 +5,7 @@ namespace :core do path = args[:path] raise "Usage: rake core:data_import['data_type', 'path/to/xml_files']" if path.blank? || type.blank? - storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) + storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) case type when "organisation" diff --git a/lib/tasks/data_import_field.rake b/lib/tasks/data_import_field.rake index 7de94cd09..523ed6146 100644 --- a/lib/tasks/data_import_field.rake +++ b/lib/tasks/data_import_field.rake @@ -5,7 +5,7 @@ namespace :core do path = args[:path] raise "Usage: rake core:data_import_field['field','path/to/xml_files']" if path.blank? || field.blank? - storage_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) + storage_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) # We only allow a reduced list of known fields to be updatable case field diff --git a/lib/tasks/full_import.rake b/lib/tasks/full_import.rake index 1c082b460..bc982b98e 100644 --- a/lib/tasks/full_import.rake +++ b/lib/tasks/full_import.rake @@ -6,9 +6,9 @@ namespace :core do archive_path = args[:archive_path] raise "Usage: rake core:full_import['path/to/archive']" if archive_path.blank? - s3_service = S3StorageService.new(PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) + s3_service = Storage::S3Service.new(Configuration::PaasConfigurationService.new, ENV["IMPORT_PAAS_INSTANCE"]) archive_io = s3_service.get_file_io(archive_path) - archive_service = ArchiveStorageService.new(archive_io) + archive_service = Storage::ArchiveService.new(archive_io) import_list = [ Import.new(Imports::OrganisationImportService, :create_organisations, "institution"), diff --git a/spec/factories/case_log.rb b/spec/factories/case_log.rb index 46c151fd2..56937698e 100644 --- a/spec/factories/case_log.rb +++ b/spec/factories/case_log.rb @@ -87,6 +87,9 @@ FactoryBot.define do chr { 1 } cap { 0 } reasonother { nil } + housingneeds { 1 } + housingneeds_type { 0 } + housingneeds_other { 0 } housingneeds_a { 1 } housingneeds_b { 0 } housingneeds_c { 0 } diff --git a/spec/features/form/checkboxes_spec.rb b/spec/features/form/checkboxes_spec.rb index cbf5e51c1..0cc987835 100644 --- a/spec/features/form/checkboxes_spec.rb +++ b/spec/features/form/checkboxes_spec.rb @@ -41,24 +41,24 @@ RSpec.describe "Checkboxes" do context "when a checkbox question is submitted with invalid answers" do before do + case_log.update!(illness: 100) allow(case_log).to receive(:update).and_return(false) end it "shows an error summary" do - visit("/logs/#{id}/accessibility-requirements") - page.check("case-log-accessibility-requirements-housingneeds-a-field") - page.check("case-log-accessibility-requirements-housingneeds-c-field") + visit("/logs/#{id}/condition-effects") + page.check("case-log-condition-effects-illness-type-1-field") + page.check("case-log-condition-effects-illness-type-2-field") click_button("Save and continue") expect(page).to have_title("Error") end it "persists the original selections" do - visit("/logs/#{id}/accessibility-requirements") - page.check("case-log-accessibility-requirements-housingneeds-a-field") - page.check("case-log-accessibility-requirements-housingneeds-c-field") + visit("/logs/#{id}/condition-effects") + page.check("case-log-condition-effects-illness-type-1-field") + page.check("case-log-condition-effects-illness-type-2-field") click_button("Save and continue") - expect(page).to have_checked_field("case-log-accessibility-requirements-housingneeds-a-field") - expect(page).to have_checked_field("case-log-accessibility-requirements-housingneeds-c-field") + expect(page).to have_checked_field("case-log-condition-effects-illness-type-2-field") end end end diff --git a/spec/fixtures/complete_case_log.json b/spec/fixtures/complete_case_log.json index 227da864b..f498cfbe4 100644 --- a/spec/fixtures/complete_case_log.json +++ b/spec/fixtures/complete_case_log.json @@ -56,12 +56,10 @@ "chr":0, "cap":0, "reasonother":"", - "housingneeds_a":0, - "housingneeds_b":0, - "housingneeds_c":1, - "housingneeds_f":0, - "housingneeds_g":0, - "housingneeds_h":0, + "housingneeds": 1, + "housingneeds_type": 2, + "housingneeds_other": 0, + "housingneeds_c": 1, "illness_type_1":null, "illness_type_2":null, "illness_type_3":null, @@ -155,7 +153,6 @@ "wtcharge":"93.0", "wtshortfall":null, "refused":1, - "housingneeds":2, "wchchrg":null, "newprop":2, "relat2":"P", diff --git a/spec/fixtures/forms/2021_2022.json b/spec/fixtures/forms/2021_2022.json index ea8b3ce40..99b4d8713 100644 --- a/spec/fixtures/forms/2021_2022.json +++ b/spec/fixtures/forms/2021_2022.json @@ -390,6 +390,9 @@ "depends_on": [ { "illness": 1 + }, + { + "illness": 100 } ] } @@ -634,386 +637,366 @@ "label": true, "i18n_template": "ecstat1" }, - {"key": "earnings", + { + "key": "earnings", "label": true, "i18n_template": "earnings" - }] - }, - "questions": { - "net_income_value_check": { - "check_answer_label": "Net income soft validation", - "hidden_in_check_answers": true, - "header": "Are you sure this is correct?", - "type": "interruption_screen", - "answer_options": { - "0": { - "value": "Yes" - }, - "1": { - "value": "No" - } + } + ] + }, + "questions": { + "net_income_value_check": { + "check_answer_label": "Net income soft validation", + "hidden_in_check_answers": true, + "header": "Are you sure this is correct?", + "type": "interruption_screen", + "answer_options": { + "0": { + "value": "Yes" + }, + "1": { + "value": "No" } } } - }, - "net_income_uc_proportion": { - "questions": { - "benefits": { - "check_answer_label": "Benefits as a proportion of income", - "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", - "type": "radio", - "answer_options": { - "0": { - "value":"All" - }, - "1": { - "value":"Some" - } + } + }, + "net_income_uc_proportion": { + "questions": { + "benefits": { + "check_answer_label": "Benefits as a proportion of income", + "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", + "type": "radio", + "answer_options": { + "0": { + "value": "All" + }, + "1": { + "value": "Some" } } } - }, - "housing_benefit": { - "questions": { - "hb": { - "check_answer_label": "Housing-related benefits received", - "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", - "type": "radio", - "answer_options": { - "0": { - "value": "Housing benefit" - }, - "1": { - "value": "Tenant prefers not to say" - } + } + }, + "housing_benefit": { + "questions": { + "hb": { + "check_answer_label": "Housing-related benefits received", + "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", + "type": "radio", + "answer_options": { + "0": { + "value": "Housing benefit" }, - "conditional_for": { - "conditional_question": [0] + "1": { + "value": "Tenant prefers not to say" } }, - "conditional_question": { - "check_answer_label": "Conditional Question", - "header": "Question to test page conditions", - "type": "radio", - "answer_options": { - "0": { - "value": "Option A" - }, - "1": { - "value": "Option B" - } + "conditional_for": { + "conditional_question": [0] + } + }, + "conditional_question": { + "check_answer_label": "Conditional Question", + "header": "Question to test page conditions", + "type": "radio", + "answer_options": { + "0": { + "value": "Option A" + }, + "1": { + "value": "Option B" } } } - }, - "dependent_page": { - "depends_on": [{ "incfreq": 1 }], - "questions": { - "dependent_question": { - "check_answer_label": "Dependent Question", - "header": "Question to test page routing", - "type": "radio", - "answer_options": { - "0": { - "value": "Option A" - }, - "1": { - "value": "Option B" - } + } + }, + "dependent_page": { + "depends_on": [{ "incfreq": 1 }], + "questions": { + "dependent_question": { + "check_answer_label": "Dependent Question", + "header": "Question to test page routing", + "type": "radio", + "answer_options": { + "0": { + "value": "Option A" + }, + "1": { + "value": "Option B" } } } } } - }, - "rent_and_charges": { - "label": "Rent", - "pages": { - "rent": { - "questions": { - "period": { - "check_answer_label": "Rent Period", - "header": "Which period are rent and other charges due?", - "type": "radio", - "answer_options": { - "1": { - "value": "Weekly for 52 weeks" - }, - "3": { - "value": "Every 4 weeks" - } + } + }, + "rent_and_charges": { + "label": "Rent", + "pages": { + "rent": { + "questions": { + "period": { + "check_answer_label": "Rent Period", + "header": "Which period are rent and other charges due?", + "type": "radio", + "answer_options": { + "1": { + "value": "Weekly for 52 weeks" + }, + "3": { + "value": "Every 4 weeks" } - }, - "brent": { - "check_answer_label": "Basic Rent", - "header": "What is the basic rent?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "width": 4, - "fields-to-add": [ - "brent", - "scharge", - "pscharge", - "supcharg" - ], - "result-field": "tcharge" - }, - "scharge": { - "check_answer_label": "Service Charge", - "header": "What is the service charge?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "width": 4, - "fields-to-add": [ - "brent", - "scharge", - "pscharge", - "supcharg" - ], - "result-field": "tcharge" - }, - "pscharge": { - "check_answer_label": "Personal Service Charge", - "header": "What is the personal service charge?", - "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", - "type": "numeric", - "min": 0, - "step": 1, - "width": 4, - "fields-to-add": [ - "brent", - "scharge", - "pscharge", - "supcharg" - ], - "result-field": "tcharge" - }, - "supcharg": { - "check_answer_label": "Support Charge", - "header": "What is the support charge?", - "hint_text": "This is to fund housing-related support services included in the tenancy agreement", - "type": "numeric", - "min": 0, - "max": 300, - "step": 1, - "width": 4, - "fields-to-add": [ - "brent", - "scharge", - "pscharge", - "supcharg" - ], - "result-field": "tcharge" - }, - "tcharge": { - "check_answer_label": "Total Charge", - "header": "Total charge?", - "hint_text": "This is the total of rent and all charges", - "type": "numeric_output", - "min": 0, - "step": 1, - "width": 4, - "readonly": true, - "requires_js": true } + }, + "brent": { + "check_answer_label": "Basic Rent", + "header": "What is the basic rent?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "width": 4, + "fields-to-add": ["brent", "scharge", "pscharge", "supcharg"], + "result-field": "tcharge" + }, + "scharge": { + "check_answer_label": "Service Charge", + "header": "What is the service charge?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "width": 4, + "fields-to-add": ["brent", "scharge", "pscharge", "supcharg"], + "result-field": "tcharge" + }, + "pscharge": { + "check_answer_label": "Personal Service Charge", + "header": "What is the personal service charge?", + "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", + "type": "numeric", + "min": 0, + "step": 1, + "width": 4, + "fields-to-add": ["brent", "scharge", "pscharge", "supcharg"], + "result-field": "tcharge" + }, + "supcharg": { + "check_answer_label": "Support Charge", + "header": "What is the support charge?", + "hint_text": "This is to fund housing-related support services included in the tenancy agreement", + "type": "numeric", + "min": 0, + "max": 300, + "step": 1, + "width": 4, + "fields-to-add": ["brent", "scharge", "pscharge", "supcharg"], + "result-field": "tcharge" + }, + "tcharge": { + "check_answer_label": "Total Charge", + "header": "Total charge?", + "hint_text": "This is the total of rent and all charges", + "type": "numeric_output", + "min": 0, + "step": 1, + "width": 4, + "readonly": true, + "requires_js": true } - }, - "weekly_net_income": { - "header": "", - "description": "", - "questions": { - "earnings": { - "check_answer_label": "Total household income", - "header": "How much income does the household have in total every week?", - "hint_text": "", - "type": "numeric", - "min": 0, - "step": "1", - "width": 5, - "prefix": "£", - "suffix": " every week" - } + } + }, + "weekly_net_income": { + "header": "", + "description": "", + "questions": { + "earnings": { + "check_answer_label": "Total household income", + "header": "How much income does the household have in total every week?", + "hint_text": "", + "type": "numeric", + "min": 0, + "step": "1", + "width": 5, + "prefix": "£", + "suffix": " every week" + } + } + }, + "care_home_charge": { + "questions": { + "offered": { + "check_answer_label": "Basic Rent", + "header": "What is the basic rent?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "width": 4 } }, - "care_home_charge": { - "questions": { - "offered": { - "check_answer_label": "Basic Rent", - "header": "What is the basic rent?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "width": 4 - } - }, - "depends_on": [{"period": 3}] + "depends_on": [{ "period": 3 }] + }, + "care_home_charge_bi_weekly": { + "questions": { + "offered": { + "check_answer_label": "Basic Rent", + "header": "What is the basic rent?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "width": 4 + } }, - "care_home_charge_bi_weekly": { - "questions": { - "offered": { - "check_answer_label": "Basic Rent", - "header": "What is the basic rent?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "width": 4 - } - }, - "depends_on": [{"period": 2}] - } + "depends_on": [{ "period": 2 }] } } } - }, - "local_authority": { - "label": "Local authority", - "subsections": { - "local_authority": { - "label": "Local authority", - "pages": { - "time_lived_in_la": { - "questions": { - "layear": { - "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", - "header": "How long has the household continuously lived in the local authority area where the new letting is located?", - "type": "radio", - "answer_options": { - "0": { - "value": "Just moved to local authority area" - }, - "1": { - "value": "Less than 1 year" - }, - "2": { - "value": "1 year but under 2 years" - }, - "3": { - "value": "2 years but under 3 years" - }, - "4": { - "value": "3 years but under 4 years" - }, - "5": { - "value": "4 years but under 5 years" - }, - "6": { - "value": "5 years or more" - }, - "divider": { - "value": true - }, - "7": { - "value": "Don’t know" - } + } + }, + "local_authority": { + "label": "Local authority", + "subsections": { + "local_authority": { + "label": "Local authority", + "pages": { + "time_lived_in_la": { + "questions": { + "layear": { + "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", + "header": "How long has the household continuously lived in the local authority area where the new letting is located?", + "type": "radio", + "answer_options": { + "0": { + "value": "Just moved to local authority area" }, - "hidden_in_check_answers": { - "depends_on": [ - { "layear": 0 }, - { "layear": 1 } - ] + "1": { + "value": "Less than 1 year" + }, + "2": { + "value": "1 year but under 2 years" + }, + "3": { + "value": "2 years but under 3 years" + }, + "4": { + "value": "3 years but under 4 years" + }, + "5": { + "value": "4 years but under 5 years" + }, + "6": { + "value": "5 years or more" + }, + "divider": { + "value": true + }, + "7": { + "value": "Don’t know" } + }, + "hidden_in_check_answers": { + "depends_on": [{ "layear": 0 }, { "layear": 1 }] } - }, - "depends_on": [{ "renewal": 0 }] + } }, - "time_on_la_waiting_list": { - "questions": { - "lawaitlist": { - "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", - "header": "How long has the household been on the local authority waiting list where the new letting is located?", - "type": "radio", - "answer_options": { - "0": { - "value": "Just moved to local authority area" - }, - "1": { - "value": "Less than 1 year" - }, - "2": { - "value": "1 year but under 2 years" - }, - "3": { - "value": "2 years but under 3 years" - }, - "4": { - "value": "3 years but under 4 years" - }, - "5": { - "value": "4 years but under 5 years" - }, - "6": { - "value": "5 years or more" - }, - "divider": { - "value": true - }, - "7": { - "value": "Don’t know" - } + "depends_on": [{ "renewal": 0 }] + }, + "time_on_la_waiting_list": { + "questions": { + "lawaitlist": { + "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", + "header": "How long has the household been on the local authority waiting list where the new letting is located?", + "type": "radio", + "answer_options": { + "0": { + "value": "Just moved to local authority area" + }, + "1": { + "value": "Less than 1 year" + }, + "2": { + "value": "1 year but under 2 years" + }, + "3": { + "value": "2 years but under 3 years" + }, + "4": { + "value": "3 years but under 4 years" + }, + "5": { + "value": "4 years but under 5 years" + }, + "6": { + "value": "5 years or more" + }, + "divider": { + "value": true + }, + "7": { + "value": "Don’t know" } } } - }, - "other_postcode": { - "questions": { - "other_postcode": { - "check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation", - "header": "Postcode for the previous accommodation", - "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", - "type": "text", - "width": 5, - "conditional_for": { "fake_key": "fake_condition" } - }, - "ppostcode_full": { - "check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation", - "header": "Postcode for the previous accommodation", - "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", - "type": "text", - "width": 5 - } + } + }, + "other_postcode": { + "questions": { + "other_postcode": { + "check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation", + "header": "Postcode for the previous accommodation", + "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", + "type": "text", + "width": 5, + "conditional_for": { "fake_key": "fake_condition" } + }, + "ppostcode_full": { + "check_answer_label": "Postcode of previous accommodation if the household has moved from settled accommodation", + "header": "Postcode for the previous accommodation", + "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", + "type": "text", + "width": 5 } - }, - "property_major_repairs": { - "questions": { - "mrcdate": { - "check_answer_label": "What was the major repairs completion date?", - "header": "What was the major repairs completion date?", - "hint_text": "For example, 27 3 2021", - "type": "date" - } + } + }, + "property_major_repairs": { + "questions": { + "mrcdate": { + "check_answer_label": "What was the major repairs completion date?", + "header": "What was the major repairs completion date?", + "hint_text": "For example, 27 3 2021", + "type": "date" } } } } } - }, - "submission": { - "label": "Submission", - "subsections": { - "declaration": { - "label": "Declaration", - "depends_on": [{ + } + }, + "submission": { + "label": "Submission", + "subsections": { + "declaration": { + "label": "Declaration", + "depends_on": [ + { "household_characteristics": "completed", "household_needs": "completed", "property_information": "completed" - }], - "pages": { - "declaration": { - "questions": { - "declaration": { - "check_answer_label": "", - "header": "Submit this lettings log ", - "type": "checkbox", - "answer_options": { - "declaration": { - "value": "The tenant has seen the Department for Levelling Up, Housing & Communities (DLUHC) privacy notice" - } + } + ], + "pages": { + "declaration": { + "questions": { + "declaration": { + "check_answer_label": "", + "header": "Submit this lettings log ", + "type": "checkbox", + "answer_options": { + "declaration": { + "value": "The tenant has seen the Department for Levelling Up, Housing & Communities (DLUHC) privacy notice" } } } @@ -1024,3 +1007,4 @@ } } } +} diff --git a/spec/lib/tasks/data_export_spec.rb b/spec/lib/tasks/data_export_spec.rb index ae0acdb0d..00d3414d4 100644 --- a/spec/lib/tasks/data_export_spec.rb +++ b/spec/lib/tasks/data_export_spec.rb @@ -5,8 +5,8 @@ describe "rake core:data_export", type: task do subject(:task) { Rake::Task["core:data_export"] } let(:paas_instance) { "paas_export_instance" } - let(:storage_service) { instance_double(S3StorageService) } - let(:paas_config_service) { instance_double(PaasConfigurationService) } + let(:storage_service) { instance_double(Storage::S3Service) } + let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) } let(:export_service) { instance_double(Exports::CaseLogExportService) } before do @@ -14,8 +14,8 @@ describe "rake core:data_export", type: task do Rake::Task.define_task(:environment) task.reenable - allow(S3StorageService).to receive(:new).and_return(storage_service) - allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service) + allow(Storage::S3Service).to receive(:new).and_return(storage_service) + allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service) allow(Exports::CaseLogExportService).to receive(:new).and_return(export_service) allow(ENV).to receive(:[]) allow(ENV).to receive(:[]).with("EXPORT_PAAS_INSTANCE").and_return(paas_instance) @@ -23,7 +23,7 @@ describe "rake core:data_export", type: task do context "when exporting case logs with no parameters" do it "starts the XML export process" do - expect(S3StorageService).to receive(:new).with(paas_config_service, paas_instance) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, paas_instance) expect(Exports::CaseLogExportService).to receive(:new).with(storage_service) expect(export_service).to receive(:export_xml_case_logs) @@ -33,7 +33,7 @@ describe "rake core:data_export", type: task do context "when exporting case logs with CSV format" do it "starts the CSV export process" do - expect(S3StorageService).to receive(:new).with(paas_config_service, paas_instance) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, paas_instance) expect(Exports::CaseLogExportService).to receive(:new).with(storage_service) expect(export_service).to receive(:export_csv_case_logs) diff --git a/spec/lib/tasks/data_import_spec.rb b/spec/lib/tasks/data_import_spec.rb index 9a88ef22e..e861c2ad2 100644 --- a/spec/lib/tasks/data_import_spec.rb +++ b/spec/lib/tasks/data_import_spec.rb @@ -5,16 +5,16 @@ describe "rake core:data_import", type: :task do subject(:task) { Rake::Task["core:data_import"] } let(:instance_name) { "paas_import_instance" } - let(:storage_service) { instance_double(S3StorageService) } - let(:paas_config_service) { instance_double(PaasConfigurationService) } + let(:storage_service) { instance_double(Storage::S3Service) } + let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) } before do Rake.application.rake_require("tasks/data_import") Rake::Task.define_task(:environment) task.reenable - allow(S3StorageService).to receive(:new).and_return(storage_service) - allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service) + allow(Storage::S3Service).to receive(:new).and_return(storage_service) + allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service) allow(ENV).to receive(:[]) allow(ENV).to receive(:[]).with("IMPORT_PAAS_INSTANCE").and_return(instance_name) end @@ -29,7 +29,7 @@ describe "rake core:data_import", type: :task do end it "creates an organisation from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::OrganisationImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_organisations).with(fixture_path) @@ -47,7 +47,7 @@ describe "rake core:data_import", type: :task do end it "creates a user from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::UserImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_users).with(fixture_path) @@ -65,7 +65,7 @@ describe "rake core:data_import", type: :task do end it "creates an organisation from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::DataProtectionConfirmationImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_data_protection_confirmations).with(fixture_path) @@ -83,7 +83,7 @@ describe "rake core:data_import", type: :task do end it "creates an organisation la from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::OrganisationRentPeriodImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_organisation_rent_periods).with(fixture_path) @@ -101,7 +101,7 @@ describe "rake core:data_import", type: :task do end it "creates case logs from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::CaseLogsImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_logs).with(fixture_path) @@ -119,7 +119,7 @@ describe "rake core:data_import", type: :task do end it "creates a scheme from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::SchemeImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_schemes).with(fixture_path) @@ -137,7 +137,7 @@ describe "rake core:data_import", type: :task do end it "creates a scheme location from the given XML file" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) expect(Imports::SchemeLocationImportService).to receive(:new).with(storage_service) expect(import_service).to receive(:create_scheme_locations).with(fixture_path) diff --git a/spec/lib/tasks/date_import_field_spec.rb b/spec/lib/tasks/date_import_field_spec.rb index 5dd96ff28..69c58697a 100644 --- a/spec/lib/tasks/date_import_field_spec.rb +++ b/spec/lib/tasks/date_import_field_spec.rb @@ -5,16 +5,16 @@ describe "rake core:data_import_field", type: :task do subject(:task) { Rake::Task["core:data_import_field"] } let(:instance_name) { "paas_import_instance" } - let(:storage_service) { instance_double(S3StorageService) } - let(:paas_config_service) { instance_double(PaasConfigurationService) } + let(:storage_service) { instance_double(Storage::S3Service) } + let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) } before do Rake.application.rake_require("tasks/data_import_field") Rake::Task.define_task(:environment) task.reenable - allow(S3StorageService).to receive(:new).and_return(storage_service) - allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service) + allow(Storage::S3Service).to receive(:new).and_return(storage_service) + allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service) allow(ENV).to receive(:[]) allow(ENV).to receive(:[]).with("IMPORT_PAAS_INSTANCE").and_return(instance_name) end @@ -32,7 +32,7 @@ describe "rake core:data_import_field", type: :task do let(:field) { "tenant_code" } it "properly configures the storage service" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) task.invoke(field, fixture_path) end @@ -46,7 +46,7 @@ describe "rake core:data_import_field", type: :task do let(:field) { "lettings_allocation" } it "properly configures the storage service" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) task.invoke(field, fixture_path) end @@ -60,7 +60,7 @@ describe "rake core:data_import_field", type: :task do let(:field) { "major_repairs" } it "properly configures the storage service" do - expect(S3StorageService).to receive(:new).with(paas_config_service, instance_name) + expect(Storage::S3Service).to receive(:new).with(paas_config_service, instance_name) task.invoke(field, fixture_path) end diff --git a/spec/lib/tasks/full_import_spec.rb b/spec/lib/tasks/full_import_spec.rb index 99f95f555..79fac87f3 100644 --- a/spec/lib/tasks/full_import_spec.rb +++ b/spec/lib/tasks/full_import_spec.rb @@ -5,19 +5,19 @@ require "zip" describe "rake core:full_import", type: :task do subject(:task) { Rake::Task["core:full_import"] } - let(:s3_service) { instance_double(S3StorageService) } - let(:archive_service) { instance_double(ArchiveStorageService) } - let(:paas_config_service) { instance_double(PaasConfigurationService) } + let(:s3_service) { instance_double(Storage::S3Service) } + let(:archive_service) { instance_double(Storage::ArchiveService) } + let(:paas_config_service) { instance_double(Configuration::PaasConfigurationService) } before do Rake.application.rake_require("tasks/full_import") Rake::Task.define_task(:environment) task.reenable - allow(PaasConfigurationService).to receive(:new).and_return(paas_config_service) - allow(S3StorageService).to receive(:new).and_return(s3_service) + allow(Configuration::PaasConfigurationService).to receive(:new).and_return(paas_config_service) + allow(Storage::S3Service).to receive(:new).and_return(s3_service) allow(s3_service).to receive(:get_file_io) - allow(ArchiveStorageService).to receive(:new).and_return(archive_service) + allow(Storage::ArchiveService).to receive(:new).and_return(archive_service) end context "when starting a full import" do diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb index eadf2d6b0..40525219e 100644 --- a/spec/models/case_log_spec.rb +++ b/spec/models/case_log_spec.rb @@ -139,10 +139,6 @@ RSpec.describe CaseLog do expect(validator).to receive(:validate_rsnvac) end - it "validates accessibility requirements" do - expect(validator).to receive(:validate_accessibility_requirements) - end - it "validates referral" do expect(validator).to receive(:validate_referral) end @@ -1440,34 +1436,6 @@ RSpec.describe CaseLog do end end - context "when the data provider is filling in household needs" do - let!(:case_log) do - described_class.create({ - managing_organisation: owning_organisation, - owning_organisation:, - created_by: created_by_user, - }) - end - - it "correctly derives and saves housing neeeds as 1" do - case_log.update!(housingneeds_a: 1) - record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0] - expect(record_from_db["housingneeds"]).to eq(1) - end - - it "correctly derives and saves housing neeeds as 2" do - case_log.update!(housingneeds_g: 1) - record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0] - expect(record_from_db["housingneeds"]).to eq(2) - end - - it "correctly derives and saves housing neeeds as 3" do - case_log.update!(housingneeds_h: 1) - record_from_db = ActiveRecord::Base.connection.execute("select housingneeds from case_logs where id=#{case_log.id}").to_a[0] - expect(record_from_db["housingneeds"]).to eq(3) - end - end - context "when it is supported housing and a care home charge has been supplied" do let!(:case_log) do described_class.create({ @@ -1753,6 +1721,99 @@ RSpec.describe CaseLog do end end end + + context "when saving accessibility needs" do + it "derives housingneeds_h as true if 'Don't know' is selected for housingneeds" do + case_log.update!({ housingneeds: 3 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_h"]).to eq(1) + expect(case_log["housingneeds_h"]).to eq(1) + end + + it "derives housingneeds_g as true if 'No' is selected for housingneeds" do + case_log.update!({ housingneeds: 2 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_g"]).to eq(1) + expect(case_log["housingneeds_g"]).to eq(1) + end + + it "derives housingneeds_a as true if 'Fully wheelchair accessible' is selected for housingneeds_type" do + case_log.update!({ housingneeds: 1, housingneeds_type: 0 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_a"]).to eq(1) + expect(case_log["housingneeds_a"]).to eq(1) + end + + it "derives housingneeds_b as true if 'Wheelchair access to essential rooms' is selected for housingneeds_type" do + case_log.update!({ housingneeds: 1, housingneeds_type: 1 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_c housingneeds_f housingneeds_g housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_b"]).to eq(1) + expect(case_log["housingneeds_b"]).to eq(1) + end + + it "derives housingneeds_c if 'Level access housing' is selected for housingneeds_type" do + case_log.update!({ housingneeds: 1, housingneeds_type: 2 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_f housingneeds_g housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_c"]).to eq(1) + expect(case_log["housingneeds_c"]).to eq(1) + end + + it "derives housingneeds_f if 'Yes' is selected for housingneeds_other" do + case_log.update!({ housingneeds: 1, housingneeds_other: 1 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_g housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_f"]).to eq(1) + expect(case_log["housingneeds_f"]).to eq(1) + end + + it "clears previously set housingneeds if 'No' is selected for housingneeds" do + case_log.update!({ housingneeds: 1, housingneeds_type: 2, housingneeds_other: 1 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + expect(record_from_db["housingneeds_c"]).to eq(1) + expect(case_log["housingneeds_c"]).to eq(1) + expect(record_from_db["housingneeds_f"]).to eq(1) + expect(case_log["housingneeds_f"]).to eq(1) + + case_log.update!({ housingneeds: 2 }) + record_from_db = ActiveRecord::Base.connection.execute("select housingneeds_a, housingneeds_b, housingneeds_c, housingneeds_f, housingneeds_g, housingneeds_h from case_logs where id=#{case_log.id}").to_a[0] + not_selected_housingneeds = %w[housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_h] + not_selected_housingneeds.each do |housingneed| + expect(record_from_db[housingneed]).to eq(0) + expect(case_log[housingneed]).to eq(0) + end + expect(record_from_db["housingneeds_g"]).to eq(1) + expect(case_log["housingneeds_g"]).to eq(1) + end + end end describe "optional fields" do diff --git a/spec/models/validations/household_validations_spec.rb b/spec/models/validations/household_validations_spec.rb index 5201adb6e..a844a612a 100644 --- a/spec/models/validations/household_validations_spec.rb +++ b/spec/models/validations/household_validations_spec.rb @@ -575,46 +575,6 @@ RSpec.describe Validations::HouseholdValidations do end end - describe "accessibility requirement validations" do - it "validates that mutually exclusive options can't be selected together" do - record.housingneeds_a = 1 - record.housingneeds_b = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]) - .to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices")) - record.housingneeds_a = 0 - record.housingneeds_b = 0 - record.housingneeds_g = 1 - record.housingneeds_f = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]) - .to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices")) - record.housingneeds_a = 1 - record.housingneeds_g = 1 - record.housingneeds_f = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]) - .to include(match I18n.t("validations.household.housingneeds_a.one_or_two_choices")) - end - - it "validates that non-mutually exclusive options can be selected together" do - record.housingneeds_a = 1 - record.housingneeds_f = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]).to be_empty - record.housingneeds_a = 0 - record.housingneeds_b = 1 - record.housingneeds_f = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]).to be_empty - record.housingneeds_b = 0 - record.housingneeds_c = 1 - record.housingneeds_f = 1 - household_validator.validate_accessibility_requirements(record) - expect(record.errors["accessibility_requirements"]).to be_empty - end - end - describe "referral validations" do context "when homelessness is assessed" do it "can be internal transfer" do diff --git a/spec/services/configuration/env_configuration_service_spec.rb b/spec/services/configuration/env_configuration_service_spec.rb new file mode 100644 index 000000000..491ecec7d --- /dev/null +++ b/spec/services/configuration/env_configuration_service_spec.rb @@ -0,0 +1,128 @@ +require "rails_helper" + +RSpec.describe Configuration::EnvConfigurationService do + subject(:config_service) { described_class.new(logger) } + + let(:logger) { instance_double(ActiveSupport::LogSubscriber) } + + context "when environment configurations are unavailable" do + before { allow(logger).to receive(:warn) } + + it "returns the S3 configuration as not present" do + expect(config_service.s3_config_present?).to be(false) + end + + it "returns the redis configuration as not present" do + expect(config_service.redis_config_present?).to be(false) + end + + it "does not retrieve any S3 bucket configuration" do + expect(config_service.s3_buckets).to be_a(Hash) + expect(config_service.s3_buckets).to be_empty + end + + it "does not retrieve any redis configuration" do + expect(config_service.redis_uris).to be_a(Hash) + expect(config_service.redis_uris).to be_empty + end + end + + context "when environment configurations are present but invalid" do + let(:env_variable) { "random text" } + + before do + allow(ENV).to receive(:[]).with("S3_CONFIG").and_return(env_variable) + allow(ENV).to receive(:[]).with("REDIS_CONFIG").and_return(env_variable) + allow(logger).to receive(:warn) + end + + it "logs an error when checking if the S3 config is present" do + expect(logger).to receive(:warn).with("Could not parse S3_CONFIG!") + config_service.s3_config_present? + end + + it "logs an error when checking if the Redis config is present" do + expect(logger).to receive(:warn).with("Could not parse REDIS_CONFIG!") + config_service.redis_config_present? + end + end + + context "when environment configurations are present with S3 configured" do + let(:s3_config) do + <<~JSON + [ + { + "instance_name": "bucket_1", + "credentials": { + "aws_access_key_id": "123", + "aws_secret_access_key": "456", + "aws_region": "eu-west-1", + "bucket_name": "my-bucket" + } + }, + { + "instance_name": "bucket_2", + "credentials": { + "aws_access_key_id": "789", + "aws_secret_access_key": "012", + "aws_region": "eu-west-2", + "bucket_name": "my-bucket2" + } + } + ] + JSON + end + + before do + allow(ENV).to receive(:[]).with("REDIS_CONFIG") + allow(ENV).to receive(:[]).with("S3_CONFIG").and_return(s3_config) + end + + it "returns the S3 configuration as present" do + expect(config_service.s3_config_present?).to be(true) + end + + it "returns the redis configuration as not present" do + expect(config_service.redis_config_present?).to be(false) + end + + it "does retrieve the S3 bucket configurations" do + s3_buckets = config_service.s3_buckets + + expect(s3_buckets).not_to be_empty + expect(s3_buckets.count).to be(2) + expect(s3_buckets).to have_key(:bucket_1) + expect(s3_buckets).to have_key(:bucket_2) + end + end + + context "when environment configurations are present with redis configured" do + let(:redis_config) do + <<-JSON + [{"instance_name": "redis_1", "credentials": {"uri": "redis_uri" }}] + JSON + end + + before do + allow(ENV).to receive(:[]).with("S3_CONFIG") + allow(ENV).to receive(:[]).with("REDIS_CONFIG").and_return(redis_config) + end + + it "returns the redis configuration as present" do + expect(config_service.redis_config_present?).to be(true) + end + + it "returns the S3 configuration as not present" do + expect(config_service.s3_config_present?).to be(false) + end + + it "does retrieve the redis configurations" do + redis_uris = config_service.redis_uris + + expect(redis_uris).not_to be_empty + expect(redis_uris.count).to be(1) + expect(redis_uris).to have_key(:redis_1) + expect(redis_uris[:redis_1]).to eq("redis_uri") + end + end +end diff --git a/spec/services/paas_configuration_service_spec.rb b/spec/services/configuration/paas_configuration_service_spec.rb similarity index 66% rename from spec/services/paas_configuration_service_spec.rb rename to spec/services/configuration/paas_configuration_service_spec.rb index 3338ad5ec..5e9e88046 100644 --- a/spec/services/paas_configuration_service_spec.rb +++ b/spec/services/configuration/paas_configuration_service_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -RSpec.describe PaasConfigurationService do +RSpec.describe Configuration::PaasConfigurationService do subject(:config_service) { described_class.new(logger) } let(:logger) { instance_double(ActiveSupport::LogSubscriber) } @@ -8,14 +8,38 @@ RSpec.describe PaasConfigurationService do context "when the paas configuration is unavailable" do before { allow(logger).to receive(:warn) } - it "returns the configuration as not present" do - expect(config_service.config_present?).to be(false) + it "returns the S3 configuration as not present" do + expect(config_service.s3_config_present?).to be(false) + end + + it "returns the redis configuration as not present" do + expect(config_service.redis_config_present?).to be(false) + end + + it "does not retrieve any S3 bucket configuration" do + expect(config_service.s3_buckets).to be_a(Hash) + expect(config_service.s3_buckets).to be_empty + end + + it "does not retrieve any redis configuration" do + expect(config_service.redis_uris).to be_a(Hash) + expect(config_service.redis_uris).to be_empty + end + end + + context "when the paas configuration is present but empty" do + before do + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}") end it "returns the S3 configuration as not present" do expect(config_service.s3_config_present?).to be(false) end + it "returns the redis configuration as not present" do + expect(config_service.redis_config_present?).to be(false) + end + it "does not retrieve any S3 bucket configuration" do expect(config_service.s3_buckets).to be_a(Hash) expect(config_service.s3_buckets).to be_empty @@ -27,7 +51,7 @@ RSpec.describe PaasConfigurationService do end end - context "when configuration is present but invalid" do + context "when the paas configuration is present but invalid" do let(:vcap_services) { "random text" } before do @@ -35,16 +59,40 @@ RSpec.describe PaasConfigurationService do allow(logger).to receive(:warn) end - it "logs an error" do + it "logs an error when checking if the S3 config is present" do expect(logger).to receive(:warn).with("Could not parse VCAP_SERVICES!") config_service.s3_config_present? end + + it "logs an error when checking if the Redis config is present" do + expect(logger).to receive(:warn).with("Could not parse VCAP_SERVICES!") + config_service.redis_config_present? + end end - context "when the paas configuration is present with S3 buckets" do + context "when the paas configuration is present with S3 configured" do let(:vcap_services) do - <<-JSON - {"aws-s3-bucket": [{"instance_name": "bucket_1"},{"instance_name": "bucket_2"}]} + <<~JSON + {"aws-s3-bucket": + [{ + "instance_name": "bucket_1", + "credentials": { + "aws_access_key_id": "123", + "aws_secret_access_key": "456", + "aws_region": "eu-west-1", + "bucket_name": "my-bucket" + } + }, + { + "instance_name": "bucket_2", + "credentials": { + "aws_access_key_id": "789", + "aws_secret_access_key": "012", + "aws_region": "eu-west-2", + "bucket_name": "my-bucket2" + } + }] + } JSON end @@ -52,14 +100,14 @@ RSpec.describe PaasConfigurationService do allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services) end - it "returns the configuration as present" do - expect(config_service.config_present?).to be(true) - end - it "returns the S3 configuration as present" do expect(config_service.s3_config_present?).to be(true) end + it "returns the redis configuration as not present" do + expect(config_service.redis_config_present?).to be(false) + end + it "does retrieve the S3 bucket configurations" do s3_buckets = config_service.s3_buckets @@ -70,26 +118,7 @@ RSpec.describe PaasConfigurationService do end end - context "when the paas configuration is present without S3 buckets" do - before do - allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}") - end - - it "returns the configuration as present" do - expect(config_service.config_present?).to be(true) - end - - it "returns the S3 configuration as not present" do - expect(config_service.s3_config_present?).to be(false) - end - - it "does not retrieve any S3 bucket configuration" do - expect(config_service.s3_buckets).to be_a(Hash) - expect(config_service.s3_buckets).to be_empty - end - end - - context "when the paas configuration is present with redis configurations" do + context "when the paas configuration is present with redis configured" do let(:vcap_services) do <<-JSON {"redis": [{"instance_name": "redis_1", "credentials": {"uri": "redis_uri" }}]} @@ -100,14 +129,14 @@ RSpec.describe PaasConfigurationService do allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services) end - it "returns the configuration as present" do - expect(config_service.config_present?).to be(true) - end - it "returns the redis configuration as present" do expect(config_service.redis_config_present?).to be(true) end + it "returns the S3 configuration as not present" do + expect(config_service.s3_config_present?).to be(false) + end + it "does retrieve the redis configurations" do redis_uris = config_service.redis_uris @@ -117,23 +146,4 @@ RSpec.describe PaasConfigurationService do expect(redis_uris[:redis_1]).to eq("redis_uri") end end - - context "when the paas configuration is present without redis configuration" do - before do - allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}") - end - - it "returns the configuration as present" do - expect(config_service.config_present?).to be(true) - end - - it "returns the redis configuration as not present" do - expect(config_service.redis_config_present?).to be(false) - end - - it "does not retrieve any redis uris from configuration" do - expect(config_service.redis_uris).to be_a(Hash) - expect(config_service.redis_uris).to be_empty - end - end end diff --git a/spec/services/csv/case_log_csv_service_spec.rb b/spec/services/csv/case_log_csv_service_spec.rb index ee3327413..d52d50874 100644 --- a/spec/services/csv/case_log_csv_service_spec.rb +++ b/spec/services/csv/case_log_csv_service_spec.rb @@ -105,12 +105,9 @@ RSpec.describe Csv::CaseLogCsvService do leftreg reservist preg_occ - housingneeds_a - housingneeds_b - housingneeds_c - housingneeds_f - housingneeds_g - housingneeds_h + housingneeds + housingneeds_type + housingneeds_other illness illness_type_4 illness_type_5 @@ -165,6 +162,12 @@ RSpec.describe Csv::CaseLogCsvService do hbrentshortfall tshortfall_known tshortfall + housingneeds_a + housingneeds_b + housingneeds_c + housingneeds_f + housingneeds_g + housingneeds_h property_owner_organisation property_manager_organisation sale_or_letting @@ -187,7 +190,6 @@ RSpec.describe Csv::CaseLogCsvService do wtcharge wtshortfall refused - housingneeds wchchrg newprop old_form_id @@ -198,8 +200,6 @@ RSpec.describe Csv::CaseLogCsvService do hhtype new_old vacdays - housingneeds_type - housingneeds_other unittype_sh scheme_code scheme_service_name diff --git a/spec/services/exports/case_log_export_service_spec.rb b/spec/services/exports/case_log_export_service_spec.rb index fc59cde4e..82124f288 100644 --- a/spec/services/exports/case_log_export_service_spec.rb +++ b/spec/services/exports/case_log_export_service_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Exports::CaseLogExportService do subject(:export_service) { described_class.new(storage_service) } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log.xml", "r:UTF-8") } let(:local_manifest_file) { File.open("spec/fixtures/exports/manifest.xml", "r:UTF-8") } diff --git a/spec/services/imports/case_logs_field_import_service_spec.rb b/spec/services/imports/case_logs_field_import_service_spec.rb index 7184ee648..e703c3786 100644 --- a/spec/services/imports/case_logs_field_import_service_spec.rb +++ b/spec/services/imports/case_logs_field_import_service_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Imports::CaseLogsFieldImportService do subject(:import_service) { described_class.new(storage_service, logger) } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") } diff --git a/spec/services/imports/case_logs_import_service_spec.rb b/spec/services/imports/case_logs_import_service_spec.rb index 30a5cc41e..075244ecf 100644 --- a/spec/services/imports/case_logs_import_service_spec.rb +++ b/spec/services/imports/case_logs_import_service_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Imports::CaseLogsImportService do subject(:case_log_service) { described_class.new(storage_service, logger) } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json", "2021_2022") } diff --git a/spec/services/imports/data_protection_confirmation_import_service_spec.rb b/spec/services/imports/data_protection_confirmation_import_service_spec.rb index db5a25046..cb14829b4 100644 --- a/spec/services/imports/data_protection_confirmation_import_service_spec.rb +++ b/spec/services/imports/data_protection_confirmation_import_service_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Imports::DataProtectionConfirmationImportService do let(:old_org_id) { "7c5bd5fb549c09a2c55d7cb90d7ba84927e64618" } let(:old_id) { old_org_id } let(:import_file) { File.open("#{fixture_directory}/#{old_id}.xml") } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } context "when importing data protection confirmations" do diff --git a/spec/services/imports/organisation_import_service_spec.rb b/spec/services/imports/organisation_import_service_spec.rb index 5eceea549..48a0d72bb 100644 --- a/spec/services/imports/organisation_import_service_spec.rb +++ b/spec/services/imports/organisation_import_service_spec.rb @@ -1,7 +1,7 @@ require "rails_helper" RSpec.describe Imports::OrganisationImportService do - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(Rails::Rack::Logger) } let(:folder_name) { "organisations" } let(:filenames) { %w[my_folder/my_file1.xml my_folder/my_file2.xml] } diff --git a/spec/services/imports/organisation_rent_period_import_service_spec.rb b/spec/services/imports/organisation_rent_period_import_service_spec.rb index b85bb64e5..adb4899e9 100644 --- a/spec/services/imports/organisation_rent_period_import_service_spec.rb +++ b/spec/services/imports/organisation_rent_period_import_service_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Imports::OrganisationRentPeriodImportService do let(:old_org_id) { "44026acc7ed5c29516b26f2a5deb639e5e37966d" } let(:old_id) { "ebd22326d33e389e9f1bfd546979d2c05f9e68d6" } let(:import_file) { File.open("#{fixture_directory}/#{old_id}.xml") } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } context "when importing organisation rent periods" do diff --git a/spec/services/imports/scheme_import_service_spec.rb b/spec/services/imports/scheme_import_service_spec.rb index b6b98d25d..efba81a1c 100644 --- a/spec/services/imports/scheme_import_service_spec.rb +++ b/spec/services/imports/scheme_import_service_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Imports::SchemeImportService do subject(:scheme_service) { described_class.new(storage_service, logger) } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } let(:fixture_directory) { "spec/fixtures/imports/mgmtgroups" } diff --git a/spec/services/imports/scheme_location_import_service_spec.rb b/spec/services/imports/scheme_location_import_service_spec.rb index ebe421f45..70ff039cd 100644 --- a/spec/services/imports/scheme_location_import_service_spec.rb +++ b/spec/services/imports/scheme_location_import_service_spec.rb @@ -3,7 +3,7 @@ require "rails_helper" RSpec.describe Imports::SchemeLocationImportService do subject(:location_service) { described_class.new(storage_service, logger) } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } let(:fixture_directory) { "spec/fixtures/imports/schemes" } diff --git a/spec/services/imports/user_import_service_spec.rb b/spec/services/imports/user_import_service_spec.rb index b9e3028c9..c4aea00bc 100644 --- a/spec/services/imports/user_import_service_spec.rb +++ b/spec/services/imports/user_import_service_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Imports::UserImportService do let(:old_user_id) { "fc7625a02b24ae16162aa63ae7cb33feeec0c373" } let(:old_org_id) { "7c5bd5fb549c09a2c55d7cb90d7ba84927e64618" } let(:user_file) { File.open("#{fixture_directory}/#{old_user_id}.xml") } - let(:storage_service) { instance_double(S3StorageService) } + let(:storage_service) { instance_double(Storage::S3Service) } let(:logger) { instance_double(ActiveSupport::Logger) } let(:notify_client) { instance_double(Notifications::Client) } let(:devise_notify_mailer) { DeviseNotifyMailer.new } diff --git a/spec/services/archive_storage_service_spec.rb b/spec/services/storage/archive_service_spec.rb similarity index 98% rename from spec/services/archive_storage_service_spec.rb rename to spec/services/storage/archive_service_spec.rb index fb33e4dd3..52808262f 100644 --- a/spec/services/archive_storage_service_spec.rb +++ b/spec/services/storage/archive_service_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -RSpec.describe ArchiveStorageService do +RSpec.describe Storage::ArchiveService do subject(:archive_service) { described_class.new(archive_content) } let(:compressed_folder) { "my_directory" } diff --git a/spec/services/s3_storage_service_spec.rb b/spec/services/storage/s3_service_spec.rb similarity index 80% rename from spec/services/s3_storage_service_spec.rb rename to spec/services/storage/s3_service_spec.rb index c89b7c1bb..36a549b21 100644 --- a/spec/services/s3_storage_service_spec.rb +++ b/spec/services/storage/s3_service_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -RSpec.describe S3StorageService do +RSpec.describe Storage::S3Service do let(:instance_name) { "instance_1" } let(:bucket_name) { "bucket_1" } let(:vcap_services) do @@ -20,18 +20,24 @@ RSpec.describe S3StorageService do end context "when we create a storage service with no PaaS Configuration present" do - subject(:storage_service) { described_class.new(PaasConfigurationService.new, "random_instance") } + subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, "random_instance") } it "raises an exception" do - expect { storage_service }.to raise_error(RuntimeError, /No PaaS configuration present/) + expect { storage_service }.to raise_error(RuntimeError, "No S3 bucket is present in the PaaS configuration") end end - context "when we create a storage service with an unknown instance name" do - subject(:storage_service) { described_class.new(PaasConfigurationService.new, "random_instance") } + context "when we create a storage service and the S3 instance name is not found in the PaaS configuration" do + subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, "random_instance") } + + let(:vcap_services) do + <<-JSON + {"aws-s3-bucket": []} + JSON + end before do - allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return("{}") + allow(ENV).to receive(:[]).with("VCAP_SERVICES").and_return(vcap_services) end it "raises an exception" do @@ -40,7 +46,7 @@ RSpec.describe S3StorageService do end context "when we create a storage service with a valid instance name" do - subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) } + subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) } before do allow(ENV).to receive(:[]) @@ -48,11 +54,11 @@ RSpec.describe S3StorageService do end it "creates a Storage Configuration" do - expect(storage_service.configuration).to be_an(StorageConfiguration) + expect(storage_service.configuration).to be_an(Storage::StorageConfiguration) end it "sets the expected parameters in the configuration" do - expected_configuration = StorageConfiguration.new( + expected_configuration = Storage::StorageConfiguration.new( { aws_access_key_id: "key_id", aws_region: "eu-west-2", @@ -65,7 +71,7 @@ RSpec.describe S3StorageService do end context "when we create a storage service and write a stubbed object" do - subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) } + subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) } let(:filename) { "my_file" } let(:content) { "content" } @@ -100,7 +106,7 @@ RSpec.describe S3StorageService do end context "when we create a storage service" do - subject(:storage_service) { described_class.new(PaasConfigurationService.new, instance_name) } + subject(:storage_service) { described_class.new(Configuration::PaasConfigurationService.new, instance_name) } let(:s3_client_stub) { Aws::S3::Client.new(stub_responses: true) }