From 8c34719987fb27a47d76c1eb99da6b1ad46abb8c Mon Sep 17 00:00:00 2001 From: Arthur Campbell <51094020+arfacamble@users.noreply.github.com> Date: Fri, 30 Jun 2023 15:18:31 +0100 Subject: [PATCH] CLDC-2291 refactor and minor updates to lettings log csv service (#1719) * form handler to return all questions from lettings forms for all years with ordering interleaved functionality and tests * refactor lettings log csv service and all associated tests remove methods on log models when we can call them directly on associated models update job to call the service directly with the collection of logs rather minor modifications to the sales log csv service update many test files to test the appropriate logic in the appropriate place * tidying final amendments to tests remove commented code rename variable * change the position of the rent value check field in the headers * CLDC-2492 add creation method field to logs (#1738) * create migrations to add creation method fields to both log types * add enum definition to logs for creation method * upadte csv export services to retrieve creation method values direct from the log, remove methods previously used from the log model * run migrations to update schema * ensure that logs created via bulk upload have this set correctly when created --- app/jobs/email_csv_job.rb | 4 +- app/models/form_handler.rb | 12 + app/models/lettings_log.rb | 17 - app/models/log.rb | 10 +- .../bulk_upload/lettings/log_creator.rb | 1 + app/services/bulk_upload/sales/log_creator.rb | 1 + app/services/csv/lettings_log_csv_service.rb | 190 +++--- app/services/csv/sales_log_csv_service.rb | 46 +- ...39_add_creation_method_to_lettings_logs.rb | 5 + ...25541_add_creation_method_to_sales_logs.rb | 5 + db/schema.rb | 6 +- .../files/lettings_log_csv_export_codes.csv | 2 + .../files/lettings_log_csv_export_labels.csv | 2 + ...tings_log_csv_export_non_support_codes.csv | 2 + ...ings_log_csv_export_non_support_labels.csv | 2 + .../fixtures/files/lettings_logs_download.csv | 2 - .../lettings_logs_download_codes_only.csv | 2 - .../lettings_logs_download_non_support.csv | 2 - .../files/sales_logs_csv_export_codes.csv | 4 +- .../files/sales_logs_csv_export_labels.csv | 4 +- spec/jobs/email_csv_job_spec.rb | 245 +++---- spec/models/form_handler_spec.rb | 51 ++ spec/models/lettings_log_spec.rb | 109 --- .../bulk_upload/lettings/log_creator_spec.rb | 6 + .../bulk_upload/sales/log_creator_spec.rb | 8 +- .../csv/lettings_log_csv_service_spec.rb | 625 ++++++------------ .../csv/sales_log_csv_service_spec.rb | 27 +- 27 files changed, 562 insertions(+), 828 deletions(-) create mode 100644 db/migrate/20230629124739_add_creation_method_to_lettings_logs.rb create mode 100644 db/migrate/20230629125541_add_creation_method_to_sales_logs.rb create mode 100644 spec/fixtures/files/lettings_log_csv_export_codes.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_labels.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_non_support_codes.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_non_support_labels.csv delete mode 100644 spec/fixtures/files/lettings_logs_download.csv delete mode 100644 spec/fixtures/files/lettings_logs_download_codes_only.csv delete mode 100644 spec/fixtures/files/lettings_logs_download_non_support.csv diff --git a/app/jobs/email_csv_job.rb b/app/jobs/email_csv_job.rb index 426c3430e..55fdcc824 100644 --- a/app/jobs/email_csv_job.rb +++ b/app/jobs/email_csv_job.rb @@ -6,15 +6,15 @@ class EmailCsvJob < ApplicationJob EXPIRATION_TIME = 3.hours.to_i def perform(user, search_term = nil, filters = {}, all_orgs = false, organisation = nil, codes_only_export = false, log_type = "lettings") # rubocop:disable Style/OptionalBooleanParameter - sidekiq can't serialise named params + export_type = codes_only_export ? "codes" : "labels" case log_type when "lettings" unfiltered_logs = organisation.present? && user.support? ? LettingsLog.visible.where(owning_organisation_id: organisation.id) : user.lettings_logs.visible filtered_logs = FilterManager.filter_logs(unfiltered_logs, search_term, filters, all_orgs, user) - csv_string = filtered_logs.to_csv(user, codes_only_export:) + csv_string = Csv::LettingsLogCsvService.new(user:, export_type:).prepare_csv(filtered_logs) when "sales" unfiltered_logs = organisation.present? && user.support? ? SalesLog.visible.where(owning_organisation_id: organisation.id) : user.sales_logs.visible filtered_logs = FilterManager.filter_logs(unfiltered_logs, search_term, filters, all_orgs, user) - export_type = codes_only_export ? "codes" : "labels" csv_string = Csv::SalesLogCsvService.new(export_type:).prepare_csv(filtered_logs) end diff --git a/app/models/form_handler.rb b/app/models/form_handler.rb index 7f858c645..c4b3c51d4 100644 --- a/app/models/form_handler.rb +++ b/app/models/form_handler.rb @@ -52,6 +52,18 @@ class FormHandler ordered_questions end + def ordered_lettings_questions_for_all_years + lettings_forms = forms.filter { |name, _form| name.end_with? "lettings" }.values + ordered_questions = lettings_forms.pop.questions.uniq(&:id) + question_ids = ordered_questions.map(&:id) + all_questions_from_previous_forms = lettings_forms.flat_map(&:questions) + deprecated_questions_by_preceding_question_id(question_ids, all_questions_from_previous_forms).each do |preceding_question_id, deprecated_question| + index_of_preceding_question = ordered_questions.index { |q| q.id == preceding_question_id } + ordered_questions.insert(index_of_preceding_question + 1, deprecated_question) + end + ordered_questions + end + def deprecated_questions_by_preceding_question_id(current_form_question_ids, all_questions_from_previous_forms) deprecated_questions = {} all_questions_from_previous_forms.each_cons(2) do |preceding_question, question| diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb index b1de54bbf..b2f3023a5 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -411,23 +411,6 @@ class LettingsLog < Log managing_organisation&.name end - def created_by_name - created_by&.name - end - - def is_dpo - created_by&.is_dpo - end - - def scheme_code - scheme&.id ? "S#{scheme.id}" : nil - end - - def self.to_csv(user = nil, codes_only_export:) - export_type = codes_only_export ? "codes" : "labels" - Csv::LettingsLogCsvService.new(user, export_type:).to_csv - end - def beds_for_la_rent_range return 0 if is_supported_housing? diff --git a/app/models/log.rb b/app/models/log.rb index f2c67771a..c17bd2c44 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -20,6 +20,12 @@ class Log < ApplicationRecord enum status: STATUS enum status_cache: STATUS, _prefix: true + CREATION_METHOD = { + "single log" => 1, + "bulk upload" => 2, + }.freeze + enum creation_method: CREATION_METHOD + scope :visible, -> { where(status: %w[not_started in_progress completed]) } scope :exportable, -> { where(status: %w[not_started in_progress completed deleted]) } @@ -178,10 +184,6 @@ class Log < ApplicationRecord end end - def creation_method - bulk_uploaded? ? "bulk upload" : "single log" - end - def bulk_uploaded? bulk_upload_id.present? end diff --git a/app/services/bulk_upload/lettings/log_creator.rb b/app/services/bulk_upload/lettings/log_creator.rb index 8d3a6cbd7..02852a2a5 100644 --- a/app/services/bulk_upload/lettings/log_creator.rb +++ b/app/services/bulk_upload/lettings/log_creator.rb @@ -14,6 +14,7 @@ class BulkUpload::Lettings::LogCreator row_parser.log.blank_invalid_non_setup_fields! row_parser.log.bulk_upload = bulk_upload + row_parser.log.creation_method = "bulk upload" row_parser.log.skip_update_status = true row_parser.log.status = "pending" row_parser.log.status_cache = row_parser.log.calculate_status diff --git a/app/services/bulk_upload/sales/log_creator.rb b/app/services/bulk_upload/sales/log_creator.rb index db389fc5c..5aa9d01c8 100644 --- a/app/services/bulk_upload/sales/log_creator.rb +++ b/app/services/bulk_upload/sales/log_creator.rb @@ -14,6 +14,7 @@ class BulkUpload::Sales::LogCreator row_parser.log.blank_invalid_non_setup_fields! row_parser.log.bulk_upload = bulk_upload + row_parser.log.creation_method = "bulk upload" row_parser.log.skip_update_status = true row_parser.log.status = "pending" row_parser.log.status_cache = row_parser.log.calculate_status diff --git a/app/services/csv/lettings_log_csv_service.rb b/app/services/csv/lettings_log_csv_service.rb index e8c2815f5..a4daf6d1a 100644 --- a/app/services/csv/lettings_log_csv_service.rb +++ b/app/services/csv/lettings_log_csv_service.rb @@ -1,26 +1,32 @@ 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 uprn_confirmed status_cache discarded_at].freeze - - def initialize(user, export_type:) + def initialize(user:, export_type:) @user = user @export_type = export_type - set_csv_attributes + @attributes = lettings_log_attributes end - def to_csv + def prepare_csv(logs) CSV.generate(headers: true) do |csv| csv << @attributes - LettingsLog.all.find_each do |record| - csv << @attributes.map { |attribute| get_value(attribute, record) } + logs.find_each do |log| + csv << @attributes.map { |attribute| value(attribute, log) } end end end private - ATTRIBUTES_OF_RELATED_OBJECTS = { + CUSTOM_CALL_CHAINS = { + created_by: { + labels: %i[created_by email], + codes: %i[created_by email], + }, + updated_by: { + labels: %i[updated_by email], + codes: %i[updated_by email], + }, location_code: { labels: %i[location id], codes: %i[location id], @@ -61,7 +67,7 @@ module Csv labels: %i[scheme sensitive], codes: %i[scheme sensitive_before_type_cast], }, - scheme_type: { + SCHTYPE: { labels: %i[scheme scheme_type], codes: %i[scheme scheme_type_before_type_cast], }, @@ -97,37 +103,67 @@ module Csv labels: %i[scheme created_at], codes: %i[scheme created_at], }, + scheme_code: { + labels: %i[scheme id_to_display], + codes: %i[scheme id_to_display], + }, + creation_method: { + labels: %i[creation_method], + codes: %i[creation_method_before_type_cast], + }, + is_dpo: { + labels: %i[created_by is_dpo?], + codes: %i[created_by is_dpo?], + }, }.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) + FIELDS_ALWAYS_EXPORTED_AS_CODES = %w[ + la + prevloc + ].freeze + + FIELDS_ALWAYS_EXPORTED_AS_LABELS = { + "la_label" => "la", + "prevloc_label" => "prevloc", + }.freeze + + DATE_FIELDS = %w[ + mrcdate + startdate + voiddate + created_at + updated_at + ].freeze + + def value(attribute, log) + 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. It can be exported as label or code. + if CUSTOM_CALL_CHAINS.key? attribute.to_sym + call_chain = CUSTOM_CALL_CHAINS[attribute.to_sym][@export_type.to_sym] + call_chain.reduce(log) { |object, next_call| object&.public_send(next_call) } + elsif FIELDS_ALWAYS_EXPORTED_AS_CODES.include? attribute + log.public_send(attribute) + elsif FIELDS_ALWAYS_EXPORTED_AS_LABELS.key? attribute + attribute = FIELDS_ALWAYS_EXPORTED_AS_LABELS[attribute] + value = log.public_send(attribute) + get_label(value, attribute, log) + elsif DATE_FIELDS.include? attribute + log.public_send(attribute)&.iso8601 else - field_value = record.send(attribute) + value = log.public_send(attribute) case @export_type when "codes" - field_value + value when "labels" - answer_label = get_label(field_value, attribute, record) - answer_label || label_if_boolean_value(field_value) || field_value + answer_label = get_label(value, attribute, log) + answer_label || label_if_boolean_value(value) || value end end end - def get_label(value, attribute, record) - record.form - .get_question(attribute, record) - &.label_from_value(value) + def get_label(value, attribute, log) + log.form + .get_question(attribute, log) + &.label_from_value(value) end def label_if_boolean_value(value) @@ -135,60 +171,52 @@ module Csv 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 + ATTRIBUTE_MAPPINGS = { + "owning_organisation_id" => %w[owning_organisation_name], + "managing_organisation_id" => %w[managing_organisation_name], + "created_by_id" => [], + "scheme_id" => [], + "location_id" => [], + "rent_type" => %w[renttype rent_type_detail], + "hb" => %w[hb has_benefits], + "age1" => %w[refused hhtype totchild totelder totadult age1], + "housingneeds_type" => %w[housingneeds_type housingneeds_a housingneeds_b housingneeds_c housingneeds_f housingneeds_g housingneeds_h], + "net_income_known" => %w[net_income_known incref], + "irproduct_other" => %w[irproduct irproduct_other lar], + "la" => %w[is_la_inferred la_label la], + "prevloc" => %w[is_previous_la_inferred prevloc_label prevloc], + "needstype" => %w[needstype lettype], + "prevten" => %w[prevten new_old], + "voiddate" => %w[voiddate vacdays], + "rsnvac" => %w[rsnvac newprop], + "household_charge" => %w[household_charge nocharge], + "brent" => %w[brent wrent rent_value_check], + "scharge" => %w[scharge wscharge], + "pscharge" => %w[pscharge wpschrge], + "supcharg" => %w[supcharg wsupchrg], + "tcharge" => %w[tcharge wtcharge], + "chcharge" => %w[chcharge wchchrg], + "tshortfall" => %w[tshortfall wtshortfall], + }.freeze - 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) + SUPPORT_ONLY_ATTRIBUTES = %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 updated_by_id bulk_upload_id uprn_confirmed].freeze + + def lettings_log_attributes + ordered_questions = FormHandler.instance.ordered_lettings_questions_for_all_years + ordered_questions.reject! { |q| q.id.match?(/rent_value_check/) } + attributes = ordered_questions.flat_map do |question| + if question.type == "checkbox" + question.answer_options.keys.reject { |key| key == "divider" } + elsif ATTRIBUTE_MAPPINGS.key? question.id + ATTRIBUTE_MAPPINGS[question.id] + else + question.id 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 + non_question_fields = %w[id status created_by is_dpo created_at updated_by updated_at creation_method old_id old_form_id collection_start_year] + scheme_and_location_attributes = %w[scheme_code scheme_service_name scheme_sensitive SCHTYPE 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_code location_postcode location_name location_units location_type_of_unit location_mobility_type location_admin_district location_startdate] + final_attributes = non_question_fields + attributes + scheme_and_location_attributes + @user.support? ? final_attributes : final_attributes - SUPPORT_ONLY_ATTRIBUTES end end end diff --git a/app/services/csv/sales_log_csv_service.rb b/app/services/csv/sales_log_csv_service.rb index a9573df41..895b544cf 100644 --- a/app/services/csv/sales_log_csv_service.rb +++ b/app/services/csv/sales_log_csv_service.rb @@ -17,13 +17,35 @@ module Csv private - ATTRIBUTES_OF_RELATED_OBJECTS = { - day: %i[saledate day], - month: %i[saledate month], - year: %i[saledate year], - is_dpo: %i[created_by is_dpo], - created_by_name: %i[created_by name], - owning_organisation_name: %i[owning_organisation name], + CUSTOM_CALL_CHAINS = { + day: { + labels: %i[saledate day], + codes: %i[saledate day], + }, + month: { + labels: %i[saledate month], + codes: %i[saledate month], + }, + year: { + labels: %i[saledate year], + codes: %i[saledate year], + }, + is_dpo: { + labels: %i[created_by is_dpo], + codes: %i[created_by is_dpo], + }, + created_by: { + labels: %i[created_by email], + codes: %i[created_by email], + }, + owning_organisation_name: { + labels: %i[owning_organisation name], + codes: %i[owning_organisation name], + }, + creation_method: { + labels: %i[creation_method], + codes: %i[creation_method_before_type_cast], + }, }.freeze FIELDS_ALWAYS_EXPORTED_AS_CODES = %w[ @@ -42,15 +64,15 @@ module Csv ].freeze def value(attribute, log) - if ATTRIBUTES_OF_RELATED_OBJECTS.key? attribute.to_sym - call_chain = ATTRIBUTES_OF_RELATED_OBJECTS[attribute.to_sym] + if CUSTOM_CALL_CHAINS.key? attribute.to_sym + call_chain = CUSTOM_CALL_CHAINS[attribute.to_sym][@export_type.to_sym] call_chain.reduce(log) { |object, next_call| object&.public_send(next_call) } elsif FIELDS_ALWAYS_EXPORTED_AS_CODES.include? attribute log.send(attribute) elsif FIELDS_ALWAYS_EXPORTED_AS_LABELS.key? attribute attribute = FIELDS_ALWAYS_EXPORTED_AS_LABELS[attribute] - field_value = log.send(attribute) - get_label(field_value, attribute, log) + value = log.send(attribute) + get_label(value, attribute, log) elsif DATE_FIELDS.include? attribute log.send(attribute)&.iso8601 else @@ -84,7 +106,7 @@ module Csv "ppostcode_full" => %w[ppostc1 ppostc2], "la" => %w[la la_label], "prevloc" => %w[prevloc prevloc_label], - "created_by_id" => %w[created_by_name], + "created_by_id" => %w[created_by], "owning_organisation_id" => %w[owning_organisation_name], }.freeze diff --git a/db/migrate/20230629124739_add_creation_method_to_lettings_logs.rb b/db/migrate/20230629124739_add_creation_method_to_lettings_logs.rb new file mode 100644 index 000000000..3b96a5af9 --- /dev/null +++ b/db/migrate/20230629124739_add_creation_method_to_lettings_logs.rb @@ -0,0 +1,5 @@ +class AddCreationMethodToLettingsLogs < ActiveRecord::Migration[7.0] + def change + add_column :lettings_logs, :creation_method, :integer, default: 1 + end +end diff --git a/db/migrate/20230629125541_add_creation_method_to_sales_logs.rb b/db/migrate/20230629125541_add_creation_method_to_sales_logs.rb new file mode 100644 index 000000000..5292973a0 --- /dev/null +++ b/db/migrate/20230629125541_add_creation_method_to_sales_logs.rb @@ -0,0 +1,5 @@ +class AddCreationMethodToSalesLogs < ActiveRecord::Migration[7.0] + def change + add_column :sales_logs, :creation_method, :integer, default: 1 + end +end diff --git a/db/schema.rb b/db/schema.rb index 625290d8a..3a47ae8aa 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_06_21_142422) do +ActiveRecord::Schema[7.0].define(version: 2023_06_29_125541) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -290,6 +290,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_06_21_142422) do t.integer "carehome_charges_value_check" t.integer "status_cache", default: 0, null: false t.datetime "discarded_at" + t.integer "creation_method", default: 1 t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id" t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id" t.index ["location_id"], name: "index_lettings_logs_on_location_id" @@ -600,11 +601,12 @@ ActiveRecord::Schema[7.0].define(version: 2023_06_21_142422) do t.integer "discounted_sale_value_check" t.integer "student_not_child_value_check" t.integer "percentage_discount_value_check" - t.integer "combined_income_value_check" t.integer "buyer_livein_value_check" t.integer "status_cache", default: 0, null: false + t.integer "combined_income_value_check" t.datetime "discarded_at" t.integer "stairowned_value_check" + t.integer "creation_method", default: 1 t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true diff --git a/spec/fixtures/files/lettings_log_csv_export_codes.csv b/spec/fixtures/files/lettings_log_csv_export_codes.csv new file mode 100644 index 000000000..e4a1c53e3 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_codes.csv @@ -0,0 +1,2 @@ +id,status,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,rent_type_detail,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,age1_known,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,ecstat1,details_known_2,relat2,age2_known,age2,sex2,ecstat2,details_known_3,relat3,age3_known,age3,sex3,ecstat3,details_known_4,relat4,age4_known,age4,sex4,ecstat4,details_known_5,relat5,age5_known,age5,sex5,ecstat5,details_known_6,relat6,age6_known,age6,sex6,ecstat6,details_known_7,relat7,age7_known,age7,sex7,ecstat7,details_known_8,relat8,age8_known,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_unknown,referral,net_income_known,incref,earnings,incfreq,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +,completed,s.port@jeemayle.com,false,2023-06-26T00:00:00+01:00,,2023-06-26T00:00:00+01:00,1,,,2023,DLUHC,DLUHC,1,7,0,2023-06-26T00:00:00+01:00,2,1,,,,HIJKLMN,ABCDEFG,0,,,fake address,,London,,NW9 5LL,false,Barnet,E09000003,0,2,6,2,2,7,1,1,3,2023-06-24T00:00:00+01:00,,,1,2023-06-25T00:00:00+01:00,,3,1,4,,2,,1,2,,0,0,4,0,0,2,35,,F,0,2,13,0,0,P,0,32,M,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,6,2,1,1,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,,2,0,0,68,1,,6,1,1,,0,2,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_labels.csv b/spec/fixtures/files/lettings_log_csv_export_labels.csv new file mode 100644 index 000000000..3c50ecff0 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_labels.csv @@ -0,0 +1,2 @@ +id,status,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,rent_type_detail,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,age1_known,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,ecstat1,details_known_2,relat2,age2_known,age2,sex2,ecstat2,details_known_3,relat3,age3_known,age3,sex3,ecstat3,details_known_4,relat4,age4_known,age4,sex4,ecstat4,details_known_5,relat5,age5_known,age5,sex5,ecstat5,details_known_6,relat6,age6_known,age6,sex6,ecstat6,details_known_7,relat7,age7_known,age7,sex7,ecstat7,details_known_8,relat8,age8_known,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,new_old,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,letting_allocation_unknown,referral,net_income_known,incref,earnings,incfreq,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +,completed,s.port@jeemayle.com,false,2023-06-26T00:00:00+01:00,,2023-06-26T00:00:00+01:00,single log,,,2023,DLUHC,DLUHC,General needs,7,No,2023-06-26T00:00:00+01:00,2,Affordable Rent,,,,HIJKLMN,ABCDEFG,No,,,fake address,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,2,2,House,Purpose built,Yes,3,2023-06-24T00:00:00+01:00,,,Yes,2023-06-25T00:00:00+01:00,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,1,2,,Yes,0,4,0,0,2,35,,Female,White,Irish,Tenant prefers not to say,Other,Yes,Partner,Yes,32,Male,Not seeking work,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,1,0,0,0,0,0,No,Yes,0,0,1,0,0,0,0,0,0,0,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,2,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,0,1,0,0,0,0,0,1,,Tenant applied directly (no referral or nomination),Yes,0,68,Weekly,,Universal Credit housing element,1,All,,0,Every 2 weeks,,,,,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_codes.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_codes.csv new file mode 100644 index 000000000..4cfdc963c --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_codes.csv @@ -0,0 +1,2 @@ +id,status,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,owning_organisation_name,managing_organisation_name,lettype,renewal,startdate,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,refused,age1,sex1,ethnic_group,ethnic,national,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,referral,incref,earnings,incfreq,hb,has_benefits,benefits,household_charge,nocharge,period,chcharge,wchchrg,carehome_charges_value_check,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +,completed,choreographer@owtluk.com,false,2023-06-26T00:00:00+01:00,,2023-06-26T00:00:00+01:00,1,2023,DLUHC,DLUHC,7,0,2023-06-26T00:00:00+01:00,,,,HIJKLMN,ABCDEFG,0,,fake address,,London,,NW9 5LL,Barnet,2,6,2,2,7,1,1,3,2023-06-24T00:00:00+01:00,,1,2023-06-25T00:00:00+01:00,,3,1,4,,2,,1,0,35,F,0,2,13,0,P,32,M,6,,,,,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,6,1,1,TN23 6LZ,Ashford,1,0,1,0,0,0,0,0,1,2,0,68,1,6,1,1,,0,2,,,,200.0,50.0,40.0,35.0,325.0,1,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_labels.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels.csv new file mode 100644 index 000000000..bb2230668 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels.csv @@ -0,0 +1,2 @@ +id,status,created_by,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,owning_organisation_name,managing_organisation_name,lettype,renewal,startdate,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,refused,age1,sex1,ethnic_group,ethnic,national,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,referral,incref,earnings,incfreq,hb,has_benefits,benefits,household_charge,nocharge,period,chcharge,wchchrg,carehome_charges_value_check,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_sensitive,SCHTYPE,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate +,completed,choreographer@owtluk.com,false,2023-06-26T00:00:00+01:00,,2023-06-26T00:00:00+01:00,single log,2023,DLUHC,DLUHC,7,No,2023-06-26T00:00:00+01:00,,,,HIJKLMN,ABCDEFG,No,,fake address,,London,,NW9 5LL,Barnet,Affordable rent basis,Tenant abandoned property,2,2,House,Purpose built,Yes,3,2023-06-24T00:00:00+01:00,,Yes,2023-06-25T00:00:00+01:00,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,1,0,35,Female,White,Irish,Tenant prefers not to say,Other,Partner,32,Male,Not seeking work,,,,,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,1,0,0,0,0,0,No,Yes,0,0,1,0,0,0,0,0,0,0,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,No,Yes,TN23 6LZ,Ashford,Yes,0,1,0,0,0,0,0,1,Tenant applied directly (no referral or nomination),0,68,Weekly,Universal Credit housing element,1,All,,0,Every 2 weeks,,,,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_logs_download.csv b/spec/fixtures/files/lettings_logs_download.csv deleted file mode 100644 index 24568524b..000000000 --- a/spec/fixtures/files/lettings_logs_download.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,discarded_at,unittype_sh,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,Supported housing,,2 October 2021,London Affordable Rent,,,,,,,,,,,,,,,,,,,,No,,,,,No,Westminster,E09000033,,SE1 1TE,,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} diff --git a/spec/fixtures/files/lettings_logs_download_codes_only.csv b/spec/fixtures/files/lettings_logs_download_codes_only.csv deleted file mode 100644 index 15d671976..000000000 --- a/spec/fixtures/files/lettings_logs_download_codes_only.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,needstype,renewal,startdate,rent_type_detail,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,hhmemb,relat2,age2,sex2,retirement_value_check,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,is_previous_la_inferred,prevloc_label,prevloc,illness_type_1,illness_type_2,is_la_inferred,la_label,la,postcode_known,postcode_full,previous_la_known,wchair,preg_occ,cbl,earnings,incfreq,net_income_value_check,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,first_time_property_let_as_social_housing,unitletas,builtype,voiddate,renttype,lettype,totchild,totelder,totadult,net_income_known,nocharge,is_carehome,household_charge,referral,tshortfall,chcharge,ppcodenk,age1_known,age2_known,age3_known,age4_known,age5_known,age6_known,age7_known,age8_known,ethnic_group,letting_allocation_unknown,details_known_2,details_known_3,details_known_4,details_known_5,details_known_6,details_known_7,details_known_8,has_benefits,wrent,wscharge,wpschrge,wsupchrg,wtcharge,wtshortfall,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,rent_value_check,old_form_id,lar,irproduct,old_id,joint,tshortfall_known,sheltered,pregnancy_value_check,hhtype,new_old,vacdays,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,unresolved,updated_by_id,uprn,uprn_known,uprn_confirmed,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,status_cache,discarded_at,unittype_sh,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,false,DLUHC,DLUHC,2021,2,,2 October 2021,2,,,,,,,,,,,,,,,,,,,,false,,,,,false,Westminster,E09000033,,SE1 1TE,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,8,0,0,0,,0,,,,,,,,,,,,,,,,,,,,,,,,0,,,,,,,0,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,,,,,,not_started,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},0,1,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,6,A,Westminster,{location_startdate} diff --git a/spec/fixtures/files/lettings_logs_download_non_support.csv b/spec/fixtures/files/lettings_logs_download_non_support.csv deleted file mode 100644 index c82dfa589..000000000 --- a/spec/fixtures/files/lettings_logs_download_non_support.csv +++ /dev/null @@ -1,2 +0,0 @@ -id,status,created_at,updated_at,created_by_name,is_dpo,owning_organisation_name,managing_organisation_name,collection_start_year,renewal,startdate,irproduct_other,tenancycode,propcode,age1,sex1,ecstat1,relat2,age2,sex2,ecstat2,armedforces,leftreg,illness,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_h,prevloc_label,illness_type_1,illness_type_2,la_label,postcode_full,wchair,preg_occ,cbl,earnings,incfreq,benefits,hb,period,brent,scharge,pscharge,supcharg,tcharge,offered,layear,ppostcode_full,mrcdate,declaration,ethnic,national,prevten,age3,sex3,ecstat3,age4,sex4,ecstat4,age5,sex5,ecstat5,age6,sex6,ecstat6,age7,sex7,ecstat7,age8,sex8,ecstat8,homeless,underoccupation_benefitcap,reservist,startertenancy,tenancylength,tenancy,rsnvac,unittype_gn,beds,waityear,reasonpref,chr,cap,reasonother,housingneeds_f,housingneeds_g,illness_type_3,illness_type_4,illness_type_8,illness_type_5,illness_type_6,illness_type_7,illness_type_9,illness_type_10,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,tenancyother,property_owner_organisation,property_manager_organisation,purchaser_code,reason,majorrepairs,hbrentshortfall,property_relet,incref,unitletas,builtype,voiddate,lettype,nocharge,household_charge,referral,tshortfall,chcharge,ppcodenk,ethnic_group,has_benefits,refused,housingneeds,wchchrg,newprop,relat3,relat4,relat5,relat6,relat7,relat8,lar,irproduct,joint,sheltered,major_repairs_date_value_check,void_date_value_check,housingneeds_type,housingneeds_other,uprn,uprn_known,address_line1,address_line2,town_or_city,county,carehome_charges_value_check,unittype_sh,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_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_admin_district,location_startdate -{id},in_progress,2022-02-08 16:52:15 +0000,2022-02-08 16:52:15 +0000,Danny Rojas,No,DLUHC,DLUHC,2021,,2 October 2021,,,,,,,,,,,,,,,,,,,,,Westminster,SE1 1TE,No,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,8,0,,,,,,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,6,{scheme_code},{scheme_service_name},{scheme_sensitive},Missing,No,DLUHC,{scheme_primary_client_group},,{scheme_secondary_client_group},{scheme_support_type},{scheme_intended_stay},2021-04-01 00:00:00 +0100,{location_code},SE1 1TE,Downing Street,20,Bungalow,Fitted with equipment and adaptations,Westminster,{location_startdate} diff --git a/spec/fixtures/files/sales_logs_csv_export_codes.csv b/spec/fixtures/files/sales_logs_csv_export_codes.csv index 31d964afe..3467917d6 100644 --- a/spec/fixtures/files/sales_logs_csv_export_codes.csv +++ b/spec/fixtures/files/sales_logs_csv_export_codes.csv @@ -1,2 +1,2 @@ -id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by_name,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant -,completed,2023-02-08T00:00:00+00:00,2023-02-08T00:00:00+00:00,,2022,single log,false,DLUHC,Danny Rojas,8,2,2023,,2,8,,,,1,1,2,1,1,0,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,1,2,1,30,X,17,17,18,1,1,P,35,X,17,,13,1,1,6,C,14,X,9,X,18,X,3,R,40,X,2,R,40,X,1,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0 +id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant +,completed,2023-02-08T00:00:00+00:00,2023-02-08T00:00:00+00:00,,2022,1,false,DLUHC,billyboy@eyeklaud.com,8,2,2023,,2,8,,,,1,1,2,1,1,0,,,Address line 1,,Town or city,,SW1A,1AA,1,E09000003,Barnet,1,2,1,30,X,17,17,18,1,1,P,35,X,17,,13,1,1,6,C,14,X,9,X,18,X,3,R,40,X,2,R,40,X,1,1,1,,,0,,,1,1,1,1,,3,,1,4,5,1,1,0,10000,1,0,10000,1,4,1,,1,2,10,,,,,,,,,,,,,,,,,110000.0,,1,20000.0,5,,10,1,80000.0,,,1,100.0,,10000.0 diff --git a/spec/fixtures/files/sales_logs_csv_export_labels.csv b/spec/fixtures/files/sales_logs_csv_export_labels.csv index aeda373f3..dc0acf9d2 100644 --- a/spec/fixtures/files/sales_logs_csv_export_labels.csv +++ b/spec/fixtures/files/sales_logs_csv_export_labels.csv @@ -1,2 +1,2 @@ -id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by_name,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant -,completed,2023-02-08T00:00:00+00:00,2023-02-08T00:00:00+00:00,,2022,single log,false,DLUHC,Danny Rojas,8,2,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,2,Flat or maisonette,Purpose built,Yes,,,Address line 1,,Town or city,,SW1A,1AA,Yes,E09000003,Barnet,Yes,Yes,1,30,Non-binary,Buyer 1 prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,17,,13,Full-time - 30 hours or more,Yes,6,Child,14,Non-binary,Child under 16,Other,18,Non-binary,"In government training into work, such as New Deal",Person prefers not to say,40,Non-binary,Part-time - Less than 30 hours,Person prefers not to say,40,Non-binary,Full-time - 30 hours or more,Local authority tenant,No,,,No,,,1,1,1,1,,3,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,Don’t know ,No,,Yes,2,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0 +id,status,created_at,updated_at,old_id,collection_start_year,creation_method,is_dpo,owning_organisation_name,created_by,day,month,year,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,beds,proptype,builtype,pcodenk,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la_known,la,la_label,wchair,noint,privacynotice,age1,sex1,ethnic_group,ethnic,national,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationalbuy2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant +,completed,2023-02-08T00:00:00+00:00,2023-02-08T00:00:00+00:00,,2022,single log,false,DLUHC,billyboy@eyeklaud.com,8,2,2023,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,2,Flat or maisonette,Purpose built,Yes,,,Address line 1,,Town or city,,SW1A,1AA,Yes,E09000003,Barnet,Yes,Yes,1,30,Non-binary,Buyer 1 prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,17,,13,Full-time - 30 hours or more,Yes,6,Child,14,Non-binary,Child under 16,Other,18,Non-binary,"In government training into work, such as New Deal",Person prefers not to say,40,Non-binary,Part-time - Less than 30 hours,Person prefers not to say,40,Non-binary,Full-time - 30 hours or more,Local authority tenant,No,,,No,,,1,1,1,1,,3,,Yes,Yes,No,Yes,Yes,Yes,10000,Yes,Yes,10000,Yes,"Don’t know ",No,,Yes,2,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0 diff --git a/spec/jobs/email_csv_job_spec.rb b/spec/jobs/email_csv_job_spec.rb index 40f13e022..f8677e493 100644 --- a/spec/jobs/email_csv_job_spec.rb +++ b/spec/jobs/email_csv_job_spec.rb @@ -7,186 +7,105 @@ describe EmailCsvJob do let(:job) { described_class.new } let(:user) { FactoryBot.create(:user) } - let(:organisation) { user.organisation } - let(:other_organisation) { FactoryBot.create(:organisation) } - let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") } + let(:storage_service) { instance_double(Storage::S3Service) } + let(:mailer) { instance_double(CsvDownloadMailer) } + let(:sales_log_csv_service) { instance_double(Csv::SalesLogCsvService) } + let(:lettings_log_csv_service) { instance_double(Csv::LettingsLogCsvService) } + let(:search_term) { "meaning" } + let(:filters) { { "user" => "yours", "status" => %w[in_progress] } } + let(:all_orgs) { false } + let(:organisation) { build(:organisation) } + let(:codes_only_export) { true } + let(:lettings_logs) { build_list(:lettings_log, 5) } + let(:sales_logs) { build_list(:sales_log, 5) } before do - allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form) + allow(Storage::S3Service).to receive(:new).and_return(storage_service) + allow(storage_service).to receive(:write_file) + allow(storage_service).to receive(:get_presigned_url).and_return(test_url) + + allow(Csv::SalesLogCsvService).to receive(:new).and_return(sales_log_csv_service) + allow(sales_log_csv_service).to receive(:prepare_csv).and_return("") + + allow(Csv::LettingsLogCsvService).to receive(:new).and_return(lettings_log_csv_service) + allow(lettings_log_csv_service).to receive(:prepare_csv).and_return("") + + allow(CsvDownloadMailer).to receive(:new).and_return(mailer) + allow(mailer).to receive(:send_csv_download_mail) end - context "when a log exists" do - let!(:lettings_log) do - FactoryBot.create( - :lettings_log, - created_by: user, - ecstat1: 1, - ) + context "when exporting lettings logs" do + before do + allow(FilterManager).to receive(:filter_logs).and_return(lettings_logs) + end + + it "uses an appropriate filename in S3" do + expect(storage_service).to receive(:write_file).with(/lettings-logs-.*\.csv/, anything) + job.perform(user) end - let(:storage_service) { instance_double(Storage::S3Service) } - let(:mailer) { instance_double(CsvDownloadMailer) } - let(:sales_log_csv_service) { instance_double(Csv::SalesLogCsvService) } + it "includes the organisation name in the filename when one is provided" do + expect(storage_service).to receive(:write_file).with(/lettings-logs-#{organisation.name}-.*\.csv/, anything) + job.perform(user, nil, {}, nil, organisation) + end + + it "calls the filter manager with the arguments provided" do + expect(FilterManager).to receive(:filter_logs).with(a_kind_of(ActiveRecord::Relation), search_term, filters, all_orgs, user) + job.perform(user, search_term, filters, all_orgs, organisation, codes_only_export) + end + it "creates a LettingsLogCsvService with the correct export type" do + expect(Csv::LettingsLogCsvService).to receive(:new).with(user:, export_type: "labels") + codes_only = false + job.perform(user, nil, {}, nil, nil, codes_only, "lettings") + expect(Csv::LettingsLogCsvService).to receive(:new).with(user:, export_type: "codes") + codes_only = true + job.perform(user, nil, {}, nil, nil, codes_only, "lettings") + end + + it "passes the logs returned by the filter manager to the csv service" do + expect(lettings_log_csv_service).to receive(:prepare_csv).with(lettings_logs) + job.perform(user, nil, {}, nil, nil, codes_only_export) + end + end + + context "when exporting sales logs" do before do - FactoryBot.create(:lettings_log, - :completed, - created_by: user, - startdate: Time.zone.local(2022, 5, 1), - voiddate: Time.zone.local(2022, 5, 1), - mrcdate: Time.zone.local(2022, 5, 1)) - - allow(Storage::S3Service).to receive(:new).and_return(storage_service) - allow(storage_service).to receive(:write_file) - allow(storage_service).to receive(:get_presigned_url).and_return(test_url) - - allow(Csv::SalesLogCsvService).to receive(:new).and_return(sales_log_csv_service) - allow(sales_log_csv_service).to receive(:prepare_csv).and_return("") - - allow(CsvDownloadMailer).to receive(:new).and_return(mailer) - allow(mailer).to receive(:send_csv_download_mail) + allow(FilterManager).to receive(:filter_logs).and_return(sales_logs) end - context "when exporting lettings logs" do - it "uses an appropriate filename in S3" do - expect(storage_service).to receive(:write_file).with(/lettings-logs-.*\.csv/, anything) - job.perform(user) - end + it "uses an appropriate filename in S3" do + expect(storage_service).to receive(:write_file).with(/sales-logs-.*\.csv/, anything) + job.perform(user, nil, {}, nil, nil, nil, "sales") + end - it "includes the organisation name in the filename when one is provided" do - expect(storage_service).to receive(:write_file).with(/lettings-logs-#{organisation.name}-.*\.csv/, anything) - job.perform(user, nil, {}, nil, organisation) - end + it "includes the organisation name in the filename when one is provided" do + expect(storage_service).to receive(:write_file).with(/sales-logs-#{organisation.name}-.*\.csv/, anything) + job.perform(user, nil, {}, nil, organisation, nil, "sales") end - context "when exporting sales logs" do - it "uses an appropriate filename in S3" do - expect(storage_service).to receive(:write_file).with(/sales-logs-.*\.csv/, anything) - job.perform(user, nil, {}, nil, nil, nil, "sales") - end - - it "includes the organisation name in the filename when one is provided" do - expect(storage_service).to receive(:write_file).with(/sales-logs-#{organisation.name}-.*\.csv/, anything) - job.perform(user, nil, {}, nil, organisation, nil, "sales") - end - - it "creates a SalesLogCsvService with the correct export type" do - expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "labels") - codes_only = false - job.perform(user, nil, {}, nil, nil, codes_only, "sales") - expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "codes") - codes_only = true - job.perform(user, nil, {}, nil, nil, codes_only, "sales") - end + it "calls the filter manager with the arguments provided" do + expect(FilterManager).to receive(:filter_logs).with(a_kind_of(ActiveRecord::Relation), search_term, filters, all_orgs, user) + job.perform(user, search_term, filters, all_orgs, organisation, codes_only_export, "sales") end - it "sends an E-mail with the presigned URL and duration" do - expect(mailer).to receive(:send_csv_download_mail).with(user, test_url, instance_of(Integer)) - job.perform(user) + it "creates a SalesLogCsvService with the correct export type" do + expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "labels") + codes_only = false + job.perform(user, nil, {}, nil, nil, codes_only, "sales") + expect(Csv::SalesLogCsvService).to receive(:new).with(export_type: "codes") + codes_only = true + job.perform(user, nil, {}, nil, nil, codes_only, "sales") end - context "when writing to S3" do - before do - FactoryBot.create_list(:lettings_log, 4, owning_organisation: other_organisation) - FactoryBot.create(:lettings_log, owning_organisation: other_organisation, status: "pending", skip_update_status: true) - end - - def expect_csv - expect(storage_service).to receive(:write_file) do |_filename, data| - # Ignore byte order marker - csv = CSV.parse(data[1..]) - yield(csv) - end - end - - it "writes CSV data with headers" do - expect_csv do |csv| - expect(csv.first.first).to eq("id") - expect(csv.second.first).to eq(lettings_log.id.to_s) - end - - job.perform(user) - end - - context "when there is no organisation provided" do - it "only writes logs from the user's organisation" do - expect_csv do |csv| - # Headings + 2 rows - expect(csv.count).to eq(3) - end - - job.perform(user) - end - end - - context "when the user is support and an organisation is provided" do - let(:user) { FactoryBot.create(:user, :support) } - - it "only writes logs from that organisation" do - expect_csv do |csv| - # other organisation => Headings + 4 rows - expect(csv.count).to eq(5) - end - - job.perform(user, nil, {}, nil, other_organisation) - end - end - - it "writes answer labels rather than values" do - expect_csv do |csv| - expect(csv.second[19]).to eq("Full-time – 30 hours or more") - end - - job.perform(user) - end - - it "writes filtered logs" do - expect_csv do |csv| - expect(csv.count).to eq(2) - end - - job.perform(user, nil, { status: "completed" }) - end - - it "writes searched logs" do - expect_csv do |csv| - expect(csv.count).to eq(LettingsLog.search_by(lettings_log.id.to_s).count + 1) - end - - job.perform(user, lettings_log.id.to_s) - end - - context "when both filter and search applied" do - let(:postcode) { "XX1 1TG" } - - before do - FactoryBot.create(:lettings_log, :in_progress, postcode_full: postcode, owning_organisation: organisation, created_by: user) - FactoryBot.create(:lettings_log, :completed, postcode_full: postcode, owning_organisation: organisation, created_by: user) - end - - it "downloads logs matching both csv and filter logs" do - expect_csv do |csv| - expect(csv.count).to eq(2) - end - - job.perform(user, postcode, { status: "completed" }) - end - end - - context "when there are more than 20 logs" do - before do - FactoryBot.create_list(:lettings_log, 26, owning_organisation: organisation) - end - - it "does not paginate, it downloads all the user's logs" do - expect_csv do |csv| - # Heading + 2 + 26 - expect(csv.count).to eq(29) - end - - job.perform(user) - end - end + it "passes the logs returned by the filter manager to the csv service" do + expect(sales_log_csv_service).to receive(:prepare_csv).with(sales_logs) + job.perform(user, nil, {}, nil, nil, codes_only_export, "sales") end end + + it "sends an E-mail with the presigned URL and duration" do + expect(mailer).to receive(:send_csv_download_mail).with(user, test_url, instance_of(Integer)) + job.perform(user) + end end diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index 547ed2f21..0c06e84fd 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -270,5 +270,56 @@ RSpec.describe FormHandler do expect(result.map(&:id)).to eq %w[1 1a_deprecated 2 2a_new 3] end end + + describe "#ordered_lettings_questions_for_all_years" do + let(:result) { described_class.instance.ordered_lettings_questions_for_all_years } + let(:now) { Time.zone.now } + + it "returns an array of questions" do + section = build(:section, :with_questions, question_ids: %w[1 2 3]) + lettings_form = FormFactory.new(year: 2936, type: "lettings") + .with_sections([section]) + .build + described_class.instance.use_fake_forms!({ only_lettings: lettings_form }) + expect(result).to(satisfy { |result| result.all? { |element| element.is_a?(Form::Question) } }) + end + + it "does not return multiple questions with the same id" do + first_section = build(:section, :with_questions, question_ids: %w[1 2 3]) + second_section = build(:section, :with_questions, question_ids: %w[2 3 4 5]) + lettings_form = FormFactory.new(year: 2936, type: "lettings") + .with_sections([first_section, second_section]) + .build + described_class.instance.use_fake_forms!({ only_lettings: lettings_form }) + expect(result.map(&:id)).to eq %w[1 2 3 4 5] + end + + it "returns the questions in the same order as the form" do + first_section = build(:section, :with_questions, question_ids: %w[1 2 3]) + second_section = build(:section, :with_questions, question_ids: %w[4 5 6]) + lettings_form = FormFactory.new(year: 2945, type: "lettings") + .with_sections([first_section, second_section]) + .build + described_class.instance.use_fake_forms!({ only_lettings: lettings_form }) + expect(result.map(&:id)).to eq %w[1 2 3 4 5 6] + end + + it "inserts questions from all years in their correct positions" do + original_section = build(:section, :with_questions, question_ids: %w[1 1a_deprecated 2 3]) + new_section = build(:section, :with_questions, question_ids: %w[1 2 2a_new 3]) + original_form = FormFactory.new(year: 2066, type: "lettings") + .with_sections([original_section]) + .build + new_form = FormFactory.new(year: 2485, type: "lettings") + .with_sections([new_section]) + .build + fake_forms = { + earlier_lettings: original_form, + newer_lettings: new_form, + } + described_class.instance.use_fake_forms!(fake_forms) + expect(result.map(&:id)).to eq %w[1 1a_deprecated 2 2a_new 3] + end + end # rubocop:enable RSpec/PredicateMatcher end diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb index f050e7fcd..990ef2b03 100644 --- a/spec/models/lettings_log_spec.rb +++ b/spec/models/lettings_log_spec.rb @@ -2857,115 +2857,6 @@ RSpec.describe LettingsLog do end end - describe "csv download" do - let(:scheme) { create(:scheme) } - let(:location) do - create( - :location, - :export, - scheme:, - type_of_unit: 6, - postcode: "SE11TE", - startdate: Time.zone.local(2021, 10, 1), - ) - end - let(:user) { create(:user, organisation: location.scheme.owning_organisation) } - let(:expected_content) { csv_export_file.read } - - after do - Timecop.unfreeze - end - - context "with values represented as human readable labels" do - before do - Timecop.freeze(Time.utc(2022, 6, 5)) - lettings_log = FactoryBot.create( - :lettings_log, - needstype: 2, - scheme:, - location:, - owning_organisation: scheme.owning_organisation, - created_by: user, - rent_type: 2, - startdate: Time.zone.local(2021, 10, 2), - created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), - updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15), - ) - expected_content.sub!(/\{id\}/, lettings_log["id"].to_s) - expected_content.sub!(/\{scheme_code\}/, "S#{scheme['id']}") - expected_content.sub!(/\{scheme_service_name\}/, scheme["service_name"].to_s) - expected_content.sub!(/\{scheme_sensitive\}/, scheme["sensitive"].to_s) - expected_content.sub!(/\{scheme_primary_client_group\}/, scheme["primary_client_group"].to_s) - expected_content.sub!(/\{scheme_secondary_client_group\}/, scheme["secondary_client_group"].to_s) - expected_content.sub!(/\{scheme_support_type\}/, scheme["support_type"].to_s) - expected_content.sub!(/\{scheme_intended_stay\}/, scheme["intended_stay"].to_s) - expected_content.sub!(/\{location_code\}/, location["id"].to_s) - expected_content.sub!(/\{location_startdate\}/, location["startdate"].to_s) - expected_content.sub!(/\{scheme_id\}/, scheme["service_name"].to_s) - expected_content.sub!(/\{location_id\}/, location["id"].to_s) - end - - around do |example| - Timecop.freeze(Time.zone.local(2022, 6, 5)) do - Singleton.__init__(FormHandler) - example.run - end - Timecop.return - Singleton.__init__(FormHandler) - end - - context "with a support user" do - let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download.csv", "r:UTF-8") } - - it "generates a correct csv from a lettings log" do - expect(described_class.to_csv(codes_only_export: false)).to eq(expected_content) - end - end - - context "with a non support user" do - let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download_non_support.csv", "r:UTF-8") } - - it "generates a correct csv from a lettings log" do - expect(described_class.to_csv(user, codes_only_export: false)).to eq(expected_content) - end - end - end - - context "with values represented as codes" do - before do - Timecop.freeze(Time.utc(2022, 6, 5)) - lettings_log = FactoryBot.create(:lettings_log, needstype: 2, scheme:, location:, owning_organisation: scheme.owning_organisation, created_by: user, rent_type: 2, startdate: Time.zone.local(2021, 10, 2), created_at: Time.zone.local(2022, 2, 8, 16, 52, 15), updated_at: Time.zone.local(2022, 2, 8, 16, 52, 15)) - expected_content.sub!(/\{id\}/, lettings_log["id"].to_s) - expected_content.sub!(/\{scheme_code\}/, "S#{scheme.id}") - expected_content.sub!(/\{scheme_service_name\}/, scheme.service_name.to_s) - expected_content.sub!(/\{scheme_sensitive\}/, scheme.sensitive_before_type_cast.to_s) - expected_content.sub!(/\{scheme_primary_client_group\}/, scheme.primary_client_group_before_type_cast.to_s) - expected_content.sub!(/\{scheme_secondary_client_group\}/, scheme.secondary_client_group_before_type_cast.to_s) - expected_content.sub!(/\{scheme_support_type\}/, scheme.support_type_before_type_cast.to_s) - expected_content.sub!(/\{scheme_intended_stay\}/, scheme.intended_stay_before_type_cast.to_s) - expected_content.sub!(/\{location_code\}/, location.id.to_s) - expected_content.sub!(/\{location_startdate\}/, location.startdate.to_s) - expected_content.sub!(/\{scheme_id\}/, scheme.service_name.to_s) - expected_content.sub!(/\{location_id\}/, location.id.to_s) - end - - let(:csv_export_file) { File.open("spec/fixtures/files/lettings_logs_download_codes_only.csv", "r:UTF-8") } - - around do |example| - Timecop.freeze(Time.zone.local(2022, 6, 5)) do - Singleton.__init__(FormHandler) - example.run - end - Timecop.return - Singleton.__init__(FormHandler) - end - - it "generates a correct csv from a lettings log" do - expect(described_class.to_csv(codes_only_export: true)).to eq(expected_content) - end - end - end - describe "#blank_invalid_non_setup_fields!" do context "when a setup field is invalid" do subject(:model) { described_class.new(needstype: 404) } diff --git a/spec/services/bulk_upload/lettings/log_creator_spec.rb b/spec/services/bulk_upload/lettings/log_creator_spec.rb index 87ac6e320..7739da110 100644 --- a/spec/services/bulk_upload/lettings/log_creator_spec.rb +++ b/spec/services/bulk_upload/lettings/log_creator_spec.rb @@ -27,6 +27,12 @@ RSpec.describe BulkUpload::Lettings::LogCreator do expect(log.bulk_upload).to eql(bulk_upload) expect(bulk_upload.lettings_logs).to include(log) end + + it "sets the creation method" do + service.call + + expect(LettingsLog.last.creation_method).to eq "bulk upload" + end end context "when a valid csv with several blank rows" do diff --git a/spec/services/bulk_upload/sales/log_creator_spec.rb b/spec/services/bulk_upload/sales/log_creator_spec.rb index 7e0082311..16bf25c66 100644 --- a/spec/services/bulk_upload/sales/log_creator_spec.rb +++ b/spec/services/bulk_upload/sales/log_creator_spec.rb @@ -15,8 +15,6 @@ RSpec.describe BulkUpload::Sales::LogCreator do Singleton.__init__(FormHandler) example.run end - Timecop.return - Singleton.__init__(FormHandler) end context "when a valid csv with new log" do @@ -36,6 +34,12 @@ RSpec.describe BulkUpload::Sales::LogCreator do expect(log.bulk_upload).to eql(bulk_upload) expect(bulk_upload.sales_logs).to include(log) end + + it "sets the creation method" do + service.call + + expect(SalesLog.last.creation_method).to eq "bulk upload" + end end context "when a valid csv with several blank rows" do diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index 04d52065d..f21ebfe4e 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -1,430 +1,227 @@ require "rails_helper" RSpec.describe Csv::LettingsLogCsvService do - context "when the user is support" do - let(:user) { create(:user, :support) } - let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") } + let(:form_handler_mock) { instance_double(FormHandler) } + let(:organisation) { create(:organisation) } + let(:fixed_time) { Time.zone.local(2023, 6, 26) } + let(:log) do + create( + :lettings_log, + :completed, + startdate: fixed_time, + created_at: fixed_time, + updated_at: fixed_time, + mrcdate: fixed_time - 1.day, + voiddate: fixed_time - 2.days, + propcode: "ABCDEFG", + tenancycode: "HIJKLMN", + postcode_full: "NW9 5LL", + ppostcode_full: "TN23 6LZ", + created_by: user, + managing_organisation: organisation, + ) + end + let(:user) { create(:user, :support, email: "s.port@jeemayle.com") } + let(:service) { described_class.new(user:, export_type:) } + let(:export_type) { "labels" } + let(:csv) { CSV.parse(service.prepare_csv(LettingsLog.where(id: logs.map(&:id)))) } + let(:logs) { [log] } + let(:headers) { csv.first } + + it "calls the form handler to get all questions in order when initialized" do + allow(FormHandler).to receive(:instance).and_return(form_handler_mock) + allow(form_handler_mock).to receive(:ordered_lettings_questions_for_all_years).and_return([]) + service + expect(form_handler_mock).to have_received(:ordered_lettings_questions_for_all_years) + end + + it "returns a string" do + result = service.prepare_csv(LettingsLog.all) + expect(result).to be_a String + end + + it "returns a csv with headers" do + expect(csv.first.first).to eq "id" + end + + context "when stubbing :ordered_lettings_questions_for_all_years" do + let(:lettings_form) do + FormFactory.new(year: 2050, type: "lettings") + .with_sections([build(:section, :with_questions, question_ids:, questions:)]) + .build + end + let(:question_ids) { nil } + let(:questions) { nil } before do - LettingsLog.create!(startdate: Time.zone.today, created_at: Time.utc(2022, 2, 8, 16, 52, 15)) - allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form) + allow(FormHandler).to receive(:instance).and_return(form_handler_mock) + allow(form_handler_mock).to receive(:form_name_from_start_year) + allow(form_handler_mock).to receive(:get_form).and_return(lettings_form) + allow(form_handler_mock).to receive(:ordered_lettings_questions_for_all_years).and_return(lettings_form.questions) + allow(form_handler_mock).to receive(:lettings_in_crossover_period?).and_return false + end + + context "when it returns questions with particular ids" do + let(:question_ids) { %w[prevten startdate brent rent_type] } + + it "includes log attributes related to questions to the headers" do + expect(headers).to include(*question_ids.first(3)) + end + + it "removes some log attributes related to questions from the headers and replaces them with their derived values in the correct order" do + expect(headers).not_to include "rent_type" + expect(headers).to include(*%w[wrent renttype rent_type_detail]) + end end - it "sets csv attributes in correct order" do - expected_csv_attributes = %w[ - id - status - created_at - updated_at - created_by_name - is_dpo - owning_organisation_name - managing_organisation_name - collection_start_year - needstype - renewal - startdate - rent_type_detail - irproduct_other - tenancycode - propcode - postcode_known - postcode_full - is_la_inferred - la_label - la - first_time_property_let_as_social_housing - unitletas - rsnvac - offered - unittype_gn - builtype - wchair - beds - voiddate - void_date_value_check - majorrepairs - mrcdate - major_repairs_date_value_check - startertenancy - tenancy - tenancyother - tenancylength - sheltered - declaration - hhmemb - pregnancy_value_check - age1_known - age1 - sex1 - ethnic_group - ethnic - national - ecstat1 - retirement_value_check - details_known_2 - relat2 - age2_known - age2 - sex2 - ecstat2 - details_known_3 - relat3 - age3_known - age3 - sex3 - ecstat3 - details_known_4 - relat4 - age4_known - age4 - sex4 - ecstat4 - details_known_5 - relat5 - age5_known - age5 - sex5 - ecstat5 - details_known_6 - relat6 - age6_known - age6 - sex6 - ecstat6 - details_known_7 - relat7 - age7_known - age7 - sex7 - ecstat7 - details_known_8 - relat8 - age8_known - age8 - sex8 - ecstat8 - armedforces - leftreg - reservist - preg_occ - housingneeds - housingneeds_type - housingneeds_other - illness - illness_type_4 - illness_type_5 - illness_type_2 - illness_type_6 - illness_type_7 - illness_type_3 - illness_type_9 - illness_type_8 - illness_type_1 - illness_type_10 - layear - waityear - reason - reasonother - prevten - underoccupation_benefitcap - homeless - ppcodenk - ppostcode_full - previous_la_known - is_previous_la_inferred - prevloc_label - prevloc - reasonpref - rp_homeless - rp_insan_unsat - rp_medwel - rp_hardship - rp_dontknow - cbl - cap - chr - letting_allocation_unknown - referral - net_income_known - earnings - incfreq - net_income_value_check - hb - benefits - household_charge - period - is_carehome - chcharge - carehome_charges_value_check - brent - scharge - pscharge - supcharg - tcharge - rent_value_check - hbrentshortfall - tshortfall_known - tshortfall - housingneeds_a - housingneeds_b - housingneeds_c - housingneeds_f - housingneeds_g - housingneeds_h - property_owner_organisation - property_manager_organisation - purchaser_code - property_relet - incref - renttype - lettype - totchild - totelder - totadult - nocharge - has_benefits - wrent - wscharge - wpschrge - wsupchrg - wtcharge - wtshortfall - refused - wchchrg - newprop - old_form_id - lar - irproduct - old_id - joint - hhtype - new_old - vacdays - unresolved - updated_by_id - uprn - uprn_known - uprn_confirmed - address_line1 - address_line2 - town_or_city - county - status_cache - discarded_at - unittype_sh - 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_code - location_postcode - location_name - location_units - location_type_of_unit - location_mobility_type - location_admin_district - location_startdate - ] - - csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv) - - expect(csv.first).to eq(expected_csv_attributes) + context "when it returns checkbox questions" do + let(:questions) do + [ + build(:question, id: "condition_effects", type: "checkbox", answer_options: { "illness_type_1" => {}, "illness_type_2" => {}, "illness_type_3" => {} }), + build(:question, id: "letting_allocation", type: "checkbox", answer_options: { "cbl" => {}, "cap" => {}, "chr" => {} }), + ] + end + + it "does not add the id of the checkbox question to the headers" do + question_ids = questions.map(&:id) + expect(headers).not_to include(*question_ids) + end + + it "adds the related log attributes from the answer options to the headers" do + log_attributes = questions.flat_map { |q| q.answer_options.keys } + expect(headers).to include(*log_attributes) + end end end - context "when the user is not support" do - let(:user) { FactoryBot.create(:user) } - let(:real_2021_2022_form) { Form.new("config/forms/2021_2022.json") } + it "adds log attributes not related to questions to the headers" do + expect(headers.first(5)).to eq %w[id status created_by is_dpo created_at] + end - before do - LettingsLog.create!(startdate: Time.zone.today, created_at: Time.utc(2022, 2, 8, 16, 52, 15)) - allow(FormHandler.instance).to receive(:get_form).and_return(real_2021_2022_form) + it "adds attributes related to associated schemes and locations to the headers" do + expect(headers).to include(*%w[scheme_service_name scheme_sensitive SCHTYPE scheme_registered_under_care_act]) + expect(headers.last(5)).to eq %w[location_units location_type_of_unit location_mobility_type location_admin_district location_startdate] + end + + context "when there are many logs" do + let(:logs) { create_list(:lettings_log, log_count) } + let(:log_count) { 30 } + + it "creates a CSV with the correct number of logs" do + expected_row_count_with_headers = log_count + 1 + expect(csv.size).to be expected_row_count_with_headers + end + end + + context "when exporting with human readable labels" do + let(:export_type) { "labels" } + + it "gives answer to radio questions as labels" do + relat2_column_index = csv.first.index("relat2") + relat2_value = csv.second[relat2_column_index] + expect(relat2_value).to eq "Partner" + end + + it "gives answers to free input questions as the user input" do + age1_column_index = csv.first.index("age1") + age1_value = csv.second[age1_column_index] + expect(age1_value).to eq 35.to_s end - it "sets csv attributes in correct order and without omitted values" do - expected_csv_attributes = %w[ - id - status - created_at - updated_at - created_by_name - is_dpo - owning_organisation_name - managing_organisation_name - collection_start_year - renewal - startdate - irproduct_other - tenancycode - propcode - postcode_full - la_label - unitletas - rsnvac - offered - unittype_gn - builtype - wchair - beds - voiddate - void_date_value_check - majorrepairs - mrcdate - major_repairs_date_value_check - startertenancy - tenancy - tenancyother - tenancylength - sheltered - declaration - age1 - sex1 - ethnic_group - ethnic - national - ecstat1 - relat2 - age2 - sex2 - ecstat2 - relat3 - age3 - sex3 - ecstat3 - relat4 - age4 - sex4 - ecstat4 - relat5 - age5 - sex5 - ecstat5 - relat6 - age6 - sex6 - ecstat6 - relat7 - age7 - sex7 - ecstat7 - relat8 - age8 - sex8 - ecstat8 - armedforces - leftreg - reservist - preg_occ - housingneeds - housingneeds_type - housingneeds_other - illness - illness_type_4 - illness_type_5 - illness_type_2 - illness_type_6 - illness_type_7 - illness_type_3 - illness_type_9 - illness_type_8 - illness_type_1 - illness_type_10 - layear - waityear - reason - reasonother - prevten - underoccupation_benefitcap - homeless - ppcodenk - ppostcode_full - prevloc_label - reasonpref - rp_homeless - rp_insan_unsat - rp_medwel - rp_hardship - rp_dontknow - cbl - cap - chr - referral - earnings - incfreq - hb - benefits - household_charge - period - chcharge - carehome_charges_value_check - brent - scharge - pscharge - supcharg - tcharge - hbrentshortfall - tshortfall - housingneeds_a - housingneeds_b - housingneeds_c - housingneeds_f - housingneeds_g - housingneeds_h - property_owner_organisation - property_manager_organisation - purchaser_code - property_relet - incref - lettype - nocharge - has_benefits - refused - wchchrg - newprop - lar - irproduct - joint - uprn - uprn_known - address_line1 - address_line2 - town_or_city - county - unittype_sh - 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_code - location_postcode - location_name - location_units - location_type_of_unit - location_mobility_type - location_admin_district - location_startdate - ] - - csv = CSV.parse(described_class.new(user, export_type: "labels").to_csv) - - expect(csv.first).to eq(expected_csv_attributes) + it "exports the code for the local authority under the heading 'la'" do + la_column_index = csv.first.index("la") + la_value = csv.second[la_column_index] + expect(la_value).to eq "E09000003" + end + + it "exports the label for the local authority under the heading 'la_label'" do + la_label_column_index = csv.first.index("la_label") + la_label_value = csv.second[la_label_column_index] + expect(la_label_value).to eq "Barnet" + end + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels.csv") + values_to_delete = %w[id vacdays] + values_to_delete.each do |attribute| + index = csv.first.index(attribute) + csv.second[index] = nil + end + expect(csv).to eq expected_content + end + end + + context "when exporting as codes" do + let(:export_type) { "codes" } + + it "gives answer to radio questions as labels" do + relat2_column_index = csv.first.index("relat2") + relat2_value = csv.second[relat2_column_index] + expect(relat2_value).to eq "P" + end + + it "gives answers to free input questions as the user input" do + age1_column_index = csv.first.index("age1") + age1_value = csv.second[age1_column_index] + expect(age1_value).to eq 35.to_s + end + + it "exports the code for the local authority under the heading 'la'" do + la_column_index = csv.first.index("la") + la_value = csv.second[la_column_index] + expect(la_value).to eq "E09000003" + end + + it "exports the label for the local authority under the heading 'la_label'" do + la_label_column_index = csv.first.index("la_label") + la_label_value = csv.second[la_label_column_index] + expect(la_label_value).to eq "Barnet" + end + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes.csv") + values_to_delete = %w[id vacdays] + values_to_delete.each do |attribute| + index = csv.first.index(attribute) + csv.second[index] = nil + end + expect(csv).to eq expected_content + end + end + + context "when the user is not a support user" do + let(:user) { create(:user, email: "choreographer@owtluk.com") } + + it "does not include certain attributes in the headers" do + expect(headers).not_to include(*%w[rent_type_detail wrent wscharge wpschrge wsupchrg wtcharge]) + end + + context "and exporting with labels" do + let(:export_type) { "labels" } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = csv.first.index(attribute) + csv.second[index] = nil + end + expect(csv).to eq expected_content + end + end + + context "and exporting values as codes" do + let(:export_type) { "codes" } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = csv.first.index(attribute) + csv.second[index] = nil + end + expect(csv).to eq expected_content + end end end end diff --git a/spec/services/csv/sales_log_csv_service_spec.rb b/spec/services/csv/sales_log_csv_service_spec.rb index 2c24bf7b1..f037603ff 100644 --- a/spec/services/csv/sales_log_csv_service_spec.rb +++ b/spec/services/csv/sales_log_csv_service_spec.rb @@ -3,23 +3,27 @@ require "rails_helper" RSpec.describe Csv::SalesLogCsvService do let(:form_handler_mock) { instance_double(FormHandler) } let(:organisation) { create(:organisation) } - let!(:log) { create(:sales_log, :completed, owning_organisation: organisation, purchid: nil) } + let(:fixed_time) { Time.zone.local(2023, 2, 8) } + let(:user) { create(:user, email: "billyboy@eyeKLAUD.com") } + let!(:log) do + create( + :sales_log, + :completed, + created_by: user, + saledate: fixed_time, + created_at: fixed_time, + updated_at: fixed_time, + owning_organisation: organisation, + purchid: nil, + ) + end let(:service) { described_class.new(export_type: "labels") } let(:csv) { CSV.parse(service.prepare_csv(SalesLog.all)) } - around do |example| - Timecop.freeze(Time.utc(2023, 2, 8)) do - Singleton.__init__(FormHandler) - example.run - end - Timecop.return - Singleton.__init__(FormHandler) - end - it "calls the form handler to get all questions in order when initialized" do allow(FormHandler).to receive(:instance).and_return(form_handler_mock) allow(form_handler_mock).to receive(:ordered_sales_questions_for_all_years).and_return([]) - described_class.new(export_type: "codes") + service expect(form_handler_mock).to have_received(:ordered_sales_questions_for_all_years) end @@ -30,7 +34,6 @@ RSpec.describe Csv::SalesLogCsvService do it "returns a csv with headers" do expect(csv.first.first).to eq "id" - expect(csv.second.first).not_to be log.id.to_s end context "when stubbing :ordered_sales_questions_for_all_years" do