From 7f11b9585234de48208530909b94053009d721e3 Mon Sep 17 00:00:00 2001 From: samyou-softwire Date: Thu, 5 Mar 2026 11:53:18 +0000 Subject: [PATCH] CLDC-4271: Only allow an error with the same message to hide a soft validation make the BU parser logic consistent across sales & lettings --- .../bulk_upload/lettings/year2025/row_parser.rb | 13 ++++++++++--- .../bulk_upload/lettings/year2026/row_parser.rb | 13 ++++++++++--- .../bulk_upload/sales/year2025/row_parser.rb | 13 ++++++++++--- .../bulk_upload/sales/year2026/row_parser.rb | 13 ++++++++++--- 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2025/row_parser.rb b/app/services/bulk_upload/lettings/year2025/row_parser.rb index ea52aa9f9..f89d1f33b 100644 --- a/app/services/bulk_upload/lettings/year2025/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2025/row_parser.rb @@ -679,10 +679,17 @@ private 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| 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) + error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ") + + # skip if an existing error with the same message on the same question. + # this is needed since a single soft validation will appear in n places on the flow + # and a soft validation contains m interruption screen question IDs. + # without this filter we'd add n * m errors + next unless errors.none? do |e| + e.options[:message] == error_message && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) end + + errors.add(field, message: error_message, category: :soft_validation) end end end diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb index 577a48190..310855989 100644 --- a/app/services/bulk_upload/lettings/year2026/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb @@ -717,10 +717,17 @@ private 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| 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) + error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ") + + # skip if an existing error with the same message on the same question. + # this is needed since a single soft validation will appear in n places on the flow + # and a soft validation contains m interruption screen question IDs. + # without this filter we'd add n * m errors + next unless errors.none? do |e| + e.options[:message] == error_message && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) end + + errors.add(field, message: error_message, category: :soft_validation) end end end diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb index 19ad2cb1b..e867e305c 100644 --- a/app/services/bulk_upload/sales/year2025/row_parser.rb +++ b/app/services/bulk_upload/sales/year2025/row_parser.rb @@ -1475,10 +1475,17 @@ private 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) + error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ") + + # skip if an existing error with the same message on the same question. + # this is needed since a single soft validation will appear in n places on the flow + # and a soft validation contains m interruption screen question IDs. + # without this filter we'd add n * m errors + next unless errors.none? do |e| + e.options[:message] == error_message && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) end + + errors.add(field, message: error_message, category: :soft_validation) end end end diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb index 35f412a7a..f985ccad5 100644 --- a/app/services/bulk_upload/sales/year2026/row_parser.rb +++ b/app/services/bulk_upload/sales/year2026/row_parser.rb @@ -1515,10 +1515,17 @@ private 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) + error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ") + + # skip if an existing error with the same message on the same question. + # this is needed since a single soft validation will appear in n places on the flow + # and a soft validation contains m interruption screen question IDs. + # without this filter we'd add n * m errors + next unless errors.none? do |e| + e.options[:message] == error_message && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) end + + errors.add(field, message: error_message, category: :soft_validation) end end end