Browse Source

Merge branch 'main' into CLDC-638-bulk_upload

pull/84/head
baarkerlounger 4 years ago
parent
commit
bc50087bb1
  1. 9
      app/constants/db_enums.rb
  2. 32
      app/helpers/check_answers_helper.rb
  3. 21
      app/helpers/tasklist_helper.rb
  4. 2
      app/models/case_log.rb
  5. 30
      app/models/form.rb
  6. 6
      app/validations/tenancy_validations.rb
  7. 4
      app/views/case_logs/_tasklist.html.erb
  8. 11
      config/forms/2021_2022.json
  9. 2
      docs/api/DLUHC-CORE-Data.v1.json
  10. 10
      lib/tasks/form_definition.rake
  11. 9
      spec/factories/case_log.rb
  12. 2
      spec/fixtures/complete_case_log.json
  13. 27
      spec/helpers/tasklist_helper_spec.rb
  14. 2
      spec/lib/tasks/form_definition_validator_spec.rb
  15. 18
      spec/models/case_log_spec.rb

9
app/constants/db_enums.rb

@ -166,11 +166,10 @@ module DbEnums
def self.tenancy
{
"Fixed term – Secure" => 1,
"Fixed term – Assured Shorthold Tenancy (AST)" => 4,
"Lifetime – Secure" => 100,
"Lifetime – Assured" => 2,
"License agreement" => 5,
"Secure (including flexible)" => 1,
"Assured" => 2,
"Assured Shorthold" => 4,
"Licence agreement (almshouses only)" => 5,
"Other" => 3,
}
end

32
app/helpers/check_answers_helper.rb

@ -16,7 +16,7 @@ module CheckAnswersHelper
while page_name.to_s != "check_answers" && subsection_keys.include?(page_name)
questions = form.questions_for_page(page_name)
applicable_questions = filter_conditional_questions(questions, case_log)
applicable_questions = form.filter_conditional_questions(questions, case_log)
total_questions = total_questions.merge(applicable_questions)
page_name = get_next_page_name(form, page_name, case_log)
@ -25,19 +25,6 @@ module CheckAnswersHelper
total_questions
end
def filter_conditional_questions(questions, case_log)
applicable_questions = questions
questions.each do |k, question|
question.fetch("conditional_for", []).each do |conditional_question_key, condition|
if condition_not_met(case_log, k, question, condition)
applicable_questions = applicable_questions.reject { |z| z == conditional_question_key }
end
end
end
applicable_questions
end
def get_next_page_name(form, page_name, case_log)
page = form.all_pages[page_name]
if page.key?("conditional_route_to")
@ -50,23 +37,6 @@ module CheckAnswersHelper
form.next_page(page_name)
end
def condition_not_met(case_log, question_key, question, condition)
case question["type"]
when "numeric"
operator = condition[/[<>=]+/].to_sym
operand = condition[/\d+/].to_i
case_log[question_key].blank? || !case_log[question_key].send(operator, operand)
when "text"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "radio"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "select"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
else
raise "Not implemented yet"
end
end
def create_update_answer_link(case_log_answer, case_log_id, page)
link_name = case_log_answer.blank? ? "Answer" : "Change"
link_to(link_name, "/case_logs/#{case_log_id}/#{page}", class: "govuk-link").html_safe

21
app/helpers/tasklist_helper.rb

