module Csv
class LettingsLogCsvService
CSV_FIELDS_TO_OMIT = %w[ hhmemb net_income_value_check first_time_property_let_as_social_housing renttype needstype postcode_known is_la_inferred totchild totelder totadult net_income_known is_carehome previous_la_known is_previous_la_inferred age1_known age2_known age3_known age4_known age5_known age6_known age7_known age8_known letting_allocation_unknown details_known_2 details_known_3 details_known_4 details_known_5 details_known_6 details_known_7 details_known_8 rent_type_detail wrent wscharge wpschrge wsupchrg wtcharge wtshortfall rent_value_check old_form_id old_id retirement_value_check tshortfall_known pregnancy_value_check hhtype new_old vacdays la prevloc unresolved updated_by_id bulk_upload_id ] . freeze
def initialize ( user , export_type : )
@user = user
@export_type = export_type
set_csv_attributes
end
def to_csv
CSV . generate ( headers : true ) do | csv |
csv << @attributes
LettingsLog . all . find_each do | record |
csv << @attributes . map { | attribute | get_value ( attribute , record ) }
end
end
end
private
ATTRIBUTES_OF_RELATED_OBJECTS = {
location_code : {
labels : % i [ location id ] ,
codes : % i [ location id ] ,
} ,
location_postcode : {
labels : % i [ location postcode ] ,
codes : % i [ location postcode ] ,
} ,
location_name : {
labels : % i [ location name ] ,
codes : % i [ location name ] ,
} ,
location_units : {
labels : % i [ location units ] ,
codes : % i [ location units ] ,
} ,
location_type_of_unit : {
labels : % i [ location type_of_unit ] ,
codes : % i [ location type_of_unit_before_type_cast ] ,
} ,
location_mobility_type : {
labels : % i [ location mobility_type ] ,
codes : % i [ location mobility_type_before_type_cast ] ,
} ,
location_admin_district : {
labels : % i [ location location_admin_district ] ,
codes : % i [ location location_admin_district ] ,
} ,
location_startdate : {
labels : % i [ location startdate ] ,
codes : % i [ location startdate ] ,
} ,
scheme_service_name : {
labels : % i [ scheme service_name ] ,
codes : % i [ scheme service_name ] ,
} ,
scheme_sensitive : {
labels : % i [ scheme sensitive ] ,
codes : % i [ scheme sensitive_before_type_cast ] ,
} ,
scheme_type : {
labels : % i [ scheme scheme_type ] ,
codes : % i [ scheme scheme_type_before_type_cast ] ,
} ,
scheme_registered_under_care_act : {
labels : % i [ scheme registered_under_care_act ] ,
codes : % i [ scheme registered_under_care_act_before_type_cast ] ,
} ,
scheme_owning_organisation_name : {
labels : % i [ scheme owning_organisation name ] ,
codes : % i [ scheme owning_organisation name ] ,
} ,
scheme_primary_client_group : {
labels : % i [ scheme primary_client_group ] ,
codes : % i [ scheme primary_client_group_before_type_cast ] ,
} ,
scheme_has_other_client_group : {
labels : % i [ scheme has_other_client_group ] ,
codes : % i [ scheme has_other_client_group_before_type_cast ] ,
} ,
scheme_secondary_client_group : {
labels : % i [ scheme secondary_client_group ] ,
codes : % i [ scheme secondary_client_group_before_type_cast ] ,
} ,
scheme_support_type : {
labels : % i [ scheme support_type ] ,
codes : % i [ scheme support_type_before_type_cast ] ,
} ,
scheme_intended_stay : {
labels : % i [ scheme intended_stay ] ,
codes : % i [ scheme intended_stay_before_type_cast ] ,
} ,
scheme_created_at : {
labels : % i [ scheme created_at ] ,
codes : % i [ scheme created_at ] ,
} ,
} . freeze
def get_value ( attribute , record )
attribute = " rent_type " if attribute == " rent_type_detail " # rent_type_detail is the requested column header for rent_type, so as not to confuse with renttype
if ATTRIBUTES_OF_RELATED_OBJECTS . key? attribute . to_sym
call_chain = ATTRIBUTES_OF_RELATED_OBJECTS [ attribute . to_sym ] [ @export_type . to_sym ]
call_chain . reduce ( record ) { | object , next_call | object & . send ( next_call ) }
elsif %w[ la prevloc ] . include? attribute # for all exports we output both the codes and labels for these location attributes
record . send ( attribute )
elsif %w[ la_label prevloc_label ] . include? attribute # as above
attribute = attribute . remove ( " _label " )
field_value = record . send ( attribute )
get_label ( field_value , attribute , record )
elsif %w[ mrcdate startdate voiddate ] . include? attribute
record . send ( attribute ) & . to_formatted_s ( :govuk_date )
else
field_value = record . send ( attribute )
case @export_type
when " codes "
field_value
when " labels "
answer_label = get_label ( field_value , attribute , record )
answer_label || label_if_boolean_value ( field_value ) || field_value
end
end
end
def get_label ( value , attribute , record )
record . form
. get_question ( attribute , record )
& . label_from_value ( value )
end
def label_if_boolean_value ( value )
return " Yes " if value == true
return " No " if value == false
end
def set_csv_attributes
metadata_fields = %w[ id status created_at updated_at created_by_name is_dpo owning_organisation_name managing_organisation_name collection_start_year ]
metadata_id_fields = %w[ managing_organisation_id owning_organisation_id created_by_id bulk_upload_id ]
scheme_and_location_ids = %w[ scheme_id location_id ]
scheme_attributes = %w[ scheme_code scheme_service_name scheme_sensitive scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at ]
location_attributes = %w[ location_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_admin_district location_startdate ]
intersecting_attributes = ordered_form_questions & LettingsLog . attribute_names - scheme_and_location_ids
remaining_attributes = LettingsLog . attribute_names - intersecting_attributes - scheme_and_location_ids
@attributes = ( metadata_fields + intersecting_attributes + remaining_attributes - metadata_id_fields + %w[ unittype_sh ] + scheme_attributes + location_attributes ) . uniq
move_la_fields
rename_attributes
@attributes -= CSV_FIELDS_TO_OMIT if @user . present? && ! @user . support?
end
def ordered_form_questions
downloaded_form_years = LettingsLog . all . map ( & :collection_start_year ) . uniq . compact
if downloaded_form_years . count == 1 && downloaded_form_years [ 0 ] . present?
form_name = FormHandler . instance . form_name_from_start_year ( downloaded_form_years [ 0 ] , " lettings " )
downloaded_form_fields = FormHandler . instance . get_form ( form_name ) . questions
else
downloaded_form_fields = FormHandler . instance . current_lettings_form . questions
end
move_checkbox_answer_options ( downloaded_form_fields )
end
def move_checkbox_answer_options ( form_questions )
checkboxes = form_questions . filter { | question | question . type == " checkbox " } . map { | question | { " #{ question . id } " : question . answer_options . keys } }
attributes = form_questions . map ( & :id ) . uniq
checkboxes . each do | checkbox_question |
checkbox_question . values [ 0 ] . each do | answer_option |
attributes . insert ( attributes . find_index ( checkbox_question . keys [ 0 ] . to_s ) , answer_option )
end
end
attributes
end
def move_la_fields
{ la : %w[ is_la_inferred la_label ] , prevloc : %w[ is_previous_la_inferred prevloc_label ] } . each do | inferred_field , fields |
fields . each do | field |
@attributes . delete ( field )
@attributes . insert ( @attributes . find_index ( inferred_field . to_s ) , field )
end
end
end
def rename_attributes
{ " rent_type " = > " rent_type_detail " } . each do | original_field , new_field |
@attributes . insert ( @attributes . find_index ( original_field ) , new_field )
@attributes . delete ( original_field )
end
end
end
end