diff --git a/app/services/bulk_upload/lettings/year2025/csv_parser.rb b/app/services/bulk_upload/lettings/year2025/csv_parser.rb index 8fb728ea1..21750b352 100644 --- a/app/services/bulk_upload/lettings/year2025/csv_parser.rb +++ b/app/services/bulk_upload/lettings/year2025/csv_parser.rb @@ -41,12 +41,7 @@ class BulkUpload::Lettings::Year2025::CsvParser hash_rows = field_numbers .zip(stripped_row) .map do |field, value| - # this is needed as a string passed to an int attribute is by default mapped to '0'. - # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it - expected_is_integer = ROW_PARSER_CLASS.attribute_types[field].is_a?(ActiveModel::Type::Integer) - # we must be certain that the user entered a string that cannot be coerced to an integer - actual_is_non_empty_string = value.present? && Integer(value, exception: false).nil? && Float(value, exception: false).nil? - field_is_valid = !(expected_is_integer && actual_is_non_empty_string) + field_is_valid = value_is_valid_for_field(field, value) correct_value = field_is_valid ? value : nil @@ -136,6 +131,20 @@ private @normalised_string end + # this is needed as a string passed to an int attribute is by default mapped to '0'. + # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it + def value_is_valid_for_field(field, value) + field_type = ROW_PARSER_CLASS.attribute_types[field] + + if field_type.is_a?(ActiveModel::Type::Integer) + value.nil? || Integer(value, exception: false).present? + elsif field_type.is_a?(ActiveModel::Type::Decimal) + value.nil? || Float(value, exception: false).present? + else + true + end + end + def first_record_start_date if with_headers? year = row_parsers.first.field_10.to_s.strip.length.between?(1, 2) ? row_parsers.first.field_10.to_i + 2000 : row_parsers.first.field_10.to_i diff --git a/app/services/bulk_upload/sales/year2025/csv_parser.rb b/app/services/bulk_upload/sales/year2025/csv_parser.rb index f1f22e2b4..0bdb756d7 100644 --- a/app/services/bulk_upload/sales/year2025/csv_parser.rb +++ b/app/services/bulk_upload/sales/year2025/csv_parser.rb @@ -41,12 +41,7 @@ class BulkUpload::Sales::Year2025::CsvParser hash_rows = field_numbers .zip(stripped_row) .map do |field, value| - # this is needed as a string passed to an int attribute is by default mapped to '0'. - # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it - expected_is_integer = ROW_PARSER_CLASS.attribute_types[field].is_a?(ActiveModel::Type::Integer) - # we must be certain that the user entered a string that cannot be coerced to an integer - actual_is_non_empty_string = value.present? && Integer(value, exception: false).nil? && Float(value, exception: false).nil? - field_is_valid = !(expected_is_integer && actual_is_non_empty_string) + field_is_valid = value_is_valid_for_field(field, value) correct_value = field_is_valid ? value : nil @@ -139,6 +134,20 @@ private @normalised_string end + # this is needed as a string passed to an int attribute is by default mapped to '0'. + # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it + def value_is_valid_for_field(field, value) + field_type = ROW_PARSER_CLASS.attribute_types[field] + + if field_type.is_a?(ActiveModel::Type::Integer) + value.nil? || Integer(value, exception: false).present? + elsif field_type.is_a?(ActiveModel::Type::Decimal) + value.nil? || Float(value, exception: false).present? + else + true + end + end + def first_record_start_date if with_headers? year = row_parsers.first.field_3.to_s.strip.length.between?(1, 2) ? row_parsers.first.field_3.to_i + 2000 : row_parsers.first.field_3.to_i diff --git a/app/services/bulk_upload/sales/year2026/csv_parser.rb b/app/services/bulk_upload/sales/year2026/csv_parser.rb index 44d067faa..94c3f8223 100644 --- a/app/services/bulk_upload/sales/year2026/csv_parser.rb +++ b/app/services/bulk_upload/sales/year2026/csv_parser.rb @@ -42,12 +42,7 @@ class BulkUpload::Sales::Year2026::CsvParser hash_rows = field_numbers .zip(stripped_row) .map do |field, value| - # this is needed as a string passed to an int attribute is by default mapped to '0'. - # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it - expected_is_integer = ROW_PARSER_CLASS.attribute_types[field].is_a?(ActiveModel::Type::Integer) - # we must be certain that the user entered a string that cannot be coerced to an integer - actual_is_non_empty_string = value.present? && Integer(value, exception: false).nil? && Float(value, exception: false).nil? - field_is_valid = !(expected_is_integer && actual_is_non_empty_string) + field_is_valid = value_is_valid_for_field(field, value) correct_value = field_is_valid ? value : nil @@ -140,6 +135,20 @@ private @normalised_string end + # this is needed as a string passed to an int attribute is by default mapped to '0'. + # this is bad as some questions will accept a '0'. so you could enter something invalid and not be told about it + def value_is_valid_for_field(field, value) + field_type = ROW_PARSER_CLASS.attribute_types[field] + + if field_type.is_a?(ActiveModel::Type::Integer) + value.nil? || Integer(value, exception: false).present? + elsif field_type.is_a?(ActiveModel::Type::Decimal) + value.nil? || Float(value, exception: false).present? + else + true + end + end + def first_record_start_date if with_headers? year = row_parsers.first.field_3.to_s.strip.length.between?(1, 2) ? row_parsers.first.field_3.to_i + 2000 : row_parsers.first.field_3.to_i