diff --git a/app/models/case_log.rb b/app/models/case_log.rb
index fd977e11e..b8bbfd0b0 100644
--- a/app/models/case_log.rb
+++ b/app/models/case_log.rb
@@ -477,12 +477,16 @@ private
(2..8).each do |idx|
if public_send("age#{idx}") && public_send("age#{idx}") < 16
self["ecstat#{idx}"] = 9
- elsif public_send("ecstat#{idx}") == 9 && (public_send("age#{idx}").nil? || public_send("age#{idx}") >= 16)
+ elsif public_send("ecstat#{idx}") == 9 && (public_send("age#{idx}").nil? || public_send("age#{idx}") >= 16) && age_known?(idx)
self["ecstat#{idx}"] = nil
end
end
end
+ def age_known?(person_num)
+ !!public_send("age#{person_num}_known")&.zero?
+ end
+
def process_postcode_changes!
self.postcode_full = postcode_full.present? ? postcode_full.upcase.gsub(/\s+/, "") : postcode_full
process_postcode(postcode_full, "postcode_known", "is_la_inferred", "la")
diff --git a/app/models/form.rb b/app/models/form.rb
index c885db64d..e339f6fdc 100644
--- a/app/models/form.rb
+++ b/app/models/form.rb
@@ -146,4 +146,27 @@ class Form
previous_page(page_ids, page_index - 1, case_log)
end
+
+ def send_chain(arr, case_log)
+ Array(arr).inject(case_log) { |o, a| o.public_send(*a) }
+ end
+
+ def depends_on_met(depends_on, case_log)
+ return true unless depends_on
+
+ depends_on.any? do |conditions_set|
+ conditions_set.all? do |question, value|
+ if value.is_a?(Hash) && value.key?("operator")
+ operator = value["operator"]
+ operand = value["operand"]
+ case_log[question]&.send(operator, operand)
+ else
+ parts = question.split(".")
+ case_log_value = send_chain(parts, case_log)
+
+ value.nil? ? case_log_value == value : !case_log_value.nil? && case_log_value == value
+ end
+ end
+ end
+ end
end
diff --git a/app/models/form/page.rb b/app/models/form/page.rb
index a2bac3bf2..155f85d20 100644
--- a/app/models/form/page.rb
+++ b/app/models/form/page.rb
@@ -14,10 +14,12 @@ class Form::Page
@subsection = subsection
end
+ delegate :form, to: :subsection
+
def routed_to?(case_log)
return true unless depends_on || subsection.depends_on
- subsection.enabled?(case_log) && depends_on_met(case_log)
+ subsection.enabled?(case_log) && form.depends_on_met(depends_on, case_log)
end
def non_conditional_questions
@@ -36,27 +38,4 @@ private
q.conditional_for.keys if q.type == "radio"
}.compact
end
-
- def send_chain(arr, case_log)
- Array(arr).inject(case_log) { |o, a| o.public_send(*a) }
- end
-
- def depends_on_met(case_log)
- return true unless depends_on
-
- depends_on.any? do |conditions_set|
- conditions_set.all? do |question, value|
- if value.is_a?(Hash) && value.key?("operator")
- operator = value["operator"]
- operand = value["operand"]
- case_log[question]&.send(operator, operand)
- else
- parts = question.split(".")
- case_log_value = send_chain(parts, case_log)
-
- value.nil? ? case_log_value == value : !case_log_value.nil? && case_log_value == value
- end
- end
- end
- end
end
diff --git a/app/models/form/question.rb b/app/models/form/question.rb
index 66d54e277..96276f48a 100644
--- a/app/models/form/question.rb
+++ b/app/models/form/question.rb
@@ -80,9 +80,9 @@ class Form::Question
false
end
- def displayed_answer_options
+ def displayed_answer_options(case_log)
answer_options.select do |_key, val|
- !val.is_a?(Hash) || !val["derived"]
+ !val.is_a?(Hash) || !val["depends_on"] || form.depends_on_met(val["depends_on"], case_log)
end
end
@@ -168,7 +168,7 @@ private
def selected_answer_option_is_derived?(case_log)
selected_option = answer_options&.dig(case_log[id].to_s.presence)
- selected_option.is_a?(Hash) && selected_option["derived"]
+ selected_option.is_a?(Hash) && selected_option["depends_on"] && form.depends_on_met(selected_option["depends_on"], case_log)
end
def has_inferred_display_value?(case_log)
diff --git a/app/views/form/_checkbox_question.html.erb b/app/views/form/_checkbox_question.html.erb
index 99551bac1..eb6cd8d40 100644
--- a/app/views/form/_checkbox_question.html.erb
+++ b/app/views/form/_checkbox_question.html.erb
@@ -6,7 +6,7 @@
hint: { text: question.hint_text&.html_safe } do %>
<% after_divider = false %>
- <% question.displayed_answer_options.map do |key, options| %>
+ <% question.displayed_answer_options(@case_log).map do |key, options| %>
<% if key.starts_with?("divider") %>
<% after_divider = true %>
<%= f.govuk_check_box_divider %>
diff --git a/app/views/form/_radio_question.html.erb b/app/views/form/_radio_question.html.erb
index a79e9422d..a6cd165f9 100644
--- a/app/views/form/_radio_question.html.erb
+++ b/app/views/form/_radio_question.html.erb
@@ -5,7 +5,7 @@
legend: legend(question, page_header, conditional),
hint: { text: question.hint_text&.html_safe } do %>
- <% question.displayed_answer_options.map do |key, options| %>
+ <% question.displayed_answer_options(@case_log).map do |key, options| %>
<% if key.starts_with?("divider") %>
<%= f.govuk_radio_divider %>
<% else %>
diff --git a/app/views/form/_select_question.html.erb b/app/views/form/_select_question.html.erb
index b5c6d94a9..52c47d66d 100644
--- a/app/views/form/_select_question.html.erb
+++ b/app/views/form/_select_question.html.erb
@@ -1,7 +1,7 @@
<%= render partial: "form/guidance/#{question.guidance_partial}" if question.guidance_partial %>
<% selected = @case_log.public_send(question.id) || "" %>
-<% answers = question.displayed_answer_options.map { |key, value| OpenStruct.new(id: key, name: value) } %>
+<% answers = question.displayed_answer_options(@case_log).map { |key, value| OpenStruct.new(id: key, name: value) } %>
<%= f.govuk_collection_select question.id.to_sym,
answers,
:id,
diff --git a/config/forms/2021_2022.json b/config/forms/2021_2022.json
index 0810e6121..af47ff1aa 100644
--- a/config/forms/2021_2022.json
+++ b/config/forms/2021_2022.json
@@ -1771,7 +1771,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age2_known": 1 },
+ { "age2": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -1990,7 +1993,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age3_known": 1 },
+ { "age3": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2206,7 +2212,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age4_known": 1 },
+ { "age4": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2419,7 +2428,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age5_known": 1 },
+ { "age5": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2629,7 +2641,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age6_known": 1 },
+ { "age6": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2836,7 +2851,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age7_known": 1 },
+ { "age7": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -3040,7 +3058,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age8_known": 1 },
+ { "age8": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json
index b03afc78b..c6b8018ce 100644
--- a/config/forms/2022_2023.json
+++ b/config/forms/2022_2023.json
@@ -1769,7 +1769,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age2_known": 1 },
+ { "age2": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -1995,7 +1998,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age3_known": 1 },
+ { "age3": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2218,7 +2224,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age4_known": 1 },
+ { "age4": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2438,7 +2447,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age5_known": 1 },
+ { "age5": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2655,7 +2667,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age6_known": 1 },
+ { "age6": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -2869,7 +2884,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age7_known": 1 },
+ { "age7": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
@@ -3080,7 +3098,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age8_known": 1 },
+ { "age8": { "operator": "<", "operand": 16 } }
+ ]
},
"0": {
"value": "Other"
diff --git a/spec/fixtures/forms/2021_2022.json b/spec/fixtures/forms/2021_2022.json
index 1aa37557b..c2582b6e8 100644
--- a/spec/fixtures/forms/2021_2022.json
+++ b/spec/fixtures/forms/2021_2022.json
@@ -188,7 +188,10 @@
},
"9": {
"value": "Child under 16",
- "derived": true
+ "depends_on": [
+ { "age2_known": 1 },
+ { "age2": { "operator": "<", "operand": 16 } }
+ ]
},
"1": {
"value": "Prefer not to say"
diff --git a/spec/fixtures/softwire_imports/case_logs/0ead17cb-1668-442d-898c-0d52879ff592.xml b/spec/fixtures/softwire_imports/case_logs/0ead17cb-1668-442d-898c-0d52879ff592.xml
index ac7ef6d5a..30f1a2289 100644
--- a/spec/fixtures/softwire_imports/case_logs/0ead17cb-1668-442d-898c-0d52879ff592.xml
+++ b/spec/fixtures/softwire_imports/case_logs/0ead17cb-1668-442d-898c-0d52879ff592.xml
@@ -54,8 +54,8 @@
6) Not Seeking Work
17 Refused
1 UK national resident in UK
- 2
-
+
+ Age_Refused
Male
Child
9) Child under 16
diff --git a/spec/models/case_log_spec.rb b/spec/models/case_log_spec.rb
index 8c483774c..7fdbd6381 100644
--- a/spec/models/case_log_spec.rb
+++ b/spec/models/case_log_spec.rb
@@ -1367,7 +1367,7 @@ RSpec.describe CaseLog do
end
it "correctly resets economic status when age changes from under 16" do
- household_case_log.update!(age7: 17)
+ household_case_log.update!(age7_known: 0, age7: 17)
record_from_db = ActiveRecord::Base.connection.execute("select ecstat7 from case_logs where id=#{household_case_log.id}").to_a[0]
expect(record_from_db["ecstat7"]).to eq(nil)
end
diff --git a/spec/models/form/question_spec.rb b/spec/models/form/question_spec.rb
index 094d521e3..4057e4687 100644
--- a/spec/models/form/question_spec.rb
+++ b/spec/models/form/question_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Form::Question, type: :model do
context "when answer options do not include derived options" do
it "displays all answer options" do
- expect(question.displayed_answer_options).to match(question.answer_options)
+ expect(question.displayed_answer_options(case_log)).to match(question.answer_options)
end
end
@@ -132,7 +132,7 @@ RSpec.describe Form::Question, type: :model do
end
it "does not include those options in the displayed options" do
- expect(question.displayed_answer_options).to match(expected_answer_options)
+ expect(question.displayed_answer_options(case_log)).to match(expected_answer_options)
end
it "can still map the value label" do