You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
326 lines
9.0 KiB
326 lines
9.0 KiB
class Form::Question |
|
attr_accessor :id, :header, :hint_text, :description, :questions, |
|
:type, :min, :max, :step, :width, :fields_to_add, :result_field, |
|
:conditional_for, :readonly, :answer_options, :page, :check_answer_label, |
|
:inferred_answers, :hidden_in_check_answers, :inferred_check_answers_value, |
|
:guidance_partial, :prefix, :suffix, :requires_js, :fields_added |
|
|
|
def initialize(id, hsh, page) |
|
@id = id |
|
@check_answer_label = hsh["check_answer_label"] |
|
@header = hsh["header"] |
|
@guidance_partial = hsh["guidance_partial"] |
|
@hint_text = hsh["hint_text"] |
|
@type = hsh["type"] |
|
@min = hsh["min"] |
|
@max = hsh["max"] |
|
@step = hsh["step"] |
|
@width = hsh["width"] |
|
@fields_to_add = hsh["fields-to-add"] |
|
@result_field = hsh["result-field"] |
|
@readonly = hsh["readonly"] |
|
@answer_options = hsh["answer_options"] |
|
@conditional_for = hsh["conditional_for"] |
|
@inferred_answers = hsh["inferred_answers"] |
|
@inferred_check_answers_value = hsh["inferred_check_answers_value"] |
|
@hidden_in_check_answers = hsh["hidden_in_check_answers"] |
|
@prefix = hsh["prefix"] |
|
@suffix = hsh["suffix"] |
|
@requires_js = hsh["requires_js"] |
|
@fields_added = hsh["fields_added"] |
|
@page = page |
|
end |
|
|
|
delegate :subsection, to: :page |
|
delegate :form, to: :subsection |
|
|
|
def answer_label(case_log) |
|
return checkbox_answer_label(case_log) if type == "checkbox" |
|
return case_log[id]&.to_formatted_s(:govuk_date).to_s if type == "date" |
|
|
|
answer = label_from_value(case_log[id]) if case_log[id].present? |
|
answer_label = [prefix, format_value(answer), suffix_label(case_log)].join("") if answer |
|
return answer_label if answer_label |
|
|
|
has_inferred_check_answers_value?(case_log) ? inferred_check_answers_value["value"] : "" |
|
end |
|
|
|
def get_inferred_answers(case_log) |
|
return [] unless inferred_answers |
|
|
|
enabled_inferred_answers(inferred_answers, case_log).keys.map do |x| |
|
form.get_question(x, case_log).label_from_value(case_log[x]) |
|
end |
|
end |
|
|
|
def read_only? |
|
!!readonly |
|
end |
|
|
|
def enabled?(case_log) |
|
return true if conditional_on.blank? |
|
|
|
conditional_on.all? { |condition| evaluate_condition(condition, case_log) } |
|
end |
|
|
|
def hidden_in_check_answers?(case_log) |
|
if hidden_in_check_answers.is_a?(Hash) |
|
hidden_in_check_answers["depends_on"].any? do |hsh| |
|
hsh.all? { |key, value| case_log[key] == value } |
|
end |
|
else |
|
hidden_in_check_answers |
|
end |
|
end |
|
|
|
def has_inferred_check_answers_value?(case_log) |
|
return true if selected_answer_option_is_derived?(case_log) |
|
return inferred_check_answers_value["condition"].values[0] == case_log[inferred_check_answers_value["condition"].keys[0]] if inferred_check_answers_value.present? |
|
|
|
false |
|
end |
|
|
|
def displayed_answer_options |
|
answer_options.select do |_key, val| |
|
!val.is_a?(Hash) || !val["derived"] |
|
end |
|
end |
|
|
|
def update_answer_link_name(case_log) |
|
link_type = if has_inferred_check_answers_value?(case_log) |
|
"Change" |
|
elsif type == "checkbox" |
|
answer_options.keys.any? { |key| value_is_yes?(case_log[key]) } ? "Change" : "Answer" |
|
else |
|
case_log[id].blank? ? "Answer" : "Change" |
|
end |
|
"#{link_type}<span class=\"govuk-visually-hidden\"> #{check_answer_label.to_s.downcase}</span>".html_safe |
|
end |
|
|
|
def completed?(case_log) |
|
return answer_options.keys.any? { |key| value_is_yes?(case_log[key]) } if type == "checkbox" |
|
|
|
case_log[id].present? || !case_log.respond_to?(id.to_sym) || has_inferred_display_value?(case_log) |
|
end |
|
|
|
def value_from_label(label) |
|
return unless label |
|
|
|
case type |
|
when "radio" |
|
answer_options.find { |opt| opt.second["value"] == label.to_s }.first |
|
when "select" |
|
answer_options.find { |opt| opt.second == label.to_s }.first |
|
else |
|
label |
|
end |
|
end |
|
|
|
def label_from_value(value) |
|
return unless value |
|
|
|
label = case type |
|
when "radio" |
|
labels = answer_options[value.to_s] |
|
labels["value"] if labels |
|
when "select" |
|
answer_options[value.to_s] |
|
else |
|
value.to_s |
|
end |
|
label || value.to_s |
|
end |
|
|
|
def value_is_yes?(value) |
|
case type |
|
when "checkbox" |
|
value == 1 |
|
when "radio" |
|
RADIO_YES_VALUE[id.to_sym]&.include?(value) |
|
else |
|
%w[yes].include?(value.downcase) |
|
end |
|
end |
|
|
|
def value_is_no?(value) |
|
case type |
|
when "checkbox" |
|
value && value.zero? |
|
when "radio" |
|
RADIO_NO_VALUE[id.to_sym]&.include?(value) |
|
else |
|
%w[no].include?(value.downcase) |
|
end |
|
end |
|
|
|
def value_is_dont_know?(value) |
|
type == "radio" && RADIO_DONT_KNOW_VALUE[id.to_sym]&.include?(value) |
|
end |
|
|
|
def value_is_refused?(value) |
|
type == "radio" && RADIO_REFUSED_VALUE[id.to_sym]&.include?(value) |
|
end |
|
|
|
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"] |
|
end |
|
|
|
def has_inferred_display_value?(case_log) |
|
inferred_check_answers_value.present? && case_log[inferred_check_answers_value["condition"].keys.first] == inferred_check_answers_value["condition"].values.first |
|
end |
|
|
|
def checkbox_answer_label(case_log) |
|
answer = [] |
|
answer_options.each { |key, options| value_is_yes?(case_log[key]) ? answer << options["value"] : nil } |
|
answer.join(", ") |
|
end |
|
|
|
def format_value(answer_label) |
|
prefix == "£" ? ActionController::Base.helpers.number_to_currency(answer_label, delimiter: ",", format: "%n") : answer_label |
|
end |
|
|
|
def suffix_label(case_log) |
|
return "" unless suffix |
|
return suffix if suffix.is_a?(String) |
|
|
|
label = "" |
|
|
|
suffix.each do |s| |
|
condition = s["depends_on"] |
|
next unless condition |
|
|
|
answer = case_log.send(condition.keys.first) |
|
if answer == condition.values.first |
|
label = ANSWER_SUFFIX_LABELS.key?(answer) ? ANSWER_SUFFIX_LABELS[answer] : answer |
|
end |
|
end |
|
label |
|
end |
|
|
|
def conditional_on |
|
@conditional_on ||= form.conditional_question_conditions.select do |condition| |
|
condition[:to] == id |
|
end |
|
end |
|
|
|
def evaluate_condition(condition, case_log) |
|
case page.questions.find { |q| q.id == condition[:from] }.type |
|
when "numeric" |
|
operator = condition[:cond][/[<>=]+/].to_sym |
|
operand = condition[:cond][/\d+/].to_i |
|
case_log[condition[:from]].present? && case_log[condition[:from]].send(operator, operand) |
|
when "text", "radio", "select" |
|
case_log[condition[:from]].present? && condition[:cond].include?(case_log[condition[:from]]) |
|
else |
|
raise "Not implemented yet" |
|
end |
|
end |
|
|
|
def enabled_inferred_answers(inferred_answers, case_log) |
|
inferred_answers.filter { |_key, value| value.all? { |condition_key, condition_value| case_log[condition_key] == condition_value } } |
|
end |
|
|
|
ANSWER_SUFFIX_LABELS = { |
|
0 => " every week", |
|
1 => " every month", |
|
2 => " every year", |
|
}.freeze |
|
|
|
RADIO_YES_VALUE = { |
|
renewal: [1], |
|
postcode_known: [1], |
|
previous_postcode_known: [1], |
|
la_known: [1], |
|
previous_la_known: [1], |
|
first_time_property_let_as_social_housing: [1], |
|
wchair: [1], |
|
majorrepairs: [1], |
|
startertenancy: [0], |
|
letting_in_sheltered_accommodation: [0, 1], |
|
armedforces: [0, 1, 2], |
|
leftreg: [0], |
|
reservist: [0], |
|
preg_occ: [0], |
|
illness: [0], |
|
underoccupation_benefitcap: [4, 5, 6], |
|
reasonpref: [1], |
|
net_income_known: [0], |
|
household_charge: [0], |
|
is_carehome: [1], |
|
rent_shortfall: [0], |
|
net_income_value_check: [0], |
|
}.freeze |
|
|
|
RADIO_NO_VALUE = { |
|
renewal: [0], |
|
postcode_known: [0], |
|
previous_postcode_known: [0], |
|
la_known: [0], |
|
previous_la_known: [0], |
|
first_time_property_let_as_social_housing: [0], |
|
wchair: [0], |
|
majorrepairs: [0], |
|
startertenancy: [1], |
|
letting_in_sheltered_accommodation: [2], |
|
armedforces: [3], |
|
leftreg: [1], |
|
reservist: [1], |
|
preg_occ: [1], |
|
illness: [1], |
|
underoccupation_benefitcap: [2], |
|
reasonpref: [2], |
|
net_income_known: [1], |
|
household_charge: [1], |
|
is_carehome: [0], |
|
rent_shortfall: [1], |
|
net_income_value_check: [1], |
|
}.freeze |
|
|
|
RADIO_DONT_KNOW_VALUE = { |
|
letting_in_sheltered_accommodation: [3], |
|
underoccupation_benefitcap: [3], |
|
reasonpref: [3], |
|
rent_shortfall: [1], |
|
layear: [7], |
|
reason_for_leaving_last_settled_home: [32], |
|
hb: [5], |
|
benefits: [3], |
|
unitletas: [3], |
|
}.freeze |
|
|
|
RADIO_REFUSED_VALUE = { |
|
sex1: %w[R], |
|
sex2: %w[R], |
|
sex3: %w[R], |
|
sex4: %w[R], |
|
sex5: %w[R], |
|
sex6: %w[R], |
|
sex7: %w[R], |
|
sex8: %w[R], |
|
relat2: [3], |
|
relat3: [3], |
|
relat4: [3], |
|
relat5: [3], |
|
relat6: [3], |
|
relat7: [3], |
|
relat8: [3], |
|
ecstat1: [10], |
|
ecstat2: [10], |
|
ecstat3: [10], |
|
ecstat4: [10], |
|
ecstat5: [10], |
|
ecstat6: [10], |
|
ecstat7: [10], |
|
ecstat8: [10], |
|
letting_in_sheltered_accommodation: [3], |
|
armedforces: [4], |
|
leftreg: [3], |
|
reservist: [2], |
|
preg_occ: [2], |
|
illness: [2], |
|
hb: [6], |
|
}.freeze |
|
end
|
|
|