From 6aef3f0900c735a75f8dc29668692a89949165c3 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 4 Nov 2021 13:30:20 +0000 Subject: [PATCH 01/26] JsonValidate_Initial --- app/helpers/json_schema_validation.rb | 88 +++++++++++++++++++++++++ spec/fixtures/forms/test_validator.json | 24 +++++++ 2 files changed, 112 insertions(+) create mode 100644 app/helpers/json_schema_validation.rb create mode 100644 spec/fixtures/forms/test_validator.json diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb new file mode 100644 index 000000000..be0a4db3a --- /dev/null +++ b/app/helpers/json_schema_validation.rb @@ -0,0 +1,88 @@ +require "json-schema" +require "json" + +# "form_type": "lettings", +# "start_year": 2021, +# "end_year": 2022, +# "sections": { +# "about_this_log": { +# "label": "About this log", +# "subsections": { +# "about_this_log": { +# "label": "About this log", +# "pages": { + # "tenant_code": { + # "header": "", + # "description": "", + # "questions": { + # "tenant_code": { + # "check_answer_label": "Tenant code", + # "header": "What is the tenant code?", + # "hint_text": "", + # "type": "text" + # } + # } + # }, + +schema = { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://example.com/product.schema.json", + "title": "Form", + "description": "A form", + "type": "object", + "properties": { + "form_type": { + "description": "", + "type": "string" + }, + "start_year": { + "description": "", + "type": "int" + }, + "end_year": { + "description": "", + "type": "int" + }, + "sections": { + "description": "", + "type": "object", + "properties": { + "page_name": { + "description": "", + "type": "string" + }, + } + } + } +} + +begin + + # file = File.open("config/forms/2021_2022.json") + file = File.open("spec/fixtures/forms/test_validator.json") + data = JSON.parse(file.read) + + if JSON::Validator.validate!(schema, data) + puts "Success" + else + puts "Validation failed" + end + + begin + JSON::Validator.validate!(schema, data) + rescue JSON::Schema::ValidationError => e + e.message + end + + # def get_all_form_paths + # form_paths = [] + # directories = ["config/forms", "spec/fixtures/forms"] + # directories.each do |directory| + # Dir.glob("#{directory}/*.json").each do |form_path| + # form_path = form_path.sub(".json", "").split("/")[-1] + # form_paths.push(form_path) + # end + # end + # form_paths + # end +end diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json new file mode 100644 index 000000000..2ac97e26d --- /dev/null +++ b/spec/fixtures/forms/test_validator.json @@ -0,0 +1,24 @@ +{ + "form_type": "lettings", + "sections": { + "household": { + "label": "About the household", + "subsections": { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + } + } + } +} From 6c272dad87defd5e3fe30958e9fb56188cf22f36 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 4 Nov 2021 15:51:01 +0000 Subject: [PATCH 02/26] can't find jsonspec --- app/helpers/json_schema_validation.rb | 63 ++++++++++++++------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index be0a4db3a..777ffc39a 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -23,44 +23,45 @@ require "json" # } # } # }, +begin -schema = { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://example.com/product.schema.json", - "title": "Form", - "description": "A form", - "type": "object", - "properties": { - "form_type": { - "description": "", - "type": "string" - }, - "start_year": { - "description": "", - "type": "int" - }, - "end_year": { - "description": "", - "type": "int" - }, - "sections": { - "description": "", - "type": "object", - "properties": { - "page_name": { - "description": "", - "type": "string" - }, + schema = { + "$schema": "https://json-schema.org/draft-04/schema#", + "$id": "https://example.com/product.schema.json", + "title": "Form", + "description": "A form", + "type": "object", + "properties": { + "form_type": { + "description": "", + "type": "string" + }, + "start_year": { + "description": "", + "type": "int" + }, + "end_year": { + "description": "", + "type": "int" + }, + "sections": { + "description": "", + "type": "object", + "properties": { + "page_name": { + "description": "", + "type": "string" + }, + } } } } -} - -begin # file = File.open("config/forms/2021_2022.json") file = File.open("spec/fixtures/forms/test_validator.json") - data = JSON.parse(file.read) + puts data = JSON.parse(file.read) + + puts JSON::Validator.validate(schema, data) if JSON::Validator.validate!(schema, data) puts "Success" From a0d73baf6ab4b7ad9a35d66e49b3f3e750a995e8 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 5 Nov 2021 16:58:44 +0000 Subject: [PATCH 03/26] basic intial operation --- app/helpers/json_schema_validation.rb | 24 +++++++++++++----------- spec/fixtures/forms/test_validator.json | 2 ++ 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 777ffc39a..dcb0c20a4 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -26,7 +26,7 @@ require "json" begin schema = { - "$schema": "https://json-schema.org/draft-04/schema#", + "$schema": "http://json-schema.org/draft-04/schema", "$id": "https://example.com/product.schema.json", "title": "Form", "description": "A form", @@ -47,27 +47,29 @@ begin "sections": { "description": "", "type": "object", - "properties": { - "page_name": { + "patternProperties": { + "^[0-9]+$": { "description": "", "type": "string" }, + "label": { + "description": "", + "type": "string" + } } } } } - # file = File.open("config/forms/2021_2022.json") - file = File.open("spec/fixtures/forms/test_validator.json") - puts data = JSON.parse(file.read) + path = "spec/fixtures/forms/test_validator.json" + # path = "config/forms/2021_2022.json" + + file = File.open(path) + data = JSON.parse(file.read) puts JSON::Validator.validate(schema, data) - if JSON::Validator.validate!(schema, data) - puts "Success" - else - puts "Validation failed" - end + puts JSON::Validator.fully_validate(schema, data, :strict => true) begin JSON::Validator.validate!(schema, data) diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index 2ac97e26d..0539a719b 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -1,5 +1,7 @@ { "form_type": "lettings", + "start_year": 2021, + "end_year": 2022, "sections": { "household": { "label": "About the household", From ceb8ea03cb4d56f231441463781362e14eb9de2e Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 5 Nov 2021 17:06:13 +0000 Subject: [PATCH 04/26] and check schema --- app/helpers/json_schema_validation.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index dcb0c20a4..4d947c450 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -55,12 +55,24 @@ begin "label": { "description": "", "type": "string" + }, + "subsections": { + "type": "object" } } } } } + metaschema = JSON::Validator.validator_for_name("draft4").metaschema + # => true + if JSON::Validator.validate(metaschema, schema) + puts "schema valid" + else + puts "schema not valid" + return + end + path = "spec/fixtures/forms/test_validator.json" # path = "config/forms/2021_2022.json" From 614851af34258c8d3496d8df6e8e50676a3d1bc2 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Sun, 7 Nov 2021 18:37:43 +0000 Subject: [PATCH 05/26] generated schema, is real 2021_2022 valid --- app/helpers/json_schema_validation.rb | 435 ++++++++++++++++++++---- spec/fixtures/forms/test_validator.json | 1 + 2 files changed, 375 insertions(+), 61 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 4d947c450..d500e018d 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -5,72 +5,385 @@ require "json" # "start_year": 2021, # "end_year": 2022, # "sections": { +# "about_this_log": { +# "label": "About this log", +# "subsections": { # "about_this_log": { # "label": "About this log", -# "subsections": { -# "about_this_log": { -# "label": "About this log", -# "pages": { - # "tenant_code": { - # "header": "", - # "description": "", - # "questions": { - # "tenant_code": { - # "check_answer_label": "Tenant code", - # "header": "What is the tenant code?", - # "hint_text": "", - # "type": "text" - # } - # } - # }, +# "pages": { + # "tenant_code": { + # "header": "", + # "description": "", + # "questions": { + # "tenant_code": { + # "check_answer_label": "Tenant code", + # "header": "What is the tenant code?", + # "hint_text": "", + # "type": "text" + # } + # } + # }, begin schema = { - "$schema": "http://json-schema.org/draft-04/schema", - "$id": "https://example.com/product.schema.json", - "title": "Form", - "description": "A form", - "type": "object", - "properties": { - "form_type": { - "description": "", - "type": "string" - }, - "start_year": { - "description": "", - "type": "int" - }, - "end_year": { - "description": "", - "type": "int" - }, + "$schema": "http://json-schema.org/draft-04/schema", + "$id": "http://example.com/example.json", + "type": "object", + "title": "The root schema", + "description": "The root schema comprises the entire JSON document.", + "default": {}, + "examples": [ + { + "form_type": "lettings", + "start_year": 2021, + "end_year": 2022, "sections": { - "description": "", - "type": "object", - "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - }, - "label": { - "description": "", - "type": "string" - }, + "household": { + "label": "About the household", "subsections": { - "type": "object" + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } } } } } - } + ], + "required": [ + "form_type", + "start_year", + "end_year", + "sections" + ], + "properties": { + "form_type": { + "$id": "#/properties/form_type", + "type": "string", + "title": "The form_type schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "lettings" + ] + }, + "start_year": { + "$id": "#/properties/start_year", + "type": "integer", + "title": "The start_year schema", + "description": "An explanation about the purpose of this instance.", + "default": 0, + "examples": [ + 2021 + ] + }, + "end_year": { + "$id": "#/properties/end_year", + "type": "integer", + "title": "The end_year schema", + "description": "An explanation about the purpose of this instance.", + "default": 0, + "examples": [ + 2022 + ] + }, + "sections": { + "$id": "#/properties/sections", + "type": "object", + "title": "The sections schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "household": { + "label": "About the household", + "subsections": { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + } + } + } + ], + "required": [ + "household" + ], + "properties": { + "household": { + "$id": "#/properties/sections/properties/household", + "type": "object", + "title": "The household schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "label": "About the household", + "subsections": { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + } + } + ], + "required": [ + "label", + "subsections" + ], + "properties": { + "label": { + "$id": "#/properties/sections/properties/household/properties/label", + "type": "string", + "title": "The label schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "About the household" + ] + }, + "subsections": { + "$id": "#/properties/sections/properties/household/properties/subsections", + "type": "object", + "title": "The subsections schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + } + ], + "required": [ + "household_characteristics" + ], + "properties": { + "household_characteristics": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics", + "type": "object", + "title": "The household_characteristics schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + ], + "required": [ + "label", + "pages" + ], + "properties": { + "label": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/label", + "type": "string", + "title": "The label schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "Household characteristics" + ] + }, + "pages": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages", + "type": "object", + "title": "The pages schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + ], + "required": [ + "tenant_code" + ], + "properties": { + "tenant_code": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code", + "type": "object", + "title": "The tenant_code schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + } + ], + "required": [ + "questions" + ], + "properties": { + "questions": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions", + "type": "object", + "title": "The questions schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + ], + "required": [ + "tenant_code" + ], + "properties": { + "tenant_code": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code", + "type": "object", + "title": "The tenant_code schema", + "description": "An explanation about the purpose of this instance.", + "default": {}, + "examples": [ + { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + ], + "required": [ + "check_answer_label", + "header", + "type" + ], + "properties": { + "check_answer_label": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/check_answer_label", + "type": "string", + "title": "The check_answer_label schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "Tenant code" + ] + }, + "header": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/header", + "type": "string", + "title": "The header schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "What is the tenant code?" + ] + }, + "type": { + "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/type", + "type": "string", + "title": "The type schema", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": [ + "text" + ] + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true + } + }, + "additionalProperties": true +} metaschema = JSON::Validator.validator_for_name("draft4").metaschema - # => true + if JSON::Validator.validate(metaschema, schema) - puts "schema valid" + puts "schema valid" else - puts "schema not valid" - return + puts "schema not valid" + return end path = "spec/fixtures/forms/test_validator.json" @@ -84,20 +397,20 @@ begin puts JSON::Validator.fully_validate(schema, data, :strict => true) begin - JSON::Validator.validate!(schema, data) + JSON::Validator.validate!(schema, data) rescue JSON::Schema::ValidationError => e - e.message + e.message end # def get_all_form_paths - # form_paths = [] - # directories = ["config/forms", "spec/fixtures/forms"] - # directories.each do |directory| - # Dir.glob("#{directory}/*.json").each do |form_path| - # form_path = form_path.sub(".json", "").split("/")[-1] - # form_paths.push(form_path) - # end + # form_paths = [] + # directories = ["config/forms", "spec/fixtures/forms"] + # directories.each do |directory| + # Dir.glob("#{directory}/*.json").each do |form_path| + # form_path = form_path.sub(".json", "").split("/")[-1] + # form_paths.push(form_path) # end - # form_paths + # end + # form_paths # end end diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index 0539a719b..13aed9e5f 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -8,6 +8,7 @@ "subsections": { "household_characteristics": { "label": "Household characteristics", + "baddata": "Shouldn't be here but what you gonna do?", "pages": { "tenant_code": { "questions": { From cf6e5a099462ce89ae602cce49944f9555ae96c8 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Sun, 7 Nov 2021 19:20:46 +0000 Subject: [PATCH 06/26] move about --- app/helpers/json_schema_validation.rb | 414 +---- config/forms/schema/2021_2022.json | 2134 +++++++++++++++++++++++++ config/forms/schema/generic.json | 38 + 3 files changed, 2206 insertions(+), 380 deletions(-) create mode 100644 config/forms/schema/2021_2022.json create mode 100644 config/forms/schema/generic.json diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index d500e018d..3e46be8e0 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -5,385 +5,39 @@ require "json" # "start_year": 2021, # "end_year": 2022, # "sections": { -# "about_this_log": { -# "label": "About this log", -# "subsections": { # "about_this_log": { # "label": "About this log", -# "pages": { - # "tenant_code": { - # "header": "", - # "description": "", - # "questions": { - # "tenant_code": { - # "check_answer_label": "Tenant code", - # "header": "What is the tenant code?", - # "hint_text": "", - # "type": "text" - # } - # } - # }, +# "subsections": { +# "about_this_log": { +# "label": "About this log", +# "pages": { + # "tenant_code": { + # "header": "", + # "description": "", + # "questions": { + # "tenant_code": { + # "check_answer_label": "Tenant code", + # "header": "What is the tenant code?", + # "hint_text": "", + # "type": "text" + # } + # } + # }, begin - schema = { - "$schema": "http://json-schema.org/draft-04/schema", - "$id": "http://example.com/example.json", - "type": "object", - "title": "The root schema", - "description": "The root schema comprises the entire JSON document.", - "default": {}, - "examples": [ - { - "form_type": "lettings", - "start_year": 2021, - "end_year": 2022, - "sections": { - "household": { - "label": "About the household", - "subsections": { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - } - } - } - } - } - ], - "required": [ - "form_type", - "start_year", - "end_year", - "sections" - ], - "properties": { - "form_type": { - "$id": "#/properties/form_type", - "type": "string", - "title": "The form_type schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "lettings" - ] - }, - "start_year": { - "$id": "#/properties/start_year", - "type": "integer", - "title": "The start_year schema", - "description": "An explanation about the purpose of this instance.", - "default": 0, - "examples": [ - 2021 - ] - }, - "end_year": { - "$id": "#/properties/end_year", - "type": "integer", - "title": "The end_year schema", - "description": "An explanation about the purpose of this instance.", - "default": 0, - "examples": [ - 2022 - ] - }, - "sections": { - "$id": "#/properties/sections", - "type": "object", - "title": "The sections schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "household": { - "label": "About the household", - "subsections": { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - } - } - } - } - ], - "required": [ - "household" - ], - "properties": { - "household": { - "$id": "#/properties/sections/properties/household", - "type": "object", - "title": "The household schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "label": "About the household", - "subsections": { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - } - } - } - ], - "required": [ - "label", - "subsections" - ], - "properties": { - "label": { - "$id": "#/properties/sections/properties/household/properties/label", - "type": "string", - "title": "The label schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "About the household" - ] - }, - "subsections": { - "$id": "#/properties/sections/properties/household/properties/subsections", - "type": "object", - "title": "The subsections schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - } - } - ], - "required": [ - "household_characteristics" - ], - "properties": { - "household_characteristics": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics", - "type": "object", - "title": "The household_characteristics schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - } - ], - "required": [ - "label", - "pages" - ], - "properties": { - "label": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/label", - "type": "string", - "title": "The label schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "Household characteristics" - ] - }, - "pages": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages", - "type": "object", - "title": "The pages schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - } - ], - "required": [ - "tenant_code" - ], - "properties": { - "tenant_code": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code", - "type": "object", - "title": "The tenant_code schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } - ], - "required": [ - "questions" - ], - "properties": { - "questions": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions", - "type": "object", - "title": "The questions schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - ], - "required": [ - "tenant_code" - ], - "properties": { - "tenant_code": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code", - "type": "object", - "title": "The tenant_code schema", - "description": "An explanation about the purpose of this instance.", - "default": {}, - "examples": [ - { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - ], - "required": [ - "check_answer_label", - "header", - "type" - ], - "properties": { - "check_answer_label": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/check_answer_label", - "type": "string", - "title": "The check_answer_label schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "Tenant code" - ] - }, - "header": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/header", - "type": "string", - "title": "The header schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "What is the tenant code?" - ] - }, - "type": { - "$id": "#/properties/sections/properties/household/properties/subsections/properties/household_characteristics/properties/pages/properties/tenant_code/properties/questions/properties/tenant_code/properties/type", - "type": "string", - "title": "The type schema", - "description": "An explanation about the purpose of this instance.", - "default": "", - "examples": [ - "text" - ] - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true - } - }, - "additionalProperties": true -} + path = "config/forms/schema/generic.json" + # path = "config/forms/schema/2021_2022.json" + + file = File.open(path) + schema = JSON.parse(file.read) metaschema = JSON::Validator.validator_for_name("draft4").metaschema if JSON::Validator.validate(metaschema, schema) - puts "schema valid" + puts "schema valid" else - puts "schema not valid" - return + puts "schema not valid" + return end path = "spec/fixtures/forms/test_validator.json" @@ -397,20 +51,20 @@ begin puts JSON::Validator.fully_validate(schema, data, :strict => true) begin - JSON::Validator.validate!(schema, data) + JSON::Validator.validate!(schema, data) rescue JSON::Schema::ValidationError => e - e.message + e.message end # def get_all_form_paths - # form_paths = [] - # directories = ["config/forms", "spec/fixtures/forms"] - # directories.each do |directory| - # Dir.glob("#{directory}/*.json").each do |form_path| - # form_path = form_path.sub(".json", "").split("/")[-1] - # form_paths.push(form_path) + # form_paths = [] + # directories = ["config/forms", "spec/fixtures/forms"] + # directories.each do |directory| + # Dir.glob("#{directory}/*.json").each do |form_path| + # form_path = form_path.sub(".json", "").split("/")[-1] + # form_paths.push(form_path) + # end # end - # end - # form_paths + # form_paths # end end diff --git a/config/forms/schema/2021_2022.json b/config/forms/schema/2021_2022.json new file mode 100644 index 000000000..2a825ffb8 --- /dev/null +++ b/config/forms/schema/2021_2022.json @@ -0,0 +1,2134 @@ +{ + "form_type": "lettings", + "start_year": 2021, + "end_year": 2022, + "sections": { + "household": { + "label": "About the household", + "subsections": { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "header": "", + "description": "", + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "hint_text": "", + "type": "text" + } + } + }, + "person_1_age": { + "header": "", + "description": "", + "questions": { + "person_1_age": { + "check_answer_label": "Tenant's age", + "header": "What is the tenant's age?", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 120, + "step": 1 + } + } + }, + "person_1_gender": { + "header": "", + "description": "", + "questions": { + "person_1_gender": { + "check_answer_label": "Tenant's gender", + "header": "Which of these best describes the tenant's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + } + } + }, + "tenant_ethnic_group": { + "header": "", + "description": "", + "questions": { + "tenant_ethnic_group": { + "check_answer_label": "Ethnicity", + "header": "What is the tenant's ethnic group?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "White: English/Scottish/Welsh/Northern Irish/British", + "1": "White: Irish", + "2": "White: Gypsy/Irish Traveller", + "3": "White: Other", + "4": "Mixed: White & Black Caribbean", + "5": "Mixed: White & Black African", + "6": "Mixed: White & Asian", + "7": "Mixed: Other", + "8": "Asian or Asian British: Indian", + "9": "Asian or Asian British: Pakistani", + "10": "Asian or Asian British: Bangladeshi", + "11": "Asian or Asian British: Chinese", + "12": "Asian or Asian British: Other", + "13": "Black: Caribbean", + "14": "Black: African", + "15": "Black: Other", + "16": "Other Ethnic Group: Arab", + "17": "Other Ethnic Group: Other", + "18": "Prefer not to say" + } + } + } + }, + "tenant_nationality": { + "header": "", + "description": "", + "questions": { + "tenant_nationality": { + "check_answer_label": "Nationality", + "header": "What is the tenant's nationality?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "UK national resident in UK", + "1": "A current or former reserve in the UK Armed Forces (exc. National Service)", + "2": "UK national returning from residence overseas", + "3": "Czech Republic", + "4": "Estonia", + "5": "Hungary", + "6": "Latvia", + "7": "Lithuania", + "8": "Poland", + "9": "Slovakia", + "10": "Bulgaria", + "11": "Romania", + "12": "Ireland", + "13": "Other EU Economic Area (EEA country)", + "14": "Any other country", + "15": "Prefer not to say" + } + } + } + }, + "tenant_economic_status": { + "header": "", + "description": "", + "questions": { + "person_1_economic_status": { + "check_answer_label": "Work", + "header": "Which of these best describes the tenant's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + } + } + }, + "household_number_of_other_members": { + "header": "", + "description": "", + "questions": { + "household_number_of_other_members": { + "check_answer_label": "Number of Other Household Members", + "header": "How many other people are there in the household?", + "hint_text": "The maximum number of others is 7", + "type": "numeric", + "min": 0, + "max": 7, + "step": 1, + "conditional_for": { + "person_2_relationship": ">0", + "person_2_age": ">0", + "person_2_gender": ">0", + "person_2_economic_status": ">0", + "person_3_relationship": ">1", + "person_3_age": ">1", + "person_3_gender": ">1", + "person_3_economic_status": ">1", + "person_4_relationship": ">2", + "person_4_age": ">2", + "person_4_gender": ">2", + "person_4_economic_status": ">2", + "person_5_relationship": ">3", + "person_5_age": ">3", + "person_5_gender": ">3", + "person_5_economic_status": ">3", + "person_6_relationship": ">4", + "person_6_age": ">4", + "person_6_gender": ">4", + "person_6_economic_status": ">4", + "person_7_relationship": ">5", + "person_7_age": ">5", + "person_7_gender": ">5", + "person_7_economic_status": ">5", + "person_8_relationship": ">6", + "person_8_age": ">6", + "person_8_gender": ">6", + "person_8_economic_status": ">6" + } + }, + "person_2_relationship": { + "check_answer_label": "Person 2's relationship to lead tenant", + "header": "What's person 2's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_2_age": { + "check_answer_label": "Person 2's age", + "header": "What's person 2's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_2_gender": { + "check_answer_label": "Person 2's gender", + "header": "Which of these best describes person 2's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_2_economic_status": { + "check_answer_label": "Person 2's Work", + "header": "Which of these best describes person 2's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_3_relationship": { + "check_answer_label": "Person 3's relationship to lead tenant", + "header": "What's person 3's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_3_age": { + "check_answer_label": "Person 3's age", + "header": "What's person 3's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_3_gender": { + "check_answer_label": "Person 3's gender", + "header": "Which of these best describes person 3's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_3_economic_status": { + "check_answer_label": "Person 3's Work", + "header": "Which of these best describes person 3's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_4_relationship": { + "check_answer_label": "Person 4's relationship to lead tenant", + "header": "What's person 4's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_4_age": { + "check_answer_label": "Person 4's age", + "header": "What's person 4's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_4_gender": { + "check_answer_label": "Person 4's gender", + "header": "Which of these best describes person 4's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_4_economic_status": { + "check_answer_label": "Person 4's Work", + "header": "Which of these best describes person 4's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_5_relationship": { + "check_answer_label": "Person 5's relationship to lead tenant", + "header": "What's person 5's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_5_age": { + "check_answer_label": "Person 5's age", + "header": "What's person 5's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_5_gender": { + "check_answer_label": "Person 5's gender", + "header": "Which of these best describes person 5's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_5_economic_status": { + "check_answer_label": "Person 5's Work", + "header": "Which of these best describes person 5's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_6_relationship": { + "check_answer_label": "Person 6's relationship to lead tenant", + "header": "What's person 6's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_6_age": { + "check_answer_label": "Person 6's age", + "header": "What's person 6's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_6_gender": { + "check_answer_label": "Person 6's gender", + "header": "Which of these best describes person 6's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_6_economic_status": { + "check_answer_label": "Person 6's Work", + "header": "Which of these best describes person 6's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_7_relationship": { + "check_answer_label": "Person 7's relationship to lead tenant", + "header": "What's person 7's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_7_age": { + "check_answer_label": "Person 7's age", + "header": "What's person 7's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_7_gender": { + "check_answer_label": "Person 7's gender", + "header": "Which of these best describes person 7's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_7_economic_status": { + "check_answer_label": "Person 7's Work", + "header": "Which of these best describes person 7's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + }, + "person_8_relationship": { + "check_answer_label": "Person 8's relationship to lead tenant", + "header": "What's person 8's relationship to lead tenant", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Partner", + "1": "Child - includes young adult and grown-up", + "2": "Other", + "3": "Prefer not to say" + } + }, + "person_8_age": { + "check_answer_label": "Person 8's age", + "header": "What's person 8's age", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "person_8_gender": { + "check_answer_label": "Person 8's gender", + "header": "Which of these best describes person 8's gender identity?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "person_8_economic_status": { + "check_answer_label": "Person 8's Work", + "header": "Which of these best describes person 8's working situation?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Part-time - Less than 30 hours", + "1": "Full-time - 30 hours or more", + "2": "In government training into work, such as New Deal", + "3": "Jobseeker", + "4": "Retired", + "5": "Not seeking work", + "6": "Full-time student", + "7": "Unable to work because of long term sick or disability", + "8": "Child under 16", + "9": "Other", + "10": "Prefer not to say" + } + } + } + } + } + }, + "household_situation": { + "label": "Household situation", + "pages": { + "previous_housing_situation": { + "header": "", + "description": "", + "questions": { + "previous_housing_situation": { + "header": "What was the tenant’s housing situation immediately before this letting?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Owner occupation (private) ", + "1": "Owner occupation (low cost home ownership)", + "2": "Private sector tenancy", + "3": "Tied housing or rented with job", + "4": "Supported housing", + "5": "Sheltered accomodation", + "6": "Residential care home", + "7": "Living with friends or family", + "8": "Refuge", + "9": "Hospital", + "10": "Prison / approved probation hostel", + "11": "Direct access hostel", + "12": "Bed & Breakfast", + "13": "Mobile home / caravan", + "14": "Any other temporary accommodation", + "15": "Home Office Asylum Support", + "16": "Children’s home / foster care", + "17": "Rough sleeping", + "18": "Other", + "19": "Fixed term Local Authority General Needs tenancy", + "20": "Lifetime Local Authority General Needs tenancy", + "21": "Fixed term PRP General Needs tenancy", + "22": "Lifetime PRP General Needs tenancy" + } + } + } + }, + "homelessness": { + "header": "", + "description": "", + "questions": { + "homelessness": { + "header": "Did the tenant experience homelessness immediately before this letting?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes - assessed as homeless by a local authority and owed a homelessness duty. Including if threatened with homelessness within 56 days", + "1": "Yes - other homelessness ", + "2": "No" + } + } + } + }, + "reason_for_leaving_last_settled_home": { + "header": "Leaving their last settled home", + "description": "", + "questions": { + "reason_for_leaving_last_settled_home": { + "header": "What is the tenant’s main reason for leaving?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Permanently decanted from another property owned by this landlord", + "1": "Left home country as a refugee", + "2": "Loss of tied accommodation", + "3": "Domestic abuse", + "4": "(Non violent) relationship breakdown with partner", + "5": "Asked to leave by family or friends", + "6": "Racial harassment", + "7": "Other problems with neighbours", + "8": "Property unsuitable because of overcrowding", + "9": "End of assured shorthold tenancy - no fault", + "10": "End of assured shorthold tenancy - tenant's fault", + "11": "End of fixed term tenancy - no fault", + "12": "End of fixed term tenancy - tenant's fault", + "13": "Repossession", + "14": "Under occupation - offered incentive to downsize", + "15": "Under occupation - no incentive", + "16": "Property unsuitable because of ill health / disability", + "17": "Property unsuitable because of poor condition", + "18": "Couldn't afford fees attached to renewing the tenancy", + "19": "Couldn't afford increase in rent", + "20": "Couldn't afford rent or mortgage - welfare reforms", + "21": "Couldn't afford rent or mortgage - employment", + "22": "Couldn't afford rent or mortgage - other", + "23": "To move nearer to family / friends / school", + "24": "To move nearer to work", + "25": "To move to accomodation with support", + "26": "To move to independent accomodation", + "27": "Hate crime", + "28": "Death of household member in last settled accomodation", + "29": "Discharged from prison", + "30": "Discharged from long stay hospital or similar institution", + "31": "Other", + "32": "Do not know", + "33": "Prefer not to say" + }, + "conditional_for": { + "other_reason_for_leaving_last_settled_home": ["Other"] + } + }, + "other_reason_for_leaving_last_settled_home": { + "header": "Please state the reason for leaving last settled home", + "hint_text": "", + "type": "text" + }, + "benefit_cap_spare_room_subsidy": { + "header": "Was the reason for leaving because of the benefit cap or removal of the spare room subsidy?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes - benefit cap", + "1": "Yes - removal of the spare room subsidy", + "2": "Yes - both the benefit cap and the removal of the spare room subsidy", + "3": "No", + "4": "Do not know", + "5": "Prefer not to say" + } + } + } + } + } + }, + "household_needs": { + "label": "Household needs", + "pages": { + "armed_forces": { + "header": "Experience of the UK Armed Forces", + "description": "", + "questions": { + "armed_forces": { + "header": "Has the tenant ever served in the UK armed forces?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Armed Forces", + "answer_options": { + "0": "Yes - a regular", + "1": "Yes - a reserve", + "2": "No", + "3": "Prefer not to say" + }, + "conditional_for": { + "armed_forces_active": ["Yes - a regular", "Yes - a reserve"], + "armed_forces_injured": ["Yes - a regular", "Yes - a reserve"] + } + }, + "armed_forces_active": { + "header": "Are they still serving?", + "hint_text": "", + "type": "radio", + "check_answer_label": "When did they leave the Armed Forces?", + "answer_options": { + "0": "Yes", + "1": "No - they left up to 5 years ago", + "2": "No - they left more than 5 years ago", + "3": "Prefer not to say" + } + }, + "armed_forces_injured": { + "header": "Were they seriously injured or ill as a result of their service?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Has anyone in the household been seriously injured or ill as a result of their service in the armed forces?", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Prefer not to say" + } + }, + "armed_forces_partner": { + "header": "Was the tenant the spouse or civil partner of someone who served in the UK armed forces?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Was the tenant the spouse or civil partner of someone who served in the UK armed forces?", + "answer_options": { + "0": "Yes - was the spouse or civil partner of a UK Armed Forces member and have separated within the last 2 years", + "1": "Yes - was the spouse or civil partner of a UK Armed Forces member who died within the last 2 years", + "2": "No", + "3": "Prefer not to say" + } + } + } + }, + "medical_conditions": { + "header": "", + "description": "", + "questions": { + "medical_conditions": { + "header": "Does anyone in the household have any of the following that they expect to last for 12 months or more:
  • Physical Condition
  • Mental Health Condition
  • Other Illness
