module Csv class SchemeCsvService include SchemesHelper include LocationsHelper def initialize(download_type:) @download_type = download_type end def prepare_csv(schemes) CSV.generate(headers: true) do |csv| csv << attributes case @download_type when "schemes" schemes.find_each do |scheme| csv << scheme_attributes.map { |attribute| scheme_value(attribute, scheme) } end when "locations" schemes.find_each do |scheme| scheme.locations.find_each do |location| csv << [scheme.id_to_display] + location_attributes.map { |attribute| location_value(attribute, location) } end end when "combined" schemes.find_each do |scheme| scheme.locations.find_each do |location| csv << scheme_attributes.map { |attribute| scheme_value(attribute, scheme) } + location_attributes.map { |attribute| location_value(attribute, location) } end end end end end private SCHEME_FIELD_FROM_ATTRIBUTE = { "scheme_code" => "id_to_display", "scheme_service_name" => "service_name", "scheme_status" => "status", "scheme_confidential" => "sensitive", "scheme_registered_under_care_act" => "registered_under_care_act", "scheme_support_services_provided_by" => "arrangement_type", "scheme_primary_client_group" => "primary_client_group", "scheme_has_other_client_group" => "has_other_client_group", "scheme_secondary_client_group" => "secondary_client_group", "scheme_support_type" => "support_type", "scheme_intended_stay" => "intended_stay", "scheme_created_at" => "created_at", }.freeze LOCATION_FIELD_FROM_ATTRIBUTE = { "location_code" => "id", "location_postcode" => "postcode", "location_name" => "name", "location_status" => "status", "location_local_authority" => "location_admin_district", "location_units" => "units", "location_type_of_unit" => "type_of_unit", "location_mobility_type" => "mobility_type", }.freeze CUSTOM_CALL_CHAINS = { scheme_owning_organisation_name: %i[owning_organisation name], }.freeze SYSTEM_DATE_FIELDS = %w[ created_at ].freeze def scheme_value(attribute, scheme) attribute = SCHEME_FIELD_FROM_ATTRIBUTE.fetch(attribute, attribute) if attribute == "scheme_active_dates" scheme_availability(scheme).gsub("\n", ", ").to_s elsif CUSTOM_CALL_CHAINS.key? attribute.to_sym call_chain = CUSTOM_CALL_CHAINS[attribute.to_sym] call_chain.reduce(scheme) { |object, next_call| object&.public_send(next_call) } elsif SYSTEM_DATE_FIELDS.include? attribute scheme.public_send(attribute)&.iso8601 else scheme.public_send(attribute) end end def location_value(attribute, location) attribute = LOCATION_FIELD_FROM_ATTRIBUTE.fetch(attribute, attribute) if attribute == "location_active_dates" location_availability(location).gsub("\n", ", ").to_s else location.public_send(attribute) end end def scheme_attributes %w[scheme_code scheme_service_name scheme_status scheme_confidential scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_support_services_provided_by scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at scheme_active_dates] end def location_attributes %w[location_code location_postcode location_name location_status location_local_authority location_units location_type_of_unit location_mobility_type location_active_dates] end def attributes case @download_type when "schemes" scheme_attributes when "locations" %w[scheme_code] + location_attributes when "combined" scheme_attributes + location_attributes end end end end