@ -13,31 +13,32 @@ module TasklistHelper
in_progress: "govuk-tag--blue",
}.freeze
def get_subsection_status(subsection_name, case_log, questions)
def get_subsection_status(subsection_name, case_log, form, questions)
applicable_questions = form.filter_conditional_questions(questions, case_log).keys
if subsection_name == "declaration"
return case_log.completed? ? :not_started : :cannot_start_yet
end
return :not_started if questions.all? { |question| case_log[question].blank? }
return :completed if questions.all? { |question| case_log[question].present? }
return :not_started if applicable_questions.all? { |question| case_log[question].blank? }
return :completed if applicable_questions.all? { |question| case_log[question].present? }
:in_progress
end
def get_next_incomplete_section(form, case_log)
subsections = form.all_subsections.keys
subsections.find { |subsection| is_incomplete?(subsection, case_log, form.questions_for_subsection(subsection).keys) }
subsections.find { |subsection| is_incomplete?(subsection, case_log, form, form.questions_for_subsection(subsection)) }
end
def get_subsections_count(form, case_log, status = :all)
subsections = form.all_subsections.keys
return subsections.count if status == :all
subsections.count { |subsection| get_subsection_status(subsection, case_log, form.questions_for_subsection(subsection).keys) == status }
subsections.count { |subsection| get_subsection_status(subsection, case_log, form, form.questions_for_subsection(subsection)) == status }
end
def get_first_page_or_check_answers(subsection, case_log, form, questions)
path = if is_started?(subsection, case_log, questions)
path = if is_started?(subsection, case_log, form, questions)
"case_log_#{subsection}_check_answers_path"
else
"case_log_#{form.first_page_for_subsection(subsection)}_path"
@ -47,13 +48,13 @@ module TasklistHelper
private
def is_incomplete?(subsection, case_log, questions)
status = get_subsection_status(subsection, case_log, questions)
def is_incomplete?(subsection, case_log, form, questions)
status = get_subsection_status(subsection, case_log, form, questions)
%i[not_started in_progress].include?(status)
end
def is_started?(subsection, case_log, questions)
status = get_subsection_status(subsection, case_log, questions)
def is_started?(subsection, case_log, form, questions)
status = get_subsection_status(subsection, case_log, form, questions)
%i[in_progress completed].include?(status)
end
end

2
app/models/case_log.rb

@ -231,7 +231,7 @@ private
dynamically_not_required << "incfreq"
end
if tenancy == "Fixed term – Secure"
if tenancy == "Secure (including flexible)"
dynamically_not_required << "tenancylength"
end

30
app/models/form.rb

@ -97,6 +97,36 @@ class Form
}.reduce(:merge)
end
def filter_conditional_questions(questions, case_log)
applicable_questions = questions
questions.each do |k, question|
question.fetch("conditional_for", []).each do |conditional_question_key, condition|
if condition_not_met(case_log, k, question, condition)
applicable_questions = applicable_questions.reject { |z| z == conditional_question_key }
end
end
end
applicable_questions
end
def condition_not_met(case_log, question_key, question, condition)
case question["type"]
when "numeric"
operator = condition[/[<>=]+/].to_sym
operand = condition[/\d+/].to_i
case_log[question_key].blank? || !case_log[question_key].send(operator, operand)
when "text"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "radio"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
when "select"
case_log[question_key].blank? || !condition.include?(case_log[question_key])
else
raise "Not implemented yet"
end
end
def get_answer_label(case_log, question_title)
question = all_questions[question_title]
if question["type"] == "checkbox"

6
app/validations/tenancy_validations.rb

@ -4,12 +4,12 @@ module TenancyValidations
def validate_fixed_term_tenancy(record)
is_present = record.tenancylength.present?
is_in_range = record.tenancylength.to_i.between?(2, 99)
is_secure = record.tenancy == "Fixed term – Secure"
is_ast = record.tenancy == "Fixed term – Assured Shorthold Tenancy (AST)"
is_secure = record.tenancy == "Secure (including flexible)"
is_ast = record.tenancy == "Assured Shorthold"
conditions = [
{ condition: !(is_secure || is_ast) && is_present, error: "You must only answer the fixed term tenancy length question if the tenancy type is fixed term" },
{ condition: is_ast && !is_in_range, error: "Fixed term – Assured Shorthold Tenancy (AST) should be between 2 and 99 years" },
{ condition: is_secure && (!is_in_range && is_present), error: "Fixed term – Secure should be between 2 and 99 years or not specified" },
{ condition: is_secure && (!is_in_range && is_present), error: "Secure (including flexible) should be between 2 and 99 years or not specified" },
]
conditions.each { |condition| condition[:condition] ? (record.errors.add :tenancylength, condition[:error]) : nil }

4
app/views/case_logs/_tasklist.html.erb