", + "hint_text": "", + "type": "radio", + "check_answer_label": "Physical, mental health or illness in the household", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Do not know", + "3": "Prefer not to say" + } + } + } + }, + "pregnancy": { + "header": "", + "description": "", + "questions": { + "pregnancy": { + "header": "Is anyone in the household pregnant?", + "hint_text": "", + "type": "radio", + "check_answer_label": "Pregnancy in the household", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Prefer not to say" + } + } + } + }, + "accessibility_requirements": { + "header": "", + "description": "", + "questions": { + "accessibility_requirements": { + "header": "Are any of these affected by their condition or illness?", + "hint_text": "Select all that apply", + "type": "checkbox", + "check_answer_label": "Disability requirements", + "answer_options": { + "accessibility_requirements_fully_wheelchair_accessible_housing": "Fully wheelchair accessible housing", + "accessibility_requirements_wheelchair_access_to_essential_rooms": "Wheelchair access to essential rooms", + "accessibility_requirements_level_access_housing": "Level access housing", + "accessibility_requirements_other_disability_requirements": "Other disability requirements", + "accessibility_requirements_no_disability_requirements": "No disability requirements", + "divider_a": true, + "accessibility_requirements_do_not_know": "Do not know", + "divider_b": true, + "accessibility_requirements_prefer_not_to_say": "Prefer not to say" + } + } + } + }, + "condition_effects": { + "header": "", + "description": "", + "questions": { + "condition_effects": { + "header": "Are any of these affected by their condition or illness?", + "hint_text": "Select all that apply", + "type": "checkbox", + "check_answer_label": "Conditions or illnesses", + "answer_options": { + "condition_effects_vision": "Vision - such as blindness or partial sight", + "condition_effects_hearing": "Hearing - such as deafness or partial hearing", + "condition_effects_mobility": "Mobility - such as walking short distances or climbing stairs", + "condition_effects_dexterity": "Dexterity - such as lifting and carrying objects or using a keyboard", + "condition_effects_stamina": "Stamina or breathing or fatigue", + "condition_effects_learning": "Learning or understanding or concentrating", + "condition_effects_memory": "Memory", + "condition_effects_mental_health": "Mental health - such as depression, anxiety, schizophrenia or bipolar", + "condition_effects_social_or_behavioral": "Socially or behaviourally - such as those associated with autism spectral disorder (ASD) including Aspergers’ or attention deficit hyperactivity disorder (ADHD))", + "condition_effects_other": "Other", + "divider": true, + "condition_effects_prefer_not_to_say": "Prefer not to say" + } + } + } + } + } + } + } + }, + "tenancy_and_property": { + "label": "Tenancy and property information", + "subsections": { + "tenancy_information": { + "label": "Tenancy information", + "pages": { + "tenancy_code": { + "header": "", + "description": "", + "questions": { + "tenancy_code": { + "check_answer_label": "What is the tenancy code?", + "header": "What is the tenancy code?", + "hint_text": "", + "type": "text" + } + } + }, + "tenancy_start_date": { + "header": "", + "description": "", + "questions": { + "tenancy_start_date": { + "check_answer_label": "When is the tenancy start date?", + "header": "What is the tenancy start date?", + "hint_text": "For example, 27 3 2007", + "type": "date" + } + } + }, + "starter_tenancy": { + "header": "", + "description": "", + "questions": { + "starter_tenancy": { + "check_answer_label": "Is this a starter or introductory tenancy?", + "header": "Is this a starter tenancy?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + }, + "fixed_term_tenancy": { + "header": "", + "description": "", + "questions": { + "fixed_term_tenancy": { + "check_answer_label": "If the main tenancy is a fixed term tenancy, please provide the length of the fixed term (to the nearest year) excluding any starter/introductory period", + "header": "If fixed-term, what is the length of the fixed-term tenancy after any starter period?", + "hint_text": "To the nearest year", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + } + } + }, + "tenancy_type": { + "header": "", + "description": "", + "questions": { + "tenancy_type": { + "check_answer_label": "Type of main tenancy (after any starter/introductory period)", + "header": "What is the type of tenancy after the starter period has ended?", + "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" + }, + "conditional_for": { + "other_tenancy_type": ["Other"] + } + }, + "other_tenancy_type": { + "header": "Please state the tenancy type", + "hint_text": "", + "type": "text" + } + } + }, + "letting_type": { + "header": "", + "description": "", + "questions": { + "letting_type": { + "check_answer_label": "Type of letting", + "header": "Which type of letting is this?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Social Rent - General Needs", + "1": "Social Rent - Supporting Housing", + "2": "Affordable Rent - General Needs", + "3": "Affordable Rent - Supporting Housing", + "4": "Rent To Buy - General Needs", + "5": "Rent To Buy - Supported Housing" + } + } + } + }, + "letting_provider": { + "header": "", + "description": "", + "questions": { + "letting_provider": { + "check_answer_label": "Provider", + "header": "Who is the letting provider?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "This landlord", + "1": "Another registered provider - includes housing association or local authority" + } + } + } + } + } + }, + "property_information": { + "label": "Property information", + "pages": { + "property_location": { + "header": "", + "description": "", + "questions": { + "property_location": { + "check_answer_label": "Property Location", + "header": "Property location", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Adur", + "1": "Allerdale", + "2": "Amber Valley", + "3": "Arun", + "4": "Ashfield", + "5": "Ashford", + "6": "Babergh", + "7": "Barking & Dagenham", + "8": "Barnet", + "9": "Barnsley", + "10": "Barrow-in-Furness", + "11": "Basildon", + "12": "Basingstoke & Deane", + "13": "Bassetlaw", + "14": "Bath & NE Somerset", + "15": "Bedford Borough Council", + "16": "Bexley", + "17": "Birmingham", + "18": "Blaby", + "19": "Blackburn", + "20": "Blackpool", + "21": "Bolsover", + "22": "Bolton", + "23": "Boston", + "24": "Bournemouth & Christchurch & Poole", + "25": "Bracknell Forest", + "26": "Bradford", + "27": "Braintree", + "28": "Breckland", + "29": "Brent", + "30": "Brentwood", + "31": "Brighton & Hove", + "32": "Bristol", + "33": "Broadland", + "34": "Bromley", + "35": "Bromsgrove", + "36": "Broxbourne", + "37": "Broxtowe", + "38": "Buckinghamshire", + "39": "Burnley", + "40": "Bury", + "41": "Calderdale", + "42": "Cambridge", + "43": "Camden", + "44": "Cannock Chase", + "45": "Canterbury", + "46": "Carlisle", + "47": "Castle Point", + "48": "Central Bedfordshire", + "49": "Charnwood", + "50": "Chelmsford", + "51": "Cheltenham", + "52": "Cherwell", + "53": "Cheshire West & Chester", + "54": "Chesterfield", + "55": "Chichester", + "56": "Chorley", + "57": "City of London", + "58": "Colchester", + "59": "Copeland", + "60": "Cornwall", + "61": "Cotswold", + "62": "Coventry", + "63": "Craven", + "64": "Crawley", + "65": "Croydon", + "66": "Dacorum", + "67": "Darlington", + "68": "Dartford", + "69": "Derby", + "70": "Derbyshire Dales", + "71": "Doncaster", + "72": "Dorset", + "73": "Dover", + "74": "Dudley", + "75": "Durham", + "76": "Ealing", + "77": "East Cambridgeshire", + "78": "East Cheshire", + "79": "East Devon", + "80": "East Hampshire", + "81": "East Herts", + "82": "East Lindsey", + "83": "East Riding", + "84": "East Staffordshire", + "85": "East Suffolk", + "86": "Eastbourne", + "87": "Eastleigh", + "88": "Eden", + "89": "Elmbridge", + "90": "Enfield", + "91": "Epping Forest", + "92": "Epsom & Ewell", + "93": "Erewash", + "94": "Exeter", + "95": "Fareham", + "96": "Fenland", + "97": "Folkestone & Hythe", + "98": "Forest of Dean", + "99": "Fylde", + "100": "Gateshead", + "101": "Gedling", + "102": "Gloucester", + "103": "Gosport", + "104": "Gravesham", + "105": "Great Yarmouth", + "106": "Greenwich", + "107": "Guildford", + "108": "Hackney", + "109": "Halton", + "110": "Hambleton", + "111": "Hammersmith & Fulham", + "112": "Harborough", + "113": "Haringey", + "114": "Harlow", + "115": "Harrogate", + "116": "Harrow", + "117": "Hart", + "118": "Hartlepool", + "119": "Hastings", + "120": "Havant", + "121": "Havering", + "122": "Herefordshire", + "123": "Hertsmere", + "124": "High Peak", + "125": "Hillingdon", + "126": "Hinckley & Bosworth", + "127": "Horsham", + "128": "Hounslow", + "129": "Huntingdonshire", + "130": "Hyndburn", + "131": "Ipswich", + "132": "Isle of Wight", + "133": "Isles of Scilly", + "134": "Islington", + "135": "Kensington & Chelsea", + "136": "Kings Lynn & West Norfolk", + "137": "Kingston-upon-Hull", + "138": "Kingston-upon-Thames", + "139": "Kirklees", + "140": "Knowsley", + "141": "Lambeth", + "142": "Lancaster", + "143": "Leeds", + "144": "Leicester", + "145": "Lewes", + "146": "Lewisham", + "147": "Lichfield", + "148": "Lincoln", + "149": "Liverpool", + "150": "Luton", + "151": "Maidstone", + "152": "Maldon", + "153": "Malvern Hills", + "154": "Manchester", + "155": "Mansfield", + "156": "Medway", + "157": "Melton", + "158": "Mendip", + "159": "Merton", + "160": "Mid Devon", + "161": "Mid Suffolk", + "162": "Mid Sussex", + "163": "Middlesbrough", + "164": "Milton Keynes", + "165": "Mole Valley", + "166": "N. Ireland", + "167": "New Forest", + "168": "Newark", + "169": "Newcastle-under-Lyme", + "170": "Newcastle-upon-Tyne", + "171": "Newham", + "172": "North Devon", + "173": "North East Derbyshire", + "174": "North East Lincolnshire", + "175": "North Hertfordshire", + "176": "North Kesteven", + "177": "North Lincolnshire", + "178": "North Norfolk", + "179": "North Northamptonshire", + "180": "North Somerset", + "181": "North Tyneside", + "182": "North Warwickshire", + "183": "North West Leics", + "184": "Northumberland", + "185": "Norwich", + "186": "Nottingham", + "187": "Nuneaton & Bedworth", + "188": "Oadby & Wigston", + "189": "Oldham", + "190": "Outside UK", + "191": "Oxford", + "192": "Pendle", + "193": "Peterborough", + "194": "Plymouth", + "195": "Portsmouth", + "196": "Preston", + "197": "Reading", + "198": "Redbridge", + "199": "Redcar & Cleveland", + "200": "Redditch", + "201": "Reigate & Banstead", + "202": "Ribble Valley", + "203": "Richmond-upon-Thames", + "204": "Richmondshire", + "205": "Rochdale", + "206": "Rochford", + "207": "Rossendale", + "208": "Rother", + "209": "Rotherham", + "210": "Rugby", + "211": "Runnymede", + "212": "Rushcliffe", + "213": "Rushmoor", + "214": "Rutland", + "215": "Ryedale", + "216": "Salford", + "217": "Sandwell", + "218": "Scarborough", + "219": "Scotland", + "220": "Sedgemoor", + "221": "Sefton", + "222": "Selby", + "223": "Sevenoaks", + "224": "Sheffield", + "225": "Shropshire", + "226": "Slough", + "227": "Solihull", + "228": "Somerset West & Taunton", + "229": "South Cambridgeshire", + "230": "South Derbyshire", + "231": "South Gloucestershire", + "232": "South Hams", + "233": "South Holland", + "234": "South Kesteven", + "235": "South Lakeland", + "236": "South Norfolk", + "237": "South Oxfordshire", + "238": "South Ribble", + "239": "South Somerset", + "240": "South Staffordshire", + "241": "South Tyneside", + "242": "Southampton", + "243": "Southend-on-Sea", + "244": "Southwark", + "245": "Spelthorne", + "246": "St Albans", + "247": "St Helens", + "248": "Stafford", + "249": "Staffordshire Moorlands", + "250": "Stevenage", + "251": "Stockport", + "252": "Stockton-on-Tees", + "253": "Stoke-on-Trent", + "254": "Stratford-on-Avon", + "255": "Stroud", + "256": "Sunderland", + "257": "Surrey Heath", + "258": "Sutton", + "259": "Swale", + "260": "Swindon", + "261": "Tameside", + "262": "Tamworth", + "263": "Tandridge", + "264": "Teignbridge", + "265": "Telford & Wrekin", + "266": "Tendring", + "267": "Test Valley", + "268": "Tewkesbury", + "269": "Thanet", + "270": "Three Rivers", + "271": "Thurrock", + "272": "Tonbridge & Malling", + "273": "Torbay", + "274": "Torridge", + "275": "Tower Hamlets", + "276": "Trafford", + "277": "Tunbridge Wells", + "278": "Uttlesford", + "279": "Vale of White Horse", + "280": "Wakefield", + "281": "Wales", + "282": "Walsall", + "283": "Waltham Forest", + "284": "Wandsworth", + "285": "Warrington", + "286": "Warwick", + "287": "Watford", + "288": "Waverley", + "289": "Wealden", + "290": "Welwyn Hatfield", + "291": "West Berkshire", + "292": "West Devon", + "293": "West Lancashire", + "294": "West Lindsey", + "295": "West Northamptonshire", + "296": "West Oxfordshire", + "297": "West Suffolk", + "298": "Westminster", + "299": "Wigan", + "300": "Wiltshire", + "301": "Winchester", + "302": "Windsor & Maidenhead", + "303": "Wirral", + "304": "Woking", + "305": "Wokingham", + "306": "Wolverhampton", + "307": "Worcester", + "308": "Worthing", + "309": "Wychavon", + "310": "Wyre", + "311": "Wyre Forest", + "312": "York" + } + } + } + }, + "property_postcode": { + "header": "", + "description": "", + "questions": { + "property_postcode": { + "check_answer_label": "What was the previous postcode?", + "header": "What is the property's postcode?", + "hint_text": "", + "type": "text" + } + } + }, + "property_relet": { + "header": "", + "description": "", + "questions": { + "property_relet": { + "check_answer_label": "Which type was the property most recently let as?", + "header": "Is this property a relet?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + }, + "property_vacancy_reason": { + "header": "", + "description": "", + "questions": { + "property_vacancy_reason": { + "check_answer_label": "What is the reason for the property vacancy?", + "header": "What is the reason for the property vacancy?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "First let of newbuild property", + "1": "First let of conversion/rehabilitation/acquired property", + "2": "First let of leased property", + "3": "Relet - tenant evicted due to arrears", + "4": "Relet - tenant evicted due to ASB or other reason", + "5": "Relet - tenant died (no succession)", + "6": "Relet - tenant moved to other social housing provider", + "7": "Relet - tenant abandoned property", + "8": "Relet - tenant moved to private sector or other accommodation", + "9": "Relet - to tenant who occupied same property as temporary accommodation", + "10": "Relet – internal transfer (excluding renewals of a fixed-term tenancy)", + "11": "Relet – renewal of fixed-term tenancy", + "12": "Relet – tenant moved to care home", + "13": "Relet – tenant involved in a succession downsize" + } + } + } + }, + "property_reference": { + "header": "", + "description": "", + "questions": { + "property_reference": { + "check_answer_label": "What’s the property reference?", + "header": "What's the property reference?", + "hint_text": "", + "type": "text" + } + } + }, + "property_unit_type": { + "header": "", + "description": "", + "questions": { + "property_unit_type": { + "check_answer_label": "Which type of unit is the property?", + "header": "Which type of unit is the property?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Flat / maisonette", + "1": "Bed-sit", + "2": "House", + "3": "Bungalow", + "4": "Shared flat / maisonette", + "5": "Shared house", + "6": "Shared bungalow", + "7": "Other" + } + } + } + }, + "property_number_of_bedrooms": { + "header": "", + "description": "", + "questions": { + "property_number_of_bedrooms": { + "check_answer_label": "How many bedrooms are there in the property?", + "header": "How many bedrooms are there in the property?", + "hint_text": "If shared accommodation, enter number of bedrooms occupied by this household; a bed-sit has 1 bedroom", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + } + } + }, + "property_major_repairs": { + "header": "", + "description": "", + "questions": { + "property_major_repairs": { + "check_answer_label": "Were major repairs carried out during the void period?", + "header": "Were any major repairs completed during the void period?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + }, + "conditional_for": { + "property_major_repairs_date": ["Yes"] + } + }, + "property_major_repairs_date": { + "check_answer_label": "What was the major repairs completion date?", + "header": "What was the major repairs completion date?", + "hint_text": "For example, 27 3 2007", + "type": "date" + } + } + }, + "property_number_of_times_relet": { + "header": "", + "description": "", + "questions": { + "property_number_of_times_relet": { + "check_answer_label": "How many times has this unit been previously offered since becoming available for relet since the last tenancy ended or as a first let?", + "header": "How many times has this unit been previously offered since becoming available for relet since the last tenancy ended or as a first let? ", + "hint_text": "For an Affordable Rent or Intermediate Rent Letting, only include number of offers as that type. For a property let at the first attempt enter '0' ", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + } + } + }, + "property_wheelchair_accessible": { + "header": "", + "description": "", + "questions": { + "property_wheelchair_accessible": { + "check_answer_label": "Is property built or adapted to wheelchair user standards?", + "header": "Is property built or adapted to wheelchair user standards?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + } + } + } + } + }, + "rent_and_charges": { + "label": "Rent and charges", + "subsections": { + "income_and_benefits": { + "label": "Income and benefits", + "pages": { + "net_income": { + "header": "", + "description": "", + "questions": { + "net_income_known": { + "check_answer_label": "Income known", + "header": "Do you know the tenant and their partner's net income?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Tenant prefers not to say" + }, + "conditional_for": { + "net_income": ["Yes"], + "net_income_frequency": ["Yes"] + } + }, + "net_income": { + "check_answer_label": "Income", + "header": "What is the tenant’s /and partner’s combined income after tax?", + "hint_text": "", + "type": "numeric", + "min": 0, + "step": "1" + }, + "net_income_frequency": { + "check_answer_label": "Income Frequency", + "header": "How often do they receive this income?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Weekly", + "1": "Monthly", + "2": "Yearly" + } + } + }, + "soft_validations": { + "override_net_income_validation": { + "check_answer_label": "Net income confirmed?", + "type": "validation_override", + "answer_options": { + "override_net_income_validation": "Yes" + } + } + } + }, + "net_income_uc_proportion": { + "header": "", + "description": "", + "questions": { + "net_income_uc_proportion": { + "check_answer_label": "Benefits as a proportion of income", + "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "All", + "1": "Some", + "2": "None", + "3": "Do not know" + } + } + } + }, + "housing_benefit": { + "header": "", + "description": "", + "questions": { + "housing_benefit": { + "check_answer_label": "Universal Credit & Housing Benefit\t", + "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Housing Benefit, but not Universal Credit", + "1": "Universal Credit with housing element, but not Housing Benefit", + "2": "Universal Credit without housing element and no Housing Benefit", + "3": "Universal Credit and Housing Benefit", + "4": "Not Housing Benefit or Universal Credit", + "5": "Do not know", + "6": "Prefer not to say" + } + } + } + } + } + }, + "rent": { + "label": "Rent", + "pages": { + "rent": { + "header": "", + "description": "", + "questions": { + "rent_frequency": { + "check_answer_label": "Rent Period", + "header": "Which period are rent and other charges due?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Weekly for 52 weeks", + "1": "Fortnightly", + "2": "Four-weekly", + "3": "Calendar monthly", + "4": "Weekly for 50 weeks", + "5": "Weekly for 49 weeks", + "6": "Weekly for 48 weeks", + "7": "Weekly for 47 weeks", + "8": "Weekly for 46 weeks", + "9": "Weekly for 53 weeks" + } + }, + "basic_rent": { + "check_answer_label": "Basic Rent", + "header": "What is the basic rent?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], + "result-field": "total_charge" + }, + "service_charge": { + "check_answer_label": "Service Charge", + "header": "What is the service charge?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], + "result-field": "total_charge" + }, + "personal_service_charge": { + "check_answer_label": "Personal Service Charge", + "header": "What is the personal service charge?", + "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], + "result-field": "total_charge" + }, + "support_charge": { + "check_answer_label": "Support Charge", + "header": "What is the support charge?", + "hint_text": "This is to fund housing-related support services included in the tenancy agreement", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], + "result-field": "total_charge" + }, + "total_charge": { + "check_answer_label": "Total Charge", + "header": "Total charge?", + "hint_text": "This is the total of rent and all charges", + "type": "numeric", + "min": 0, + "step": 1, + "readonly": true + }, + "outstanding_rent_or_charges": { + "check_answer_label": "After housing benefit and/or housing element of UC payment is received, will there be an outstanding amount for basic rent and/or benefit eligible charges?", + "header": "After housing benefit and/or housing element of UC payment is received, will there be an outstanding amount for basic rent and/or benefit eligible charges?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + }, + "conditional_for": { + "outstanding_amount": ["Yes"] + } + }, + "outstanding_amount": { + "check_answer_label": "Outstanding amount", + "header": "What do you expect the amount to be?", + "hint_text": "If the amount is unknown you can estimate", + "type": "numeric", + "min": 0, + "step": 1 + } + } + } + } + } + } + }, + "local_authority": { + "label": "Local authority", + "subsections": { + "local_authority": { + "label": "Local authority", + "pages": { + "time_lived_in_la": { + "header": "", + "description": "", + "questions": { + "time_lived_in_la": { + "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", + "header": "How long has the household continuously lived in the local authority area where the new letting is located?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Just moved to local authority area", + "1": "Less than 1 year", + "2": "1 to 2 years", + "3": "2 to 3 years", + "4": "3 to 4 years", + "5": "4 to 5 years", + "6": "5 years or more", + "7": "Do not know" + } + } + } + }, + "time_on_la_waiting_list": { + "header": "", + "description": "", + "questions": { + "time_on_la_waiting_list": { + "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", + "header": "How long has the household been on the local authority waiting list where the new letting is located?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Just moved to local authority area", + "1": "Less than 1 year", + "2": "1 to 2 years", + "3": "2 to 3 years", + "4": "3 to 4 years", + "5": "4 to 5 years", + "6": "5 years or more", + "7": "Do not know" + } + } + } + }, + "previous_la": { + "header": "", + "description": "", + "questions": { + "previous_la": { + "check_answer_label": "The LA in which household lived immediately before this letting\t", + "header": "Which local authority area did the household live in immediately before this letting?", + "hint_text": "Includes temporary accommodation", + "type": "radio", + "answer_options": { + "0": "Adur", + "1": "Allerdale", + "2": "Amber Valley", + "3": "Arun", + "4": "Ashfield", + "5": "Ashford", + "6": "Babergh", + "7": "Barking & Dagenham", + "8": "Barnet", + "9": "Barnsley", + "10": "Barrow-in-Furness", + "11": "Basildon", + "12": "Basingstoke & Deane", + "13": "Bassetlaw", + "14": "Bath & NE Somerset", + "15": "Bedford Borough Council", + "16": "Bexley", + "17": "Birmingham", + "18": "Blaby", + "19": "Blackburn", + "20": "Blackpool", + "21": "Bolsover", + "22": "Bolton", + "23": "Boston", + "24": "Bournemouth & Christchurch & Poole", + "25": "Bracknell Forest", + "26": "Bradford", + "27": "Braintree", + "28": "Breckland", + "29": "Brent", + "30": "Brentwood", + "31": "Brighton & Hove", + "32": "Bristol", + "33": "Broadland", + "34": "Bromley", + "35": "Bromsgrove", + "36": "Broxbourne", + "37": "Broxtowe", + "38": "Buckinghamshire", + "39": "Burnley", + "40": "Bury", + "41": "Calderdale", + "42": "Cambridge", + "43": "Camden", + "44": "Cannock Chase", + "45": "Canterbury", + "46": "Carlisle", + "47": "Castle Point", + "48": "Central Bedfordshire", + "49": "Charnwood", + "50": "Chelmsford", + "51": "Cheltenham", + "52": "Cherwell", + "53": "Cheshire West & Chester", + "54": "Chesterfield", + "55": "Chichester", + "56": "Chorley", + "57": "City of London", + "58": "Colchester", + "59": "Copeland", + "60": "Cornwall", + "61": "Cotswold", + "62": "Coventry", + "63": "Craven", + "64": "Crawley", + "65": "Croydon", + "66": "Dacorum", + "67": "Darlington", + "68": "Dartford", + "69": "Derby", + "70": "Derbyshire Dales", + "71": "Doncaster", + "72": "Dorset", + "73": "Dover", + "74": "Dudley", + "75": "Durham", + "76": "Ealing", + "77": "East Cambridgeshire", + "78": "East Cheshire", + "79": "East Devon", + "80": "East Hampshire", + "81": "East Herts", + "82": "East Lindsey", + "83": "East Riding", + "84": "East Staffordshire", + "85": "East Suffolk", + "86": "Eastbourne", + "87": "Eastleigh", + "88": "Eden", + "89": "Elmbridge", + "90": "Enfield", + "91": "Epping Forest", + "92": "Epsom & Ewell", + "93": "Erewash", + "94": "Exeter", + "95": "Fareham", + "96": "Fenland", + "97": "Folkestone & Hythe", + "98": "Forest of Dean", + "99": "Fylde", + "100": "Gateshead", + "101": "Gedling", + "102": "Gloucester", + "103": "Gosport", + "104": "Gravesham", + "105": "Great Yarmouth", + "106": "Greenwich", + "107": "Guildford", + "108": "Hackney", + "109": "Halton", + "110": "Hambleton", + "111": "Hammersmith & Fulham", + "112": "Harborough", + "113": "Haringey", + "114": "Harlow", + "115": "Harrogate", + "116": "Harrow", + "117": "Hart", + "118": "Hartlepool", + "119": "Hastings", + "120": "Havant", + "121": "Havering", + "122": "Herefordshire", + "123": "Hertsmere", + "124": "High Peak", + "125": "Hillingdon", + "126": "Hinckley & Bosworth", + "127": "Horsham", + "128": "Hounslow", + "129": "Huntingdonshire", + "130": "Hyndburn", + "131": "Ipswich", + "132": "Isle of Wight", + "133": "Isles of Scilly", + "134": "Islington", + "135": "Kensington & Chelsea", + "136": "Kings Lynn & West Norfolk", + "137": "Kingston-upon-Hull", + "138": "Kingston-upon-Thames", + "139": "Kirklees", + "140": "Knowsley", + "141": "Lambeth", + "142": "Lancaster", + "143": "Leeds", + "144": "Leicester", + "145": "Lewes", + "146": "Lewisham", + "147": "Lichfield", + "148": "Lincoln", + "149": "Liverpool", + "150": "Luton", + "151": "Maidstone", + "152": "Maldon", + "153": "Malvern Hills", + "154": "Manchester", + "155": "Mansfield", + "156": "Medway", + "157": "Melton", + "158": "Mendip", + "159": "Merton", + "160": "Mid Devon", + "161": "Mid Suffolk", + "162": "Mid Sussex", + "163": "Middlesbrough", + "164": "Milton Keynes", + "165": "Mole Valley", + "166": "N. Ireland", + "167": "New Forest", + "168": "Newark", + "169": "Newcastle-under-Lyme", + "170": "Newcastle-upon-Tyne", + "171": "Newham", + "172": "North Devon", + "173": "North East Derbyshire", + "174": "North East Lincolnshire", + "175": "North Hertfordshire", + "176": "North Kesteven", + "177": "North Lincolnshire", + "178": "North Norfolk", + "179": "North Northamptonshire", + "180": "North Somerset", + "181": "North Tyneside", + "182": "North Warwickshire", + "183": "North West Leics", + "184": "Northumberland", + "185": "Norwich", + "186": "Nottingham", + "187": "Nuneaton & Bedworth", + "188": "Oadby & Wigston", + "189": "Oldham", + "190": "Outside UK", + "191": "Oxford", + "192": "Pendle", + "193": "Peterborough", + "194": "Plymouth", + "195": "Portsmouth", + "196": "Preston", + "197": "Reading", + "198": "Redbridge", + "199": "Redcar & Cleveland", + "200": "Redditch", + "201": "Reigate & Banstead", + "202": "Ribble Valley", + "203": "Richmond-upon-Thames", + "204": "Richmondshire", + "205": "Rochdale", + "206": "Rochford", + "207": "Rossendale", + "208": "Rother", + "209": "Rotherham", + "210": "Rugby", + "211": "Runnymede", + "212": "Rushcliffe", + "213": "Rushmoor", + "214": "Rutland", + "215": "Ryedale", + "216": "Salford", + "217": "Sandwell", + "218": "Scarborough", + "219": "Scotland", + "220": "Sedgemoor", + "221": "Sefton", + "222": "Selby", + "223": "Sevenoaks", + "224": "Sheffield", + "225": "Shropshire", + "226": "Slough", + "227": "Solihull", + "228": "Somerset West & Taunton", + "229": "South Cambridgeshire", + "230": "South Derbyshire", + "231": "South Gloucestershire", + "232": "South Hams", + "233": "South Holland", + "234": "South Kesteven", + "235": "South Lakeland", + "236": "South Norfolk", + "237": "South Oxfordshire", + "238": "South Ribble", + "239": "South Somerset", + "240": "South Staffordshire", + "241": "South Tyneside", + "242": "Southampton", + "243": "Southend-on-Sea", + "244": "Southwark", + "245": "Spelthorne", + "246": "St Albans", + "247": "St Helens", + "248": "Stafford", + "249": "Staffordshire Moorlands", + "250": "Stevenage", + "251": "Stockport", + "252": "Stockton-on-Tees", + "253": "Stoke-on-Trent", + "254": "Stratford-on-Avon", + "255": "Stroud", + "256": "Sunderland", + "257": "Surrey Heath", + "258": "Sutton", + "259": "Swale", + "260": "Swindon", + "261": "Tameside", + "262": "Tamworth", + "263": "Tandridge", + "264": "Teignbridge", + "265": "Telford & Wrekin", + "266": "Tendring", + "267": "Test Valley", + "268": "Tewkesbury", + "269": "Thanet", + "270": "Three Rivers", + "271": "Thurrock", + "272": "Tonbridge & Malling", + "273": "Torbay", + "274": "Torridge", + "275": "Tower Hamlets", + "276": "Trafford", + "277": "Tunbridge Wells", + "278": "Uttlesford", + "279": "Vale of White Horse", + "280": "Wakefield", + "281": "Wales", + "282": "Walsall", + "283": "Waltham Forest", + "284": "Wandsworth", + "285": "Warrington", + "286": "Warwick", + "287": "Watford", + "288": "Waverley", + "289": "Wealden", + "290": "Welwyn Hatfield", + "291": "West Berkshire", + "292": "West Devon", + "293": "West Lancashire", + "294": "West Lindsey", + "295": "West Northamptonshire", + "296": "West Oxfordshire", + "297": "West Suffolk", + "298": "Westminster", + "299": "Wigan", + "300": "Wiltshire", + "301": "Winchester", + "302": "Windsor & Maidenhead", + "303": "Wirral", + "304": "Woking", + "305": "Wokingham", + "306": "Wolverhampton", + "307": "Worcester", + "308": "Worthing", + "309": "Wychavon", + "310": "Wyre", + "311": "Wyre Forest", + "312": "York" + } + } + } + }, + "previous_postcode": { + "header": "", + "description": "", + "questions": { + "previous_postcode": { + "check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation", + "header": "Postcode for the previous accommodation", + "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", + "type": "text" + } + } + }, + "reasonable_preference": { + "header": "", + "description": "", + "questions": { + "reasonable_preference": { + "check_answer_label": "Was the household given Reasonable Preference (i.e. priority) for housing by the Local Authority?", + "header": "Was the household given reasonable preference by the local authority?", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + }, + "conditional_for": { + "reasonable_preference_reason": ["Yes"] + } + }, + "reasonable_preference_reason": { + "check_answer_label": "Reason for reasonable preference", + "header": "Why were they given reasonable preference?", + "hint_text": "Select all that apply", + "type": "checkbox", + "answer_options": { + "reasonable_preference_reason_homeless": "Homeless or about to lose their home (within 56 days)", + "reasonable_preference_reason_unsatisfactory_housing": "Living in insanitary or overcrowded or unsatisfactory housing", + "reasonable_preference_reason_medical_grounds": "A need to move on medical and welfare grounds (including a disability)", + "reasonable_preference_reason_avoid_hardship": "A need to move to avoid hardship to themselves or others", + "divider": true, + "reasonable_preference_reason_do_not_know": "Do not know" + } + } + } + }, + "lettings_policy": { + "header": "", + "description": "", + "questions": { + "cbl_letting": { + "check_answer_label": "Choice-based letting?", + "header": "Was the letting made under choice-based lettings (CBL)? ", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + }, + "chr_letting": { + "check_answer_label": "Common housing register letting?", + "header": "Was the letting made under common housing register (CHR)? ", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + }, + "cap_letting": { + "check_answer_label": "Common allocation policy letting?", + "header": "Was the letting made under common allocation policy (CAP)? ", + "hint_text": "", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + } + } + } + } + }, + "submission": { + "label": "Submission", + "subsections": { + "declaration": { + "label": "Declaration", + "pages": { + "declaration": { + "header": "", + "description": "", + "questions": { + "declaration": { + "check_answer_label": "", + "header": "What is the tenant code?", + "hint_text": "", + "type": "text" + } + } + } + } + } + } + } + } + } + \ No newline at end of file diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json new file mode 100644 index 000000000..a52897c43 --- /dev/null +++ b/config/forms/schema/generic.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema", + "$id": "https://example.com/product.schema.json", + "title": "Form", + "description": "A form", + "type": "object", + "properties": { + "form_type": { + "description": "", + "type": "string" + }, + "start_year": { + "description": "", + "type": "integer" + }, + "end_year": { + "description": "", + "type": "integer" + }, + "sections": { + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + }, + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "type": "object" + } + } + } + } +} \ No newline at end of file From 78547d4a2c3c397bbadb8ef1845aa38f6ebf5bdb Mon Sep 17 00:00:00 2001 From: magicmilo Date: Sun, 7 Nov 2021 22:24:04 +0000 Subject: [PATCH 07/26] dir loop --- app/helpers/json_schema_validation.rb | 91 ++++++++++++++------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 3e46be8e0..329186831 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -2,35 +2,45 @@ require "json-schema" require "json" # "form_type": "lettings", -# "start_year": 2021, -# "end_year": 2022, -# "sections": { -# "about_this_log": { -# "label": "About this log", -# "subsections": { -# "about_this_log": { -# "label": "About this log", -# "pages": { - # "tenant_code": { - # "header": "", - # "description": "", - # "questions": { - # "tenant_code": { - # "check_answer_label": "Tenant code", - # "header": "What is the tenant code?", - # "hint_text": "", - # "type": "text" - # } - # } - # }, +#start_year": 2021, +#end_year": 2022, +#sections": { +# about_this_log": { +# label": "About this log", +# subsections": { +# about_this_log": { +# label": "About this log", +# pages": { +# "tenant_code": { +# header": "", +# description": "", +# questions": { +# tenant_code": { +# check_answer_label": "Tenant code", +# header": "What is the tenant code?", +# hint_text": "", +# type": "text" +# } +# } +# } + +def get_all_form_paths(directories) + form_paths = [] + directories.each do |directory| + Dir.glob("#{directory}/*.json").each do |form_path| + form_paths.push(form_path) + end + end + form_paths +end + begin - path = "config/forms/schema/generic.json" - # path = "config/forms/schema/2021_2022.json" + # path = "config/forms/schema/generic.json" + path = "config/forms/schema/2021_2022.json" file = File.open(path) schema = JSON.parse(file.read) - metaschema = JSON::Validator.validator_for_name("draft4").metaschema if JSON::Validator.validate(metaschema, schema) @@ -43,28 +53,21 @@ begin path = "spec/fixtures/forms/test_validator.json" # path = "config/forms/2021_2022.json" - file = File.open(path) - data = JSON.parse(file.read) + directories = ["config/forms", "spec/fixtures/forms"] - puts JSON::Validator.validate(schema, data) + get_all_form_paths(directories).each do |path| + puts path + file = File.open(path) + data = JSON.parse(file.read) - puts JSON::Validator.fully_validate(schema, data, :strict => true) + puts JSON::Validator.validate(schema, data) - begin - JSON::Validator.validate!(schema, data) - rescue JSON::Schema::ValidationError => e - e.message - end + puts JSON::Validator.fully_validate(schema, data, :strict => true) - # def get_all_form_paths - # form_paths = [] - # directories = ["config/forms", "spec/fixtures/forms"] - # directories.each do |directory| - # Dir.glob("#{directory}/*.json").each do |form_path| - # form_path = form_path.sub(".json", "").split("/")[-1] - # form_paths.push(form_path) - # end - # end - # form_paths - # end + begin + JSON::Validator.validate!(schema, data) + rescue JSON::Schema::ValidationError => e + e.message + end + end end From ebc79e49828f211dc4aaba62abdad535173cf0d9 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Mon, 8 Nov 2021 09:44:40 +0000 Subject: [PATCH 08/26] . --- app/helpers/json_schema_validation.rb | 4 ++-- config/forms/schema/generic.json | 6 ++++-- spec/fixtures/forms/test_validator.json | 15 +++++++++++++++ 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 329186831..5435f02e6 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -36,8 +36,8 @@ end begin - # path = "config/forms/schema/generic.json" - path = "config/forms/schema/2021_2022.json" + path = "config/forms/schema/generic.json" + # path = "config/forms/schema/2021_2022.json" file = File.open(path) schema = JSON.parse(file.read) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index a52897c43..024990b8b 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -11,11 +11,13 @@ }, "start_year": { "description": "", - "type": "integer" + "type": "integer", + "optional": "true" }, "end_year": { "description": "", - "type": "integer" + "type": "integer", + "required": "false" }, "sections": { "description": "", diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index 13aed9e5f..e0fe13361 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -19,6 +19,21 @@ } } } + }, + "person_1_age": { + "header": "", + "description": "", + "questions": { + "person_1_age": { + "check_answer_label": "Tenant's age", + "header": "What is the tenant's age?", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 120, + "step": 1 + } + } } } } From f844f9273e263ab84ec7026463ce216cb872fd46 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Tue, 9 Nov 2021 14:34:17 +0000 Subject: [PATCH 09/26] outline --- app/helpers/json_schema_validation.rb | 30 ++----------- config/forms/schema/generic.json | 63 +++++++++++++++++++++++++-- spec/fixtures/forms/test_form.json | 2 + 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 5435f02e6..dd0655d3b 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -1,29 +1,6 @@ require "json-schema" require "json" -# "form_type": "lettings", -#start_year": 2021, -#end_year": 2022, -#sections": { -# about_this_log": { -# label": "About this log", -# subsections": { -# about_this_log": { -# label": "About this log", -# pages": { -# "tenant_code": { -# header": "", -# description": "", -# questions": { -# tenant_code": { -# check_answer_label": "Tenant code", -# header": "What is the tenant code?", -# hint_text": "", -# type": "text" -# } -# } -# } - def get_all_form_paths(directories) form_paths = [] directories.each do |directory| @@ -43,6 +20,8 @@ begin schema = JSON.parse(file.read) metaschema = JSON::Validator.validator_for_name("draft4").metaschema + puts path + if JSON::Validator.validate(metaschema, schema) puts "schema valid" else @@ -50,9 +29,6 @@ begin return end - path = "spec/fixtures/forms/test_validator.json" - # path = "config/forms/2021_2022.json" - directories = ["config/forms", "spec/fixtures/forms"] get_all_form_paths(directories).each do |path| @@ -60,7 +36,7 @@ begin file = File.open(path) data = JSON.parse(file.read) - puts JSON::Validator.validate(schema, data) + puts JSON::Validator.validate(schema, data, :strict => true) puts JSON::Validator.fully_validate(schema, data, :strict => true) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index 024990b8b..b9502c0e1 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -1,5 +1,5 @@ { - "$schema": "http://json-schema.org/draft-04/schema", + "$schema": "http://json-schema.org/draft-04/schema#", "$id": "https://example.com/product.schema.json", "title": "Form", "description": "A form", @@ -16,8 +16,7 @@ }, "end_year": { "description": "", - "type": "integer", - "required": "false" + "type": "integer" }, "sections": { "description": "", @@ -32,7 +31,63 @@ "type": "string" }, "subsections": { - "type": "object" + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + }, + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + }, + "label": { + "description": "", + "type": "string" + }, + "pages": { + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + } + }, + "questions": { + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + }, + "conditional_for": { + "type": "object", + "properties": "" + } + } + }, + "conditional_route_to": { + "type": "object", + "properties": "" + }, + "default_next_page": { + "type" : "string" + } + } + } + } + } } } } diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json index 2bcd34aaa..0d26827fa 100644 --- a/spec/fixtures/forms/test_form.json +++ b/spec/fixtures/forms/test_form.json @@ -1,5 +1,7 @@ { "form_type": "lettings", + "start_year": 2021, + "end_year": 2022, "sections": { "household": { "label": "About the household", From e1f758ba07df15d91720f28c222acfd1cb37052e Mon Sep 17 00:00:00 2001 From: magicmilo Date: Tue, 9 Nov 2021 16:44:18 +0000 Subject: [PATCH 10/26] save --- app/helpers/json_schema_validation.rb | 3 +- config/forms/schema/generic.json | 4 +- config/forms/schema/test.json | 80 ++++ spec/fixtures/forms/test_form.json | 515 +------------------------- 4 files changed, 85 insertions(+), 517 deletions(-) create mode 100644 config/forms/schema/test.json diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index dd0655d3b..12084b020 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -13,7 +13,8 @@ end begin - path = "config/forms/schema/generic.json" + # path = "config/forms/schema/generic.json" + path = "config/forms/schema/test.json" # path = "config/forms/schema/2021_2022.json" file = File.open(path) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index b9502c0e1..d7e71468d 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -4,6 +4,7 @@ "title": "Form", "description": "A form", "type": "object", + "required": ["form_type", "start_year", "end_year", "sections"], "properties": { "form_type": { "description": "", @@ -11,8 +12,7 @@ }, "start_year": { "description": "", - "type": "integer", - "optional": "true" + "type": "integer" }, "end_year": { "description": "", diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json new file mode 100644 index 000000000..998146adf --- /dev/null +++ b/config/forms/schema/test.json @@ -0,0 +1,80 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "https://example.com/product.schema.json", + "title": "Form", + "description": "A form", + "type": "object", + "required": ["form_type", "start_year", "end_year", "sections"], + "properties": { + "form_type": { + "description": "", + "type": "string" + }, + "start_year": { + "description": "", + "type": "integer" + }, + "end_year": { + "description": "", + "type": "integer" + }, + "sections": { + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "string" + }, + "properties": { + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "description": "", + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "description": "", + "type": "object", + "required": ["label"], + "properties": { + "label": { + "description": "", + "type": "string" + }, + "pages": { + "type": "object", + "patternProperties": { + "^[0-9]+$": { + "properties": { + "header": { + "description": "", + "type": "string" + }, + "description": { + "description": "", + "type": "string" + }, + "questions": { + "type": "object", + "properties": { + + } + } + } + } + } + } + } + }, + "additionalProperties": false, + "maxProperties": 1, + "minProperties": 1 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json index 0d26827fa..73df96635 100644 --- a/spec/fixtures/forms/test_form.json +++ b/spec/fixtures/forms/test_form.json @@ -17,520 +17,6 @@ "type": "text" } } - }, - "person_1_age": { - "questions": { - "person_1_age": { - "check_answer_label": "Tenant's age", - "header": "What is the tenant's age?", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - } - } - }, - "person_1_gender": { - "questions": { - "person_1_gender": { - "check_answer_label": "Tenant's gender", - "header": "Which of these best describes the tenant's gender identity?", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - } - } - }, - "household_number_of_other_members": { - "questions": { - "household_number_of_other_members": { - "check_answer_label": "Number of Other Household Members", - "header": "How many other people are there in the household?", - "hint_text": "The maximum number of others is 1", - "type": "numeric", - "min": 0, - "max": 1, - "step": 1, - "conditional_for": { - "person_2_relationship": ">0", - "person_2_age": ">0", - "person_2_gender": ">0", - "person_2_economic_status": ">0" - } - }, - "person_2_relationship": { - "check_answer_label": "Person 2's relationship to lead tenant", - "header": "What's person 2's relationship to lead tenant", - "type": "radio", - "answer_options": { - "0": "Other", - "1": "Prefer not to say" - } - }, - "person_2_age": { - "check_answer_label": "Person 2's age", - "header": "What's person 2's age", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_2_gender": { - "check_answer_label": "Person 2's gender", - "header": "Which of these best describes person 2's gender identity?", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_2_economic_status": { - "check_answer_label": "Person 2's Work", - "header": "Which of these best describes person 2's working situation?", - "type": "radio", - "answer_options": { - "0": "Other", - "1": "Prefer not to say" - } - } - } - } - } - }, - "household_needs": { - "label": "Household needs", - "pages": { - "armed_forces": { - "header": "Experience of the UK Armed Forces", - "questions": { - "armed_forces": { - "header": "Has the tenant ever served in the UK armed forces?", - "type": "radio", - "check_answer_label": "Armed Forces", - "answer_options": { - "0": "Yes - a regular", - "1": "Yes - a reserve", - "2": "No", - "3": "Prefer not to say" - }, - "conditional_for": { - "armed_forces_active": [ - "Yes - a regular", - "Yes - a reserve" - ], - "armed_forces_injured": [ - "Yes - a regular", - "Yes - a reserve" - ] - } - }, - "armed_forces_active": { - "header": "Are they still serving?", - "type": "radio", - "check_answer_label": "When did they leave the Armed Forces?", - "answer_options": { - "0": "Yes", - "1": "No - they left up to 5 years ago", - "2": "No - they left more than 5 years ago", - "3": "Prefer not to say" - } - }, - "armed_forces_injured": { - "header": "Were they seriously injured or ill as a result of their service?", - "type": "radio", - "check_answer_label": "Has anyone in the household been seriously injured or ill as a result of their service in the armed forces?", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Prefer not to say" - } - } - } - }, - "medical_conditions": { - "questions": { - "medical_conditions": { - "header": "Does anyone in the household have any of the following that they expect to last for 12 months or more:
  • Physical Condition
  • Mental Health Condition
  • Other Illness
