From 52a0b2761179eaa3c3b957b1ae1a2b8510e90549 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:59:12 +0000 Subject: [PATCH] CLDC-2442 Remove 2022/23 BU code (#2153) * Remove 2022/23 BU code * Add empty lines to csvs * Update feature tests * More tests * Remove forms and update a test * rebase tests --- .../bulk_upload_sales_logs_controller.rb | 2 + app/controllers/start_controller.rb | 48 - .../bulk_upload_lettings/prepare_your_file.rb | 16 +- .../bulk_upload_sales/prepare_your_file.rb | 15 +- .../bulk_upload/lettings/log_creator.rb | 2 - .../bulk_upload/lettings/validator.rb | 2 - .../lettings/year2022/csv_parser.rb | 109 - .../lettings/year2022/row_parser.rb | 1476 ----------- app/services/bulk_upload/sales/log_creator.rb | 2 - app/services/bulk_upload/sales/validator.rb | 2 - .../bulk_upload/sales/year2022/csv_parser.rb | 83 - .../bulk_upload/sales/year2022/row_parser.rb | 1156 --------- .../forms/prepare_your_file_2022.html.erb | 41 - .../forms/prepare_your_file_2022.html.erb | 34 - config/routes.rb | 8 - public/files/2022_23_lettings_paper_form.pdf | Bin 653905 -> 0 bytes public/files/2022_23_sales_paper_form.pdf | Bin 394585 -> 0 bytes ...upload-lettings-specification-2022-23.xlsx | Bin 52988 -> 0 bytes ...bulk-upload-lettings-template-2022-23.xlsx | Bin 35928 -> 0 bytes ...lk-upload-sales-specification-2022-23.xlsx | Bin 24108 -> 0 bytes .../bulk-upload-sales-template-2022-23.xlsx | Bin 13838 -> 0 bytes .../bulk_upload_error_row_component_spec.rb | 4 +- spec/factories/bulk_upload.rb | 2 +- .../bulk_upload_lettings_logs_spec.rb | 28 +- spec/features/bulk_upload_sales_logs_spec.rb | 12 +- .../files/2021_22_lettings_bulk_upload.csv | 20 - .../files/2021_22_lettings_bulk_upload.xlsx | Bin 25878 -> 0 bytes .../2021_22_lettings_bulk_upload_empty.xlsx | Bin 24693 -> 0 bytes .../files/2022_23_lettings_bulk_upload.csv | 74 - .../files/2023_24_lettings_bulk_upload.csv | 50 + .../files/2023_24_lettings_bulk_upload.xlsx | Bin 0 -> 15019 bytes ... 2023_24_lettings_bulk_upload_invalid.csv} | 1 + .../files/2023_24_sales_bulk_upload.csv | 12 + .../2023_24_sales_bulk_upload_invalid.csv | 12 + .../completed_2022_23_sales_bulk_upload.csv | 119 - spec/mailers/bulk_upload_mailer_spec.rb | 4 +- ...upload_lettings_results_controller_spec.rb | 4 +- ..._upload_lettings_resume_controller_spec.rb | 4 +- ..._soft_validations_check_controller_spec.rb | 2 +- ...lk_upload_sales_results_controller_spec.rb | 2 +- ...ulk_upload_sales_resume_controller_spec.rb | 4 +- ..._soft_validations_check_controller_spec.rb | 2 +- .../bulk_upload/lettings/log_creator_spec.rb | 53 +- .../bulk_upload/lettings/validator_spec.rb | 179 +- .../lettings/year2022/csv_parser_spec.rb | 218 -- .../lettings/year2022/row_parser_spec.rb | 2181 ----------------- spec/services/bulk_upload/processor_spec.rb | 88 +- .../bulk_upload/sales/log_creator_spec.rb | 55 +- .../bulk_upload/sales/validator_spec.rb | 61 +- .../sales/year2022/csv_parser_spec.rb | 150 -- .../sales/year2022/row_parser_spec.rb | 921 ------- 51 files changed, 229 insertions(+), 7029 deletions(-) delete mode 100644 app/services/bulk_upload/lettings/year2022/csv_parser.rb delete mode 100644 app/services/bulk_upload/lettings/year2022/row_parser.rb delete mode 100644 app/services/bulk_upload/sales/year2022/csv_parser.rb delete mode 100644 app/services/bulk_upload/sales/year2022/row_parser.rb delete mode 100644 app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2022.html.erb delete mode 100644 app/views/bulk_upload_sales_logs/forms/prepare_your_file_2022.html.erb delete mode 100644 public/files/2022_23_lettings_paper_form.pdf delete mode 100644 public/files/2022_23_sales_paper_form.pdf delete mode 100644 public/files/bulk-upload-lettings-specification-2022-23.xlsx delete mode 100644 public/files/bulk-upload-lettings-template-2022-23.xlsx delete mode 100644 public/files/bulk-upload-sales-specification-2022-23.xlsx delete mode 100644 public/files/bulk-upload-sales-template-2022-23.xlsx delete mode 100644 spec/fixtures/files/2021_22_lettings_bulk_upload.csv delete mode 100644 spec/fixtures/files/2021_22_lettings_bulk_upload.xlsx delete mode 100644 spec/fixtures/files/2021_22_lettings_bulk_upload_empty.xlsx delete mode 100644 spec/fixtures/files/2022_23_lettings_bulk_upload.csv create mode 100644 spec/fixtures/files/2023_24_lettings_bulk_upload.csv create mode 100644 spec/fixtures/files/2023_24_lettings_bulk_upload.xlsx rename spec/fixtures/files/{2022_23_lettings_bulk_upload_empty_with_headers.csv => 2023_24_lettings_bulk_upload_invalid.csv} (98%) create mode 100644 spec/fixtures/files/2023_24_sales_bulk_upload.csv create mode 100644 spec/fixtures/files/2023_24_sales_bulk_upload_invalid.csv delete mode 100644 spec/fixtures/files/completed_2022_23_sales_bulk_upload.csv delete mode 100644 spec/services/bulk_upload/lettings/year2022/csv_parser_spec.rb delete mode 100644 spec/services/bulk_upload/lettings/year2022/row_parser_spec.rb delete mode 100644 spec/services/bulk_upload/sales/year2022/csv_parser_spec.rb delete mode 100644 spec/services/bulk_upload/sales/year2022/row_parser_spec.rb diff --git a/app/controllers/bulk_upload_sales_logs_controller.rb b/app/controllers/bulk_upload_sales_logs_controller.rb index de70ffc5d..c1004ced4 100644 --- a/app/controllers/bulk_upload_sales_logs_controller.rb +++ b/app/controllers/bulk_upload_sales_logs_controller.rb @@ -35,6 +35,8 @@ private end def in_crossover_period? + return true if FeatureToggle.force_crossover? + FormHandler.instance.sales_in_crossover_period? end diff --git a/app/controllers/start_controller.rb b/app/controllers/start_controller.rb index e07615901..afc6e4a49 100644 --- a/app/controllers/start_controller.rb +++ b/app/controllers/start_controller.rb @@ -21,14 +21,6 @@ class StartController < ApplicationController ) end - def download_22_23_sales_form - send_file( - Rails.root.join("public/files/2022_23_sales_paper_form.pdf"), - filename: "2022-23 Sales paper form.pdf", - type: "application/pdf", - ) - end - def download_24_25_lettings_form send_file( Rails.root.join("public/files/2024_25_lettings_paper_form.pdf"), @@ -45,14 +37,6 @@ class StartController < ApplicationController ) end - def download_22_23_lettings_form - send_file( - Rails.root.join("public/files/2022_23_lettings_paper_form.pdf"), - filename: "2022-23 Lettings paper form.pdf", - type: "application/pdf", - ) - end - def download_24_25_lettings_bulk_upload_template send_file( Rails.root.join("public/files/bulk-upload-lettings-template-2024-25.xlsx"), @@ -132,36 +116,4 @@ class StartController < ApplicationController type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ) end - - def download_22_23_lettings_bulk_upload_template - send_file( - Rails.root.join("public/files/bulk-upload-lettings-template-2022-23.xlsx"), - filename: "2022-23-lettings-bulk-upload-template.xlsx", - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ) - end - - def download_22_23_lettings_bulk_upload_specification - send_file( - Rails.root.join("public/files/bulk-upload-lettings-specification-2022-23.xlsx"), - filename: "2022-23-lettings-bulk-upload-specification.xlsx", - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ) - end - - def download_22_23_sales_bulk_upload_template - send_file( - Rails.root.join("public/files/bulk-upload-sales-template-2022-23.xlsx"), - filename: "2022-23-sales-bulk-upload-template.xlsx", - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ) - end - - def download_22_23_sales_bulk_upload_specification - send_file( - Rails.root.join("public/files/bulk-upload-sales-specification-2022-23.xlsx"), - filename: "2022-23-sales-bulk-upload-specification.xlsx", - type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - ) - end end diff --git a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb index 601f09848..042ec132a 100644 --- a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb @@ -10,9 +10,7 @@ module Forms def view_path case year - when 2022 - "bulk_upload_lettings_logs/forms/prepare_your_file_2022" - else + when 2023 "bulk_upload_lettings_logs/forms/prepare_your_file_2023" end end @@ -32,27 +30,21 @@ module Forms def legacy_template_path case year - when 2022 - "/files/bulk-upload-lettings-template-2022-23.xlsx" - else + when 2023 "/files/bulk-upload-lettings-legacy-template-2023-24.xlsx" end end def template_path case year - when 2022 - "/files/bulk-upload-lettings-template-2022-23.xlsx" - else + when 2023 "/files/bulk-upload-lettings-template-2023-24.xlsx" end end def specification_path case year - when 2022 - "/files/bulk-upload-lettings-specification-2022-23.xlsx" - else + when 2023 "/files/bulk-upload-lettings-specification-2023-24.xlsx" end end diff --git a/app/models/forms/bulk_upload_sales/prepare_your_file.rb b/app/models/forms/bulk_upload_sales/prepare_your_file.rb index 9425a6662..04d52802f 100644 --- a/app/models/forms/bulk_upload_sales/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_sales/prepare_your_file.rb @@ -9,9 +9,7 @@ module Forms def view_path case year - when 2022 - "bulk_upload_sales_logs/forms/prepare_your_file_2022" - else + when 2023 "bulk_upload_sales_logs/forms/prepare_your_file_2023" end end @@ -30,17 +28,13 @@ module Forms def legacy_template_path case year - when 2022 - "/files/bulk-upload-sales-template-2022-23.xlsx" - else + when 2023 "/files/bulk-upload-sales-legacy-template-2023-24.xlsx" end end def template_path case year - when 2022 - "/files/bulk-upload-sales-template-2022-23.xlsx" when 2023 "/files/bulk-upload-sales-template-2023-24.xlsx" end @@ -48,8 +42,7 @@ module Forms def specification_path case year - when 2022 - "/files/bulk-upload-sales-specification-2022-23.xlsx" + when 2023 "/files/bulk-upload-sales-specification-2023-24.xlsx" end @@ -66,6 +59,8 @@ module Forms private def in_crossover_period? + return true if FeatureToggle.force_crossover? + FormHandler.instance.sales_in_crossover_period? end end diff --git a/app/services/bulk_upload/lettings/log_creator.rb b/app/services/bulk_upload/lettings/log_creator.rb index 99cfd4390..dd8820b35 100644 --- a/app/services/bulk_upload/lettings/log_creator.rb +++ b/app/services/bulk_upload/lettings/log_creator.rb @@ -31,8 +31,6 @@ private def csv_parser @csv_parser ||= case bulk_upload.year - when 2022 - BulkUpload::Lettings::Year2022::CsvParser.new(path:) when 2023 BulkUpload::Lettings::Year2023::CsvParser.new(path:) else diff --git a/app/services/bulk_upload/lettings/validator.rb b/app/services/bulk_upload/lettings/validator.rb index 7f811f709..59d837acf 100644 --- a/app/services/bulk_upload/lettings/validator.rb +++ b/app/services/bulk_upload/lettings/validator.rb @@ -98,8 +98,6 @@ private def csv_parser @csv_parser ||= case bulk_upload.year - when 2022 - BulkUpload::Lettings::Year2022::CsvParser.new(path:) when 2023 BulkUpload::Lettings::Year2023::CsvParser.new(path:) else diff --git a/app/services/bulk_upload/lettings/year2022/csv_parser.rb b/app/services/bulk_upload/lettings/year2022/csv_parser.rb deleted file mode 100644 index 9e672ade5..000000000 --- a/app/services/bulk_upload/lettings/year2022/csv_parser.rb +++ /dev/null @@ -1,109 +0,0 @@ -require "csv" - -class BulkUpload::Lettings::Year2022::CsvParser - FIELDS = 134 - MAX_COLUMNS = 135 - FORM_YEAR = 2022 - - attr_reader :path - - def initialize(path:) - @path = path - end - - def row_offset - if with_headers? - rows.find_index { |row| row[0].match(/field number/i) } + 1 - else - 0 - end - end - - def col_offset - with_headers? ? 1 : 0 - end - - def cols - @cols ||= ("A".."EE").to_a - end - - def row_parsers - @row_parsers ||= body_rows.map do |row| - stripped_row = row[col_offset..] - hash = Hash[field_numbers.zip(stripped_row)] - - BulkUpload::Lettings::Year2022::RowParser.new(hash) - end - end - - def body_rows - rows[row_offset..] - end - - def rows - @rows ||= CSV.parse(normalised_string, row_sep:) - end - - def column_for_field(field) - cols[field_numbers.find_index(field) + col_offset] - end - - def correct_field_count? - valid_field_numbers_count = field_numbers.count { |f| f != "field_blank" } - - valid_field_numbers_count == FIELDS - end - - def too_many_columns? - return if with_headers? - - max_columns_count = body_rows.map(&:size).max - col_offset - - max_columns_count > MAX_COLUMNS - end - - def wrong_template_for_year? - !(first_record_start_date >= form.start_date && first_record_start_date <= form.new_logs_end_date) - end - -private - - def form - @form ||= FormHandler.instance.lettings_form_for_start_year(FORM_YEAR) - end - - def first_record_start_date - @first_record_start_date ||= row_parsers.first.startdate || Date.new - end - - def default_field_numbers - ("field_1".."field_#{FIELDS}").to_a - end - - def field_numbers - @field_numbers ||= if with_headers? - rows[row_offset - 1][col_offset..].map { |h| h.present? && h.match?(/^[0-9]+$/) ? "field_#{h}" : "field_blank" } - else - default_field_numbers - end - end - - def with_headers? - rows.map { |r| r[0] }.any? { |cell| cell&.match?(/field number/i) } - end - - def row_sep - "\n" - end - - def normalised_string - return @normalised_string if @normalised_string - - @normalised_string = File.read(path, encoding: "bom|utf-8") - @normalised_string.gsub!("\r\n", "\n") - @normalised_string.scrub!("") - @normalised_string.tr!("\r", "\n") - - @normalised_string - end -end diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb deleted file mode 100644 index 8aaa38b43..000000000 --- a/app/services/bulk_upload/lettings/year2022/row_parser.rb +++ /dev/null @@ -1,1476 +0,0 @@ -class BulkUpload::Lettings::Year2022::RowParser - include ActiveModel::Model - include ActiveModel::Attributes - include InterruptionScreenHelper - - QUESTIONS = { - field_1: "What is the letting type?", - field_2: "This question has been removed", - field_3: "This question has been removed", - field_4: "Management group code", - field_5: "Scheme code", - field_6: "This question has been removed", - field_7: "What is the tenant code?", - field_8: "Is this a starter tenancy?", - field_9: "What is the tenancy type?", - field_10: "If 'Other', what is the tenancy type?", - field_11: "What is the length of the fixed-term tenancy to the nearest year?", - field_12: "Age of person 1", - field_13: "Age of person 2", - field_14: "Age of person 3", - field_15: "Age of person 4", - field_16: "Age of person 5", - field_17: "Age of person 6", - field_18: "Age of person 7", - field_19: "Age of person 8", - field_20: "Gender identity of person 1", - field_21: "Gender identity of person 2", - field_22: "Gender identity of person 3", - field_23: "Gender identity of person 4", - field_24: "Gender identity of person 5", - field_25: "Gender identity of person 6", - field_26: "Gender identity of person 7", - field_27: "Gender identity of person 8", - field_28: "Relationship to person 1 for person 2", - field_29: "Relationship to person 1 for person 3", - field_30: "Relationship to person 1 for person 4", - field_31: "Relationship to person 1 for person 5", - field_32: "Relationship to person 1 for person 6", - field_33: "Relationship to person 1 for person 7", - field_34: "Relationship to person 1 for person 8", - field_35: "Working situation of person 1", - field_36: "Working situation of person 2", - field_37: "Working situation of person 3", - field_38: "Working situation of person 4", - field_39: "Working situation of person 5", - field_40: "Working situation of person 6", - field_41: "Working situation of person 7", - field_42: "Working situation of person 8", - field_43: "What is the lead tenant's ethnic group?", - field_44: "What is the lead tenant's nationality?", - field_45: "Does anybody in the household have links to the UK armed forces?", - field_46: "Was the person seriously injured or ill as a result of serving in the UK armed forces?", - field_47: "Is anybody in the household pregnant?", - field_48: "Is the tenant likely to be receiving benefits related to housing?", - field_49: "How much of the household's income is from Universal Credit, state pensions or benefits?", - field_50: "How much income does the household have in total?", - field_51: "Do you know the household's income?", - field_52: "What is the tenant's main reason for the household leaving their last settled home?", - field_53: "If 'Other', what was the main reason for leaving their last settled home?", - field_54: "This question has been removed", - field_55: "Does anybody in the household have any disabled access needs?", - field_56: "Does anybody in the household have any disabled access needs?", - field_57: "Does anybody in the household have any disabled access needs?", - field_58: "Does anybody in the household have any disabled access needs?", - field_59: "Does anybody in the household have any disabled access needs?", - field_60: "Does anybody in the household have any disabled access needs?", - field_61: "Where was the household immediately before this letting?", - field_62: "What is the local authority of the household's last settled home?", - field_63: "Part 1 of postcode of last settled home", - field_64: "Part 2 of postcode of last settled home", - field_65: "Do you know the postcode of last settled home?", - field_66: "How long has the household continuously lived in the local authority area of the new letting?", - field_67: "How long has the household been on the waiting list for the new letting?", - field_68: "Was the tenant homeless directly before this tenancy?", - field_69: "Was the household given 'reasonable preference' by the local authority?", - field_70: "Reasonable preference. They were homeless or about to lose their home (within 56 days)", - field_71: "Reasonable preference. They were living in insanitary, overcrowded or unsatisfactory housing", - field_72: "Reasonable preference. They needed to move on medical and welfare grounds (including a disability)", - field_73: "Reasonable preference. They needed to move to avoid hardship to themselves or others", - field_74: "Reasonable preference. Don't know", - field_75: "Was the letting made under any of the following allocations systems?", - field_76: "Was the letting made under any of the following allocations systems?", - field_77: "Was the letting made under any of the following allocations systems?", - field_78: "What was the source of referral for this letting?", - field_79: "How often does the household pay rent and other charges?", - field_80: "What is the basic rent?", - field_81: "What is the service charge?", - field_82: "What is the personal service charge?", - field_83: "What is the support charge?", - field_84: "Total Charge", - field_85: "If this is a care home, how much does the household pay every [time period]?", - field_86: "Does the household pay rent or other charges for the accommodation?", - field_87: "After the household has received any housing-related benefits, will they still need to pay basic rent and other charges?", - field_88: "What do you expect the outstanding amount to be?", - field_89: "What is the void date?", - field_90: "What is the void date?", - field_91: "What is the void date?", - field_92: "What date were major repairs completed on?", - field_93: "What date were major repairs completed on?", - field_94: "What date were major repairs completed on?", - field_95: "This question has been removed", - field_96: "What date did the tenancy start?", - field_97: "What date did the tenancy start?", - field_98: "What date did the tenancy start?", - field_99: "Since becoming available, how many times has the property been previously offered?", - field_100: "What is the property reference?", - field_101: "How many bedrooms does the property have?", - field_102: "What type of unit is the property?", - field_103: "Which type of building is the property?", - field_104: "Is the property built or adapted to wheelchair-user standards?", - field_105: "What type was the property most recently let as?", - field_106: "What is the reason for the property being vacant?", - field_107: "What is the local authority of the property?", - field_108: "Part 1 of postcode of the property", - field_109: "Part 2 of postcode of the property", - field_110: "This question has been removed", - field_111: "Which organisation owns this property?", - field_112: "Username field", - field_113: "Which organisation manages this property?", - field_114: "Is the person still serving in the UK armed forces?", - field_115: "This question has been removed", - field_116: "How often does the household receive income?", - field_117: "Is this letting sheltered accommodation?", - field_118: "Does anybody in the household have a physical or mental health condition (or other illness) expected to last for 12 months or more?", - field_119: "Vision, for example blindness or partial sight", - field_120: "Hearing, for example deafness or partial hearing", - field_121: "Mobility, for example walking short distances or climbing stairs", - field_122: "Dexterity, for example lifting and carrying objects, using a keyboard", - field_123: "Learning or understanding or concentrating", - field_124: "Memory", - field_125: "Mental health", - field_126: "Stamina or breathing or fatigue", - field_127: "Socially or behaviourally, for example associated with autism spectral disorder (ASD) which include Aspergers' or attention deficit hyperactivity disorder (ADHD)", - field_128: "Other", - field_129: "Is this letting a London Affordable Rent letting?", - field_130: "Which type of Intermediate Rent is this letting?", - field_131: "Which 'Other' type of Intermediate Rent is this letting?", - field_132: "Data Protection", - field_133: "Is this a joint tenancy?", - field_134: "Is this letting a renewal?", - }.freeze - - attribute :bulk_upload - attribute :block_log_creation, :boolean, default: -> { false } - - attribute :field_blank - - attribute :field_1, :integer - attribute :field_2 - attribute :field_3 - attribute :field_4, :string - attribute :field_5, :integer - attribute :field_6 - attribute :field_7, :string - attribute :field_8, :integer - attribute :field_9, :integer - attribute :field_10, :string - attribute :field_11, :integer - attribute :field_12, :string - attribute :field_13, :string - attribute :field_14, :string - attribute :field_15, :string - attribute :field_16, :string - attribute :field_17, :string - attribute :field_18, :string - attribute :field_19, :string - attribute :field_20, :string - attribute :field_21, :string - attribute :field_22, :string - attribute :field_23, :string - attribute :field_24, :string - attribute :field_25, :string - attribute :field_26, :string - attribute :field_27, :string - attribute :field_28, :string - attribute :field_29, :string - attribute :field_30, :string - attribute :field_31, :string - attribute :field_32, :string - attribute :field_33, :string - attribute :field_34, :string - attribute :field_35, :integer - attribute :field_36, :integer - attribute :field_37, :integer - attribute :field_38, :integer - attribute :field_39, :integer - attribute :field_40, :integer - attribute :field_41, :integer - attribute :field_42, :integer - attribute :field_43, :integer - attribute :field_44, :integer - attribute :field_45, :integer - attribute :field_46, :integer - attribute :field_47, :integer - attribute :field_48, :integer - attribute :field_49, :integer - attribute :field_50, :decimal - attribute :field_51, :integer - attribute :field_52, :integer - attribute :field_53, :string - attribute :field_54 - attribute :field_55, :integer - attribute :field_56, :integer - attribute :field_57, :integer - attribute :field_58, :integer - attribute :field_59, :integer - attribute :field_60, :integer - attribute :field_61, :integer - attribute :field_62, :string - attribute :field_63, :string - attribute :field_64, :string - attribute :field_65, :integer - attribute :field_66, :integer - attribute :field_67, :integer - attribute :field_68, :integer - attribute :field_69, :integer - attribute :field_70, :integer - attribute :field_71, :integer - attribute :field_72, :integer - attribute :field_73, :integer - attribute :field_74, :integer - attribute :field_75, :integer - attribute :field_76, :integer - attribute :field_77, :integer - attribute :field_78, :integer - attribute :field_79, :integer - attribute :field_80, :decimal - attribute :field_81, :decimal - attribute :field_82, :decimal - attribute :field_83, :decimal - attribute :field_84, :decimal - attribute :field_85, :decimal - attribute :field_86, :integer - attribute :field_87, :integer - attribute :field_88, :decimal - attribute :field_89, :integer - attribute :field_90, :integer - attribute :field_91, :integer - attribute :field_92, :integer - attribute :field_93, :integer - attribute :field_94, :integer - attribute :field_95 - attribute :field_96, :integer - attribute :field_97, :integer - attribute :field_98, :integer - attribute :field_99, :integer - attribute :field_100, :string - attribute :field_101, :integer - attribute :field_102, :integer - attribute :field_103, :integer - attribute :field_104, :integer - attribute :field_105, :integer - attribute :field_106, :integer - attribute :field_107, :string - attribute :field_108, :string - attribute :field_109, :string - attribute :field_110 - attribute :field_111, :string - attribute :field_112, :string - attribute :field_113, :string - attribute :field_114, :integer - attribute :field_115 - attribute :field_116, :integer - attribute :field_117, :integer - attribute :field_118, :integer - attribute :field_119, :integer - attribute :field_120, :integer - attribute :field_121, :integer - attribute :field_122, :integer - attribute :field_123, :integer - attribute :field_124, :integer - attribute :field_125, :integer - attribute :field_126, :integer - attribute :field_127, :integer - attribute :field_128, :integer - attribute :field_129, :integer - attribute :field_130, :integer - attribute :field_131, :string - attribute :field_132, :integer - attribute :field_133, :integer - attribute :field_134, :integer - - validate :validate_valid_radio_option, on: :before_log - - validates :field_1, - presence: { - message: I18n.t("validations.not_answered", question: "letting type"), - category: :setup, - }, - inclusion: { - in: (1..12).to_a, - message: I18n.t("validations.invalid_option", question: "letting type"), - category: :setup, - unless: -> { field_1.blank? }, - }, - on: :after_log - - validates :field_12, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }, on: :after_log - validates :field_13, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_14, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_15, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_16, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_17, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_18, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true, on: :after_log - validates :field_19, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true, on: :after_log - - validates :field_96, - presence: { - message: I18n.t("validations.not_answered", question: "tenancy start date (day)"), - category: :setup, - }, on: :after_log - - validates :field_97, - presence: { - message: I18n.t("validations.not_answered", question: "tenancy start date (month)"), - category: :setup, - }, - on: :after_log - - validates :field_98, - presence: { - message: I18n.t("validations.not_answered", question: "tenancy start date (year)"), - category: :setup, - }, - format: { - with: /\A\d{2}\z/, - message: I18n.t("validations.setup.startdate.year_not_two_digits"), - unless: -> { field_98.blank? }, - category: :setup, - }, - on: :after_log - - validate :validate_data_types, on: :after_log - validate :validate_relevant_collection_window, on: :after_log - validate :validate_la_with_local_housing_referral, on: :after_log - validate :validate_cannot_be_la_referral_if_general_needs_and_la, on: :after_log - validate :validate_leaving_reason_for_renewal, on: :after_log - validate :validate_lettings_type_matches_bulk_upload, on: :after_log - validate :validate_only_one_housing_needs_type, on: :after_log - validate :validate_no_disabled_needs_conjunction, on: :after_log - validate :validate_dont_know_disabled_needs_conjunction, on: :after_log - validate :validate_no_and_dont_know_disabled_needs_conjunction, on: :after_log - validate :validate_no_housing_needs_questions_answered, on: :after_log - validate :validate_reasonable_preference_homeless, on: :after_log - validate :validate_condition_effects, on: :after_log - validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? } - - validate :validate_owning_org_data_given, on: :after_log - validate :validate_owning_org_exists, on: :after_log - validate :validate_owning_org_owns_stock, on: :after_log - validate :validate_owning_org_permitted, on: :after_log - - validate :validate_managing_org_data_given, on: :after_log - validate :validate_managing_org_exists, on: :after_log - validate :validate_managing_org_related, on: :after_log - - validate :validate_related_scheme_exists, on: :after_log - validate :validate_scheme_data_given, on: :after_log - - validate :validate_related_location_exists, on: :after_log - validate :validate_location_data_given, on: :after_log - - validate :validate_created_by_exists, on: :after_log - validate :validate_created_by_related, on: :after_log - validate :validate_rent_type, on: :after_log - - validate :validate_declaration_acceptance, on: :after_log - - validate :validate_incomplete_soft_validations, on: :after_log - - validate :validate_nulls, on: :after_log - - def self.question_for_field(field) - QUESTIONS[field] - end - - def valid? - return @valid if @valid - - errors.clear - - return @valid = true if blank_row? - - super(:before_log) - before_errors = errors.dup - - log.valid? - - super(:after_log) - errors.merge!(before_errors) - - log.errors.each do |error| - fields = field_mapping_for_errors[error.attribute] || [] - - fields.each do |field| - unless errors.include?(field) - errors.add(field, error.message) - end - end - end - - @valid = errors.blank? - end - - def blank_row? - attribute_set - .to_hash - .reject { |k, _| %w[bulk_upload block_log_creation field_blank].include?(k) } - .values - .reject(&:blank?) - .compact - .empty? - end - - def log - @log ||= LettingsLog.new(attributes_for_log) - end - - def block_log_creation! - self.block_log_creation = true - end - - def block_log_creation? - block_log_creation - end - - def tenant_code - field_7 - end - - def property_ref - field_100 - end - - def log_already_exists? - @log_already_exists ||= LettingsLog - .where(status: %w[not_started in_progress completed]) - .exists?(duplicate_check_fields.index_with { |field| log.public_send(field) }) - end - - def spreadsheet_duplicate_hash - attributes.slice( - bulk_upload.needstype != 1 ? "field_5" : nil, # location - "field_12", # age1 - "field_20", # sex1 - "field_35", # ecstat1 - "field_84", # tcharge - "field_96", # startdate - "field_97", # startdate - "field_98", # startdate - bulk_upload.needstype != 2 ? "field_108" : nil, # postcode - bulk_upload.needstype != 2 ? "field_109" : nil, # postcode - "field_111", # owning org - ) - end - - def add_duplicate_found_in_spreadsheet_errors - spreadsheet_duplicate_hash.each_key do |field| - errors.add(field, :spreadsheet_dupe, category: :setup) - end - end - - def startdate - Date.new(field_98 + 2000, field_97, field_96) if field_98.present? && field_97.present? && field_96.present? - rescue Date::Error - Date.new - end - -private - - def validate_declaration_acceptance - unless field_132 == 1 - errors.add(:field_132, I18n.t("validations.declaration.missing"), category: :setup) - end - end - - def validate_valid_radio_option - log.attributes.each do |question_id, _v| - question = log.form.get_question(question_id, log) - - next unless question&.type == "radio" - next if log[question_id].blank? || question.answer_options.key?(log[question_id].to_s) || !question.page.routed_to?(log, nil) - - fields = field_mapping_for_errors[question_id.to_sym] || [] - - fields.each do |field| - if setup_question?(question) - errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field]), category: :setup) - else - errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field])) - end - end - end - end - - def validate_created_by_exists - return if field_112.blank? - - unless created_by - errors.add(:field_112, "User with the specified email could not be found") - end - end - - def validate_created_by_related - return unless created_by - - unless (created_by.organisation == owning_organisation) || (created_by.organisation == managing_organisation) - block_log_creation! - errors.add(:field_112, "User must be related to owning organisation or managing organisation") - end - end - - def created_by - @created_by ||= User.where("lower(email) = ?", field_112&.downcase).first - end - - def duplicate_check_fields - [ - "startdate", - "age1", - "sex1", - "ecstat1", - "owning_organisation", - "tcharge", - bulk_upload.needstype != 2 ? "postcode_full" : nil, - bulk_upload.needstype != 1 ? "location" : nil, - log.chcharge.present? ? "chcharge" : nil, - ].compact - end - - def location - return if scheme.nil? - - @location ||= scheme.locations.find_by_id_on_multiple_fields(field_5) - end - - def validate_related_location_exists - if scheme && field_5.present? && location.nil? - block_log_creation! - errors.add(:field_5, "Scheme code must relate to a scheme that is owned by the owning organisation or managing organisation", category: :setup) - end - end - - def validate_location_data_given - if bulk_upload.supported_housing? && field_5.blank? - block_log_creation! - errors.add(:field_5, I18n.t("validations.not_answered", question: "scheme code"), category: :setup) - end - end - - def validate_related_scheme_exists - if field_4.present? && owning_organisation.present? && managing_organisation.present? && scheme.nil? - block_log_creation! - errors.add(:field_4, "This management group code does not belong to the owning organisation or managing organisation", category: :setup) - end - end - - def validate_scheme_data_given - if bulk_upload.supported_housing? && field_4.blank? - block_log_creation! - errors.add(:field_4, I18n.t("validations.not_answered", question: "management group code"), category: :setup) - end - end - - def validate_managing_org_related - if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) - block_log_creation! - - if errors[:field_113].blank? - errors.add(:field_113, "This managing organisation does not have a relationship with the owning organisation", category: :setup) - end - end - end - - def validate_managing_org_exists - if managing_organisation.nil? - block_log_creation! - - if errors[:field_113].blank? - errors.add(:field_113, "The managing organisation code is incorrect", category: :setup) - end - end - end - - def validate_managing_org_data_given - if field_113.blank? - block_log_creation! - errors.add(:field_113, I18n.t("validations.not_answered", question: "managing organisation"), category: :setup) - end - end - - def validate_owning_org_owns_stock - if owning_organisation && !owning_organisation.holds_own_stock? - block_log_creation! - - if errors[:field_111].blank? - errors.add(:field_111, "The owning organisation code provided is for an organisation that does not own stock", category: :setup) - end - end - end - - def validate_owning_org_exists - if owning_organisation.nil? - block_log_creation! - - if errors[:field_111].blank? - errors.add(:field_111, "The owning organisation code is incorrect", category: :setup) - end - end - end - - def validate_owning_org_data_given - if field_111.blank? - block_log_creation! - - if errors[:field_111].blank? - errors.add(:field_111, I18n.t("validations.not_answered", question: "owning organisation"), category: :setup) - end - end - end - - def validate_owning_org_permitted - if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation) - block_log_creation! - - if errors[:field_111].blank? - errors.add(:field_111, "You do not have permission to add logs for this owning organisation", category: :setup) - end - end - end - - def validate_no_and_dont_know_disabled_needs_conjunction - if field_59 == 1 && field_60 == 1 - errors.add(:field_59, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) - errors.add(:field_60, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) - end - end - - def validate_dont_know_disabled_needs_conjunction - if field_60 == 1 && [field_55, field_56, field_57, field_58].count(1).positive? - %i[field_60 field_55 field_56 field_57 field_58].each do |field| - errors.add(field, I18n.t("validations.household.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1 - end - end - end - - def validate_no_disabled_needs_conjunction - if field_59 == 1 && [field_55, field_56, field_57, field_58].count(1).positive? - %i[field_59 field_55 field_56 field_57 field_58].each do |field| - errors.add(field, I18n.t("validations.household.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1 - end - end - end - - def validate_only_one_housing_needs_type - if [field_55, field_56, field_57].count(1) > 1 - %i[field_55 field_56 field_57].each do |field| - errors.add(field, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) if send(field) == 1 - end - end - end - - def validate_no_housing_needs_questions_answered - if [field_55, field_56, field_57, field_58, field_59, field_60].all?(&:blank?) - errors.add(:field_59, I18n.t("validations.not_answered", question: "anybody with disabled access needs")) - errors.add(:field_58, I18n.t("validations.not_answered", question: "other access needs")) - %i[field_55 field_56 field_57].each do |field| - errors.add(field, I18n.t("validations.not_answered", question: "disabled access needs type")) - end - end - end - - def validate_reasonable_preference_homeless - reason_fields = %i[field_70 field_71 field_72 field_73 field_74] - if field_69 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? } - reason_fields.each do |field| - errors.add(field, I18n.t("validations.not_answered", question: "reason for reasonable preference")) - end - end - end - - def validate_condition_effects - illness_option_fields = %i[field_119 field_120 field_121 field_122 field_123 field_124 field_125 field_126 field_127 field_128] - if household_no_illness? - illness_option_fields.each do |field| - if attributes[field.to_s] == 1 - errors.add(field, I18n.t("validations.household.condition_effects.no_choices")) - end - end - elsif illness_option_fields.all? { |field| attributes[field.to_s].blank? } - illness_option_fields.each do |field| - errors.add(field, I18n.t("validations.not_answered", question: "how is person affected by condition or illness")) - end - end - end - - def household_no_illness? - field_118 != 1 - end - - def validate_lettings_type_matches_bulk_upload - if [1, 3, 5, 7, 9, 11].include?(field_1) && !bulk_upload.general_needs? - errors.add(:field_1, I18n.t("validations.setup.lettype.supported_housing_mismatch")) - end - - if [2, 4, 6, 8, 10, 12].include?(field_1) && !bulk_upload.supported_housing? - errors.add(:field_1, I18n.t("validations.setup.lettype.general_needs_mismatch")) - end - end - - def validate_cannot_be_la_referral_if_general_needs_and_la - if field_78 == 4 && bulk_upload.general_needs? && owning_organisation && owning_organisation.la? - errors.add :field_78, I18n.t("validations.household.referral.la_general_needs.prp_referred_by_la") - end - end - - def validate_la_with_local_housing_referral - if field_78 == 3 && owning_organisation && owning_organisation.la? - errors.add(:field_78, I18n.t("validations.household.referral.nominated_by_local_ha_but_la")) - end - end - - def validate_leaving_reason_for_renewal - if field_134 == 1 && ![40, 42].include?(field_52) - errors.add(:field_52, I18n.t("validations.household.reason.renewal_reason_needed")) - end - end - - def validate_relevant_collection_window - return if start_date.blank? || bulk_upload.form.blank? - - unless bulk_upload.form.valid_start_date_for_form?(start_date) - errors.add(:field_96, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - errors.add(:field_97, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - errors.add(:field_98, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - end - end - - def start_date - return if field_98.blank? || field_97.blank? || field_96.blank? - - Date.parse("20#{field_98.to_s.rjust(2, '0')}-#{field_97}-#{field_96}") - rescue StandardError - nil - end - - def attribute_set - @attribute_set ||= instance_variable_get(:@attributes) - end - - def validate_data_types - unless attribute_set["field_1"].value_before_type_cast&.match?(/^\d+\.?0*$/) - errors.add(:field_1, I18n.t("validations.invalid_number", question: "letting type")) - end - end - - def validate_rent_type - if [9, 10, 11, 12].include?(field_1) && field_130.blank? - errors.add(:field_130, I18n.t("validations.not_answered", question: "intermediate rent type"), category: :setup) - elsif [5, 6, 7, 8].include?(field_1) && field_129.blank? - errors.add(:field_129, I18n.t("validations.not_answered", question: "affordable rent type"), category: :setup) - end - end - - def postcode_full - "#{field_108} #{field_109}" if field_108 && field_109 - end - - def postcode_known - if postcode_full.present? - 1 - elsif field_107.present? - 0 - end - end - - def questions - @questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) } - end - - def validate_nulls - field_mapping_for_errors.each do |error_key, fields| - question_id = error_key.to_s - question = questions.find { |q| q.id == question_id } - - next unless question - next if log.optional_fields.include?(question.id) - next if question.completed?(log) - - if setup_question?(question) - fields.each do |field| - if errors.select { |e| fields.include?(e.attribute) }.none? - errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label&.downcase), category: :setup) - end - end - else - fields.each do |field| - unless errors.any? { |e| fields.include?(e.attribute) } - errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label&.downcase)) - end - end - end - end - end - - def validate_incomplete_soft_validations - routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }.compact - routed_to_soft_validation_questions.each do |question| - next if question.completed?(log) - - question.page.interruption_screen_question_ids.each do |interruption_screen_question_id| - next if log.form.questions.none? { |q| q.id == interruption_screen_question_id && q.page.routed_to?(log, nil) } - - field_mapping_for_errors[interruption_screen_question_id.to_sym]&.each do |field| - if errors.none? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) } - error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(". ") - errors.add(field, message: error_message, category: :soft_validation) - end - end - end - end - end - - def setup_question?(question) - log.form.setup_sections[0].subsections[0].questions.include?(question) - end - - def validate_if_log_already_exists - if log_already_exists? - error_message = "This is a duplicate log" - - errors.add(:field_5, error_message) if bulk_upload.needstype != 1 # location - errors.add(:field_7, error_message) # tenancycode - errors.add(:field_12, error_message) # age1 - errors.add(:field_20, error_message) # sex1 - errors.add(:field_35, error_message) # ecstat1 - errors.add(:field_84, error_message) # tcharge - errors.add(:field_85, error_message) if log.chcharge.present? # chcharge - errors.add(:field_86, error_message) if bulk_upload.needstype != 1 # household_charge - errors.add(:field_96, error_message) # startdate - errors.add(:field_97, error_message) # startdate - errors.add(:field_98, error_message) # startdate - errors.add(:field_108, error_message) if bulk_upload.needstype != 2 # postcode_full - errors.add(:field_109, error_message) if bulk_upload.needstype != 2 # postcode_full - errors.add(:field_111, error_message) # owning_organisation - end - end - - def field_mapping_for_errors - { - lettype: [:field_1], - tenancycode: [:field_7], - postcode_known: %i[field_107 field_108 field_109], - postcode_full: %i[field_107 field_108 field_109], - la: %i[field_107], - owning_organisation: [:field_111], - managing_organisation: [:field_113], - owning_organisation_id: [:field_111], - managing_organisation_id: [:field_113], - renewal: [:field_134], - scheme: %i[field_4 field_5], - created_by: [:field_112], - needstype: [], - rent_type: %i[field_1 field_129 field_130], - startdate: %i[field_98 field_97 field_96], - unittype_gn: %i[field_102], - builtype: %i[field_103], - wchair: %i[field_104], - beds: %i[field_101], - joint: %i[field_133], - startertenancy: %i[field_8], - tenancy: %i[field_9], - tenancyother: %i[field_10], - tenancylength: %i[field_11], - declaration: %i[field_132], - - age1_known: %i[field_12], - age1: %i[field_12], - age2_known: %i[field_13], - age2: %i[field_13], - age3_known: %i[field_14], - age3: %i[field_14], - age4_known: %i[field_15], - age4: %i[field_15], - age5_known: %i[field_16], - age5: %i[field_16], - age6_known: %i[field_17], - age6: %i[field_17], - age7_known: %i[field_18], - age7: %i[field_18], - age8_known: %i[field_19], - age8: %i[field_19], - - sex1: %i[field_20], - sex2: %i[field_21], - sex3: %i[field_22], - sex4: %i[field_23], - sex5: %i[field_24], - sex6: %i[field_25], - sex7: %i[field_26], - sex8: %i[field_27], - - ethnic_group: %i[field_43], - ethnic: %i[field_43], - national: %i[field_44], - - relat2: %i[field_28], - relat3: %i[field_29], - relat4: %i[field_30], - relat5: %i[field_31], - relat6: %i[field_32], - relat7: %i[field_33], - relat8: %i[field_34], - - ecstat1: %i[field_35], - ecstat2: %i[field_36], - ecstat3: %i[field_37], - ecstat4: %i[field_38], - ecstat5: %i[field_39], - ecstat6: %i[field_40], - ecstat7: %i[field_41], - ecstat8: %i[field_42], - - armedforces: %i[field_45], - leftreg: %i[field_114], - reservist: %i[field_46], - - preg_occ: %i[field_47], - - housingneeds: %i[field_47], - - illness: %i[field_118], - - layear: %i[field_66], - waityear: %i[field_67], - reason: %i[field_52], - reasonother: %i[field_53], - prevten: %i[field_61], - homeless: %i[field_68], - - prevloc: %i[field_62], - previous_la_known: %i[field_62], - ppcodenk: %i[field_65], - ppostcode_full: %i[field_63 field_64], - - reasonpref: %i[field_69], - rp_homeless: %i[field_70], - rp_insan_unsat: %i[field_71], - rp_medwel: %i[field_72], - rp_hardship: %i[field_73], - rp_dontknow: %i[field_74], - - cbl: %i[field_75], - chr: %i[field_76], - cap: %i[field_77], - letting_allocation: %i[field_75 field_76 field_77], - - referral: %i[field_78], - - net_income_known: %i[field_51], - earnings: %i[field_50], - incfreq: %i[field_116], - hb: %i[field_48], - benefits: %i[field_49], - - period: %i[field_79], - brent: %i[field_80], - scharge: %i[field_81], - pscharge: %i[field_82], - supcharg: %i[field_83], - tcharge: %i[field_84], - chcharge: %i[field_85], - household_charge: %i[field_86], - hbrentshortfall: %i[field_87], - tshortfall: %i[field_88], - - unitletas: %i[field_105], - rsnvac: %i[field_106], - sheltered: %i[field_117], - - illness_type_1: %i[field_119], - illness_type_2: %i[field_120], - illness_type_3: %i[field_121], - illness_type_4: %i[field_122], - illness_type_5: %i[field_123], - illness_type_6: %i[field_124], - illness_type_7: %i[field_125], - illness_type_8: %i[field_126], - illness_type_9: %i[field_127], - illness_type_10: %i[field_128], - - irproduct_other: %i[field_131], - - offered: %i[field_99], - - propcode: %i[field_100], - - majorrepairs: %i[field_92 field_93 field_94], - mrcdate: %i[field_92 field_93 field_94], - - voiddate: %i[field_89 field_90 field_91], - is_carehome: %i[field_85], - } - end - - def renttype - case field_1 - when 1, 2, 3, 4 - :social - when 5, 6, 7, 8 - :affordable - when 9, 10, 11, 12 - :intermediate - end - end - - def rent_type - case renttype - when :social - LettingsLog::RENT_TYPE[:social_rent] - when :affordable - if field_129 == 1 - LettingsLog::RENT_TYPE[:london_affordable_rent] - else - LettingsLog::RENT_TYPE[:affordable_rent] - end - when :intermediate - case field_130 - when 1 - LettingsLog::RENT_TYPE[:rent_to_buy] - when 2 - LettingsLog::RENT_TYPE[:london_living_rent] - when 3 - LettingsLog::RENT_TYPE[:other_intermediate_rent_product] - end - end - end - - def owning_organisation - Organisation.find_by_id_on_multiple_fields(field_111) - end - - def managing_organisation - Organisation.find_by_id_on_multiple_fields(field_113) - end - - def attributes_for_log - attributes = {} - - attributes["lettype"] = field_1 - attributes["tenancycode"] = field_7 - attributes["la"] = field_107 - attributes["postcode_known"] = postcode_known - attributes["postcode_full"] = postcode_full - attributes["owning_organisation"] = owning_organisation - attributes["managing_organisation"] = managing_organisation - attributes["renewal"] = renewal - attributes["scheme"] = scheme - attributes["location"] = location - attributes["created_by"] = created_by || bulk_upload.user - attributes["needstype"] = bulk_upload.needstype - attributes["rent_type"] = rent_type - attributes["startdate"] = startdate - attributes["unittype_gn"] = field_102 - attributes["builtype"] = field_103 - attributes["wchair"] = field_104 - attributes["beds"] = field_101 - attributes["joint"] = field_133 - attributes["startertenancy"] = field_8 - attributes["tenancy"] = field_9 - attributes["tenancyother"] = field_10 - attributes["tenancylength"] = field_11 - attributes["declaration"] = field_132 - - attributes["age1_known"] = age1_known? - attributes["age1"] = field_12 if attributes["age1_known"].zero? && field_12&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age2_known"] = age2_known? - attributes["age2"] = field_13 if attributes["age2_known"].zero? && field_13&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age3_known"] = age3_known? - attributes["age3"] = field_14 if attributes["age3_known"].zero? && field_14&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age4_known"] = age4_known? - attributes["age4"] = field_15 if attributes["age4_known"].zero? && field_15&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age5_known"] = age5_known? - attributes["age5"] = field_16 if attributes["age5_known"].zero? && field_16&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age6_known"] = age6_known? - attributes["age6"] = field_17 if attributes["age6_known"].zero? && field_17&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age7_known"] = age7_known? - attributes["age7"] = field_18 if attributes["age7_known"].zero? && field_18&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age8_known"] = age8_known? - attributes["age8"] = field_19 if attributes["age8_known"].zero? && field_19&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["sex1"] = field_20 - attributes["sex2"] = field_21 - attributes["sex3"] = field_22 - attributes["sex4"] = field_23 - attributes["sex5"] = field_24 - attributes["sex6"] = field_25 - attributes["sex7"] = field_26 - attributes["sex8"] = field_27 - - attributes["ethnic_group"] = ethnic_group_from_ethnic - attributes["ethnic"] = field_43 - attributes["national"] = field_44 - - attributes["relat2"] = field_28 - attributes["relat3"] = field_29 - attributes["relat4"] = field_30 - attributes["relat5"] = field_31 - attributes["relat6"] = field_32 - attributes["relat7"] = field_33 - attributes["relat8"] = field_34 - - attributes["ecstat1"] = field_35 - attributes["ecstat2"] = field_36 - attributes["ecstat3"] = field_37 - attributes["ecstat4"] = field_38 - attributes["ecstat5"] = field_39 - attributes["ecstat6"] = field_40 - attributes["ecstat7"] = field_41 - attributes["ecstat8"] = field_42 - - attributes["details_known_2"] = details_known?(2) - attributes["details_known_3"] = details_known?(3) - attributes["details_known_4"] = details_known?(4) - attributes["details_known_5"] = details_known?(5) - attributes["details_known_6"] = details_known?(6) - attributes["details_known_7"] = details_known?(7) - attributes["details_known_8"] = details_known?(8) - - attributes["armedforces"] = field_45 - attributes["leftreg"] = leftreg - attributes["reservist"] = field_46 - - attributes["preg_occ"] = field_47 - - attributes["housingneeds"] = housingneeds - attributes["housingneeds_type"] = housingneeds_type - attributes["housingneeds_other"] = housingneeds_other - - attributes["illness"] = field_118 - - attributes["layear"] = field_66 - attributes["waityear"] = field_67 - attributes["reason"] = field_52 - attributes["reasonother"] = field_53 - attributes["prevten"] = field_61 - attributes["homeless"] = homeless - - attributes["prevloc"] = prevloc - attributes["previous_la_known"] = previous_la_known - attributes["ppcodenk"] = ppcodenk - attributes["ppostcode_full"] = ppostcode_full - - attributes["reasonpref"] = field_69 - attributes["rp_homeless"] = field_70 - attributes["rp_insan_unsat"] = field_71 - attributes["rp_medwel"] = field_72 - attributes["rp_hardship"] = field_73 - attributes["rp_dontknow"] = field_74 - - attributes["cbl"] = cbl - attributes["chr"] = chr - attributes["cap"] = cap - attributes["letting_allocation_unknown"] = letting_allocation_unknown - - attributes["referral"] = field_78 - - attributes["net_income_known"] = net_income_known - attributes["earnings"] = earnings - attributes["incfreq"] = field_116 - attributes["hb"] = field_48 - attributes["benefits"] = field_49 - - attributes["period"] = field_79 - attributes["brent"] = field_80 - attributes["scharge"] = field_81 - attributes["pscharge"] = field_82 - attributes["supcharg"] = field_83 - attributes["tcharge"] = field_84 - attributes["chcharge"] = field_85 - attributes["is_carehome"] = field_85.present? ? 1 : 0 - attributes["household_charge"] = field_86 - attributes["hbrentshortfall"] = field_87 - attributes["tshortfall_known"] = tshortfall_known - attributes["tshortfall"] = field_88 - - attributes["hhmemb"] = hhmemb - - attributes["unitletas"] = field_105 - attributes["rsnvac"] = rsnvac - attributes["sheltered"] = field_117 - - attributes["illness_type_1"] = field_119 - attributes["illness_type_2"] = field_120 - attributes["illness_type_3"] = field_121 - attributes["illness_type_4"] = field_122 - attributes["illness_type_5"] = field_123 - attributes["illness_type_6"] = field_124 - attributes["illness_type_7"] = field_125 - attributes["illness_type_8"] = field_126 - attributes["illness_type_9"] = field_127 - attributes["illness_type_10"] = field_128 - - attributes["irproduct_other"] = field_131 - - attributes["offered"] = field_99 - - attributes["propcode"] = field_100 - - attributes["majorrepairs"] = majorrepairs - - attributes["mrcdate"] = mrcdate - - attributes["voiddate"] = voiddate - - attributes["first_time_property_let_as_social_housing"] = first_time_property_let_as_social_housing - - attributes - end - - def first_time_property_let_as_social_housing - case rsnvac - when 15, 16, 17 - 1 - else - 0 - end - end - - def rsnvac - field_106 - end - - def voiddate - Date.new(field_91 + 2000, field_90, field_89) if field_91.present? && field_90.present? && field_89.present? - rescue Date::Error - Date.new - end - - def majorrepairs - mrcdate.present? ? 1 : 0 - end - - def mrcdate - Date.new(field_94 + 2000, field_93, field_92) if field_94.present? && field_93.present? && field_92.present? - rescue Date::Error - Date.new - end - - def prevloc - field_62 - end - - def previous_la_known - prevloc.present? ? 1 : 0 - end - - def ppcodenk - case field_65 - when 1 - 0 - when 2 - 1 - end - end - - def earnings - field_50.round if field_50.present? - end - - def net_income_known - case field_51 - when 1 - 0 - when 2 - 1 - when 3 - 1 - when 4 - 2 - end - end - - def leftreg - field_114 - end - - def homeless - case field_68 - when 1 - 1 - when 12 - 11 - end - end - - def renewal - case field_134 - when 1 - 1 - when 2 - 0 - when nil - rsnvac == 14 ? 1 : 0 - else - field_134 - end - end - - def age1_known? - return 1 if field_12 == "R" - return 1 if field_12.blank? - - 0 - end - - [ - { person: 2, field: :field_13 }, - { person: 3, field: :field_14 }, - { person: 4, field: :field_15 }, - { person: 5, field: :field_16 }, - { person: 6, field: :field_17 }, - { person: 7, field: :field_18 }, - { person: 8, field: :field_19 }, - ].each do |hash| - define_method("age#{hash[:person]}_known?") do - return 1 if public_send(hash[:field]) == "R" - return 0 if send("person_#{hash[:person]}_present?") - return 1 if public_send(hash[:field]).blank? - - 0 - end - end - - def details_known?(person_n) - send("person_#{person_n}_present?") ? 0 : 1 - end - - def hhmemb - [ - person_2_present?, - person_3_present?, - person_4_present?, - person_5_present?, - person_6_present?, - person_7_present?, - person_8_present?, - ].count(true) + 1 - end - - def person_2_present? - field_13.present? || field_21.present? || field_28.present? - end - - def person_3_present? - field_14.present? || field_22.present? || field_29.present? - end - - def person_4_present? - field_15.present? || field_23.present? || field_30.present? - end - - def person_5_present? - field_16.present? || field_24.present? || field_31.present? - end - - def person_6_present? - field_17.present? || field_25.present? || field_32.present? - end - - def person_7_present? - field_18.present? || field_26.present? || field_33.present? - end - - def person_8_present? - field_19.present? || field_27.present? || field_34.present? - end - - def tshortfall_known - field_87 == 1 ? 0 : 1 - end - - def letting_allocation_unknown - [cbl, chr, cap].all?(0) ? 1 : 0 - end - - def cbl - case field_75 - when 2 - 0 - when 1 - 1 - end - end - - def chr - case field_76 - when 2 - 0 - when 1 - 1 - end - end - - def cap - case field_77 - when 2 - 0 - when 1 - 1 - end - end - - def ppostcode_full - "#{field_63} #{field_64}".strip.gsub(/\s+/, " ") - end - - def housingneeds - if field_59 == 1 - 2 - elsif field_60 == 1 - 3 - elsif field_59.blank? || field_59&.zero? - 1 - end - end - - def housingneeds_type - if field_55 == 1 - 0 - elsif field_56 == 1 - 1 - elsif field_57 == 1 - 2 - else - 3 - end - end - - def housingneeds_other - return 1 if field_58 == 1 - return 0 if [field_55, field_56, field_57].include?(1) - end - - def ethnic_group_from_ethnic - return nil if field_43.blank? - - case field_43 - when 1, 2, 3, 18 - 0 - when 4, 5, 6, 7 - 1 - when 8, 9, 10, 11, 15 - 2 - when 12, 13, 14 - 3 - when 16, 19 - 4 - when 17 - 17 - end - end - - def scheme - return if field_4.nil? || owning_organisation.nil? || managing_organisation.nil? - - @scheme ||= Scheme.where(id: (owning_organisation.owned_schemes + managing_organisation.owned_schemes).map(&:id)).find_by_id_on_multiple_fields(field_4, field_5) - end -end diff --git a/app/services/bulk_upload/sales/log_creator.rb b/app/services/bulk_upload/sales/log_creator.rb index 3028914b9..1036ac8ff 100644 --- a/app/services/bulk_upload/sales/log_creator.rb +++ b/app/services/bulk_upload/sales/log_creator.rb @@ -31,8 +31,6 @@ private def csv_parser @csv_parser ||= case bulk_upload.year - when 2022 - BulkUpload::Sales::Year2022::CsvParser.new(path:) when 2023 BulkUpload::Sales::Year2023::CsvParser.new(path:) else diff --git a/app/services/bulk_upload/sales/validator.rb b/app/services/bulk_upload/sales/validator.rb index aaee69849..1a3234911 100644 --- a/app/services/bulk_upload/sales/validator.rb +++ b/app/services/bulk_upload/sales/validator.rb @@ -92,8 +92,6 @@ private def csv_parser @csv_parser ||= case bulk_upload.year - when 2022 - BulkUpload::Sales::Year2022::CsvParser.new(path:) when 2023 BulkUpload::Sales::Year2023::CsvParser.new(path:) else diff --git a/app/services/bulk_upload/sales/year2022/csv_parser.rb b/app/services/bulk_upload/sales/year2022/csv_parser.rb deleted file mode 100644 index d14284f50..000000000 --- a/app/services/bulk_upload/sales/year2022/csv_parser.rb +++ /dev/null @@ -1,83 +0,0 @@ -require "csv" - -class BulkUpload::Sales::Year2022::CsvParser - MAX_COLUMNS = 126 - FORM_YEAR = 2022 - - attr_reader :path - - def initialize(path:) - @path = path - end - - def row_offset - with_headers? ? 5 : 0 - end - - def col_offset - with_headers? ? 1 : 0 - end - - def cols - @cols ||= ("A".."DV").to_a - end - - def row_parsers - @row_parsers ||= body_rows.map do |row| - stripped_row = row[col_offset..] - headers = ("field_1".."field_125").to_a - hash = Hash[headers.zip(stripped_row)] - - BulkUpload::Sales::Year2022::RowParser.new(hash) - end - end - - def body_rows - rows[row_offset..] - end - - def rows - @rows ||= CSV.parse(normalised_string, row_sep:) - end - - def column_for_field(field) - cols[headers.find_index(field) + col_offset] - end - - def wrong_template_for_year? - !(first_record_sale_date >= form.start_date && first_record_sale_date <= form.new_logs_end_date) - end - -private - - def form - @form ||= FormHandler.instance.sales_form_for_start_year(FORM_YEAR) - end - - def first_record_sale_date - @first_record_sale_date ||= row_parsers.first.saledate || Date.new - end - - def headers - @headers ||= ("field_1".."field_125").to_a - end - - def with_headers? - rows.map { |r| r[0] }.any? { |cell| cell&.match?(/field number/i) } - end - - def row_sep - "\n" - end - - def normalised_string - return @normalised_string if @normalised_string - - @normalised_string = File.read(path, encoding: "bom|utf-8") - @normalised_string.gsub!("\r\n", "\n") - @normalised_string.scrub!("") - @normalised_string.tr!("\r", "\n") - - @normalised_string - end -end diff --git a/app/services/bulk_upload/sales/year2022/row_parser.rb b/app/services/bulk_upload/sales/year2022/row_parser.rb deleted file mode 100644 index 603860bcf..000000000 --- a/app/services/bulk_upload/sales/year2022/row_parser.rb +++ /dev/null @@ -1,1156 +0,0 @@ -class BulkUpload::Sales::Year2022::RowParser - include ActiveModel::Model - include ActiveModel::Attributes - include InterruptionScreenHelper - - QUESTIONS = { - field_1: "What is the purchaser code?", - field_2: "What is the day of the sale completion date? - DD", - field_3: "What is the month of the sale completion date? - MM", - field_4: "What is the year of the sale completion date? - YY", - field_5: "This question has been removed", - field_6: "Was the buyer interviewed for any of the answers you will provide on this log?", - field_7: "Age of buyer 1", - field_8: "Age of person 2", - field_9: "Age of person 3", - field_10: "Age of person 4", - field_11: "Age of person 5", - field_12: "Age of person 6", - field_13: "Gender identity of buyer 1", - field_14: "Gender identity of person 2", - field_15: "Gender identity of person 3", - field_16: "Gender identity of person 4", - field_17: "Gender identity of person 5", - field_18: "Gender identity of person 6", - field_19: "Relationship to buyer 1 for person 2", - field_20: "Relationship to buyer 1 for person 3", - field_21: "Relationship to buyer 1 for person 4", - field_22: "Relationship to buyer 1 for person 5", - field_23: "Relationship to buyer 1 for person 6", - field_24: "Working situation of buyer 1", - field_25: "Working situation of person 2", - field_26: "Working situation of person 3", - field_27: "Working situation of person 4", - field_28: "Working situation of person 5", - field_29: "Working situation of person 6", - field_30: "What is buyer 1's ethnic group?", - field_31: "What is buyer 1's nationality?", - field_32: "What is buyer 1's gross annual income?", - field_33: "What is buyer 2's gross annual income?", - field_34: "Was buyer 1's income used for a mortgage application?", - field_35: "Was buyer 2's income used for a mortgage application?", - field_36: "What is the total amount the buyers had in savings before they paid any deposit for the property?", - field_37: "Have any of the purchasers previously owned a property?", - field_38: "This question has been removed", - field_39: "What was buyer 1's previous tenure?", - field_40: "What is the local authority of buyer 1's last settled home?", - field_41: "Part 1 of postcode of buyer 1's last settled home", - field_42: "Part 2 of postcode of buyer 1's last settled home", - field_43: "Do you know the postcode of buyer 1's last settled home?", - field_44: "Was the buyer registered with their PRP (HA)?", - field_45: "Was the buyer registered with the local authority?", - field_46: "Was the buyer registered with a Help to Buy agent?", - field_47: "Was the buyer registered with another PRP (HA)?", - field_48: "Does anyone in the household consider themselves to have a disability?", - field_49: "Does anyone in the household use a wheelchair?", - field_50: "How many bedrooms does the property have?", - field_51: "What type of unit is the property?", - field_52: "Which type of bulding is the property?", - field_53: "What is the local authority of the property?", - field_54: "Part 1 of postcode of property", - field_55: "Part 2 of postcode of property", - field_56: "Is the property built or adapted to wheelchair user standards?", - field_57: "What is the type of shared ownership sale?", - field_58: "Is this a resale?", - field_59: "What is the day of the practical completion or handover date?", - field_60: "What is the month of the practical completion or handover date?", - field_61: "What is the year of the practical completion or handover date?", - field_62: "What is the day of the exchange of contracts date?", - field_63: "What is the month of the exchange of contracts date?", - field_64: "What is the year of the exchange of contracts date?", - field_65: "Was the household re-housed under a local authority nominations agreement?", - field_66: "How many bedrooms did the buyer's previous property have?", - field_67: "What was the type of the buyer's previous property?", - field_68: "What was the full purchase price?", - field_69: "What was the initial percentage equity stake purchased?", - field_70: "What is the mortgage amount?", - field_71: "Does this include any extra borrowing?", - field_72: "How much was the cash deposit paid on the property?", - field_73: "How much cash discount was given through Social Homebuy?", - field_74: "What is the basic monthly rent?", - field_75: "What are the total monthly leasehold charges for the property?", - field_76: "What is the type of discounted ownership sale?", - field_77: "What was the full purchase price?", - field_78: "What was the amount of any loan, grant, discount or subsidy given?", - field_79: "What was the percentage discount?", - field_80: "What is the mortgage amount?", - field_81: "Does this include any extra borrowing?", - field_82: "How much was the cash deposit paid on the property?", - field_83: "What are the total monthly leasehold charges for the property?", - field_84: "What is the type of outright sale?", - field_85: "If 'other', what is the 'other' type?", - field_86: "This question has been removed", - field_87: "What is the full purchase price?", - field_88: "What is the mortgage amount?", - field_89: "Does this include any extra borrowing?", - field_90: "How much was the cash deposit paid on the property?", - field_91: "What are the total monthly leasehold charges for the property?", - field_92: "Which organisation owned this property before the sale?", - field_93: "Username", - field_94: "This question has been removed", - field_95: "Has the buyer ever served in the UK Armed Forces and for how long?", - field_96: "This question has been removed", - field_97: "Are any of the buyers a spouse or civil partner of a UK Armed Forces regular who died in service within the last 2 years?", - field_98: "What is the name of the mortgage lender? - Shared ownership", - field_99: "If 'other', what is the name of the mortgage lender?", - field_100: "What is the name of the mortgage lender? - Discounted ownership", - field_101: "If 'other', what is the name of the mortgage lender?", - field_102: "What is the name of the mortgage lender? - Outright sale", - field_103: "If 'other', what is the name of the mortgage lender?", - field_104: "Were the buyers receiving any of these housing-related benefits immediately before buying this property?", - field_105: "What is the length of the mortgage in years? - Shared ownership", - field_106: "What is the length of the mortgage in years? - Discounted ownership", - field_107: "What is the length of the mortgage in years? - Outright sale", - field_108: "How long have the buyers been living in the property before the purchase? - Discounted ownership", - field_109: "Are there more than two joint purchasers of this property?", - field_110: "How long have the buyers been living in the property before the purchase? - Shared ownership", - field_111: "Is this a staircasing transaction?", - field_112: "Data Protection question", - field_113: "Was this purchase made through an ownership scheme?", - field_114: "Is the buyer a company?", - field_115: "Will the buyers live in the property?", - field_116: "Is this a joint purchase?", - field_117: "Will buyer 1 live in the property?", - field_118: "Will buyer 2 live in the property?", - field_119: "Besides the buyers, how many people will live in the property?", - field_120: "What percentage of the property has been bought in this staircasing transaction?", - field_121: "What percentage of the property does the buyer now own in total?", - field_122: "What was the rent type of the buyer's previous property?", - field_123: "Was a mortgage used for the purchase of this property? - Shared ownership", - field_124: "Was a mortgage used for the purchase of this property? - Discounted ownership", - field_125: "Was a mortgage used for the purchase of this property? - Outright sale", - }.freeze - - attribute :bulk_upload - attribute :block_log_creation, :boolean, default: -> { false } - - attribute :field_1, :string - attribute :field_2, :integer - attribute :field_3, :integer - attribute :field_4, :integer - attribute :field_5 - attribute :field_6, :integer - attribute :field_7, :string - attribute :field_8, :string - attribute :field_9, :string - attribute :field_10, :string - attribute :field_11, :string - attribute :field_12, :string - attribute :field_13, :string - attribute :field_14, :string - attribute :field_15, :string - attribute :field_16, :string - attribute :field_17, :string - attribute :field_18, :string - attribute :field_19, :string - attribute :field_20, :string - attribute :field_21, :string - attribute :field_22, :string - attribute :field_23, :string - attribute :field_24, :integer - attribute :field_25, :integer - attribute :field_26, :integer - attribute :field_27, :integer - attribute :field_28, :integer - attribute :field_29, :integer - attribute :field_30, :integer - attribute :field_31, :integer - attribute :field_32, :integer - attribute :field_33, :integer - attribute :field_34, :integer - attribute :field_35, :integer - attribute :field_36, :integer - attribute :field_37, :integer - attribute :field_38 - attribute :field_39, :integer - attribute :field_40, :string - attribute :field_41, :string - attribute :field_42, :string - attribute :field_43, :integer - attribute :field_44, :integer - attribute :field_45, :integer - attribute :field_46, :integer - attribute :field_47, :integer - attribute :field_48, :integer - attribute :field_49, :integer - attribute :field_50, :integer - attribute :field_51, :integer - attribute :field_52, :integer - attribute :field_53, :string - attribute :field_54, :string - attribute :field_55, :string - attribute :field_56, :integer - attribute :field_57, :integer - attribute :field_58, :integer - attribute :field_59, :integer - attribute :field_60, :integer - attribute :field_61, :integer - attribute :field_62, :integer - attribute :field_63, :integer - attribute :field_64, :integer - attribute :field_65, :integer - attribute :field_66, :integer - attribute :field_67, :integer - attribute :field_68, :integer - attribute :field_69, :integer - attribute :field_70, :integer - attribute :field_71, :integer - attribute :field_72, :integer - attribute :field_73, :integer - attribute :field_74, :decimal - attribute :field_75, :decimal - attribute :field_76, :integer - attribute :field_77, :integer - attribute :field_78, :integer - attribute :field_79, :integer - attribute :field_80, :integer - attribute :field_81, :integer - attribute :field_82, :integer - attribute :field_83, :integer - attribute :field_84, :integer - attribute :field_85, :string - attribute :field_86 - attribute :field_87, :integer - attribute :field_88, :integer - attribute :field_89, :integer - attribute :field_90, :integer - attribute :field_91, :integer - attribute :field_92, :string - attribute :field_93, :string - attribute :field_94 - attribute :field_95, :integer - attribute :field_96 - attribute :field_97, :integer - attribute :field_98, :integer - attribute :field_99, :string - attribute :field_100, :integer - attribute :field_101, :string - attribute :field_102, :integer - attribute :field_103, :string - attribute :field_104, :integer - attribute :field_105, :integer - attribute :field_106, :integer - attribute :field_107, :integer - attribute :field_108, :integer - attribute :field_109, :integer - attribute :field_110, :integer - attribute :field_111, :integer - attribute :field_112, :integer - attribute :field_113, :integer - attribute :field_114, :integer - attribute :field_115, :integer - attribute :field_116, :integer - attribute :field_117, :integer - attribute :field_118, :integer - attribute :field_119, :integer - attribute :field_120, :integer - attribute :field_121, :integer - attribute :field_122, :integer - attribute :field_123, :integer - attribute :field_124, :integer - attribute :field_125, :integer - - validates :field_2, presence: { message: I18n.t("validations.not_answered", question: "sale completion date (day)"), category: :setup }, on: :after_log - validates :field_3, presence: { message: I18n.t("validations.not_answered", question: "sale completion date (month)"), category: :setup }, on: :after_log - validates :field_4, presence: { message: I18n.t("validations.not_answered", question: "sale completion date (year)"), category: :setup }, on: :after_log - validates :field_4, format: { with: /\A\d{2}\z/, message: I18n.t("validations.setup.saledate.year_not_two_digits") }, on: :after_log - - validates :field_57, - inclusion: { - in: [2, 16, 18, 24, 28, 30, 31], - category: :setup, - question: QUESTIONS[:field_57].downcase, - }, - if: proc { field_57.present? && shared_ownership? }, - on: :before_log - - validates :field_57, - presence: { - message: I18n.t("validations.not_answered", question: "type of shared ownership sale"), - category: :setup, - }, - if: :shared_ownership?, - on: :after_log - - validates :field_76, - inclusion: { - in: [8, 14, 27, 9, 29, 21, 22], - category: :setup, - question: QUESTIONS[:field_76].downcase, - }, - if: proc { field_76.present? && discounted_ownership? }, - on: :before_log - - validates :field_76, - presence: { - message: I18n.t("validations.not_answered", question: "type of discounted ownership sale"), - category: :setup, - }, - if: :discounted_ownership?, - on: :after_log - - validates :field_84, - inclusion: { - in: [10, 12], - category: :setup, - question: QUESTIONS[:field_84].downcase, - }, - if: proc { field_84.present? && outright_sale? }, - on: :before_log - - validates :field_84, - presence: { - message: I18n.t("validations.not_answered", question: "type of outright sale"), - category: :setup, - }, - if: :outright_sale?, - on: :after_log - - validates :field_85, - presence: { - message: I18n.t("validations.not_answered", question: "type of outright sale"), - category: :setup, - }, - if: proc { field_84 == 12 }, - on: :after_log - - validates :field_68, - presence: { - message: I18n.t("validations.not_answered", question: "What was the full purchase price?"), - }, - if: :shared_ownership?, - on: :after_log - - validates :field_77, - presence: { - message: I18n.t("validations.not_answered", question: "What was the full purchase price?"), - }, - if: :discounted_ownership?, - on: :after_log - - validates :field_87, - presence: { - message: I18n.t("validations.not_answered", question: "What was the full purchase price?"), - }, - if: :outright_sale?, - on: :after_log - - validates :field_109, presence: { message: I18n.t("validations.not_answered", question: "more than 2 joint buyers"), category: :setup }, if: :joint_purchase?, on: :after_log - - validates :field_113, presence: { message: I18n.t("validations.not_answered", question: "purchase made under ownership scheme"), category: :setup }, on: :after_log - - validates :field_114, presence: { message: I18n.t("validations.not_answered", question: "company buyer"), category: :setup }, if: :outright_sale?, on: :after_log - - validates :field_115, presence: { message: I18n.t("validations.not_answered", question: "buyers living in property"), category: :setup }, if: :outright_sale?, on: :after_log - - validates :field_116, presence: { message: I18n.t("validations.not_answered", question: "joint purchase"), category: :setup }, if: :joint_purchase_asked?, on: :after_log - - validate :validate_buyer1_economic_status, on: :before_log - validate :validate_nulls, on: :after_log - validate :validate_valid_radio_option, on: :before_log - - validate :validate_owning_org_data_given, on: :after_log - validate :validate_owning_org_exists, on: :after_log - validate :validate_owning_org_permitted, on: :after_log - - validate :validate_created_by_exists, on: :after_log - validate :validate_created_by_related, on: :after_log - validate :validate_relevant_collection_window, on: :after_log - validate :validate_incomplete_soft_validations, on: :after_log - validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? } - - validate :validate_data_protection_answered, on: :after_log - validate :validate_buyers_organisations, on: :after_log - - def self.question_for_field(field) - QUESTIONS[field] - end - - def attribute_set - @attribute_set ||= instance_variable_get(:@attributes) - end - - def blank_row? - attribute_set - .to_hash - .reject { |k, _| %w[bulk_upload block_log_creation].include?(k) } - .values - .compact - .empty? - end - - def log - @log ||= SalesLog.new(attributes_for_log) - end - - def valid? - errors.clear - - return true if blank_row? - - super(:before_log) - before_errors = errors.dup - - log.valid? - - super(:after_log) - errors.merge!(before_errors) - - log.errors.each do |error| - fields = field_mapping_for_errors[error.attribute] || [] - - fields.each do |field| - unless errors.include?(field) - errors.add(field, error.message) - end - end - end - - errors.blank? - end - - def block_log_creation? - block_log_creation - end - - def log_already_exists? - @log_already_exists ||= SalesLog - .where(status: %w[not_started in_progress completed]) - .exists?(duplicate_check_fields.index_with { |field| log.public_send(field) }) - end - - def purchaser_code - field_1 - end - - def spreadsheet_duplicate_hash - attributes.slice( - "field_1", # purcahser code - "field_2", # saledate - "field_3", # saledate - "field_4", # saledate - "field_7", # age1 - "field_13", # sex1 - "field_24", # ecstat1 - "field_54", # postcode - "field_55", # postcode - "field_92", # owning org - ) - end - - def add_duplicate_found_in_spreadsheet_errors - spreadsheet_duplicate_hash.each_key do |field| - errors.add(field, :spreadsheet_dupe, category: :setup) - end - end - - def saledate - Date.new(field_4 + 2000, field_3, field_2) if field_2.present? && field_3.present? && field_4.present? - rescue Date::Error - Date.new - end - -private - - def validate_data_protection_answered - unless field_112 == 1 - errors.add(:field_112, I18n.t("validations.not_answered", question: QUESTIONS[:field_112].downcase), category: :setup) - end - end - - def validate_buyers_organisations - organisations_fields = %i[field_44 field_45 field_46 field_47] - if organisations_fields.all? { |field| attributes[field.to_s].blank? } - organisations_fields.each do |field| - errors.add(field, "At least one option must be selected of these four") - end - end - end - - def buyer_not_interviewed? - field_6 == 1 - end - - def shared_ownership? - field_113 == 1 - end - - def discounted_ownership? - field_113 == 2 - end - - def outright_sale? - field_113 == 3 - end - - def joint_purchase? - field_116 == 1 - end - - def joint_purchase_asked? - shared_ownership? || discounted_ownership? || field_114 == 2 - end - - def field_mapping_for_errors - { - purchid: %i[field_1], - saledate: %i[field_2 field_3 field_4], - noint: %i[field_6], - age1_known: %i[field_7], - age1: %i[field_7], - age2_known: %i[field_8], - age2: %i[field_8], - age3_known: %i[field_9], - age3: %i[field_9], - age4_known: %i[field_10], - age4: %i[field_10], - age5_known: %i[field_11], - age5: %i[field_11], - age6_known: %i[field_12], - age6: %i[field_12], - sex1: %i[field_13], - sex2: %i[field_14], - sex3: %i[field_15], - sex4: %i[field_16], - sex5: %i[field_17], - sex6: %i[field_18], - relat2: %i[field_19], - relat3: %i[field_20], - relat4: %i[field_21], - relat5: %i[field_22], - relat6: %i[field_23], - ecstat1: %i[field_24], - ecstat2: %i[field_25], - ecstat3: %i[field_26], - ecstat4: %i[field_27], - ecstat5: %i[field_28], - ecstat6: %i[field_29], - ethnic_group: %i[field_30], - ethnic: %i[field_30], - national: %i[field_31], - income1nk: %i[field_32], - income1: %i[field_32], - income2nk: %i[field_33], - income2: %i[field_33], - inc1mort: %i[field_34], - inc2mort: %i[field_35], - savingsnk: %i[field_36], - savings: %i[field_36], - prevown: %i[field_37], - prevten: %i[field_39], - prevloc: %i[field_40], - previous_la_known: %i[field_40], - ppcodenk: %i[field_43], - ppostcode_full: %i[field_41 field_42], - pregyrha: %i[field_44], - pregla: %i[field_45], - pregghb: %i[field_46], - pregother: %i[field_47], - disabled: %i[field_48], - wheel: %i[field_49], - beds: %i[field_50], - proptype: %i[field_51], - builtype: %i[field_52], - la_known: %i[field_53], - la: %i[field_53], - is_la_inferred: %i[field_53], - pcodenk: %i[field_54 field_55], - postcode_full: %i[field_54 field_55], - wchair: %i[field_56], - type: %i[field_57 field_76 field_84 field_113], - resale: %i[field_58], - hodate: %i[field_59 field_60 field_61], - exdate: %i[field_62 field_63 field_64], - lanomagr: %i[field_65], - frombeds: %i[field_66], - fromprop: %i[field_67], - equity: %i[field_69], - mortgage: %i[field_70 field_80 field_88], - extrabor: %i[field_71 field_81 field_89], - deposit: %i[field_72 field_82 field_90], - cashdis: %i[field_73], - mrent: %i[field_74], - has_mscharge: %i[field_75 field_83 field_91], - mscharge: %i[field_75 field_83 field_91], - grant: %i[field_78], - discount: %i[field_79], - othtype: %i[field_85], - owning_organisation_id: %i[field_92], - created_by: %i[field_93], - hhregres: %i[field_95], - hhregresstill: %i[field_95], - armedforcesspouse: %i[field_97], - mortgagelender: %i[field_98 field_100 field_102], - mortgagelenderother: %i[field_99 field_101 field_103], - hb: %i[field_104], - mortlen: %i[field_105 field_106 field_107], - proplen: %i[field_108 field_110], - jointmore: %i[field_109], - staircase: %i[field_111], - privacynotice: %i[field_112], - ownershipsch: %i[field_113], - companybuy: %i[field_114], - buylivein: %i[field_115], - jointpur: %i[field_116], - buy1livein: %i[field_117], - buy2livein: %i[field_118], - hholdcount: %i[field_119], - stairbought: %i[field_120], - stairowned: %i[field_121], - socprevten: %i[field_122], - mortgageused: %i[field_123 field_124 field_125], - soctenant: %i[field_39 field_113], - uprn: %i[], - } - end - - def attributes_for_log - attributes = {} - attributes["purchid"] = purchaser_code - attributes["saledate"] = saledate - - attributes["noint"] = field_6 - - attributes["details_known_2"] = details_known?(2) - attributes["details_known_3"] = details_known?(3) - attributes["details_known_4"] = details_known?(4) - attributes["details_known_5"] = details_known?(5) - attributes["details_known_6"] = details_known?(6) - - attributes["age1_known"] = age1_known? - attributes["age1"] = field_7 if attributes["age1_known"].zero? && field_7&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age2_known"] = age2_known? - attributes["age2"] = field_8 if attributes["age2_known"].zero? && field_8&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age3_known"] = age3_known? - attributes["age3"] = field_9 if attributes["age3_known"].zero? && field_9&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age4_known"] = age4_known? - attributes["age4"] = field_10 if attributes["age4_known"].zero? && field_10&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age5_known"] = age5_known? - attributes["age5"] = field_11 if attributes["age5_known"].zero? && field_11&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["age6_known"] = age6_known? - attributes["age6"] = field_12 if attributes["age6_known"].zero? && field_12&.match(/\A\d{1,3}\z|\AR\z/) - - attributes["sex1"] = field_13 - attributes["sex2"] = field_14 - attributes["sex3"] = field_15 - attributes["sex4"] = field_16 - attributes["sex5"] = field_17 - attributes["sex6"] = field_18 - - attributes["relat2"] = field_19 - attributes["relat3"] = field_20 - attributes["relat4"] = field_21 - attributes["relat5"] = field_22 - attributes["relat6"] = field_23 - - attributes["ecstat1"] = buyer_not_interviewed? && field_24.blank? ? 10 : field_24 - attributes["ecstat2"] = field_25 - attributes["ecstat3"] = field_26 - attributes["ecstat4"] = field_27 - attributes["ecstat5"] = field_28 - attributes["ecstat6"] = field_29 - - attributes["ethnic_group"] = ethnic_group_from_ethnic - attributes["ethnic"] = field_30 - attributes["national"] = buyer_not_interviewed? && field_31.blank? ? 13 : field_31 - attributes["income1nk"] = income1nk - attributes["income1"] = field_32 - attributes["income2nk"] = field_33.present? ? 0 : 1 - attributes["income2"] = field_33 - attributes["inc1mort"] = buyer_not_interviewed? && field_32.blank? ? 2 : field_34 - attributes["inc2mort"] = field_35 - attributes["savingsnk"] = savingsnk - attributes["savings"] = field_36 - attributes["prevown"] = buyer_not_interviewed? && field_37.blank? ? 3 : field_37 - - attributes["prevten"] = buyer_not_interviewed? && field_39.blank? ? 0 : field_39 - attributes["prevloc"] = field_40 - attributes["previous_la_known"] = previous_la_known - attributes["ppcodenk"] = previous_postcode_known - attributes["ppostcode_full"] = ppostcode_full - - attributes["pregyrha"] = field_44 - attributes["pregla"] = field_45 - attributes["pregghb"] = field_46 - attributes["pregother"] = field_47 - - attributes["disabled"] = buyer_not_interviewed? && field_48.blank? ? 3 : field_48 - attributes["wheel"] = buyer_not_interviewed? && field_49.blank? ? 3 : field_49 - attributes["beds"] = field_50 - attributes["proptype"] = field_51 - attributes["builtype"] = field_52 - attributes["la_known"] = field_53.present? ? 1 : 0 - attributes["la"] = field_53 - attributes["is_la_inferred"] = false - attributes["pcodenk"] = 0 if postcode_full.present? - attributes["postcode_full"] = postcode_full - attributes["wchair"] = field_56 - - attributes["type"] = sale_type - - attributes["resale"] = field_58 - - attributes["hodate"] = hodate - attributes["exdate"] = exdate - - attributes["lanomagr"] = field_65 - - attributes["frombeds"] = field_66 - attributes["fromprop"] = field_67 - - attributes["value"] = value - attributes["equity"] = field_69 - attributes["mortgage"] = mortgage - attributes["extrabor"] = extrabor - attributes["deposit"] = deposit - attributes["cashdis"] = field_73 - attributes["mrent"] = field_74 - attributes["mscharge"] = mscharge if mscharge&.positive? - attributes["has_mscharge"] = attributes["mscharge"].present? ? 1 : 0 - attributes["grant"] = field_78 - attributes["discount"] = field_79 - - attributes["othtype"] = field_85 - - attributes["owning_organisation"] = owning_organisation - attributes["managing_organisation"] = owning_organisation - attributes["created_by"] = created_by || bulk_upload.user - attributes["hhregres"] = hhregres - attributes["hhregresstill"] = hhregresstill - attributes["armedforcesspouse"] = field_97 - - attributes["mortgagelender"] = mortgagelender - attributes["mortgagelenderother"] = mortgagelenderother - - attributes["hb"] = field_104 - - attributes["mortlen"] = mortlen - - attributes["proplen"] = proplen - attributes["jointmore"] = field_109 - attributes["staircase"] = field_111 - attributes["privacynotice"] = field_112 - attributes["ownershipsch"] = field_113 - attributes["companybuy"] = field_114 - attributes["buylivein"] = field_115 - attributes["jointpur"] = field_116 - attributes["buy1livein"] = field_117 - attributes["buy2livein"] = field_118 - attributes["hholdcount"] = field_119 - attributes["stairbought"] = field_120 - attributes["stairowned"] = field_121 - attributes["socprevten"] = field_122 - attributes["mortgageused"] = mortgageused - attributes["soctenant"] = soctenant - - attributes - end - - def income1nk - if field_32.present? - 0 - else - buyer_not_interviewed? ? 1 : nil - end - end - - def savingsnk - if field_36.present? - 0 - else - buyer_not_interviewed? ? 1 : nil - end - end - - def hodate - Date.new(field_61 + 2000, field_60, field_59) if field_59.present? && field_60.present? && field_61.present? - rescue Date::Error - Date.new - end - - def exdate - Date.new(field_64 + 2000, field_63, field_62) if field_62.present? && field_63.present? && field_64.present? - rescue Date::Error - Date.new - end - - def age1_known? - return 1 if field_7 == "R" - return 1 if field_7.blank? - - 0 - end - - [ - { person: 2, field: :field_8 }, - { person: 3, field: :field_9 }, - { person: 4, field: :field_10 }, - { person: 5, field: :field_11 }, - { person: 6, field: :field_12 }, - ].each do |hash| - define_method("age#{hash[:person]}_known?") do - return 1 if public_send(hash[:field]) == "R" - return 0 if send("person_#{hash[:person]}_present?") - return 1 if public_send(hash[:field]).blank? - - 0 - end - end - - def person_2_present? - field_8.present? || field_14.present? || field_19.present? - end - - def person_3_present? - field_9.present? || field_15.present? || field_20.present? - end - - def person_4_present? - field_10.present? || field_16.present? || field_21.present? - end - - def person_5_present? - field_11.present? || field_17.present? || field_22.present? - end - - def person_6_present? - field_12.present? || field_18.present? || field_23.present? - end - - def details_known?(person_n) - send("person_#{person_n}_present?") ? 1 : 2 - end - - def ethnic_group_from_ethnic - if field_30.blank? - buyer_not_interviewed? ? 17 : nil - else - case field_30 - when 1, 2, 3, 18 - 0 - when 4, 5, 6, 7 - 1 - when 8, 9, 10, 11, 15 - 2 - when 12, 13, 14 - 3 - when 16, 19 - 4 - when 17 - 17 - end - end - end - - def postcode_full - "#{field_54} #{field_55}" if field_54 && field_55 - end - - def ppostcode_full - "#{field_41} #{field_42}" if field_41 && field_42 - end - - def sale_type - return field_57 if shared_ownership? - return field_76 if discounted_ownership? - return field_84 if outright_sale? - end - - def value - return field_68 if shared_ownership? - return field_77 if discounted_ownership? - return field_87 if outright_sale? - end - - def mortgage - return field_70 if shared_ownership? - return field_80 if discounted_ownership? - return field_88 if outright_sale? - end - - def extrabor - return field_71 if shared_ownership? - return field_81 if discounted_ownership? - return field_89 if outright_sale? - end - - def deposit - return field_72 if shared_ownership? - return field_82 if discounted_ownership? - return field_90 if outright_sale? - end - - def mscharge - return field_75 if shared_ownership? - return field_83 if discounted_ownership? - return field_91 if outright_sale? - end - - def mortgagelender - return field_98 if shared_ownership? - return field_100 if discounted_ownership? - return field_102 if outright_sale? - end - - def mortgagelenderother - return field_99 if shared_ownership? - return field_101 if discounted_ownership? - return field_103 if outright_sale? - end - - def mortlen - return field_105 if shared_ownership? - return field_106 if discounted_ownership? - return field_107 if outright_sale? - end - - def proplen - return field_110 if shared_ownership? - return field_108 if discounted_ownership? - end - - def mortgageused - return field_123 if shared_ownership? - return field_124 if discounted_ownership? - return field_125 if outright_sale? - end - - def owning_organisation - @owning_organisation ||= Organisation.find_by_id_on_multiple_fields(field_92) - end - - def created_by - @created_by ||= User.where("lower(email) = ?", field_93&.downcase).first - end - - def hhregres - case field_95 - when 3 then 3 - when 4, 5, 6 then 1 - when 7 then 7 - when 8 then 8 - end - end - - def hhregresstill - return unless hhregres == 1 - - field_95 - end - - def previous_la_known - field_40.present? ? 1 : 0 - end - - def previous_postcode_known - return 1 if field_43.blank? - - 0 if field_43 == 1 - end - - def soctenant - return unless field_39 && field_113 - - if (field_39 == 1 || field_39 == 2) && field_113 == 1 - 1 - elsif field_113 == 1 - 2 - end - end - - def block_log_creation! - self.block_log_creation = true - end - - def questions - @questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) } - end - - def duplicate_check_fields - %w[ - saledate - age1 - sex1 - ecstat1 - owning_organisation - postcode_full - purchid - ] - end - - def validate_owning_org_data_given - if field_92.blank? - block_log_creation! - - if errors[:field_92].blank? - errors.add(:field_92, "The owning organisation code is incorrect", category: :setup) - end - end - end - - def validate_owning_org_exists - if owning_organisation.nil? - block_log_creation! - - if errors[:field_92].blank? - errors.add(:field_92, "The owning organisation code is incorrect", category: :setup) - end - end - end - - def validate_owning_org_owns_stock - if owning_organisation && !owning_organisation.holds_own_stock? - block_log_creation! - - if errors[:field_92].blank? - errors.add(:field_92, "The owning organisation code provided is for an organisation that does not own stock", category: :setup) - end - end - end - - def validate_owning_org_permitted - if owning_organisation && !bulk_upload.user.organisation.affiliated_stock_owners.include?(owning_organisation) - block_log_creation! - - if errors[:field_92].blank? - errors.add(:field_92, "You do not have permission to add logs for this owning organisation", category: :setup) - end - end - end - - def validate_created_by_exists - return if field_93.blank? - - unless created_by - errors.add(:field_93, "User with the specified email could not be found") - end - end - - def validate_created_by_related - return unless created_by - - unless created_by.organisation == owning_organisation - block_log_creation! - errors.add(:field_93, "User must be related to owning organisation") - end - end - - def setup_question?(question) - log.form.setup_sections[0].subsections[0].questions.include?(question) - end - - def validate_nulls - field_mapping_for_errors.each do |error_key, fields| - question_id = error_key.to_s - question = questions.find { |q| q.id == question_id } - - next unless question - next if log.optional_fields.include?(question.id) - next if question.completed?(log) - - fields.each do |field| - unless errors.any? { |e| fields.include?(e.attribute) } - if setup_question?(question) - errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label&.downcase), category: :setup) - else - errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label&.downcase)) - end - end - end - end - end - - def validate_valid_radio_option - log.attributes.each do |question_id, _v| - next if question_id == "type" - - question = log.form.get_question(question_id, log) - - next unless question&.type == "radio" - next if log[question_id].blank? || question.answer_options.key?(log[question_id].to_s) || !question.page.routed_to?(log, nil) - - fields = field_mapping_for_errors[question_id.to_sym] || [] - - if setup_question?(question) - fields.each do |field| - if errors[field].none? - block_log_creation! - errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field].downcase), category: :setup) - end - end - else - fields.each do |field| - if errors.none? { |e| fields.include?(e.attribute) } - errors.add(field, I18n.t("validations.invalid_option", question: QUESTIONS[field])) - end - end - end - end - end - - def validate_relevant_collection_window - return if saledate.blank? || bulk_upload.form.blank? - - unless bulk_upload.form.valid_start_date_for_form?(saledate) - errors.add(:field_2, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - errors.add(:field_3, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - errors.add(:field_4, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) - end - end - - def validate_incomplete_soft_validations - routed_to_soft_validation_questions = log.form.questions.filter { |q| q.type == "interruption_screen" && q.page.routed_to?(log, nil) }.compact - routed_to_soft_validation_questions.each do |question| - next if question.completed?(log) - - question.page.interruption_screen_question_ids.each do |interruption_screen_question_id| - next if log.form.questions.none? { |q| q.id == interruption_screen_question_id && q.page.routed_to?(log, nil) } - - field_mapping_for_errors[interruption_screen_question_id.to_sym]&.each do |field| - if errors.none? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) } - error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(". ") - errors.add(field, message: error_message, category: :soft_validation) - end - end - end - end - end - - def validate_if_log_already_exists - if log_already_exists? - error_message = "This is a duplicate log" - - errors.add(:field_92, error_message) # Owning org - errors.add(:field_2, error_message) # Sale completion date - errors.add(:field_3, error_message) # Sale completion date - errors.add(:field_4, error_message) # Sale completion date - errors.add(:field_41, error_message) # Postcode - errors.add(:field_42, error_message) # Postcode - errors.add(:field_7, error_message) # Buyer 1 age - errors.add(:field_13, error_message) # Buyer 1 gender - errors.add(:field_24, error_message) # Buyer 1 working situation - errors.add(:field_1, error_message) # Purchaser code - end - end - - def validate_buyer1_economic_status - if field_24 == 9 - errors.add(:field_24, "Buyer 1 cannot be a child under 16") - end - end -end diff --git a/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2022.html.erb b/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2022.html.erb deleted file mode 100644 index 60fc158a2..000000000 --- a/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2022.html.erb +++ /dev/null @@ -1,41 +0,0 @@ -<% content_for :before_content do %> - <%= govuk_back_link href: @form.back_path %> -<% end %> - -
FIR&yKYzS1zP94>MyUn$dUHEo>hmND^n)y^1X%|c2rD1;x!%F$-T4R
zq(O$9VEvK1SLDi~{bYj1zY%CDd-O;vjXc|i4zZu?$k#)1^Gc*>cjdMTeSl2E<-pPA
zjk#mwz!^uOmTWmOJ|5)z{PY^O0R)X2XC}Dd&JShIoGb$JkUCo`YVt9G!V)9iTn&g1
zQkn7P2t@LWPCu}4DVf|ZG08p@4vahhmDepE&ECFiut{1PDIJMi`ktsvYK
z&llT?ph)z|vuunEa=I7?z&B%g`!(rw5xJ;n{f@#JO-OsW;abHtl}!ombzGOLGo~i|
zj6&MP0@mzL8@
>o{#5~R&Mahhn#D6IIfLGTcF
z$|i(KFFZo}WyPQ!vUnn>Dx#|4_VHx-ye&&jPGb0>iA)`73N29R-rXOUZHej{n|9?=
zcPrJfC^{P#P0P|Q=0!THR0WT%j`YJVT)=ftP$y>ldD9(anxxcK`jh^a67z$UeyZkf
zT;nr2MvfwOGCP}(N=SNq<_|Nj@N*riY;T>5!hP2sS6bPqJgW7F6PHJ^BrU>S4NAll
zCGNsG4p1;wF`5?Ke8&-|^%2G{RlY!d(8fB*?qf5dnM?MnCa87CtrL>wvP-kMwT&Sj
z>Ef%BH0fGO;($
@>
mqlSsGKbJ3ytyF1PZAC1P*jwj7kn6=4QpQBX6PzJbsU^
zkJo6V+4*s~8crX6pFwXmJhSV1>Bso>wmP|++x~UG^Fiiai-VH|UIy
OpTjmzr=T4qtJBxg8x%7gluk)MD0|T$bvm
z@e9U(*2?IB!|)miV;6Fonw;D{X|9P1tu>$F!
H
zM};t4ro7aUhri6ZX3V^j^YwqKXxn=nXxu_1B6)U}JRFhS^?rP=FfiKd(0|;2{@0DC
z65wU0y?ncI5%E!rKN$nTd1fu)Q@J$lv%+kiBIM-A`cSGprpOA^k-4H4Hsxe(=|X&q
zAgC~+^h+6@^~6~7G>3x_zk7VR#h93Ikk!awT`dEFSUi`Bvqj`+s$Iplfy7vw
z;$;FjWk6}iGBTv(!5*MWJd>l?i_>jJ?Kz%&U28Tmg_bJ+#uA1|;mq6&jc!*8>zcv=
zW(k1UY3eVs!xM#sylqJ+_HcZi7M%@1k;`jS8i(BOXET?pX`ExN1^c$Kr9c-52i9mV
zFW67wd8UUi@nU4&_^96OBr&-pi(V+=5zdRa+kSt5Atq*NaDBju3_10IuOIWHSU(ez
z-Cty<5-Kvlx8=Ew7$!(5;%@I*FeVytUAb|^o?)-2v7S*+WfRllfuz%Ax7rxx8IAu2
zfW&VH&jz}X>alX$I?ND?2eJK`A4O4gYszFmMr!1A88eJUnHjuEH-W$*3^l
zUo&UHGd1w?7k