@ -9,10 +9,10 @@
<ul class="app-task-list__items">
<% section_value["subsections"].map do |subsection_key, subsection_value| %>
<li class="app-task-list__item" id=<%= subsection_key %>>
<% questions_for_subsection = @form.questions_for_subsection(subsection_key).keys %>
<% questions_for_subsection = @form.questions_for_subsection(subsection_key) %>
<% next_page_path = get_first_page_or_check_answers(subsection_key, @case_log, @form, questions_for_subsection) %>
<%= link_to subsection_value["label"], next_page_path, class: "task-name govuk-link" %>
<% subsection_status = get_subsection_status(subsection_key, @case_log, questions_for_subsection) %>
<% subsection_status = get_subsection_status(subsection_key, @case_log, @form, questions_for_subsection) %>
<strong class="govuk-tag app-task-list__tag <%= TasklistHelper::STYLES[subsection_status] %>">
<%= TasklistHelper::STATUSES[subsection_status] %>
</strong>

11
config/forms/2021_2022.json

@ -1068,12 +1068,11 @@
"hint_text": "",
"type": "radio",
"answer_options": {
"0": "Fixed term – Secure",
"1": "Fixed term – Assured Shorthold Tenancy (AST)",
"2": "Lifetime – Secure",
"3": "Lifetime – Assured",
"4": "License agreement",
"5": "Other"
"0": "Secure (including flexible)",
"1": "Assured",
"2": "Assured Shorthold",
"3": "Licence agreement (almshouses only)",
"4": "Other"
},
"conditional_for": {
"other_tenancy_type": ["Other"]

2
docs/api/DLUHC-CORE-Data.v1.json

@ -306,7 +306,7 @@
"startdate": "12/03/2019",
"startertenancy": "No",
"tenancylength": "No",
"tenancy": "Fixed term – Secure",
"tenancy": "Secure (including flexible)",
"lettype": "Affordable Rent - General Needs",
"landlord": "This landlord",
"la": "Barnet",

10
lib/tasks/form_definition.rake

@ -32,12 +32,12 @@ namespace :form_definition do
schema = JSON.parse(file.read)
meta_schema = JSON::Validator.validator_for_name("draft4").metaschema
puts path
puts path unless Rails.env.test?
if JSON::Validator.validate(meta_schema, schema)
puts "Schema Definition is Valid"
puts "Schema Definition is Valid" unless Rails.env.test?
else
puts "Schema Definition in #{path} is not valid against draft4 json schema."
puts "Schema Definition in #{path} is not valid against draft4 json schema." unless Rails.env.test?
next
end
@ -45,8 +45,8 @@ namespace :form_definition do
file = File.open(path)
form_definition = JSON.parse(file.read)
puts path
puts JSON::Validator.fully_validate(schema, form_definition, strict: true)
puts path unless Rails.env.test?
puts JSON::Validator.fully_validate(schema, form_definition, strict: true) unless Rails.env.test?
begin
JSON::Validator.validate!(schema, form_definition)

9
spec/factories/case_log.rb

@ -19,6 +19,15 @@ FactoryBot.define do
earnings { 750 }
incfreq { "Weekly" }
end
trait :conditional_section_complete do
tenant_code { "TH356" }
age1 { 34 }
sex1 { "M" }
ethnic { 2 }
national { 4 }
ecstat1 { 2 }
other_hhmemb { 0 }
end
created_at { Time.zone.now }
updated_at { Time.zone.now }
end

2
spec/fixtures/complete_case_log.json vendored

@ -52,7 +52,7 @@
"startdate": "12/03/2019",
"startertenancy": "No",
"tenancylength": "5",
"tenancy": "Fixed term – Secure",
"tenancy": "Secure (including flexible)",
"lettype": "Affordable Rent - General Needs",
"landlord": "This landlord",
"la": "Barnet",

27
spec/helpers/tasklist_helper_spec.rb

@ -6,26 +6,27 @@ RSpec.describe TasklistHelper do
let(:completed_case_log) { FactoryBot.build(:case_log, :completed) }
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:household_characteristics_questions) { form.questions_for_subsection("household_characteristics") }
describe "get subsection status" do
let(:section) { "income_and_benefits" }
let(:income_and_benefits_questions) { form.questions_for_subsection("income_and_benefits").keys }
let(:declaration_questions) { form.questions_for_subsection("declaration").keys }
let(:local_authority_questions) { form.questions_for_subsection("local_authority").keys }
let(:income_and_benefits_questions) { form.questions_for_subsection("income_and_benefits") }
let(:declaration_questions) { form.questions_for_subsection("declaration") }
let(:local_authority_questions) { form.questions_for_subsection("local_authority") }
it "returns not started if none of the questions in the subsection are answered" do
status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions)
status = get_subsection_status("income_and_benefits", case_log, form, income_and_benefits_questions)
expect(status).to eq(:not_started)
end
it "returns cannot start yet if the subsection is declaration" do
status = get_subsection_status("declaration", case_log, declaration_questions)
status = get_subsection_status("declaration", case_log, form, declaration_questions)
expect(status).to eq(:cannot_start_yet)
end
it "returns in progress if some of the questions have been answered" do
case_log["previous_postcode"] = "P0 5TT"
status = get_subsection_status("local_authority", case_log, local_authority_questions)
status = get_subsection_status("local_authority", case_log, form, local_authority_questions)
expect(status).to eq(:in_progress)
end
@ -35,14 +36,22 @@ RSpec.describe TasklistHelper do
case_log["benefits"] = "All"
case_log["hb"] = "Do not know"
status = get_subsection_status("income_and_benefits", case_log, income_and_benefits_questions)
status = get_subsection_status("income_and_benefits", case_log, form, income_and_benefits_questions)
expect(status).to eq(:completed)
end
it "returns not started if the subsection is declaration and all the questions are completed" do
status = get_subsection_status("declaration", completed_case_log, declaration_questions)
status = get_subsection_status("declaration", completed_case_log, form, declaration_questions)
expect(status).to eq(:not_started)
end
let(:conditional_section_complete_case_log) { FactoryBot.build(:case_log, :conditional_section_complete) }
it "sets the correct status for sections with conditional questions" do
status = get_subsection_status(
"household_characteristics", conditional_section_complete_case_log, form, household_characteristics_questions
)
expect(status).to eq(:completed)
end
end
describe "get next incomplete section" do
@ -79,8 +88,6 @@ RSpec.describe TasklistHelper do
end
describe "get_first_page_or_check_answers" do
let(:household_characteristics_questions) { form.questions_for_subsection("household_characteristics").keys }
it "returns the check answers page path if the section has been started already" do
expect(get_first_page_or_check_answers("household_characteristics", case_log, form, household_characteristics_questions)).to match(/check_answers/)
end