", - "type": "radio", - "check_answer_label": "Physical, mental health or illness in the household", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Do not know", - "3": "Prefer not to say" - } - } - } - }, - "accessibility_requirements": { - "questions": { - "accessibility_requirements": { - "header": "Are any of these affected by their condition or illness?", - "hint_text": "Select all that apply", - "type": "checkbox", - "check_answer_label": "Disability requirements", - "answer_options": { - "accessibility_requirements_fully_wheelchair_accessible_housing": "Fully wheelchair accessible housing", - "accessibility_requirements_wheelchair_access_to_essential_rooms": "Wheelchair access to essential rooms", - "accessibility_requirements_level_access_housing": "Level access housing", - "divider_a": true, - "accessibility_requirements_do_not_know": "Do not know" - } - } - } - }, - "condition_effects": { - "questions": { - "condition_effects": { - "header": "Are any of these affected by their condition or illness?", - "hint_text": "Select all that apply", - "type": "checkbox", - "check_answer_label": "Conditions or illnesses", - "answer_options": { - "condition_effects_vision": "Vision - such as blindness or partial sight", - "condition_effects_hearing": "Hearing - such as deafness or partial hearing" - } - } - } - } - } - } - } - }, - "tenancy_and_property": { - "label": "Tenancy and property information", - "subsections": { - "tenancy_information": { - "label": "Tenancy information", - "pages": { - "tenancy_code": { - "questions": { - "tenancy_code": { - "check_answer_label": "What is the tenancy code?", - "header": "What is the tenancy code?", - "type": "text" - } - } - } - } - }, - "property_information": { - "label": "Property information", - "pages": { - "property_wheelchair_accessible": { - "questions": { - "property_wheelchair_accessible": { - "check_answer_label": "Is property built or adapted to wheelchair user standards?", - "header": "Is property built or adapted to wheelchair user standards?", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - } - } - }, - "conditional_question": { - "label": "Conditional question", - "pages": { - "conditional_question": { - "questions": { - "pregnancy": { - "check_answer_label": "Has the condition been met?", - "header": "Has the condition been met?", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - }, - "conditional_route_to": { - "rent": { "pregnancy": "Yes", "person_1_gender": "Female" }, - "conditional_question_yes_page": { "pregnancy": "Yes" }, - "conditional_question_no_page": { "pregnancy": "No" } - }, - "default_next_page": "check_answers" - }, - "conditional_question_yes_page": { - "questions": { - "cbl_letting": { - "check_answer_label": "Has the next condition been met?", - "header": "Has the next condition been met?", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - }, - "default_next_page": "check_answers" - }, - "conditional_question_no_page": { - "questions": { - "conditional_question_no_question": { - "check_answer_label": "Has the condition not been met?", - "header": "Has the next condition not been met?", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - }, - "default_next_page": "conditional_question_no_second_page" - }, - "conditional_question_no_second_page": { - "questions": { - "conditional_question_no_second_question": { - "check_answer_label": "Has the condition not been met again?", - "header": "Has the next condition not been met again?", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - } - } - } - } - }, - "rent_and_charges": { - "label": "Rent and charges", - "subsections": { - "income_and_benefits": { - "label": "Income and benefits", - "pages": { - "net_income": { - "questions": { - "net_income": { - "check_answer_label": "Income", - "header": "What is the tenant’s /and partner’s combined income after tax?", - "type": "numeric", - "min": 0, - "step": "1" - }, - "net_income_frequency": { - "check_answer_label": "Income Frequency", - "header": "How often do they receive this income?", - "type": "radio", - "answer_options": { - "0": "Weekly", - "1": "Monthly", - "2": "Yearly" - } - } - }, - "soft_validations": { - "override_net_income_validation": { - "check_answer_label": "Net income confirmed?", - "type": "validation_override", - "answer_options": { - "override_net_income_validation": "Yes" - } - } - } - }, - "net_income_uc_proportion": { - "questions": { - "net_income_uc_proportion": { - "check_answer_label": "Benefits as a proportion of income", - "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", - "type": "radio", - "answer_options": { - "0": "All", - "1": "Some" - } - } - } - }, - "housing_benefit": { - "questions": { - "housing_benefit": { - "check_answer_label": "Universal Credit & Housing Benefit", - "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", - "type": "radio", - "answer_options": { - "0": "Housing Benefit, but not Universal Credit", - "1": "Prefer not to say" - } - } - } - } - } - }, - "rent": { - "label": "Rent", - "pages": { - "rent": { - "questions": { - "rent_frequency": { - "check_answer_label": "Rent Period", - "header": "Which period are rent and other charges due?", - "type": "radio", - "answer_options": { - "0": "Weekly for 52 weeks", - "1": "Fortnightly" - } - }, - "basic_rent": { - "check_answer_label": "Basic Rent", - "header": "What is the basic rent?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": [ - "basic_rent", - "service_charge", - "personal_service_charge", - "support_charge" - ], - "result-field": "total_charge" - }, - "service_charge": { - "check_answer_label": "Service Charge", - "header": "What is the service charge?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": [ - "basic_rent", - "service_charge", - "personal_service_charge", - "support_charge" - ], - "result-field": "total_charge" - }, - "personal_service_charge": { - "check_answer_label": "Personal Service Charge", - "header": "What is the personal service charge?", - "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": [ - "basic_rent", - "service_charge", - "personal_service_charge", - "support_charge" - ], - "result-field": "total_charge" - }, - "support_charge": { - "check_answer_label": "Support Charge", - "header": "What is the support charge?", - "hint_text": "This is to fund housing-related support services included in the tenancy agreement", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": [ - "basic_rent", - "service_charge", - "personal_service_charge", - "support_charge" - ], - "result-field": "total_charge" - }, - "total_charge": { - "check_answer_label": "Total Charge", - "header": "Total charge?", - "hint_text": "This is the total of rent and all charges", - "type": "numeric", - "min": 0, - "step": 1, - "readonly": true - } - } - } - } - } - } - }, - "local_authority": { - "label": "Local authority", - "subsections": { - "local_authority": { - "label": "Local authority", - "pages": { - "time_lived_in_la": { - "questions": { - "time_lived_in_la": { - "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", - "header": "How long has the household continuously lived in the local authority area where the new letting is located?", - "type": "radio", - "answer_options": { - "0": "Just moved to local authority area", - "1": "Less than 1 year", - "2": "1 to 2 years", - "3": "2 to 3 years", - "4": "3 to 4 years", - "5": "4 to 5 years", - "6": "5 years or more", - "7": "Do not know" - } - } - } - }, - "time_on_la_waiting_list": { - "questions": { - "time_on_la_waiting_list": { - "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", - "header": "How long has the household been on the local authority waiting list where the new letting is located?", - "type": "radio", - "answer_options": { - "0": "Just moved to local authority area", - "1": "Less than 1 year", - "2": "1 to 2 years", - "3": "2 to 3 years", - "4": "3 to 4 years", - "5": "4 to 5 years", - "6": "5 years or more", - "7": "Do not know" - } - } - } - }, - "previous_postcode": { - "questions": { - "previous_postcode": { - "check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation", - "header": "Postcode for the previous accommodation", - "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", - "type": "text", - "conditional_for": { "faake_key": "fake_condition" } - } - } - } - } - } - } - }, - "submission": { - "label": "Submission", - "subsections": { - "declaration": { - "label": "Declaration", - "pages": { - "declaration": { - "questions": { - "declaration": { - "check_answer_label": "", - "header": "What is the tenant code?", - "type": "text" - } - } } } } @@ -538,3 +24,4 @@ } } } + \ No newline at end of file From 152e3a17f0d4533d424c953ba455b76a5f066779 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Wed, 10 Nov 2021 09:58:45 +0000 Subject: [PATCH 11/26] . --- config/forms/schema/test.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json index 998146adf..9058f70c4 100644 --- a/config/forms/schema/test.json +++ b/config/forms/schema/test.json @@ -45,6 +45,7 @@ }, "pages": { "type": "object", + "required": ["header"], "patternProperties": { "^[0-9]+$": { "properties": { From 8517613c64344daca12c4b2674403021abeb98e7 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Wed, 10 Nov 2021 14:20:22 +0000 Subject: [PATCH 12/26] . --- config/forms/schema/generic.json | 113 ++++++++++++++--------------- config/forms/schema/test.json | 75 +++++++------------ spec/fixtures/forms/test_form.json | 9 --- 3 files changed, 80 insertions(+), 117 deletions(-) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index d7e71468d..50c08369c 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -19,77 +19,74 @@ "type": "integer" }, "sections": { - "description": "", "type": "object", "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - }, - "label": { + "[a-z_\/#]+": { "description": "", - "type": "string" + "type": "object" }, - "subsections": { - "description": "", - "type": "object", - "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - }, - "label": { - "description": "", - "type": "string" - }, - "subsections": { - "description": "", - "type": "object", - "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - }, - "label": { - "description": "", - "type": "string" - }, - "pages": { - "description": "", - "type": "object", - "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - } - }, - "questions": { + "properties": { + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "description": "", + "type": "object", + "patternProperties": { + "[a-z_\/#]+": { + "description": "", + "type": "object", + "required": ["label"], + "properties": { + "label": { "description": "", + "type": "string", + "required": "true" + }, + "pages": { "type": "object", + "required": ["header"], "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "string" - }, - "conditional_for": { - "type": "object", - "properties": "" + "type": "object", + "[a-z_]+": { + "properties": { + "header": { + "description": "", + "type": "string" + }, + "description": { + "description": "", + "type": "string" + }, + "questions": { + "type": "object", + "patternProperties": { + "type": "object", + "[a-z_]+": { + "properties": { + "check_answer_label": { + "type": "string" + } + } + } + }, + "minProperties": 8 + }, + "minProperties": 8 + } } - } - }, - "conditional_route_to": { - "type": "object", - "properties": "" - }, - "default_next_page": { - "type" : "string" + }, + "minProperties": 8 } } } - } + }, + "minProperties": 8 } } - } + }, + "minProperties": 1 } } } \ No newline at end of file diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json index 9058f70c4..90a06942d 100644 --- a/config/forms/schema/test.json +++ b/config/forms/schema/test.json @@ -21,61 +21,36 @@ "sections": { "type": "object", "patternProperties": { - "^[0-9]+$": { + "[a-z_\/#]+": { "description": "", - "type": "string" - }, - "properties": { - "label": { - "description": "", - "type": "string" - }, - "subsections": { - "description": "", - "type": "object", - "patternProperties": { - "^[0-9]+$": { - "description": "", - "type": "object", - "required": ["label"], - "properties": { - "label": { - "description": "", - "type": "string" - }, - "pages": { - "type": "object", - "required": ["header"], - "patternProperties": { - "^[0-9]+$": { - "properties": { - "header": { - "description": "", - "type": "string" - }, - "description": { - "description": "", - "type": "string" - }, - "questions": { - "type": "object", - "properties": { - - } - } - } - } + "type": "object", + "properties": { + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "type": "object", + "patternProperties": { + "[a-z_\/#]+": { + "description": "", + "type": "object", + "required": ["label"], + "properties": { + "label": { + "description": "", + "type": "string" } - } + }, + "minProperties": 1 } - }, - "additionalProperties": false, - "maxProperties": 1, - "minProperties": 1 + } } - } + }, + "minProperties": 2 } - } + }, + "minProperties": 1 } } } \ No newline at end of file diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json index 73df96635..b5467a48f 100644 --- a/spec/fixtures/forms/test_form.json +++ b/spec/fixtures/forms/test_form.json @@ -9,15 +9,6 @@ "household_characteristics": { "label": "Household characteristics", "pages": { - "tenant_code": { - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "type": "text" - } - } - } } } } From 16685a25e2a5d327d85afc52884540d3b2fed485 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Wed, 10 Nov 2021 19:50:02 +0000 Subject: [PATCH 13/26] nearly working --- config/forms/schema/test.json | 35 +++++++++++++++++++++++++++++++++++ db/schema.rb | 13 ++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json index 90a06942d..f81b52d6c 100644 --- a/config/forms/schema/test.json +++ b/config/forms/schema/test.json @@ -40,6 +40,41 @@ "label": { "description": "", "type": "string" + }, + "pages": { + "type": "object", + "patternProperties": { + "[a-z_\/#]+": { + "description": "", + "type": "object", + "properties": { + "questions": { + "type": "object", + "patternProperties": { + "[a-z_\/#]+": { + "description": "", + "type": "object", + "properties": { + "check_answer_label": { + "description": "", + "type": "string" + }, + "header": { + "description": "", + "type": "string" + }, + "type": { + "description": "", + "type": "string" + } + } + } + } + } + }, + "minProperties": 1 + } + } } }, "minProperties": 1 diff --git a/db/schema.rb b/db/schema.rb index 7f75e5e87..ddd456c43 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2021_10_28_095000) do +ActiveRecord::Schema.define(version: 2021_11_02_100820) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -133,6 +133,17 @@ ActiveRecord::Schema.define(version: 2021_10_28_095000) do t.boolean "reasonable_preference_reason_do_not_know" t.datetime "discarded_at" t.string "other_tenancy_type" + t.string "gdpr_acceptance" + t.string "gdpr_declined" + t.string "property_owner_organisation" + t.string "property_manager_organisation" + t.string "sale_or_letting" + t.string "tenant_same_property_renewal" + t.string "rent_type" + t.string "intermediate_rent_product_name" + t.string "needs_type" + t.string "sale_completion_date" + t.string "purchaser_code" t.boolean "override_net_income_validation" t.string "net_income_known" t.index ["discarded_at"], name: "index_case_logs_on_discarded_at" From 5dacd38187693731e2907798cd466f165dce194f Mon Sep 17 00:00:00 2001 From: magicmilo Date: Wed, 10 Nov 2021 20:05:54 +0000 Subject: [PATCH 14/26] blank conditional for --- config/forms/schema/test.json | 25 +++++++++++++++++++++---- spec/fixtures/forms/test_validator.json | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json index f81b52d6c..93eaf9a6d 100644 --- a/config/forms/schema/test.json +++ b/config/forms/schema/test.json @@ -21,7 +21,7 @@ "sections": { "type": "object", "patternProperties": { - "[a-z_\/#]+": { + "[a-z_]+": { "description": "", "type": "object", "properties": { @@ -32,7 +32,7 @@ "subsections": { "type": "object", "patternProperties": { - "[a-z_\/#]+": { + "[a-z_]+": { "description": "", "type": "object", "required": ["label"], @@ -44,16 +44,25 @@ "pages": { "type": "object", "patternProperties": { - "[a-z_\/#]+": { + "[a-z_]+": { "description": "", "type": "object", "properties": { + "header": { + "description": "", + "type": "string" + }, + "description": { + "description": "", + "type": "string" + }, "questions": { "type": "object", "patternProperties": { - "[a-z_\/#]+": { + "[a-z_]+": { "description": "", "type": "object", + "required": ["header"], "properties": { "check_answer_label": { "description": "", @@ -66,6 +75,14 @@ "type": { "description": "", "type": "string" + }, + "hint_text": { + "description": "", + "type": "string" + }, + "answer_options": { + "description": "", + "type": "string" } } } diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index e0fe13361..e83c4d970 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -8,7 +8,7 @@ "subsections": { "household_characteristics": { "label": "Household characteristics", - "baddata": "Shouldn't be here but what you gonna do?", + "ShouldThrowError": "Shouldn't be here but what you gonna do?", "pages": { "tenant_code": { "questions": { From 8c27ae6ffc63ec17ca4594462bd11522a3e30ea2 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 11 Nov 2021 11:39:02 +0000 Subject: [PATCH 15/26] Validate structure correctly --- app/helpers/json_schema_validation.rb | 3 +- config/forms/schema/2021_2022.json | 2230 ++--------------------- config/forms/schema/generic.json | 140 +- config/forms/schema/test.json | 108 -- spec/fixtures/forms/test_form.json | 18 - spec/fixtures/forms/test_validator.json | 3 +- 6 files changed, 191 insertions(+), 2311 deletions(-) delete mode 100644 config/forms/schema/test.json delete mode 100644 spec/fixtures/forms/test_form.json diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 12084b020..dd0655d3b 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -13,8 +13,7 @@ end begin - # path = "config/forms/schema/generic.json" - path = "config/forms/schema/test.json" + path = "config/forms/schema/generic.json" # path = "config/forms/schema/2021_2022.json" file = File.open(path) diff --git a/config/forms/schema/2021_2022.json b/config/forms/schema/2021_2022.json index 2a825ffb8..cd8f13530 100644 --- a/config/forms/schema/2021_2022.json +++ b/config/forms/schema/2021_2022.json @@ -1,2134 +1,112 @@ { - "form_type": "lettings", - "start_year": 2021, - "end_year": 2022, + "$schema": "http://json-schema.org/draft-04/schema#", + "$id": "https://example.com/product.schema.json", + "title": "Form", + "description": "A form", + "type": "object", + "required": ["form_type", "start_year", "end_year", "sections"], + "properties": { + "form_type": { + "description": "", + "type": "string" + }, + "start_year": { + "description": "", + "type": "integer" + }, + "end_year": { + "description": "", + "type": "integer" + }, "sections": { - "household": { - "label": "About the household", - "subsections": { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - "tenant_code": { - "header": "", - "description": "", - "questions": { - "tenant_code": { - "check_answer_label": "Tenant code", - "header": "What is the tenant code?", - "hint_text": "", - "type": "text" - } - } - }, - "person_1_age": { - "header": "", - "description": "", - "questions": { - "person_1_age": { - "check_answer_label": "Tenant's age", - "header": "What is the tenant's age?", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 120, - "step": 1 - } - } - }, - "person_1_gender": { - "header": "", - "description": "", - "questions": { - "person_1_gender": { - "check_answer_label": "Tenant's gender", - "header": "Which of these best describes the tenant's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - } - } - }, - "tenant_ethnic_group": { - "header": "", - "description": "", - "questions": { - "tenant_ethnic_group": { - "check_answer_label": "Ethnicity", - "header": "What is the tenant's ethnic group?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "White: English/Scottish/Welsh/Northern Irish/British", - "1": "White: Irish", - "2": "White: Gypsy/Irish Traveller", - "3": "White: Other", - "4": "Mixed: White & Black Caribbean", - "5": "Mixed: White & Black African", - "6": "Mixed: White & Asian", - "7": "Mixed: Other", - "8": "Asian or Asian British: Indian", - "9": "Asian or Asian British: Pakistani", - "10": "Asian or Asian British: Bangladeshi", - "11": "Asian or Asian British: Chinese", - "12": "Asian or Asian British: Other", - "13": "Black: Caribbean", - "14": "Black: African", - "15": "Black: Other", - "16": "Other Ethnic Group: Arab", - "17": "Other Ethnic Group: Other", - "18": "Prefer not to say" - } - } - } - }, - "tenant_nationality": { - "header": "", - "description": "", - "questions": { - "tenant_nationality": { - "check_answer_label": "Nationality", - "header": "What is the tenant's nationality?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "UK national resident in UK", - "1": "A current or former reserve in the UK Armed Forces (exc. National Service)", - "2": "UK national returning from residence overseas", - "3": "Czech Republic", - "4": "Estonia", - "5": "Hungary", - "6": "Latvia", - "7": "Lithuania", - "8": "Poland", - "9": "Slovakia", - "10": "Bulgaria", - "11": "Romania", - "12": "Ireland", - "13": "Other EU Economic Area (EEA country)", - "14": "Any other country", - "15": "Prefer not to say" - } - } - } - }, - "tenant_economic_status": { - "header": "", - "description": "", - "questions": { - "person_1_economic_status": { - "check_answer_label": "Work", - "header": "Which of these best describes the tenant's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - } - } - }, - "household_number_of_other_members": { - "header": "", - "description": "", - "questions": { - "household_number_of_other_members": { - "check_answer_label": "Number of Other Household Members", - "header": "How many other people are there in the household?", - "hint_text": "The maximum number of others is 7", - "type": "numeric", - "min": 0, - "max": 7, - "step": 1, - "conditional_for": { - "person_2_relationship": ">0", - "person_2_age": ">0", - "person_2_gender": ">0", - "person_2_economic_status": ">0", - "person_3_relationship": ">1", - "person_3_age": ">1", - "person_3_gender": ">1", - "person_3_economic_status": ">1", - "person_4_relationship": ">2", - "person_4_age": ">2", - "person_4_gender": ">2", - "person_4_economic_status": ">2", - "person_5_relationship": ">3", - "person_5_age": ">3", - "person_5_gender": ">3", - "person_5_economic_status": ">3", - "person_6_relationship": ">4", - "person_6_age": ">4", - "person_6_gender": ">4", - "person_6_economic_status": ">4", - "person_7_relationship": ">5", - "person_7_age": ">5", - "person_7_gender": ">5", - "person_7_economic_status": ">5", - "person_8_relationship": ">6", - "person_8_age": ">6", - "person_8_gender": ">6", - "person_8_economic_status": ">6" - } - }, - "person_2_relationship": { - "check_answer_label": "Person 2's relationship to lead tenant", - "header": "What's person 2's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_2_age": { - "check_answer_label": "Person 2's age", - "header": "What's person 2's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_2_gender": { - "check_answer_label": "Person 2's gender", - "header": "Which of these best describes person 2's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_2_economic_status": { - "check_answer_label": "Person 2's Work", - "header": "Which of these best describes person 2's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_3_relationship": { - "check_answer_label": "Person 3's relationship to lead tenant", - "header": "What's person 3's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_3_age": { - "check_answer_label": "Person 3's age", - "header": "What's person 3's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_3_gender": { - "check_answer_label": "Person 3's gender", - "header": "Which of these best describes person 3's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_3_economic_status": { - "check_answer_label": "Person 3's Work", - "header": "Which of these best describes person 3's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_4_relationship": { - "check_answer_label": "Person 4's relationship to lead tenant", - "header": "What's person 4's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_4_age": { - "check_answer_label": "Person 4's age", - "header": "What's person 4's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_4_gender": { - "check_answer_label": "Person 4's gender", - "header": "Which of these best describes person 4's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_4_economic_status": { - "check_answer_label": "Person 4's Work", - "header": "Which of these best describes person 4's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_5_relationship": { - "check_answer_label": "Person 5's relationship to lead tenant", - "header": "What's person 5's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_5_age": { - "check_answer_label": "Person 5's age", - "header": "What's person 5's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_5_gender": { - "check_answer_label": "Person 5's gender", - "header": "Which of these best describes person 5's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_5_economic_status": { - "check_answer_label": "Person 5's Work", - "header": "Which of these best describes person 5's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_6_relationship": { - "check_answer_label": "Person 6's relationship to lead tenant", - "header": "What's person 6's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_6_age": { - "check_answer_label": "Person 6's age", - "header": "What's person 6's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_6_gender": { - "check_answer_label": "Person 6's gender", - "header": "Which of these best describes person 6's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_6_economic_status": { - "check_answer_label": "Person 6's Work", - "header": "Which of these best describes person 6's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_7_relationship": { - "check_answer_label": "Person 7's relationship to lead tenant", - "header": "What's person 7's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_7_age": { - "check_answer_label": "Person 7's age", - "header": "What's person 7's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_7_gender": { - "check_answer_label": "Person 7's gender", - "header": "Which of these best describes person 7's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_7_economic_status": { - "check_answer_label": "Person 7's Work", - "header": "Which of these best describes person 7's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - }, - "person_8_relationship": { - "check_answer_label": "Person 8's relationship to lead tenant", - "header": "What's person 8's relationship to lead tenant", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Partner", - "1": "Child - includes young adult and grown-up", - "2": "Other", - "3": "Prefer not to say" - } - }, - "person_8_age": { - "check_answer_label": "Person 8's age", - "header": "What's person 8's age", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - }, - "person_8_gender": { - "check_answer_label": "Person 8's gender", - "header": "Which of these best describes person 8's gender identity?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Female", - "1": "Male", - "2": "Non-binary", - "3": "Prefer not to say" - } - }, - "person_8_economic_status": { - "check_answer_label": "Person 8's Work", - "header": "Which of these best describes person 8's working situation?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Part-time - Less than 30 hours", - "1": "Full-time - 30 hours or more", - "2": "In government training into work, such as New Deal", - "3": "Jobseeker", - "4": "Retired", - "5": "Not seeking work", - "6": "Full-time student", - "7": "Unable to work because of long term sick or disability", - "8": "Child under 16", - "9": "Other", - "10": "Prefer not to say" - } - } - } - } - } - }, - "household_situation": { - "label": "Household situation", - "pages": { - "previous_housing_situation": { - "header": "", - "description": "", - "questions": { - "previous_housing_situation": { - "header": "What was the tenant’s housing situation immediately before this letting?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Owner occupation (private) ", - "1": "Owner occupation (low cost home ownership)", - "2": "Private sector tenancy", - "3": "Tied housing or rented with job", - "4": "Supported housing", - "5": "Sheltered accomodation", - "6": "Residential care home", - "7": "Living with friends or family", - "8": "Refuge", - "9": "Hospital", - "10": "Prison / approved probation hostel", - "11": "Direct access hostel", - "12": "Bed & Breakfast", - "13": "Mobile home / caravan", - "14": "Any other temporary accommodation", - "15": "Home Office Asylum Support", - "16": "Children’s home / foster care", - "17": "Rough sleeping", - "18": "Other", - "19": "Fixed term Local Authority General Needs tenancy", - "20": "Lifetime Local Authority General Needs tenancy", - "21": "Fixed term PRP General Needs tenancy", - "22": "Lifetime PRP General Needs tenancy" - } - } - } - }, - "homelessness": { - "header": "", - "description": "", - "questions": { - "homelessness": { - "header": "Did the tenant experience homelessness immediately before this letting?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes - assessed as homeless by a local authority and owed a homelessness duty. Including if threatened with homelessness within 56 days", - "1": "Yes - other homelessness ", - "2": "No" - } - } - } - }, - "reason_for_leaving_last_settled_home": { - "header": "Leaving their last settled home", - "description": "", - "questions": { - "reason_for_leaving_last_settled_home": { - "header": "What is the tenant’s main reason for leaving?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Permanently decanted from another property owned by this landlord", - "1": "Left home country as a refugee", - "2": "Loss of tied accommodation", - "3": "Domestic abuse", - "4": "(Non violent) relationship breakdown with partner", - "5": "Asked to leave by family or friends", - "6": "Racial harassment", - "7": "Other problems with neighbours", - "8": "Property unsuitable because of overcrowding", - "9": "End of assured shorthold tenancy - no fault", - "10": "End of assured shorthold tenancy - tenant's fault", - "11": "End of fixed term tenancy - no fault", - "12": "End of fixed term tenancy - tenant's fault", - "13": "Repossession", - "14": "Under occupation - offered incentive to downsize", - "15": "Under occupation - no incentive", - "16": "Property unsuitable because of ill health / disability", - "17": "Property unsuitable because of poor condition", - "18": "Couldn't afford fees attached to renewing the tenancy", - "19": "Couldn't afford increase in rent", - "20": "Couldn't afford rent or mortgage - welfare reforms", - "21": "Couldn't afford rent or mortgage - employment", - "22": "Couldn't afford rent or mortgage - other", - "23": "To move nearer to family / friends / school", - "24": "To move nearer to work", - "25": "To move to accomodation with support", - "26": "To move to independent accomodation", - "27": "Hate crime", - "28": "Death of household member in last settled accomodation", - "29": "Discharged from prison", - "30": "Discharged from long stay hospital or similar institution", - "31": "Other", - "32": "Do not know", - "33": "Prefer not to say" - }, - "conditional_for": { - "other_reason_for_leaving_last_settled_home": ["Other"] - } - }, - "other_reason_for_leaving_last_settled_home": { - "header": "Please state the reason for leaving last settled home", - "hint_text": "", - "type": "text" - }, - "benefit_cap_spare_room_subsidy": { - "header": "Was the reason for leaving because of the benefit cap or removal of the spare room subsidy?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes - benefit cap", - "1": "Yes - removal of the spare room subsidy", - "2": "Yes - both the benefit cap and the removal of the spare room subsidy", - "3": "No", - "4": "Do not know", - "5": "Prefer not to say" - } - } - } - } - } - }, - "household_needs": { - "label": "Household needs", - "pages": { - "armed_forces": { - "header": "Experience of the UK Armed Forces", - "description": "", - "questions": { - "armed_forces": { - "header": "Has the tenant ever served in the UK armed forces?", - "hint_text": "", - "type": "radio", - "check_answer_label": "Armed Forces", - "answer_options": { - "0": "Yes - a regular", - "1": "Yes - a reserve", - "2": "No", - "3": "Prefer not to say" - }, - "conditional_for": { - "armed_forces_active": ["Yes - a regular", "Yes - a reserve"], - "armed_forces_injured": ["Yes - a regular", "Yes - a reserve"] - } - }, - "armed_forces_active": { - "header": "Are they still serving?", - "hint_text": "", - "type": "radio", - "check_answer_label": "When did they leave the Armed Forces?", - "answer_options": { - "0": "Yes", - "1": "No - they left up to 5 years ago", - "2": "No - they left more than 5 years ago", - "3": "Prefer not to say" - } - }, - "armed_forces_injured": { - "header": "Were they seriously injured or ill as a result of their service?", - "hint_text": "", - "type": "radio", - "check_answer_label": "Has anyone in the household been seriously injured or ill as a result of their service in the armed forces?", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Prefer not to say" - } - }, - "armed_forces_partner": { - "header": "Was the tenant the spouse or civil partner of someone who served in the UK armed forces?", - "hint_text": "", - "type": "radio", - "check_answer_label": "Was the tenant the spouse or civil partner of someone who served in the UK armed forces?", - "answer_options": { - "0": "Yes - was the spouse or civil partner of a UK Armed Forces member and have separated within the last 2 years", - "1": "Yes - was the spouse or civil partner of a UK Armed Forces member who died within the last 2 years", - "2": "No", - "3": "Prefer not to say" - } - } - } - }, - "medical_conditions": { - "header": "", - "description": "", - "questions": { - "medical_conditions": { - "header": "Does anyone in the household have any of the following that they expect to last for 12 months or more:
  • Physical Condition
  • Mental Health Condition
  • Other Illness
", - "hint_text": "", - "type": "radio", - "check_answer_label": "Physical, mental health or illness in the household", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Do not know", - "3": "Prefer not to say" - } - } - } - }, - "pregnancy": { - "header": "", - "description": "", - "questions": { - "pregnancy": { - "header": "Is anyone in the household pregnant?", - "hint_text": "", - "type": "radio", - "check_answer_label": "Pregnancy in the household", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Prefer not to say" - } - } - } - }, - "accessibility_requirements": { - "header": "", - "description": "", - "questions": { - "accessibility_requirements": { - "header": "Are any of these affected by their condition or illness?", - "hint_text": "Select all that apply", - "type": "checkbox", - "check_answer_label": "Disability requirements", - "answer_options": { - "accessibility_requirements_fully_wheelchair_accessible_housing": "Fully wheelchair accessible housing", - "accessibility_requirements_wheelchair_access_to_essential_rooms": "Wheelchair access to essential rooms", - "accessibility_requirements_level_access_housing": "Level access housing", - "accessibility_requirements_other_disability_requirements": "Other disability requirements", - "accessibility_requirements_no_disability_requirements": "No disability requirements", - "divider_a": true, - "accessibility_requirements_do_not_know": "Do not know", - "divider_b": true, - "accessibility_requirements_prefer_not_to_say": "Prefer not to say" - } - } - } - }, - "condition_effects": { - "header": "", - "description": "", - "questions": { - "condition_effects": { - "header": "Are any of these affected by their condition or illness?", - "hint_text": "Select all that apply", - "type": "checkbox", - "check_answer_label": "Conditions or illnesses", - "answer_options": { - "condition_effects_vision": "Vision - such as blindness or partial sight", - "condition_effects_hearing": "Hearing - such as deafness or partial hearing", - "condition_effects_mobility": "Mobility - such as walking short distances or climbing stairs", - "condition_effects_dexterity": "Dexterity - such as lifting and carrying objects or using a keyboard", - "condition_effects_stamina": "Stamina or breathing or fatigue", - "condition_effects_learning": "Learning or understanding or concentrating", - "condition_effects_memory": "Memory", - "condition_effects_mental_health": "Mental health - such as depression, anxiety, schizophrenia or bipolar", - "condition_effects_social_or_behavioral": "Socially or behaviourally - such as those associated with autism spectral disorder (ASD) including Aspergers’ or attention deficit hyperactivity disorder (ADHD))", - "condition_effects_other": "Other", - "divider": true, - "condition_effects_prefer_not_to_say": "Prefer not to say" - } - } - } - } - } - } - } - }, - "tenancy_and_property": { - "label": "Tenancy and property information", - "subsections": { - "tenancy_information": { - "label": "Tenancy information", - "pages": { - "tenancy_code": { - "header": "", - "description": "", - "questions": { - "tenancy_code": { - "check_answer_label": "What is the tenancy code?", - "header": "What is the tenancy code?", - "hint_text": "", - "type": "text" - } - } - }, - "tenancy_start_date": { - "header": "", - "description": "", - "questions": { - "tenancy_start_date": { - "check_answer_label": "When is the tenancy start date?", - "header": "What is the tenancy start date?", - "hint_text": "For example, 27 3 2007", - "type": "date" - } - } - }, - "starter_tenancy": { - "header": "", - "description": "", - "questions": { - "starter_tenancy": { - "check_answer_label": "Is this a starter or introductory tenancy?", - "header": "Is this a starter tenancy?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - }, - "fixed_term_tenancy": { - "header": "", - "description": "", - "questions": { - "fixed_term_tenancy": { - "check_answer_label": "If the main tenancy is a fixed term tenancy, please provide the length of the fixed term (to the nearest year) excluding any starter/introductory period", - "header": "If fixed-term, what is the length of the fixed-term tenancy after any starter period?", - "hint_text": "To the nearest year", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - } - } - }, - "tenancy_type": { - "header": "", - "description": "", - "questions": { - "tenancy_type": { - "check_answer_label": "Type of main tenancy (after any starter/introductory period)", - "header": "What is the type of tenancy after the starter period has ended?", - "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" - }, - "conditional_for": { - "other_tenancy_type": ["Other"] - } - }, - "other_tenancy_type": { - "header": "Please state the tenancy type", - "hint_text": "", - "type": "text" - } - } - }, - "letting_type": { - "header": "", - "description": "", - "questions": { - "letting_type": { - "check_answer_label": "Type of letting", - "header": "Which type of letting is this?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Social Rent - General Needs", - "1": "Social Rent - Supporting Housing", - "2": "Affordable Rent - General Needs", - "3": "Affordable Rent - Supporting Housing", - "4": "Rent To Buy - General Needs", - "5": "Rent To Buy - Supported Housing" - } - } - } - }, - "letting_provider": { - "header": "", - "description": "", - "questions": { - "letting_provider": { - "check_answer_label": "Provider", - "header": "Who is the letting provider?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "This landlord", - "1": "Another registered provider - includes housing association or local authority" - } - } - } - } - } - }, - "property_information": { - "label": "Property information", - "pages": { - "property_location": { - "header": "", - "description": "", - "questions": { - "property_location": { - "check_answer_label": "Property Location", - "header": "Property location", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Adur", - "1": "Allerdale", - "2": "Amber Valley", - "3": "Arun", - "4": "Ashfield", - "5": "Ashford", - "6": "Babergh", - "7": "Barking & Dagenham", - "8": "Barnet", - "9": "Barnsley", - "10": "Barrow-in-Furness", - "11": "Basildon", - "12": "Basingstoke & Deane", - "13": "Bassetlaw", - "14": "Bath & NE Somerset", - "15": "Bedford Borough Council", - "16": "Bexley", - "17": "Birmingham", - "18": "Blaby", - "19": "Blackburn", - "20": "Blackpool", - "21": "Bolsover", - "22": "Bolton", - "23": "Boston", - "24": "Bournemouth & Christchurch & Poole", - "25": "Bracknell Forest", - "26": "Bradford", - "27": "Braintree", - "28": "Breckland", - "29": "Brent", - "30": "Brentwood", - "31": "Brighton & Hove", - "32": "Bristol", - "33": "Broadland", - "34": "Bromley", - "35": "Bromsgrove", - "36": "Broxbourne", - "37": "Broxtowe", - "38": "Buckinghamshire", - "39": "Burnley", - "40": "Bury", - "41": "Calderdale", - "42": "Cambridge", - "43": "Camden", - "44": "Cannock Chase", - "45": "Canterbury", - "46": "Carlisle", - "47": "Castle Point", - "48": "Central Bedfordshire", - "49": "Charnwood", - "50": "Chelmsford", - "51": "Cheltenham", - "52": "Cherwell", - "53": "Cheshire West & Chester", - "54": "Chesterfield", - "55": "Chichester", - "56": "Chorley", - "57": "City of London", - "58": "Colchester", - "59": "Copeland", - "60": "Cornwall", - "61": "Cotswold", - "62": "Coventry", - "63": "Craven", - "64": "Crawley", - "65": "Croydon", - "66": "Dacorum", - "67": "Darlington", - "68": "Dartford", - "69": "Derby", - "70": "Derbyshire Dales", - "71": "Doncaster", - "72": "Dorset", - "73": "Dover", - "74": "Dudley", - "75": "Durham", - "76": "Ealing", - "77": "East Cambridgeshire", - "78": "East Cheshire", - "79": "East Devon", - "80": "East Hampshire", - "81": "East Herts", - "82": "East Lindsey", - "83": "East Riding", - "84": "East Staffordshire", - "85": "East Suffolk", - "86": "Eastbourne", - "87": "Eastleigh", - "88": "Eden", - "89": "Elmbridge", - "90": "Enfield", - "91": "Epping Forest", - "92": "Epsom & Ewell", - "93": "Erewash", - "94": "Exeter", - "95": "Fareham", - "96": "Fenland", - "97": "Folkestone & Hythe", - "98": "Forest of Dean", - "99": "Fylde", - "100": "Gateshead", - "101": "Gedling", - "102": "Gloucester", - "103": "Gosport", - "104": "Gravesham", - "105": "Great Yarmouth", - "106": "Greenwich", - "107": "Guildford", - "108": "Hackney", - "109": "Halton", - "110": "Hambleton", - "111": "Hammersmith & Fulham", - "112": "Harborough", - "113": "Haringey", - "114": "Harlow", - "115": "Harrogate", - "116": "Harrow", - "117": "Hart", - "118": "Hartlepool", - "119": "Hastings", - "120": "Havant", - "121": "Havering", - "122": "Herefordshire", - "123": "Hertsmere", - "124": "High Peak", - "125": "Hillingdon", - "126": "Hinckley & Bosworth", - "127": "Horsham", - "128": "Hounslow", - "129": "Huntingdonshire", - "130": "Hyndburn", - "131": "Ipswich", - "132": "Isle of Wight", - "133": "Isles of Scilly", - "134": "Islington", - "135": "Kensington & Chelsea", - "136": "Kings Lynn & West Norfolk", - "137": "Kingston-upon-Hull", - "138": "Kingston-upon-Thames", - "139": "Kirklees", - "140": "Knowsley", - "141": "Lambeth", - "142": "Lancaster", - "143": "Leeds", - "144": "Leicester", - "145": "Lewes", - "146": "Lewisham", - "147": "Lichfield", - "148": "Lincoln", - "149": "Liverpool", - "150": "Luton", - "151": "Maidstone", - "152": "Maldon", - "153": "Malvern Hills", - "154": "Manchester", - "155": "Mansfield", - "156": "Medway", - "157": "Melton", - "158": "Mendip", - "159": "Merton", - "160": "Mid Devon", - "161": "Mid Suffolk", - "162": "Mid Sussex", - "163": "Middlesbrough", - "164": "Milton Keynes", - "165": "Mole Valley", - "166": "N. Ireland", - "167": "New Forest", - "168": "Newark", - "169": "Newcastle-under-Lyme", - "170": "Newcastle-upon-Tyne", - "171": "Newham", - "172": "North Devon", - "173": "North East Derbyshire", - "174": "North East Lincolnshire", - "175": "North Hertfordshire", - "176": "North Kesteven", - "177": "North Lincolnshire", - "178": "North Norfolk", - "179": "North Northamptonshire", - "180": "North Somerset", - "181": "North Tyneside", - "182": "North Warwickshire", - "183": "North West Leics", - "184": "Northumberland", - "185": "Norwich", - "186": "Nottingham", - "187": "Nuneaton & Bedworth", - "188": "Oadby & Wigston", - "189": "Oldham", - "190": "Outside UK", - "191": "Oxford", - "192": "Pendle", - "193": "Peterborough", - "194": "Plymouth", - "195": "Portsmouth", - "196": "Preston", - "197": "Reading", - "198": "Redbridge", - "199": "Redcar & Cleveland", - "200": "Redditch", - "201": "Reigate & Banstead", - "202": "Ribble Valley", - "203": "Richmond-upon-Thames", - "204": "Richmondshire", - "205": "Rochdale", - "206": "Rochford", - "207": "Rossendale", - "208": "Rother", - "209": "Rotherham", - "210": "Rugby", - "211": "Runnymede", - "212": "Rushcliffe", - "213": "Rushmoor", - "214": "Rutland", - "215": "Ryedale", - "216": "Salford", - "217": "Sandwell", - "218": "Scarborough", - "219": "Scotland", - "220": "Sedgemoor", - "221": "Sefton", - "222": "Selby", - "223": "Sevenoaks", - "224": "Sheffield", - "225": "Shropshire", - "226": "Slough", - "227": "Solihull", - "228": "Somerset West & Taunton", - "229": "South Cambridgeshire", - "230": "South Derbyshire", - "231": "South Gloucestershire", - "232": "South Hams", - "233": "South Holland", - "234": "South Kesteven", - "235": "South Lakeland", - "236": "South Norfolk", - "237": "South Oxfordshire", - "238": "South Ribble", - "239": "South Somerset", - "240": "South Staffordshire", - "241": "South Tyneside", - "242": "Southampton", - "243": "Southend-on-Sea", - "244": "Southwark", - "245": "Spelthorne", - "246": "St Albans", - "247": "St Helens", - "248": "Stafford", - "249": "Staffordshire Moorlands", - "250": "Stevenage", - "251": "Stockport", - "252": "Stockton-on-Tees", - "253": "Stoke-on-Trent", - "254": "Stratford-on-Avon", - "255": "Stroud", - "256": "Sunderland", - "257": "Surrey Heath", - "258": "Sutton", - "259": "Swale", - "260": "Swindon", - "261": "Tameside", - "262": "Tamworth", - "263": "Tandridge", - "264": "Teignbridge", - "265": "Telford & Wrekin", - "266": "Tendring", - "267": "Test Valley", - "268": "Tewkesbury", - "269": "Thanet", - "270": "Three Rivers", - "271": "Thurrock", - "272": "Tonbridge & Malling", - "273": "Torbay", - "274": "Torridge", - "275": "Tower Hamlets", - "276": "Trafford", - "277": "Tunbridge Wells", - "278": "Uttlesford", - "279": "Vale of White Horse", - "280": "Wakefield", - "281": "Wales", - "282": "Walsall", - "283": "Waltham Forest", - "284": "Wandsworth", - "285": "Warrington", - "286": "Warwick", - "287": "Watford", - "288": "Waverley", - "289": "Wealden", - "290": "Welwyn Hatfield", - "291": "West Berkshire", - "292": "West Devon", - "293": "West Lancashire", - "294": "West Lindsey", - "295": "West Northamptonshire", - "296": "West Oxfordshire", - "297": "West Suffolk", - "298": "Westminster", - "299": "Wigan", - "300": "Wiltshire", - "301": "Winchester", - "302": "Windsor & Maidenhead", - "303": "Wirral", - "304": "Woking", - "305": "Wokingham", - "306": "Wolverhampton", - "307": "Worcester", - "308": "Worthing", - "309": "Wychavon", - "310": "Wyre", - "311": "Wyre Forest", - "312": "York" - } - } - } - }, - "property_postcode": { - "header": "", - "description": "", - "questions": { - "property_postcode": { - "check_answer_label": "What was the previous postcode?", - "header": "What is the property's postcode?", - "hint_text": "", - "type": "text" - } - } - }, - "property_relet": { - "header": "", - "description": "", - "questions": { - "property_relet": { - "check_answer_label": "Which type was the property most recently let as?", - "header": "Is this property a relet?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - }, - "property_vacancy_reason": { - "header": "", - "description": "", - "questions": { - "property_vacancy_reason": { - "check_answer_label": "What is the reason for the property vacancy?", - "header": "What is the reason for the property vacancy?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "First let of newbuild property", - "1": "First let of conversion/rehabilitation/acquired property", - "2": "First let of leased property", - "3": "Relet - tenant evicted due to arrears", - "4": "Relet - tenant evicted due to ASB or other reason", - "5": "Relet - tenant died (no succession)", - "6": "Relet - tenant moved to other social housing provider", - "7": "Relet - tenant abandoned property", - "8": "Relet - tenant moved to private sector or other accommodation", - "9": "Relet - to tenant who occupied same property as temporary accommodation", - "10": "Relet – internal transfer (excluding renewals of a fixed-term tenancy)", - "11": "Relet – renewal of fixed-term tenancy", - "12": "Relet – tenant moved to care home", - "13": "Relet – tenant involved in a succession downsize" - } - } - } - }, - "property_reference": { - "header": "", - "description": "", - "questions": { - "property_reference": { - "check_answer_label": "What’s the property reference?", - "header": "What's the property reference?", - "hint_text": "", - "type": "text" - } - } - }, - "property_unit_type": { - "header": "", - "description": "", - "questions": { - "property_unit_type": { - "check_answer_label": "Which type of unit is the property?", - "header": "Which type of unit is the property?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Flat / maisonette", - "1": "Bed-sit", - "2": "House", - "3": "Bungalow", - "4": "Shared flat / maisonette", - "5": "Shared house", - "6": "Shared bungalow", - "7": "Other" - } - } - } - }, - "property_number_of_bedrooms": { - "header": "", - "description": "", - "questions": { - "property_number_of_bedrooms": { - "check_answer_label": "How many bedrooms are there in the property?", - "header": "How many bedrooms are there in the property?", - "hint_text": "If shared accommodation, enter number of bedrooms occupied by this household; a bed-sit has 1 bedroom", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - } - } - }, - "property_major_repairs": { - "header": "", - "description": "", - "questions": { - "property_major_repairs": { - "check_answer_label": "Were major repairs carried out during the void period?", - "header": "Were any major repairs completed during the void period?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" + "type": "object", + "patternProperties": { + "[a-z_]+": { + "description": "", + "type": "object", + "properties": { + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "type": "object", + "patternProperties": { + "[a-z_]+": { + "description": "", + "type": "object", + "required": ["label"], + "properties": { + "label": { + "description": "", + "type": "string" }, - "conditional_for": { - "property_major_repairs_date": ["Yes"] - } - }, - "property_major_repairs_date": { - "check_answer_label": "What was the major repairs completion date?", - "header": "What was the major repairs completion date?", - "hint_text": "For example, 27 3 2007", - "type": "date" - } - } - }, - "property_number_of_times_relet": { - "header": "", - "description": "", - "questions": { - "property_number_of_times_relet": { - "check_answer_label": "How many times has this unit been previously offered since becoming available for relet since the last tenancy ended or as a first let?", - "header": "How many times has this unit been previously offered since becoming available for relet since the last tenancy ended or as a first let? ", - "hint_text": "For an Affordable Rent or Intermediate Rent Letting, only include number of offers as that type. For a property let at the first attempt enter '0' ", - "type": "numeric", - "min": 0, - "max": 150, - "step": 1 - } - } - }, - "property_wheelchair_accessible": { - "header": "", - "description": "", - "questions": { - "property_wheelchair_accessible": { - "check_answer_label": "Is property built or adapted to wheelchair user standards?", - "header": "Is property built or adapted to wheelchair user standards?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - } + "pages": { + "type": "object", + "patternProperties": { + "[a-z_]+": { + "description": "", + "type": "object", + "properties": { + "header": { + "description": "", + "type": "string" + }, + "description": { + "description": "", + "type": "string" + }, + "questions": { + "type": "object", + "patternProperties": { + "[a-z_]+": { + "description": "", + "type": "object", + "required": ["header", "check_answer_label"], + "properties": { + "check_answer_label": { + "description": "", + "type": "string" + }, + "header": { + "description": "", + "type": "string" + }, + "type": { + "description": "", + "type": "string" + }, + "hint_text": { + "description": "", + "type": "string" + }, + "answer_options": { + "description": "", + "type": "object" + }, + "conditional_for": { + "description": "", + "type": "object" + } + } + } + } + } + }, + "minProperties": 1 + } + } + } + }, + "minProperties": 1 + } + } } - } + }, + "minProperties": 2 } }, - "rent_and_charges": { - "label": "Rent and charges", - "subsections": { - "income_and_benefits": { - "label": "Income and benefits", - "pages": { - "net_income": { - "header": "", - "description": "", - "questions": { - "net_income_known": { - "check_answer_label": "Income known", - "header": "Do you know the tenant and their partner's net income?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No", - "2": "Tenant prefers not to say" - }, - "conditional_for": { - "net_income": ["Yes"], - "net_income_frequency": ["Yes"] - } - }, - "net_income": { - "check_answer_label": "Income", - "header": "What is the tenant’s /and partner’s combined income after tax?", - "hint_text": "", - "type": "numeric", - "min": 0, - "step": "1" - }, - "net_income_frequency": { - "check_answer_label": "Income Frequency", - "header": "How often do they receive this income?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Weekly", - "1": "Monthly", - "2": "Yearly" - } - } - }, - "soft_validations": { - "override_net_income_validation": { - "check_answer_label": "Net income confirmed?", - "type": "validation_override", - "answer_options": { - "override_net_income_validation": "Yes" - } - } - } - }, - "net_income_uc_proportion": { - "header": "", - "description": "", - "questions": { - "net_income_uc_proportion": { - "check_answer_label": "Benefits as a proportion of income", - "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "All", - "1": "Some", - "2": "None", - "3": "Do not know" - } - } - } - }, - "housing_benefit": { - "header": "", - "description": "", - "questions": { - "housing_benefit": { - "check_answer_label": "Universal Credit & Housing Benefit\t", - "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Housing Benefit, but not Universal Credit", - "1": "Universal Credit with housing element, but not Housing Benefit", - "2": "Universal Credit without housing element and no Housing Benefit", - "3": "Universal Credit and Housing Benefit", - "4": "Not Housing Benefit or Universal Credit", - "5": "Do not know", - "6": "Prefer not to say" - } - } - } - } - } - }, - "rent": { - "label": "Rent", - "pages": { - "rent": { - "header": "", - "description": "", - "questions": { - "rent_frequency": { - "check_answer_label": "Rent Period", - "header": "Which period are rent and other charges due?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Weekly for 52 weeks", - "1": "Fortnightly", - "2": "Four-weekly", - "3": "Calendar monthly", - "4": "Weekly for 50 weeks", - "5": "Weekly for 49 weeks", - "6": "Weekly for 48 weeks", - "7": "Weekly for 47 weeks", - "8": "Weekly for 46 weeks", - "9": "Weekly for 53 weeks" - } - }, - "basic_rent": { - "check_answer_label": "Basic Rent", - "header": "What is the basic rent?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], - "result-field": "total_charge" - }, - "service_charge": { - "check_answer_label": "Service Charge", - "header": "What is the service charge?", - "hint_text": "Eligible for housing benefit or Universal Credit", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], - "result-field": "total_charge" - }, - "personal_service_charge": { - "check_answer_label": "Personal Service Charge", - "header": "What is the personal service charge?", - "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], - "result-field": "total_charge" - }, - "support_charge": { - "check_answer_label": "Support Charge", - "header": "What is the support charge?", - "hint_text": "This is to fund housing-related support services included in the tenancy agreement", - "type": "numeric", - "min": 0, - "step": 1, - "fields-to-add": ["basic_rent", "service_charge", "personal_service_charge", "support_charge"], - "result-field": "total_charge" - }, - "total_charge": { - "check_answer_label": "Total Charge", - "header": "Total charge?", - "hint_text": "This is the total of rent and all charges", - "type": "numeric", - "min": 0, - "step": 1, - "readonly": true - }, - "outstanding_rent_or_charges": { - "check_answer_label": "After housing benefit and/or housing element of UC payment is received, will there be an outstanding amount for basic rent and/or benefit eligible charges?", - "header": "After housing benefit and/or housing element of UC payment is received, will there be an outstanding amount for basic rent and/or benefit eligible charges?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - }, - "conditional_for": { - "outstanding_amount": ["Yes"] - } - }, - "outstanding_amount": { - "check_answer_label": "Outstanding amount", - "header": "What do you expect the amount to be?", - "hint_text": "If the amount is unknown you can estimate", - "type": "numeric", - "min": 0, - "step": 1 - } - } - } - } - } - } - }, - "local_authority": { - "label": "Local authority", - "subsections": { - "local_authority": { - "label": "Local authority", - "pages": { - "time_lived_in_la": { - "header": "", - "description": "", - "questions": { - "time_lived_in_la": { - "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", - "header": "How long has the household continuously lived in the local authority area where the new letting is located?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Just moved to local authority area", - "1": "Less than 1 year", - "2": "1 to 2 years", - "3": "2 to 3 years", - "4": "3 to 4 years", - "5": "4 to 5 years", - "6": "5 years or more", - "7": "Do not know" - } - } - } - }, - "time_on_la_waiting_list": { - "header": "", - "description": "", - "questions": { - "time_on_la_waiting_list": { - "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", - "header": "How long has the household been on the local authority waiting list where the new letting is located?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Just moved to local authority area", - "1": "Less than 1 year", - "2": "1 to 2 years", - "3": "2 to 3 years", - "4": "3 to 4 years", - "5": "4 to 5 years", - "6": "5 years or more", - "7": "Do not know" - } - } - } - }, - "previous_la": { - "header": "", - "description": "", - "questions": { - "previous_la": { - "check_answer_label": "The LA in which household lived immediately before this letting\t", - "header": "Which local authority area did the household live in immediately before this letting?", - "hint_text": "Includes temporary accommodation", - "type": "radio", - "answer_options": { - "0": "Adur", - "1": "Allerdale", - "2": "Amber Valley", - "3": "Arun", - "4": "Ashfield", - "5": "Ashford", - "6": "Babergh", - "7": "Barking & Dagenham", - "8": "Barnet", - "9": "Barnsley", - "10": "Barrow-in-Furness", - "11": "Basildon", - "12": "Basingstoke & Deane", - "13": "Bassetlaw", - "14": "Bath & NE Somerset", - "15": "Bedford Borough Council", - "16": "Bexley", - "17": "Birmingham", - "18": "Blaby", - "19": "Blackburn", - "20": "Blackpool", - "21": "Bolsover", - "22": "Bolton", - "23": "Boston", - "24": "Bournemouth & Christchurch & Poole", - "25": "Bracknell Forest", - "26": "Bradford", - "27": "Braintree", - "28": "Breckland", - "29": "Brent", - "30": "Brentwood", - "31": "Brighton & Hove", - "32": "Bristol", - "33": "Broadland", - "34": "Bromley", - "35": "Bromsgrove", - "36": "Broxbourne", - "37": "Broxtowe", - "38": "Buckinghamshire", - "39": "Burnley", - "40": "Bury", - "41": "Calderdale", - "42": "Cambridge", - "43": "Camden", - "44": "Cannock Chase", - "45": "Canterbury", - "46": "Carlisle", - "47": "Castle Point", - "48": "Central Bedfordshire", - "49": "Charnwood", - "50": "Chelmsford", - "51": "Cheltenham", - "52": "Cherwell", - "53": "Cheshire West & Chester", - "54": "Chesterfield", - "55": "Chichester", - "56": "Chorley", - "57": "City of London", - "58": "Colchester", - "59": "Copeland", - "60": "Cornwall", - "61": "Cotswold", - "62": "Coventry", - "63": "Craven", - "64": "Crawley", - "65": "Croydon", - "66": "Dacorum", - "67": "Darlington", - "68": "Dartford", - "69": "Derby", - "70": "Derbyshire Dales", - "71": "Doncaster", - "72": "Dorset", - "73": "Dover", - "74": "Dudley", - "75": "Durham", - "76": "Ealing", - "77": "East Cambridgeshire", - "78": "East Cheshire", - "79": "East Devon", - "80": "East Hampshire", - "81": "East Herts", - "82": "East Lindsey", - "83": "East Riding", - "84": "East Staffordshire", - "85": "East Suffolk", - "86": "Eastbourne", - "87": "Eastleigh", - "88": "Eden", - "89": "Elmbridge", - "90": "Enfield", - "91": "Epping Forest", - "92": "Epsom & Ewell", - "93": "Erewash", - "94": "Exeter", - "95": "Fareham", - "96": "Fenland", - "97": "Folkestone & Hythe", - "98": "Forest of Dean", - "99": "Fylde", - "100": "Gateshead", - "101": "Gedling", - "102": "Gloucester", - "103": "Gosport", - "104": "Gravesham", - "105": "Great Yarmouth", - "106": "Greenwich", - "107": "Guildford", - "108": "Hackney", - "109": "Halton", - "110": "Hambleton", - "111": "Hammersmith & Fulham", - "112": "Harborough", - "113": "Haringey", - "114": "Harlow", - "115": "Harrogate", - "116": "Harrow", - "117": "Hart", - "118": "Hartlepool", - "119": "Hastings", - "120": "Havant", - "121": "Havering", - "122": "Herefordshire", - "123": "Hertsmere", - "124": "High Peak", - "125": "Hillingdon", - "126": "Hinckley & Bosworth", - "127": "Horsham", - "128": "Hounslow", - "129": "Huntingdonshire", - "130": "Hyndburn", - "131": "Ipswich", - "132": "Isle of Wight", - "133": "Isles of Scilly", - "134": "Islington", - "135": "Kensington & Chelsea", - "136": "Kings Lynn & West Norfolk", - "137": "Kingston-upon-Hull", - "138": "Kingston-upon-Thames", - "139": "Kirklees", - "140": "Knowsley", - "141": "Lambeth", - "142": "Lancaster", - "143": "Leeds", - "144": "Leicester", - "145": "Lewes", - "146": "Lewisham", - "147": "Lichfield", - "148": "Lincoln", - "149": "Liverpool", - "150": "Luton", - "151": "Maidstone", - "152": "Maldon", - "153": "Malvern Hills", - "154": "Manchester", - "155": "Mansfield", - "156": "Medway", - "157": "Melton", - "158": "Mendip", - "159": "Merton", - "160": "Mid Devon", - "161": "Mid Suffolk", - "162": "Mid Sussex", - "163": "Middlesbrough", - "164": "Milton Keynes", - "165": "Mole Valley", - "166": "N. Ireland", - "167": "New Forest", - "168": "Newark", - "169": "Newcastle-under-Lyme", - "170": "Newcastle-upon-Tyne", - "171": "Newham", - "172": "North Devon", - "173": "North East Derbyshire", - "174": "North East Lincolnshire", - "175": "North Hertfordshire", - "176": "North Kesteven", - "177": "North Lincolnshire", - "178": "North Norfolk", - "179": "North Northamptonshire", - "180": "North Somerset", - "181": "North Tyneside", - "182": "North Warwickshire", - "183": "North West Leics", - "184": "Northumberland", - "185": "Norwich", - "186": "Nottingham", - "187": "Nuneaton & Bedworth", - "188": "Oadby & Wigston", - "189": "Oldham", - "190": "Outside UK", - "191": "Oxford", - "192": "Pendle", - "193": "Peterborough", - "194": "Plymouth", - "195": "Portsmouth", - "196": "Preston", - "197": "Reading", - "198": "Redbridge", - "199": "Redcar & Cleveland", - "200": "Redditch", - "201": "Reigate & Banstead", - "202": "Ribble Valley", - "203": "Richmond-upon-Thames", - "204": "Richmondshire", - "205": "Rochdale", - "206": "Rochford", - "207": "Rossendale", - "208": "Rother", - "209": "Rotherham", - "210": "Rugby", - "211": "Runnymede", - "212": "Rushcliffe", - "213": "Rushmoor", - "214": "Rutland", - "215": "Ryedale", - "216": "Salford", - "217": "Sandwell", - "218": "Scarborough", - "219": "Scotland", - "220": "Sedgemoor", - "221": "Sefton", - "222": "Selby", - "223": "Sevenoaks", - "224": "Sheffield", - "225": "Shropshire", - "226": "Slough", - "227": "Solihull", - "228": "Somerset West & Taunton", - "229": "South Cambridgeshire", - "230": "South Derbyshire", - "231": "South Gloucestershire", - "232": "South Hams", - "233": "South Holland", - "234": "South Kesteven", - "235": "South Lakeland", - "236": "South Norfolk", - "237": "South Oxfordshire", - "238": "South Ribble", - "239": "South Somerset", - "240": "South Staffordshire", - "241": "South Tyneside", - "242": "Southampton", - "243": "Southend-on-Sea", - "244": "Southwark", - "245": "Spelthorne", - "246": "St Albans", - "247": "St Helens", - "248": "Stafford", - "249": "Staffordshire Moorlands", - "250": "Stevenage", - "251": "Stockport", - "252": "Stockton-on-Tees", - "253": "Stoke-on-Trent", - "254": "Stratford-on-Avon", - "255": "Stroud", - "256": "Sunderland", - "257": "Surrey Heath", - "258": "Sutton", - "259": "Swale", - "260": "Swindon", - "261": "Tameside", - "262": "Tamworth", - "263": "Tandridge", - "264": "Teignbridge", - "265": "Telford & Wrekin", - "266": "Tendring", - "267": "Test Valley", - "268": "Tewkesbury", - "269": "Thanet", - "270": "Three Rivers", - "271": "Thurrock", - "272": "Tonbridge & Malling", - "273": "Torbay", - "274": "Torridge", - "275": "Tower Hamlets", - "276": "Trafford", - "277": "Tunbridge Wells", - "278": "Uttlesford", - "279": "Vale of White Horse", - "280": "Wakefield", - "281": "Wales", - "282": "Walsall", - "283": "Waltham Forest", - "284": "Wandsworth", - "285": "Warrington", - "286": "Warwick", - "287": "Watford", - "288": "Waverley", - "289": "Wealden", - "290": "Welwyn Hatfield", - "291": "West Berkshire", - "292": "West Devon", - "293": "West Lancashire", - "294": "West Lindsey", - "295": "West Northamptonshire", - "296": "West Oxfordshire", - "297": "West Suffolk", - "298": "Westminster", - "299": "Wigan", - "300": "Wiltshire", - "301": "Winchester", - "302": "Windsor & Maidenhead", - "303": "Wirral", - "304": "Woking", - "305": "Wokingham", - "306": "Wolverhampton", - "307": "Worcester", - "308": "Worthing", - "309": "Wychavon", - "310": "Wyre", - "311": "Wyre Forest", - "312": "York" - } - } - } - }, - "previous_postcode": { - "header": "", - "description": "", - "questions": { - "previous_postcode": { - "check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation", - "header": "Postcode for the previous accommodation", - "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", - "type": "text" - } - } - }, - "reasonable_preference": { - "header": "", - "description": "", - "questions": { - "reasonable_preference": { - "check_answer_label": "Was the household given Reasonable Preference (i.e. priority) for housing by the Local Authority?", - "header": "Was the household given reasonable preference by the local authority?", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - }, - "conditional_for": { - "reasonable_preference_reason": ["Yes"] - } - }, - "reasonable_preference_reason": { - "check_answer_label": "Reason for reasonable preference", - "header": "Why were they given reasonable preference?", - "hint_text": "Select all that apply", - "type": "checkbox", - "answer_options": { - "reasonable_preference_reason_homeless": "Homeless or about to lose their home (within 56 days)", - "reasonable_preference_reason_unsatisfactory_housing": "Living in insanitary or overcrowded or unsatisfactory housing", - "reasonable_preference_reason_medical_grounds": "A need to move on medical and welfare grounds (including a disability)", - "reasonable_preference_reason_avoid_hardship": "A need to move to avoid hardship to themselves or others", - "divider": true, - "reasonable_preference_reason_do_not_know": "Do not know" - } - } - } - }, - "lettings_policy": { - "header": "", - "description": "", - "questions": { - "cbl_letting": { - "check_answer_label": "Choice-based letting?", - "header": "Was the letting made under choice-based lettings (CBL)? ", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - }, - "chr_letting": { - "check_answer_label": "Common housing register letting?", - "header": "Was the letting made under common housing register (CHR)? ", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - }, - "cap_letting": { - "check_answer_label": "Common allocation policy letting?", - "header": "Was the letting made under common allocation policy (CAP)? ", - "hint_text": "", - "type": "radio", - "answer_options": { - "0": "Yes", - "1": "No" - } - } - } - } - } - } - } - }, - "submission": { - "label": "Submission", - "subsections": { - "declaration": { - "label": "Declaration", - "pages": { - "declaration": { - "header": "", - "description": "", - "questions": { - "declaration": { - "check_answer_label": "", - "header": "What is the tenant code?", - "hint_text": "", - "type": "text" - } - } - } - } - } - } - } + "minProperties": 1 } } - \ No newline at end of file +} \ No newline at end of file diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index 50c08369c..d7654e063 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -21,69 +21,97 @@ "sections": { "type": "object", "patternProperties": { - "[a-z_\/#]+": { - "description": "", - "type": "object" - }, - "properties": { - "label": { - "description": "", - "type": "string" - }, - "subsections": { - "description": "", - "type": "object", - "patternProperties": { - "[a-z_\/#]+": { - "description": "", - "type": "object", - "required": ["label"], - "properties": { - "label": { - "description": "", - "type": "string", - "required": "true" - }, - "pages": { - "type": "object", - "required": ["header"], - "patternProperties": { + "[a-z_]+": { + "description": "Section Name", + "type": "object", + "properties": { + "label": { + "description": "", + "type": "string" + }, + "subsections": { + "type": "object", + "patternProperties": { + "[a-z_]+": { + "description": "SubSection Name", + "type": "object", + "required": ["label"], + "properties": { + "label": { + "description": "", + "type": "string" + }, + "pages": { "type": "object", - "[a-z_]+": { - "properties": { - "header": { - "description": "", - "type": "string" - }, - "description": { - "description": "", - "type": "string" - }, - "questions": { - "type": "object", - "patternProperties": { + "patternProperties": { + "[a-z_]+": { + "description": "Page Name", + "type": "object", + "required": ["header", "questions"], + "properties": { + "header": { + "description": "", + "type": "string" + }, + "description": { + "description": "", + "type": "string" + }, + "questions": { "type": "object", - "[a-z_]+": { - "properties": { - "check_answer_label": { - "type": "string" - } + "patternProperties": { + "[a-z_]+": { + "description": "Question Name", + "type": "object", + "required": ["header", "type"], + "properties": { + "header": { + "description": "", + "type": "string" + }, + "type": { + "description": "", + "type": "string" + } + }, + "additionalProperties": { + "hint_text": { + "optional": "true", + "description": "", + "type": "string" + }, + "answer_options": { + "optional": "true", + "description": "", + "type": "object" + }, + "check_answer_label": { + "description": "", + "type": "string" + } + }, + "minProperties": 1 } } - }, - "minProperties": 8 + } }, - "minProperties": 8 + "additionalProperties": { + "conditional_route_to": { + "description": "", + "type": "object" + } + }, + "minProperties": 1 } - } - }, - "minProperties": 8 - } + } + } + }, + "minProperties": 1 } - } - }, - "minProperties": 8 - } + } + } + }, + "minProperties": 2 } }, "minProperties": 1 diff --git a/config/forms/schema/test.json b/config/forms/schema/test.json deleted file mode 100644 index 93eaf9a6d..000000000 --- a/config/forms/schema/test.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-04/schema#", - "$id": "https://example.com/product.schema.json", - "title": "Form", - "description": "A form", - "type": "object", - "required": ["form_type", "start_year", "end_year", "sections"], - "properties": { - "form_type": { - "description": "", - "type": "string" - }, - "start_year": { - "description": "", - "type": "integer" - }, - "end_year": { - "description": "", - "type": "integer" - }, - "sections": { - "type": "object", - "patternProperties": { - "[a-z_]+": { - "description": "", - "type": "object", - "properties": { - "label": { - "description": "", - "type": "string" - }, - "subsections": { - "type": "object", - "patternProperties": { - "[a-z_]+": { - "description": "", - "type": "object", - "required": ["label"], - "properties": { - "label": { - "description": "", - "type": "string" - }, - "pages": { - "type": "object", - "patternProperties": { - "[a-z_]+": { - "description": "", - "type": "object", - "properties": { - "header": { - "description": "", - "type": "string" - }, - "description": { - "description": "", - "type": "string" - }, - "questions": { - "type": "object", - "patternProperties": { - "[a-z_]+": { - "description": "", - "type": "object", - "required": ["header"], - "properties": { - "check_answer_label": { - "description": "", - "type": "string" - }, - "header": { - "description": "", - "type": "string" - }, - "type": { - "description": "", - "type": "string" - }, - "hint_text": { - "description": "", - "type": "string" - }, - "answer_options": { - "description": "", - "type": "string" - } - } - } - } - } - }, - "minProperties": 1 - } - } - } - }, - "minProperties": 1 - } - } - } - }, - "minProperties": 2 - } - }, - "minProperties": 1 - } - } -} \ No newline at end of file diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json deleted file mode 100644 index b5467a48f..000000000 --- a/spec/fixtures/forms/test_form.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "form_type": "lettings", - "start_year": 2021, - "end_year": 2022, - "sections": { - "household": { - "label": "About the household", - "subsections": { - "household_characteristics": { - "label": "Household characteristics", - "pages": { - } - } - } - } - } -} - \ No newline at end of file diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index e83c4d970..487b990f4 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -17,7 +17,8 @@ "header": "What is the tenant code?", "type": "text" } - } + }, + "conditional_route_to": {"test": "Yes"} } }, "person_1_age": { From d1db7528421d14c1ffff0250e6df5c0d4fb1c4a3 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 11 Nov 2021 11:45:33 +0000 Subject: [PATCH 16/26] only validate real forms --- app/helpers/json_schema_validation.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index dd0655d3b..086110c54 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -29,7 +29,8 @@ begin return end - directories = ["config/forms", "spec/fixtures/forms"] + # directories = ["config/forms", "spec/fixtures/forms"] + directories = ["config/forms"] get_all_form_paths(directories).each do |path| puts path From c67fccdcd0da0b04cc55d744021adcc65224d8c4 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 11 Nov 2021 12:37:26 +0000 Subject: [PATCH 17/26] change pattern to ignore conditional_route_to --- app/helpers/json_schema_validation.rb | 1 - config/forms/schema/generic.json | 6 +++++- spec/fixtures/forms/test_validator.json | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 086110c54..07ba995e6 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -14,7 +14,6 @@ end begin path = "config/forms/schema/generic.json" - # path = "config/forms/schema/2021_2022.json" file = File.open(path) schema = JSON.parse(file.read) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index d7654e063..d9b0f8cc5 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -44,7 +44,7 @@ "pages": { "type": "object", "patternProperties": { - "[a-z_]+": { + "^(?!(conditional_route_to))[a-z_]+$": { "description": "Page Name", "type": "object", "required": ["header", "questions"], @@ -88,6 +88,10 @@ "check_answer_label": { "description": "", "type": "string" + }, + "conditional_for": { + "description": "", + "type": "object" } }, "minProperties": 1 diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index 487b990f4..630145f35 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -11,6 +11,7 @@ "ShouldThrowError": "Shouldn't be here but what you gonna do?", "pages": { "tenant_code": { + "ShouldThrowError": "Shouldn't be here but what you gonna do?", "questions": { "tenant_code": { "check_answer_label": "Tenant code", @@ -19,7 +20,8 @@ } }, "conditional_route_to": {"test": "Yes"} - } + }, + "conditional_route_to": {"test": "Yes"} }, "person_1_age": { "header": "", From 967ee6b0e1203f17d5e5c4ea685483b9be404fa8 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 11 Nov 2021 13:49:11 +0000 Subject: [PATCH 18/26] more fix --- app/helpers/json_schema_validation.rb | 4 ++-- spec/fixtures/forms/test_validator.json | 31 ++++++++++++++----------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index 07ba995e6..d6eb46700 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -28,8 +28,8 @@ begin return end - # directories = ["config/forms", "spec/fixtures/forms"] - directories = ["config/forms"] + directories = ["config/forms", "spec/fixtures/forms"] + # directories = ["config/forms"] get_all_form_paths(directories).each do |path| puts path diff --git a/spec/fixtures/forms/test_validator.json b/spec/fixtures/forms/test_validator.json index 630145f35..2f8e770d3 100644 --- a/spec/fixtures/forms/test_validator.json +++ b/spec/fixtures/forms/test_validator.json @@ -11,30 +11,33 @@ "ShouldThrowError": "Shouldn't be here but what you gonna do?", "pages": { "tenant_code": { + "header": "", + "description": "", "ShouldThrowError": "Shouldn't be here but what you gonna do?", "questions": { "tenant_code": { "check_answer_label": "Tenant code", "header": "What is the tenant code?", + "description": "", "type": "text" } }, "conditional_route_to": {"test": "Yes"} }, - "conditional_route_to": {"test": "Yes"} - }, - "person_1_age": { - "header": "", - "description": "", - "questions": { - "person_1_age": { - "check_answer_label": "Tenant's age", - "header": "What is the tenant's age?", - "hint_text": "", - "type": "numeric", - "min": 0, - "max": 120, - "step": 1 + "conditional_route_to": {"test": "Yes"}, + "person_1_age": { + "header": "", + "description": "", + "questions": { + "person_1_age": { + "check_answer_label": "Tenant's age", + "header": "What is the tenant's age?", + "hint_text": "", + "type": "numeric", + "min": 0, + "max": 120, + "step": 1 + } } } } From ebdf41764b0bee1a5c9ef89fdceacf1d3958045b Mon Sep 17 00:00:00 2001 From: magicmilo Date: Thu, 11 Nov 2021 15:26:58 +0000 Subject: [PATCH 19/26] add check answer label requirement --- config/forms/schema/generic.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/config/forms/schema/generic.json b/config/forms/schema/generic.json index d9b0f8cc5..1499878f0 100644 --- a/config/forms/schema/generic.json +++ b/config/forms/schema/generic.json @@ -72,7 +72,12 @@ "type": { "description": "", "type": "string" - } + }, + "check_answer_label": { + "description": "", + "type": "string", + "optional": "true" + } }, "additionalProperties": { "hint_text": { From bda09d78865ea1b0323d7d193913f3ffd574a979 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 11:43:37 +0000 Subject: [PATCH 20/26] update readme for schema validation --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 5af61d33e..1b88f529f 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ The JSON should follow the structure: "[snake_case_question_name_string]": { "header": String, "hint_text": String, + "check_answer_label": String, "type": "text" / "numeric" / "radio" / "checkbox" / "date", "min": Integer, // numeric only "max": Integer, // numeric only @@ -133,6 +134,10 @@ The JSON should follow the structure: "[snake_case_question_to_enable_2_name_string]": ["condition-that-enables"] } } + }, + "conditional_route_to": { + "[page_name_to_route_to]": {"question_name": "expected_answer"}, + "[page_name_to_route_to]": {"question_name": "expected_answer"} } } } @@ -155,6 +160,16 @@ Assumptions made by the format: - Radio question answer option selected matches one of conditional e.g. ["answer-options-1-string", "answer-option-3-string"] - Numeric question value matches condition e.g. [">2"], ["<7"] or ["== 6"] +## JSON Form Validation against Schema + +To validate the form JSON against the schema you can run: +`ruby app/helpers/json_schema_validation.rb` + +This will validate all forms in: +directories = ["config/forms", "spec/fixtures/forms"] + +against the schema in (config/forms/schema/generic.json) + ## Useful documentation (external dependencies) ### GOV.UK Design System Form Builder for Rails From fa86626d37570c0084aa3756e2a3742daf369eae Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 13:37:58 +0000 Subject: [PATCH 21/26] added rake form_definition (can't load json-schema) --- README.md | 3 +++ app/helpers/json_schema_validation.rb | 5 +---- lib/tasks/form_definition.rake | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 lib/tasks/form_definition.rake diff --git a/README.md b/README.md index 1b88f529f..98deac23e 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,9 @@ Assumptions made by the format: ## JSON Form Validation against Schema To validate the form JSON against the schema you can run: +`rake form_definition:validate` + +This will run: `ruby app/helpers/json_schema_validation.rb` This will validate all forms in: diff --git a/app/helpers/json_schema_validation.rb b/app/helpers/json_schema_validation.rb index d6eb46700..994955e4e 100644 --- a/app/helpers/json_schema_validation.rb +++ b/app/helpers/json_schema_validation.rb @@ -1,5 +1,5 @@ -require "json-schema" require "json" +require "json-schema" def get_all_form_paths(directories) form_paths = [] @@ -12,7 +12,6 @@ def get_all_form_paths(directories) end begin - path = "config/forms/schema/generic.json" file = File.open(path) @@ -36,8 +35,6 @@ begin file = File.open(path) data = JSON.parse(file.read) - puts JSON::Validator.validate(schema, data, :strict => true) - puts JSON::Validator.fully_validate(schema, data, :strict => true) begin diff --git a/lib/tasks/form_definition.rake b/lib/tasks/form_definition.rake new file mode 100644 index 000000000..c066e9a90 --- /dev/null +++ b/lib/tasks/form_definition.rake @@ -0,0 +1,6 @@ +namespace :form_definition do + desc "Validate JSON against Generic Form Schema" + task :validate do + ruby "app/helpers/json_schema_validation.rb" + end + end \ No newline at end of file From 5699c90e066e169186b8ec8429ab96f99da22f2f Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 14:12:16 +0000 Subject: [PATCH 22/26] fixed dependency and updated readme --- Gemfile | 2 ++ Gemfile.lock | 3 +++ README.md | 2 +- lib/tasks/form_definition.rake | 5 ++++- {app/helpers => lib/tasks}/json_schema_validation.rb | 0 5 files changed, 10 insertions(+), 2 deletions(-) rename {app/helpers => lib/tasks}/json_schema_validation.rb (100%) diff --git a/Gemfile b/Gemfile index fa743fa4a..a147a5a2f 100644 --- a/Gemfile +++ b/Gemfile @@ -29,6 +29,8 @@ gem "discard" gem "activeadmin" # Admin charts gem "chartkick" +#Json Schema +gem "json-schema" group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console diff --git a/Gemfile.lock b/Gemfile.lock index 386f2d68b..df4d7bf5c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -196,6 +196,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + json-schema (2.8.1) + addressable (>= 2.4) kaminari (1.2.1) activesupport (>= 4.1.0) kaminari-actionview (= 1.2.1) @@ -398,6 +400,7 @@ DEPENDENCIES govuk_design_system_formbuilder hotwire-rails jbuilder (~> 2.7) + json-schema listen (~> 3.3) overcommit (>= 0.37.0) pg (~> 1.1) diff --git a/README.md b/README.md index 98deac23e..50d25ea40 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ To validate the form JSON against the schema you can run: `rake form_definition:validate` This will run: -`ruby app/helpers/json_schema_validation.rb` +`ruby lib/tasks/json_schema_validation.rb` This will validate all forms in: directories = ["config/forms", "spec/fixtures/forms"] diff --git a/lib/tasks/form_definition.rake b/lib/tasks/form_definition.rake index c066e9a90..ed8be8c11 100644 --- a/lib/tasks/form_definition.rake +++ b/lib/tasks/form_definition.rake @@ -1,6 +1,9 @@ +# require "app/helpers/json_schema_validation.rb" + namespace :form_definition do desc "Validate JSON against Generic Form Schema" task :validate do - ruby "app/helpers/json_schema_validation.rb" + puts "#{Rails.root}" + ruby "lib/tasks/json_schema_validation.rb" end end \ No newline at end of file diff --git a/app/helpers/json_schema_validation.rb b/lib/tasks/json_schema_validation.rb similarity index 100% rename from app/helpers/json_schema_validation.rb rename to lib/tasks/json_schema_validation.rb From 57e117b09ef19a5bf1cc7428eac8dbed2280eec9 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 14:33:21 +0000 Subject: [PATCH 23/26] run db migration --- db/schema.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 614c895c2..1ef990508 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -122,8 +122,6 @@ ActiveRecord::Schema.define(version: 2021_11_12_105348) do t.integer "rp_dontknow" t.datetime "discarded_at" t.string "tenancyother" - t.integer "override_net_income_validation" - t.string "net_income_known" t.string "gdpr_acceptance" t.string "gdpr_declined" t.string "property_owner_organisation" @@ -135,6 +133,8 @@ ActiveRecord::Schema.define(version: 2021_11_12_105348) do t.string "needs_type" t.string "sale_completion_date" t.string "purchaser_code" + t.integer "override_net_income_validation" + t.string "net_income_known" t.integer "reason" t.string "propcode" t.integer "majorrepairs" From 127958a47f06ec91605753aba08e2ce711a66572 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 15:17:28 +0000 Subject: [PATCH 24/26] readd testform --- spec/fixtures/forms/test_form.json | 548 +++++++++++++++++++++++++++++ 1 file changed, 548 insertions(+) create mode 100644 spec/fixtures/forms/test_form.json diff --git a/spec/fixtures/forms/test_form.json b/spec/fixtures/forms/test_form.json new file mode 100644 index 000000000..28feb44b9 --- /dev/null +++ b/spec/fixtures/forms/test_form.json @@ -0,0 +1,548 @@ +{ + "form_type": "lettings", + "sections": { + "household": { + "label": "About the household", + "subsections": { + "household_characteristics": { + "label": "Household characteristics", + "pages": { + "tenant_code": { + "questions": { + "tenant_code": { + "check_answer_label": "Tenant code", + "header": "What is the tenant code?", + "type": "text" + } + } + }, + "person_1_age": { + "questions": { + "age1": { + "check_answer_label": "Tenant's age", + "header": "What is the tenant's age?", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + } + } + }, + "person_1_gender": { + "questions": { + "sex1": { + "check_answer_label": "Tenant's gender", + "header": "Which of these best describes the tenant's gender identity?", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + } + } + }, + "household_number_of_other_members": { + "questions": { + "other_hhmemb": { + "check_answer_label": "Number of Other Household Members", + "header": "How many other people are there in the household?", + "hint_text": "The maximum number of others is 1", + "type": "numeric", + "min": 0, + "max": 1, + "step": 1, + "conditional_for": { + "relat2": ">0", + "age2": ">0", + "sex2": ">0", + "ecstat2": ">0" + } + }, + "relat2": { + "check_answer_label": "Person 2's relationship to lead tenant", + "header": "What's person 2's relationship to lead tenant", + "type": "radio", + "answer_options": { + "0": "Other", + "1": "Prefer not to say" + } + }, + "age2": { + "check_answer_label": "Person 2's age", + "header": "What's person 2's age", + "type": "numeric", + "min": 0, + "max": 150, + "step": 1 + }, + "sex2": { + "check_answer_label": "Person 2's gender", + "header": "Which of these best describes person 2's gender identity?", + "type": "radio", + "answer_options": { + "0": "Female", + "1": "Male", + "2": "Non-binary", + "3": "Prefer not to say" + } + }, + "ecstat2": { + "check_answer_label": "Person 2's Work", + "header": "Which of these best describes person 2's working situation?", + "type": "radio", + "answer_options": { + "0": "Other", + "1": "Prefer not to say" + } + } + } + } + } + }, + "household_needs": { + "label": "Household needs", + "pages": { + "armed_forces": { + "header": "Experience of the UK Armed Forces", + "questions": { + "armed_forces": { + "header": "Has the tenant ever served in the UK armed forces?", + "type": "radio", + "check_answer_label": "Armed Forces", + "answer_options": { + "0": "Yes - a regular", + "1": "Yes - a reserve", + "2": "No", + "3": "Prefer not to say" + }, + "conditional_for": { + "leftreg": ["Yes - a regular", "Yes - a reserve"], + "reservist": ["Yes - a regular", "Yes - a reserve"] + } + }, + "leftreg": { + "header": "Are they still serving?", + "type": "radio", + "check_answer_label": "When did they leave the Armed Forces?", + "answer_options": { + "0": "Yes", + "1": "No - they left up to 5 years ago", + "2": "No - they left more than 5 years ago", + "3": "Prefer not to say" + } + }, + "reservist": { + "header": "Were they seriously injured or ill as a result of their service?", + "type": "radio", + "check_answer_label": "Has anyone in the household been seriously injured or ill as a result of their service in the armed forces?", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Prefer not to say" + } + } + } + }, + "medical_conditions": { + "questions": { + "illness": { + "header": "Does anyone in the household have any of the following that they expect to last for 12 months or more:
  • Physical Condition
  • Mental Health Condition
  • Other Illness
", + "type": "radio", + "check_answer_label": "Physical, mental health or illness in the household", + "answer_options": { + "0": "Yes", + "1": "No", + "2": "Do not know", + "3": "Prefer not to say" + } + } + } + }, + "accessibility_requirements": { + "questions": { + "accessibility_requirements": { + "header": "Are any of these affected by their condition or illness?", + "hint_text": "Select all that apply", + "type": "checkbox", + "check_answer_label": "Disability requirements", + "answer_options": { + "housingneeds_a": "Fully wheelchair accessible housing", + "housingneeds_b": "Wheelchair access to essential rooms", + "housingneeds_c": "Level access housing", + "divider_a": true, + "housingneeds_h": "Do not know" + } + } + } + }, + "condition_effects": { + "questions": { + "condition_effects": { + "header": "Are any of these affected by their condition or illness?", + "hint_text": "Select all that apply", + "type": "checkbox", + "check_answer_label": "Conditions or illnesses", + "answer_options": { + "illness_type_1": "Vision - such as blindness or partial sight", + "illness_type_2": "Hearing - such as deafness or partial hearing" + } + } + } + } + } + } + } + }, + "tenancy_and_property": { + "label": "Tenancy and property information", + "subsections": { + "tenancy_information": { + "label": "Tenancy information", + "pages": { + "tenancy_code": { + "questions": { + "tenancy_code": { + "check_answer_label": "What is the tenancy code?", + "header": "What is the tenancy code?", + "type": "text" + } + } + } + } + }, + "property_information": { + "label": "Property information", + "pages": { + "property_wheelchair_accessible": { + "questions": { + "wchair": { + "check_answer_label": "Is property built or adapted to wheelchair user standards?", + "header": "Is property built or adapted to wheelchair user standards?", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + } + } + }, + "conditional_question": { + "label": "Conditional question", + "pages": { + "conditional_question": { + "questions": { + "preg_occ": { + "check_answer_label": "Has the condition been met?", + "header": "Has the condition been met?", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + }, + "conditional_route_to": { + "rent": { "preg_occ": "Yes", "sex1": "Female" }, + "conditional_question_yes_page": { "preg_occ": "Yes" }, + "conditional_question_no_page": { "preg_occ": "No" } + }, + "default_next_page": "check_answers" + }, + "conditional_question_yes_page": { + "questions": { + "cbl": { + "check_answer_label": "Has the next condition been met?", + "header": "Has the next condition been met?", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + }, + "default_next_page": "check_answers" + }, + "conditional_question_no_page": { + "questions": { + "conditional_question_no_question": { + "check_answer_label": "Has the condition not been met?", + "header": "Has the next condition not been met?", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + }, + "default_next_page": "conditional_question_no_second_page" + }, + "conditional_question_no_second_page": { + "questions": { + "conditional_question_no_second_question": { + "check_answer_label": "Has the condition not been met again?", + "header": "Has the next condition not been met again?", + "type": "radio", + "answer_options": { + "0": "Yes", + "1": "No" + } + } + } + } + } + } + } + }, + "rent_and_charges": { + "label": "Rent and charges", + "subsections": { + "income_and_benefits": { + "label": "Income and benefits", + "pages": { + "net_income": { + "questions": { + "earnings": { + "check_answer_label": "Income", + "header": "What is the tenant’s /and partner’s combined income after tax?", + "type": "numeric", + "min": 0, + "step": "1" + }, + "incfreq": { + "check_answer_label": "Income Frequency", + "header": "How often do they receive this income?", + "type": "radio", + "answer_options": { + "0": "Weekly", + "1": "Monthly", + "2": "Yearly" + } + } + }, + "soft_validations": { + "override_net_income_validation": { + "check_answer_label": "Net income confirmed?", + "type": "validation_override", + "answer_options": { + "override_net_income_validation": "Yes" + } + } + } + }, + "net_income_uc_proportion": { + "questions": { + "benefits": { + "check_answer_label": "Benefits as a proportion of income", + "header": "How much of the tenant’s income is from Universal Credit, state pensions or benefits?", + "type": "radio", + "answer_options": { + "0": "All", + "1": "Some" + } + } + } + }, + "housing_benefit": { + "questions": { + "hb": { + "check_answer_label": "Universal Credit & Housing Benefit", + "header": "Is the tenant likely to be in receipt of any of these housing-related benefits?", + "type": "radio", + "answer_options": { + "0": "Housing Benefit, but not Universal Credit", + "1": "Prefer not to say" + } + } + } + } + } + }, + "rent": { + "label": "Rent", + "pages": { + "rent": { + "questions": { + "rent_frequency": { + "check_answer_label": "Rent Period", + "header": "Which period are rent and other charges due?", + "type": "radio", + "answer_options": { + "0": "Weekly for 52 weeks", + "1": "Fortnightly" + } + }, + "brent": { + "check_answer_label": "Basic Rent", + "header": "What is the basic rent?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": [ + "brent", + "scharge", + "pscharge", + "supcharg" + ], + "result-field": "tcharge" + }, + "scharge": { + "check_answer_label": "Service Charge", + "header": "What is the service charge?", + "hint_text": "Eligible for housing benefit or Universal Credit", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": [ + "brent", + "scharge", + "pscharge", + "supcharg" + ], + "result-field": "tcharge" + }, + "pscharge": { + "check_answer_label": "Personal Service Charge", + "header": "What is the personal service charge?", + "hint_text": "Not eligible for housing benefit or Universal Credit. For example, hot water excluding water rates.", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": [ + "brent", + "scharge", + "pscharge", + "supcharg" + ], + "result-field": "tcharge" + }, + "supcharg": { + "check_answer_label": "Support Charge", + "header": "What is the support charge?", + "hint_text": "This is to fund housing-related support services included in the tenancy agreement", + "type": "numeric", + "min": 0, + "step": 1, + "fields-to-add": [ + "brent", + "scharge", + "pscharge", + "supcharg" + ], + "result-field": "tcharge" + }, + "tcharge": { + "check_answer_label": "Total Charge", + "header": "Total charge?", + "hint_text": "This is the total of rent and all charges", + "type": "numeric", + "min": 0, + "step": 1, + "readonly": true + } + } + } + } + } + } + }, + "local_authority": { + "label": "Local authority", + "subsections": { + "local_authority": { + "label": "Local authority", + "pages": { + "time_lived_in_la": { + "questions": { + "layear": { + "check_answer_label": "How long has the household continuously lived in the local authority area where the new letting is located?", + "header": "How long has the household continuously lived in the local authority area where the new letting is located?", + "type": "radio", + "answer_options": { + "0": "Just moved to local authority area", + "1": "Less than 1 year", + "2": "1 to 2 years", + "3": "2 to 3 years", + "4": "3 to 4 years", + "5": "4 to 5 years", + "6": "5 years or more", + "7": "Do not know" + } + } + } + }, + "time_on_la_waiting_list": { + "questions": { + "lawaitlist": { + "check_answer_label": "How long has the household been on the local authority waiting list where the new letting is located?", + "header": "How long has the household been on the local authority waiting list where the new letting is located?", + "type": "radio", + "answer_options": { + "0": "Just moved to local authority area", + "1": "Less than 1 year", + "2": "1 to 2 years", + "3": "2 to 3 years", + "4": "3 to 4 years", + "5": "4 to 5 years", + "6": "5 years or more", + "7": "Do not know" + } + } + } + }, + "property_postcode": { + "questions": { + "property_postcode": { + "check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation", + "header": "Postcode for the previous accommodation", + "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", + "type": "text", + "conditional_for": { "faake_key": "fake_condition" } + }, + "previous_postcode": { + "check_answer_label": "Postcode of previous accomodation if the household has moved from settled accommodation", + "header": "Postcode for the previous accommodation", + "hint_text": "If the household has moved from settled accommodation immediately prior to being re-housed", + "type": "text" + } + } + }, + "major_repairs_date": { + "questions": { + "mrcdate": { + "check_answer_label": "What was the major repairs completion date?", + "header": "What was the major repairs completion date?", + "hint_text": "For example, 27 3 2007", + "type": "date" + } + } + } + } + } + } + }, + "submission": { + "label": "Submission", + "subsections": { + "declaration": { + "label": "Declaration", + "pages": { + "declaration": { + "questions": { + "declaration": { + "check_answer_label": "", + "header": "What is the tenant code?", + "type": "text" + } + } + } + } + } + } + } + } + } \ No newline at end of file From c49b919a503cf9a2c901897f20671ca7d6161639 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 15:23:18 +0000 Subject: [PATCH 25/26] put validation all into rake file --- lib/tasks/form_definition.rake | 47 +++++++++++++++++++++++++++-- lib/tasks/json_schema_validation.rb | 46 ---------------------------- 2 files changed, 44 insertions(+), 49 deletions(-) delete mode 100644 lib/tasks/json_schema_validation.rb diff --git a/lib/tasks/form_definition.rake b/lib/tasks/form_definition.rake index ed8be8c11..565728064 100644 --- a/lib/tasks/form_definition.rake +++ b/lib/tasks/form_definition.rake @@ -1,9 +1,50 @@ -# require "app/helpers/json_schema_validation.rb" +require "json" +require "json-schema" + +def get_all_form_paths(directories) + form_paths = [] + directories.each do |directory| + Dir.glob("#{directory}/*.json").each do |form_path| + form_paths.push(form_path) + end + end + form_paths +end namespace :form_definition do desc "Validate JSON against Generic Form Schema" task :validate do - puts "#{Rails.root}" - ruby "lib/tasks/json_schema_validation.rb" + puts "#{Rails.root}" + path = "config/forms/schema/generic.json" + + file = File.open(path) + schema = JSON.parse(file.read) + metaschema = JSON::Validator.validator_for_name("draft4").metaschema + + puts path + + if JSON::Validator.validate(metaschema, schema) + puts "schema valid" + else + puts "schema not valid" + return + end + + directories = ["config/forms", "spec/fixtures/forms"] + # directories = ["config/forms"] + + get_all_form_paths(directories).each do |path| + puts path + file = File.open(path) + data = JSON.parse(file.read) + + puts JSON::Validator.fully_validate(schema, data, :strict => true) + + begin + JSON::Validator.validate!(schema, data) + rescue JSON::Schema::ValidationError => e + e.message + end + end end end \ No newline at end of file diff --git a/lib/tasks/json_schema_validation.rb b/lib/tasks/json_schema_validation.rb deleted file mode 100644 index 994955e4e..000000000 --- a/lib/tasks/json_schema_validation.rb +++ /dev/null @@ -1,46 +0,0 @@ -require "json" -require "json-schema" - -def get_all_form_paths(directories) - form_paths = [] - directories.each do |directory| - Dir.glob("#{directory}/*.json").each do |form_path| - form_paths.push(form_path) - end - end - form_paths -end - -begin - path = "config/forms/schema/generic.json" - - file = File.open(path) - schema = JSON.parse(file.read) - metaschema = JSON::Validator.validator_for_name("draft4").metaschema - - puts path - - if JSON::Validator.validate(metaschema, schema) - puts "schema valid" - else - puts "schema not valid" - return - end - - directories = ["config/forms", "spec/fixtures/forms"] - # directories = ["config/forms"] - - get_all_form_paths(directories).each do |path| - puts path - file = File.open(path) - data = JSON.parse(file.read) - - puts JSON::Validator.fully_validate(schema, data, :strict => true) - - begin - JSON::Validator.validate!(schema, data) - rescue JSON::Schema::ValidationError => e - e.message - end - end -end From ba1afdbf653fd457c224fa77959932997a2dd813 Mon Sep 17 00:00:00 2001 From: magicmilo Date: Fri, 12 Nov 2021 15:24:06 +0000 Subject: [PATCH 26/26] change readme --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 50d25ea40..b637e606e 100644 --- a/README.md +++ b/README.md @@ -165,9 +165,6 @@ Assumptions made by the format: To validate the form JSON against the schema you can run: `rake form_definition:validate` -This will run: -`ruby lib/tasks/json_schema_validation.rb` - This will validate all forms in: directories = ["config/forms", "spec/fixtures/forms"]