2
spec/lib/tasks/form_definition_validator_spec.rb

@ -27,7 +27,7 @@ describe "rake form_definition:validate", type: :task do
end
it "runs the validate task for the given form definition" do
expect(JSON::Validator).to receive(:validate!).at_least(2).times
expect(JSON::Validator).to receive(:validate!).at_least(1).time
task.invoke("config/forms/2021_2022.json")
end
end

18
spec/models/case_log_spec.rb

@ -182,39 +182,39 @@ RSpec.describe Form, type: :model do
it "Must be completed and between 2 and 99 if type of tenancy is Assured shorthold" do
expect {
CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
CaseLog.create!(tenancy: "Assured Shorthold",
tenancylength: 1)
}.to raise_error(ActiveRecord::RecordInvalid)
expect {
CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
CaseLog.create!(tenancy: "Assured Shorthold",
tenancylength: nil)
}.to raise_error(ActiveRecord::RecordInvalid)
expect {
CaseLog.create!(tenancy: "Fixed term – Assured Shorthold Tenancy (AST)",
CaseLog.create!(tenancy: "Assured Shorthold",
tenancylength: 2)
}.not_to raise_error
end
it "Must be empty or between 2 and 99 if type of tenancy is Secure" do
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancylength: 1)
}.to raise_error(ActiveRecord::RecordInvalid)
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancylength: 100)
}.to raise_error(ActiveRecord::RecordInvalid)
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancylength: nil)
}.not_to raise_error
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancylength: 2)
}.not_to raise_error
end
@ -294,12 +294,12 @@ RSpec.describe Form, type: :model do
it "must not be provided if tenancy type is not other" do
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancyother: "the other reason provided")
}.to raise_error(ActiveRecord::RecordInvalid)
expect {
CaseLog.create!(tenancy: "Fixed term – Secure",
CaseLog.create!(tenancy: "Secure (including flexible)",
tenancyother: nil)
}.not_to raise_error
end

Loading…
Cancel
Save