From 3c62e947b9965fbea508c4b314773ee59cf60cd5 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:17:45 +0000 Subject: [PATCH 01/13] Update 2024 discount max (#2213) --- app/models/form/sales/questions/discount.rb | 2 +- .../form/sales/pages/about_price_rtb_spec.rb | 4 ++++ .../models/form/sales/questions/discount_spec.rb | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/models/form/sales/questions/discount.rb b/app/models/form/sales/questions/discount.rb index ee39b8916..4c4595ce1 100644 --- a/app/models/form/sales/questions/discount.rb +++ b/app/models/form/sales/questions/discount.rb @@ -6,7 +6,7 @@ class Form::Sales::Questions::Discount < ::Form::Question @header = "What was the percentage discount?" @type = "numeric" @min = 0 - @max = 100 + @max = form.start_year_after_2024? ? 70 : 100 @step = 1 @width = 5 @suffix = "%" diff --git a/spec/models/form/sales/pages/about_price_rtb_spec.rb b/spec/models/form/sales/pages/about_price_rtb_spec.rb index c73a83b61..81cfbc6fc 100644 --- a/spec/models/form/sales/pages/about_price_rtb_spec.rb +++ b/spec/models/form/sales/pages/about_price_rtb_spec.rb @@ -7,6 +7,10 @@ RSpec.describe Form::Sales::Pages::AboutPriceRtb, type: :model do let(:page_definition) { nil } let(:subsection) { instance_double(Form::Subsection) } + before do + allow(subsection).to receive(:form).and_return(instance_double(Form, start_year_after_2024?: false)) + end + it "has correct subsection" do expect(page.subsection).to eq(subsection) end diff --git a/spec/models/form/sales/questions/discount_spec.rb b/spec/models/form/sales/questions/discount_spec.rb index f40b2eded..c3b7d24a1 100644 --- a/spec/models/form/sales/questions/discount_spec.rb +++ b/spec/models/form/sales/questions/discount_spec.rb @@ -6,6 +6,12 @@ RSpec.describe Form::Sales::Questions::Discount, type: :model do let(:question_id) { nil } let(:question_definition) { nil } let(:page) { instance_double(Form::Page) } + let(:subsection) { instance_double(Form::Subsection) } + + before do + allow(page).to receive(:subsection).and_return(subsection) + allow(subsection).to receive(:form).and_return(instance_double(Form, start_year_after_2024?: false)) + end it "has correct page" do expect(question.page).to eq(page) @@ -52,4 +58,14 @@ RSpec.describe Form::Sales::Questions::Discount, type: :model do it "has correct max" do expect(question.max).to eq(100) end + + context "with form start year after 2024" do + before do + allow(subsection).to receive(:form).and_return(instance_double(Form, start_year_after_2024?: true)) + end + + it "has correct max" do + expect(question.max).to eq(70) + end + end end From 5bf30c37c32a62e0df1372754d69a0973a5c9e06 Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:51:39 +0000 Subject: [PATCH 02/13] CLDC-3162 Update buyers living in property for 24/25 (#2194) * feat: update header and test * refactor: lint * feat: update tests --- app/models/form/sales/questions/buyer_live.rb | 2 +- .../form/sales/pages/buyer_live_spec.rb | 6 ++++ .../form/sales/questions/buyer_live_spec.rb | 28 ++++++++++++++++--- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/app/models/form/sales/questions/buyer_live.rb b/app/models/form/sales/questions/buyer_live.rb index ee0a79611..2a3bf7eaf 100644 --- a/app/models/form/sales/questions/buyer_live.rb +++ b/app/models/form/sales/questions/buyer_live.rb @@ -3,7 +3,7 @@ class Form::Sales::Questions::BuyerLive < ::Form::Question super @id = "buylivein" @check_answer_label = "Buyers living in property" - @header = "Will the buyers live in the property?" + @header = form.start_year_after_2024? ? "Will any buyers live in the property?" : "Will the buyers live in the property?" @type = "radio" @answer_options = ANSWER_OPTIONS @question_number = 8 diff --git a/spec/models/form/sales/pages/buyer_live_spec.rb b/spec/models/form/sales/pages/buyer_live_spec.rb index 685798f59..be75458b3 100644 --- a/spec/models/form/sales/pages/buyer_live_spec.rb +++ b/spec/models/form/sales/pages/buyer_live_spec.rb @@ -6,6 +6,12 @@ RSpec.describe Form::Sales::Pages::BuyerLive, type: :model do let(:page_id) { nil } let(:page_definition) { nil } let(:subsection) { instance_double(Form::Subsection) } + let(:form) { instance_double(Form) } + + before do + allow(form).to receive(:start_year_after_2024?).and_return(false) + allow(subsection).to receive(:form).and_return(form) + end it "has correct subsection" do expect(page.subsection).to eq(subsection) diff --git a/spec/models/form/sales/questions/buyer_live_spec.rb b/spec/models/form/sales/questions/buyer_live_spec.rb index a946a7905..cea2736e5 100644 --- a/spec/models/form/sales/questions/buyer_live_spec.rb +++ b/spec/models/form/sales/questions/buyer_live_spec.rb @@ -6,6 +6,14 @@ RSpec.describe Form::Sales::Questions::BuyerLive, type: :model do let(:question_id) { nil } let(:question_definition) { nil } let(:page) { instance_double(Form::Page) } + let(:subsection) { instance_double(Form::Subsection) } + let(:form) { instance_double(Form) } + + before do + allow(form).to receive(:start_year_after_2024?).and_return(false) + allow(page).to receive(:subsection).and_return(subsection) + allow(subsection).to receive(:form).and_return(form) + end it "has correct page" do expect(question.page).to eq(page) @@ -15,10 +23,6 @@ RSpec.describe Form::Sales::Questions::BuyerLive, type: :model do expect(question.id).to eq("buylivein") end - it "has the correct header" do - expect(question.header).to eq("Will the buyers live in the property?") - end - it "has the correct check_answer_label" do expect(question.check_answer_label).to eq("Buyers living in property") end @@ -37,4 +41,20 @@ RSpec.describe Form::Sales::Questions::BuyerLive, type: :model do "2" => { "value" => "No" }, }) end + + context "with 2023/24 form" do + it "has the correct header" do + expect(question.header).to eq("Will the buyers live in the property?") + end + end + + context "with 2024/25 form" do + before do + allow(form).to receive(:start_year_after_2024?).and_return(true) + end + + it "has the correct header" do + expect(question.header).to eq("Will any buyers live in the property?") + end + end end From 8ce222dcaad88720ab88146d993f72b46a44dc71 Mon Sep 17 00:00:00 2001 From: natdeanlewissoftwire <94526761+natdeanlewissoftwire@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:52:04 +0000 Subject: [PATCH 03/13] CLDC-3151 Update reason for leaving for 24/25 (#2192) * feat: update ansewrs, hint text and test * refactor: lint * refactor: save lines --- app/models/form/lettings/questions/reason.rb | 190 +++++++--------- .../form/lettings/questions/reason_renewal.rb | 40 ++-- .../lettings/questions/reason_renewal_spec.rb | 85 +++++++ .../form/lettings/questions/reason_spec.rb | 215 ++++++++---------- 4 files changed, 286 insertions(+), 244 deletions(-) create mode 100644 spec/models/form/lettings/questions/reason_renewal_spec.rb diff --git a/app/models/form/lettings/questions/reason.rb b/app/models/form/lettings/questions/reason.rb index 9598780ec..a60cc3b3f 100644 --- a/app/models/form/lettings/questions/reason.rb +++ b/app/models/form/lettings/questions/reason.rb @@ -6,8 +6,7 @@ class Form::Lettings::Questions::Reason < ::Form::Question @header = "What is the tenant’s main reason for the household leaving their last settled home?" @type = "radio" @check_answers_card_number = 0 - @hint_text = "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously." - @answer_options = ANSWER_OPTIONS + @hint_text = form.start_year_after_2024? ? "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously." : "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously." @conditional_for = { "reasonother" => [ 20, @@ -16,114 +15,81 @@ class Form::Lettings::Questions::Reason < ::Form::Question @question_number = 77 end - ANSWER_OPTIONS = { - "40" => { - "value" => "End of assured shorthold tenancy (no fault)", - }, - "41" => { - "value" => "End of assured shorthold tenancy (eviction or tenant at fault)", - }, - "42" => { - "value" => "End of fixed term tenancy (no fault)", - }, - "43" => { - "value" => "End of fixed term tenancy (eviction or tenant at fault)", - }, - "1" => { - "value" => "Permanently decanted from another property owned by this landlord", - }, - "46" => { - "value" => "Discharged from long-stay hospital or similar institution", - }, - "45" => { - "value" => "Discharged from prison", - }, - "2" => { - "value" => "Left home country as a refugee", - }, - "4" => { - "value" => "Loss of tied accommodation", - }, - "9" => { - "value" => "Asked to leave by family or friends", - }, - "44" => { - "value" => "Death of household member in last settled accommodation", - }, - "8" => { - "value" => "Relationship breakdown (non-violent) with partner", - }, - "16" => { - "value" => "To move nearer to family, friends or school", - }, - "17" => { - "value" => "To move nearer to work", - }, - "48" => { - "value" => "Domestic abuse - previously joint tenancy with partner", - }, - "49" => { - "value" => "Domestic abuse - other", - }, - "31" => { - "value" => "Hate crime", - }, - "10" => { - "value" => "Racial harassment", - }, - "11" => { - "value" => "Other problems with neighbours", - }, - "35" => { - "value" => "Couldn’t afford fees attached to renewing the tenancy", - }, - "36" => { - "value" => "Couldn’t afford increase in rent", - }, - "38" => { - "value" => "Couldn’t afford rent or mortgage (employment)", - }, - "37" => { - "value" => "Couldn’t afford rent or mortgage (welfare reforms)", - }, - "39" => { - "value" => "Couldn’t afford rent or mortgage (other)", - }, - "34" => { - "value" => "Repossession", - }, - "12" => { - "value" => "Property unsuitable because of overcrowding", - }, - "13" => { - "value" => "Property unsuitable because of ill health or disability", - }, - "14" => { - "value" => "Property unsuitable because of poor condition", - }, - "18" => { - "value" => "To move to accommodation with support", - }, - "19" => { - "value" => "To move to independent accommodation", - }, - "30" => { - "value" => "Under occupation (no incentive)", - }, - "29" => { - "value" => "Under occupation (offered incentive to downsize)", - }, - "20" => { - "value" => "Other", - }, - "47" => { - "value" => "Tenant prefers not to say", - }, - "divider" => { - "value" => true, - }, - "28" => { - "value" => "Don’t know", - }, - }.freeze + def answer_options + if form.start_year_after_2024? + { + "50" => { "value" => "End of social housing tenancy - no fault" }, + "51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, + "52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, + "53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, + "1" => { "value" => "Permanently decanted from another property owned by this landlord" }, + "2" => { "value" => "Left home country as a refugee" }, + "45" => { "value" => "Discharged from prison" }, + "46" => { "value" => "Discharged from long-stay hospital or similar institution" }, + "4" => { "value" => "Loss of tied accommodation" }, + "9" => { "value" => "Asked to leave by family or friends" }, + "8" => { "value" => "Relationship breakdown (non-violent) with partner" }, + "44" => { "value" => "Death of household member in last settled accommodation" }, + "16" => { "value" => "To move nearer to family, friends or school" }, + "17" => { "value" => "To move nearer to work" }, + "48" => { "value" => "Domestic abuse - previously joint tenancy with partner" }, + "49" => { "value" => "Domestic abuse - other" }, + "10" => { "value" => "Racial harassment" }, + "31" => { "value" => "Hate crime" }, + "11" => { "value" => "Other problems with neighbours" }, + "34" => { "value" => "Repossession" }, + "54" => { "value" => "Could no longer afford rent or mortgage" }, + "12" => { "value" => "Property unsuitable because of overcrowding" }, + "13" => { "value" => "Property unsuitable because of ill health or disability" }, + "14" => { "value" => "Property unsuitable because of poor condition" }, + "29" => { "value" => "Under occupation (offered incentive to downsize)" }, + "30" => { "value" => "Under occupation (no incentive)" }, + "18" => { "value" => "To move to accommodation with support" }, + "19" => { "value" => "To move to independent accommodation" }, + "20" => { "value" => "Other" }, + "28" => { "value" => "Don’t know" }, + "divider" => { "value" => true }, + "47" => { "value" => "Tenant prefers not to say" }, + }.freeze + else + { + "40" => { "value" => "End of assured shorthold tenancy (no fault)" }, + "41" => { "value" => "End of assured shorthold tenancy (eviction or tenant at fault)" }, + "42" => { "value" => "End of fixed term tenancy (no fault)" }, + "43" => { "value" => "End of fixed term tenancy (eviction or tenant at fault)" }, + "1" => { "value" => "Permanently decanted from another property owned by this landlord" }, + "46" => { "value" => "Discharged from long-stay hospital or similar institution" }, + "45" => { "value" => "Discharged from prison" }, + "2" => { "value" => "Left home country as a refugee" }, + "4" => { "value" => "Loss of tied accommodation" }, + "9" => { "value" => "Asked to leave by family or friends" }, + "44" => { "value" => "Death of household member in last settled accommodation" }, + "8" => { "value" => "Relationship breakdown (non-violent) with partner" }, + "16" => { "value" => "To move nearer to family, friends or school" }, + "17" => { "value" => "To move nearer to work" }, + "48" => { "value" => "Domestic abuse - previously joint tenancy with partner" }, + "49" => { "value" => "Domestic abuse - other" }, + "31" => { "value" => "Hate crime" }, + "10" => { "value" => "Racial harassment" }, + "11" => { "value" => "Other problems with neighbours" }, + "35" => { "value" => "Couldn’t afford fees attached to renewing the tenancy" }, + "36" => { "value" => "Couldn’t afford increase in rent" }, + "38" => { "value" => "Couldn’t afford rent or mortgage (employment)" }, + "37" => { "value" => "Couldn’t afford rent or mortgage (welfare reforms)" }, + "39" => { "value" => "Couldn’t afford rent or mortgage (other)" }, + "34" => { "value" => "Repossession" }, + "12" => { "value" => "Property unsuitable because of overcrowding" }, + "13" => { "value" => "Property unsuitable because of ill health or disability" }, + "14" => { "value" => "Property unsuitable because of poor condition" }, + "18" => { "value" => "To move to accommodation with support" }, + "19" => { "value" => "To move to independent accommodation" }, + "30" => { "value" => "Under occupation (no incentive)" }, + "29" => { "value" => "Under occupation (offered incentive to downsize)" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }.freeze + end + end end diff --git a/app/models/form/lettings/questions/reason_renewal.rb b/app/models/form/lettings/questions/reason_renewal.rb index 0158eba63..526df044c 100644 --- a/app/models/form/lettings/questions/reason_renewal.rb +++ b/app/models/form/lettings/questions/reason_renewal.rb @@ -7,7 +7,6 @@ class Form::Lettings::Questions::ReasonRenewal < ::Form::Question @type = "radio" @check_answers_card_number = 0 @hint_text = "You told us this letting is a renewal. We have removed some options because of this." - @answer_options = ANSWER_OPTIONS @question_number = 77 @conditional_for = { "reasonother" => [ @@ -16,20 +15,27 @@ class Form::Lettings::Questions::ReasonRenewal < ::Form::Question } end - ANSWER_OPTIONS = { - "40" => { "value" => "End of assured shorthold tenancy (no fault)" }, - "42" => { "value" => "End of fixed term tenancy (no fault)" }, - "20" => { - "value" => "Other", - }, - "47" => { - "value" => "Tenant prefers not to say", - }, - "divider" => { - "value" => true, - }, - "28" => { - "value" => "Don’t know", - }, - }.freeze + def answer_options + if form.start_year_after_2024? + { + "50" => { "value" => "End of social housing tenancy - no fault" }, + "51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, + "52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, + "53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }.freeze + else + { + "40" => { "value" => "End of assured shorthold tenancy (no fault)" }, + "42" => { "value" => "End of fixed term tenancy (no fault)" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }.freeze + end + end end diff --git a/spec/models/form/lettings/questions/reason_renewal_spec.rb b/spec/models/form/lettings/questions/reason_renewal_spec.rb new file mode 100644 index 000000000..f861fc2af --- /dev/null +++ b/spec/models/form/lettings/questions/reason_renewal_spec.rb @@ -0,0 +1,85 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::ReasonRenewal, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + let(:subsection) { instance_double(Form::Subsection) } + let(:form) { instance_double(Form) } + + before do + allow(form).to receive(:start_year_after_2024?).and_return(false) + allow(page).to receive(:subsection).and_return(subsection) + allow(subsection).to receive(:form).and_return(form) + end + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("reason") + end + + it "has the correct header" do + expect(question.header).to eq("What is the tenant’s main reason for the household leaving their last settled home?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Reason for leaving last settled home") + end + + it "has the correct type" do + expect(question.type).to eq("radio") + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to eq(0) + end + + it "has the correct hint" do + expect(question.hint_text).to eq("You told us this letting is a renewal. We have removed some options because of this.") + end + + it "has the correct conditional_for" do + expect(question.conditional_for).to eq({ "reasonother" => [20] }) + end + + it "is not marked as derived" do + expect(question).not_to be_derived + end + + context "with 2023/24 form" do + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "40" => { "value" => "End of assured shorthold tenancy (no fault)" }, + "42" => { "value" => "End of fixed term tenancy (no fault)" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }) + end + end + + context "with 2024/25 form" do + before do + allow(form).to receive(:start_year_after_2024?).and_return(true) + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "50" => { "value" => "End of social housing tenancy - no fault" }, + "51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, + "52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, + "53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }) + end + end +end diff --git a/spec/models/form/lettings/questions/reason_spec.rb b/spec/models/form/lettings/questions/reason_spec.rb index 24d28fd4b..4ea1a4a35 100644 --- a/spec/models/form/lettings/questions/reason_spec.rb +++ b/spec/models/form/lettings/questions/reason_spec.rb @@ -6,6 +6,14 @@ RSpec.describe Form::Lettings::Questions::Reason, type: :model do let(:question_id) { nil } let(:question_definition) { nil } let(:page) { instance_double(Form::Page) } + let(:subsection) { instance_double(Form::Subsection) } + let(:form) { instance_double(Form) } + + before do + allow(form).to receive(:start_year_after_2024?).and_return(false) + allow(page).to receive(:subsection).and_return(subsection) + allow(subsection).to receive(:form).and_return(form) + end it "has correct page" do expect(question.page).to eq(page) @@ -31,10 +39,6 @@ RSpec.describe Form::Lettings::Questions::Reason, type: :model do expect(question.check_answers_card_number).to eq(0) end - it "has the correct hint" do - expect(question.hint_text).to eq("The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously.") - end - it "has the correct conditional_for" do expect(question.conditional_for).to eq({ "reasonother" => [20] }) end @@ -43,116 +47,97 @@ RSpec.describe Form::Lettings::Questions::Reason, type: :model do expect(question).not_to be_derived end - it "has the correct answer_options" do - expect(question.answer_options).to eq({ - "40" => { - "value" => "End of assured shorthold tenancy (no fault)", - }, - "41" => { - "value" => "End of assured shorthold tenancy (eviction or tenant at fault)", - }, - "42" => { - "value" => "End of fixed term tenancy (no fault)", - }, - "43" => { - "value" => "End of fixed term tenancy (eviction or tenant at fault)", - }, - "1" => { - "value" => "Permanently decanted from another property owned by this landlord", - }, - "46" => { - "value" => "Discharged from long-stay hospital or similar institution", - }, - "45" => { - "value" => "Discharged from prison", - }, - "2" => { - "value" => "Left home country as a refugee", - }, - "4" => { - "value" => "Loss of tied accommodation", - }, - "9" => { - "value" => "Asked to leave by family or friends", - }, - "44" => { - "value" => "Death of household member in last settled accommodation", - }, - "8" => { - "value" => "Relationship breakdown (non-violent) with partner", - }, - "16" => { - "value" => "To move nearer to family, friends or school", - }, - "17" => { - "value" => "To move nearer to work", - }, - "48" => { - "value" => "Domestic abuse - previously joint tenancy with partner", - }, - "49" => { - "value" => "Domestic abuse - other", - }, - "31" => { - "value" => "Hate crime", - }, - "10" => { - "value" => "Racial harassment", - }, - "11" => { - "value" => "Other problems with neighbours", - }, - "35" => { - "value" => "Couldn’t afford fees attached to renewing the tenancy", - }, - "36" => { - "value" => "Couldn’t afford increase in rent", - }, - "38" => { - "value" => "Couldn’t afford rent or mortgage (employment)", - }, - "37" => { - "value" => "Couldn’t afford rent or mortgage (welfare reforms)", - }, - "39" => { - "value" => "Couldn’t afford rent or mortgage (other)", - }, - "34" => { - "value" => "Repossession", - }, - "12" => { - "value" => "Property unsuitable because of overcrowding", - }, - "13" => { - "value" => "Property unsuitable because of ill health or disability", - }, - "14" => { - "value" => "Property unsuitable because of poor condition", - }, - "18" => { - "value" => "To move to accommodation with support", - }, - "19" => { - "value" => "To move to independent accommodation", - }, - "30" => { - "value" => "Under occupation (no incentive)", - }, - "29" => { - "value" => "Under occupation (offered incentive to downsize)", - }, - "20" => { - "value" => "Other", - }, - "47" => { - "value" => "Tenant prefers not to say", - }, - "divider" => { - "value" => true, - }, - "28" => { - "value" => "Don’t know", - }, - }) + context "with 2023/24 form" do + it "has the correct hint" do + expect(question.hint_text).to eq("The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation or sleeping rough, their last settled home is where they were living previously.") + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "40" => { "value" => "End of assured shorthold tenancy (no fault)" }, + "41" => { "value" => "End of assured shorthold tenancy (eviction or tenant at fault)" }, + "42" => { "value" => "End of fixed term tenancy (no fault)" }, + "43" => { "value" => "End of fixed term tenancy (eviction or tenant at fault)" }, + "1" => { "value" => "Permanently decanted from another property owned by this landlord" }, + "46" => { "value" => "Discharged from long-stay hospital or similar institution" }, + "45" => { "value" => "Discharged from prison" }, + "2" => { "value" => "Left home country as a refugee" }, + "4" => { "value" => "Loss of tied accommodation" }, + "9" => { "value" => "Asked to leave by family or friends" }, + "44" => { "value" => "Death of household member in last settled accommodation" }, + "8" => { "value" => "Relationship breakdown (non-violent) with partner" }, + "16" => { "value" => "To move nearer to family, friends or school" }, + "17" => { "value" => "To move nearer to work" }, + "48" => { "value" => "Domestic abuse - previously joint tenancy with partner" }, + "49" => { "value" => "Domestic abuse - other" }, + "31" => { "value" => "Hate crime" }, + "10" => { "value" => "Racial harassment" }, + "11" => { "value" => "Other problems with neighbours" }, + "35" => { "value" => "Couldn’t afford fees attached to renewing the tenancy" }, + "36" => { "value" => "Couldn’t afford increase in rent" }, + "38" => { "value" => "Couldn’t afford rent or mortgage (employment)" }, + "37" => { "value" => "Couldn’t afford rent or mortgage (welfare reforms)" }, + "39" => { "value" => "Couldn’t afford rent or mortgage (other)" }, + "34" => { "value" => "Repossession" }, + "12" => { "value" => "Property unsuitable because of overcrowding" }, + "13" => { "value" => "Property unsuitable because of ill health or disability" }, + "14" => { "value" => "Property unsuitable because of poor condition" }, + "18" => { "value" => "To move to accommodation with support" }, + "19" => { "value" => "To move to independent accommodation" }, + "30" => { "value" => "Under occupation (no incentive)" }, + "29" => { "value" => "Under occupation (offered incentive to downsize)" }, + "20" => { "value" => "Other" }, + "47" => { "value" => "Tenant prefers not to say" }, + "divider" => { "value" => true }, + "28" => { "value" => "Don’t know" }, + }) + end + end + + context "with 2024/25 form" do + before do + allow(form).to receive(:start_year_after_2024?).and_return(true) + end + + it "has the correct hint" do + expect(question.hint_text).to eq("The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously.") + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "50" => { "value" => "End of social housing tenancy - no fault" }, + "51" => { "value" => "End of social housing tenancy - evicted due to anti-social behaviour (ASB)" }, + "52" => { "value" => "End of social housing tenancy - evicted due to rent arrears" }, + "53" => { "value" => "End of social housing tenancy - evicted for any other reason" }, + "1" => { "value" => "Permanently decanted from another property owned by this landlord" }, + "2" => { "value" => "Left home country as a refugee" }, + "45" => { "value" => "Discharged from prison" }, + "46" => { "value" => "Discharged from long-stay hospital or similar institution" }, + "4" => { "value" => "Loss of tied accommodation" }, + "9" => { "value" => "Asked to leave by family or friends" }, + "8" => { "value" => "Relationship breakdown (non-violent) with partner" }, + "44" => { "value" => "Death of household member in last settled accommodation" }, + "16" => { "value" => "To move nearer to family, friends or school" }, + "17" => { "value" => "To move nearer to work" }, + "48" => { "value" => "Domestic abuse - previously joint tenancy with partner" }, + "49" => { "value" => "Domestic abuse - other" }, + "10" => { "value" => "Racial harassment" }, + "31" => { "value" => "Hate crime" }, + "11" => { "value" => "Other problems with neighbours" }, + "34" => { "value" => "Repossession" }, + "54" => { "value" => "Could no longer afford rent or mortgage" }, + "12" => { "value" => "Property unsuitable because of overcrowding" }, + "13" => { "value" => "Property unsuitable because of ill health or disability" }, + "14" => { "value" => "Property unsuitable because of poor condition" }, + "29" => { "value" => "Under occupation (offered incentive to downsize)" }, + "30" => { "value" => "Under occupation (no incentive)" }, + "18" => { "value" => "To move to accommodation with support" }, + "19" => { "value" => "To move to independent accommodation" }, + "20" => { "value" => "Other" }, + "28" => { "value" => "Don’t know" }, + "divider" => { "value" => true }, + "47" => { "value" => "Tenant prefers not to say" }, + }) + end end end From 5bcd6779611d9e778ee632987571b750b1546fd5 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:04:41 +0000 Subject: [PATCH 04/13] CLDC-3178 Update grant validation type (#2209) * Remove soft grant validation for 2024 onwards * Validate grant amount for 24/25 onwards * Only run the hard validation for Social HomeBuy and RTA * Fix soft validation --- .../sales/sale_information_validations.rb | 9 +++ .../validations/sales/soft_validations.rb | 3 +- config/locales/en.yml | 2 + .../sale_information_validations_spec.rb | 72 +++++++++++++++++++ .../sales/soft_validations_spec.rb | 30 ++++++++ 5 files changed, 115 insertions(+), 1 deletion(-) diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index 5b036580d..54d49b7e0 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -55,4 +55,13 @@ module Validations::Sales::SaleInformationValidations record.errors.add :type, I18n.t("validations.sale_information.monthly_rent.higher_than_expected") end end + + def validate_grant_amount(record) + return unless record.saledate && record.form.start_year_after_2024? + return unless record.grant && (record.type == 8 || record.type == 21) + + unless record.grant.between?(9_000, 16_000) + record.errors.add :grant, I18n.t("validations.sale_information.grant.out_of_range") + end + end end diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb index fce544754..ae9ee66cc 100644 --- a/app/models/validations/sales/soft_validations.rb +++ b/app/models/validations/sales/soft_validations.rb @@ -116,7 +116,8 @@ module Validations::Sales::SoftValidations end def grant_outside_common_range? - return unless grant + return unless grant && type && saledate + return if form.start_year_after_2024? && (type == 21 || type == 8) !grant.between?(9_000, 16_000) end diff --git a/config/locales/en.yml b/config/locales/en.yml index b9638ba94..7fc5f9d57 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -615,6 +615,8 @@ en: discounted_ownership_value: "The mortgage, deposit, and grant when added together is %{mortgage_deposit_and_grant_total}, and the purchase purchase price times by the discount is %{value_with_discount}. These figures should be the same" monthly_rent: higher_than_expected: "Basic monthly rent must be between £0.00 and £9,999.00" + grant: + out_of_range: "Loan, grants or subsidies must be between £9,000 and £16,000" merge_request: organisation_part_of_another_merge: "This organisation is part of another merge - select a different one" organisation_not_selected: "Select an organisation from the search list" diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index 392686ac7..c890afed1 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -467,4 +467,76 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end end end + + describe "#validate_grant_amount" do + context "when within permitted bounds" do + let(:record) { build(:sales_log, grant: 10_000, saledate: Time.zone.local(2024, 4, 5)) } + + it "does not add an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors).not_to be_present + end + end + + context "when over the max" do + let(:record) { build(:sales_log, type: 8, grant: 17_000, saledate: Time.zone.local(2024, 4, 5)) } + + it "adds an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors[:grant]).to include("Loan, grants or subsidies must be between £9,000 and £16,000") + end + end + + context "when under the min" do + let(:record) { build(:sales_log, type: 21, grant: 3, saledate: Time.zone.local(2024, 4, 5)) } + + it "adds an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors[:grant]).to include("Loan, grants or subsidies must be between £9,000 and £16,000") + end + end + + context "when grant is blank" do + let(:record) { build(:sales_log, type: 21, grant: nil, saledate: Time.zone.local(2024, 4, 5)) } + + it "does not add an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors).not_to be_present + end + end + + context "when over the max and type is not RTA of social homebuy" do + let(:record) { build(:sales_log, type: 9, grant: 17_000, saledate: Time.zone.local(2024, 4, 5)) } + + it "does not add an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors).not_to be_present + end + end + + context "when under the min and type is not RTA of social homebuy" do + let(:record) { build(:sales_log, type: 9, grant: 17_000, saledate: Time.zone.local(2024, 4, 5)) } + + it "does not add error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors).not_to be_present + end + end + + context "with log before 2024/25 collection" do + let(:record) { build(:sales_log, type: 8, grant: 3, saledate: Time.zone.local(2023, 4, 5)) } + + it "does not add an error" do + sale_information_validator.validate_grant_amount(record) + + expect(record.errors).not_to be_present + end + end + end end diff --git a/spec/models/validations/sales/soft_validations_spec.rb b/spec/models/validations/sales/soft_validations_spec.rb index 8718eee86..e417fbd8e 100644 --- a/spec/models/validations/sales/soft_validations_spec.rb +++ b/spec/models/validations/sales/soft_validations_spec.rb @@ -660,21 +660,51 @@ RSpec.describe Validations::Sales::SoftValidations do describe "#grant_outside_common_range?" do it "returns true if grant is below 9000" do record.grant = 1_000 + record.type = 9 + record.saledate = Time.zone.local(2024, 1, 1) expect(record).to be_grant_outside_common_range end it "returns true if grant is above 16000" do record.grant = 100_000 + record.type = 9 + record.saledate = Time.zone.local(2024, 1, 1) expect(record).to be_grant_outside_common_range end it "returns false if grant is within expected range" do record.grant = 10_000 + record.type = 9 + record.saledate = Time.zone.local(2024, 1, 1) expect(record).not_to be_grant_outside_common_range end + + it "returns false for logs after 2024 with RTA" do + record.grant = 100_000 + record.type = 8 + record.saledate = Time.zone.local(2025, 1, 1) + + expect(record).not_to be_grant_outside_common_range + end + + it "returns false for logs after 2024 with socialBuy" do + record.grant = 100_000 + record.type = 21 + record.saledate = Time.zone.local(2025, 1, 1) + + expect(record).not_to be_grant_outside_common_range + end + + it "returns true for logs after 2024 with other type" do + record.grant = 100_000 + record.type = 9 + record.saledate = Time.zone.local(2025, 1, 1) + + expect(record).to be_grant_outside_common_range + end end describe "#staircase_bought_above_fifty" do From bdeca082f6c4fe135a7fa6fd7343de310d9ba79d Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:13:32 +0000 Subject: [PATCH 05/13] CLDC-3207 Update prepare your file and guidance pages (#2215) * Update prepare your file and guidance pages * test * Update more content --- .../bulk_upload_lettings/prepare_your_file.rb | 4 +++ .../bulk_upload_sales/prepare_your_file.rb | 5 ++- .../forms/prepare_your_file_2024.html.erb | 17 +++------- .../forms/prepare_your_file_2024.html.erb | 11 +++---- .../bulk_upload_shared/guidance.html.erb | 31 ++++++++++++------- ...lk_upload_lettings_logs_controller_spec.rb | 4 +-- .../bulk_upload_sales_logs_controller_spec.rb | 4 +-- 7 files changed, 40 insertions(+), 36 deletions(-) diff --git a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb index a2d59a370..a2dfcd8e4 100644 --- a/app/models/forms/bulk_upload_lettings/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_lettings/prepare_your_file.rb @@ -41,6 +41,8 @@ module Forms case year when 2023 "/files/bulk-upload-lettings-template-2023-24.xlsx" + when 2024 + "/files/bulk-upload-lettings-template-2024-25.xlsx" end end @@ -48,6 +50,8 @@ module Forms case year when 2023 "/files/bulk-upload-lettings-specification-2023-24.xlsx" + when 2024 + "/files/bulk-upload-lettings-specification-2024-25.xlsx" end end diff --git a/app/models/forms/bulk_upload_sales/prepare_your_file.rb b/app/models/forms/bulk_upload_sales/prepare_your_file.rb index 227137d72..f72e41d55 100644 --- a/app/models/forms/bulk_upload_sales/prepare_your_file.rb +++ b/app/models/forms/bulk_upload_sales/prepare_your_file.rb @@ -39,14 +39,17 @@ module Forms case year when 2023 "/files/bulk-upload-sales-template-2023-24.xlsx" + when 2024 + "/files/bulk-upload-sales-template-2024-25.xlsx" end end def specification_path case year - when 2023 "/files/bulk-upload-sales-specification-2023-24.xlsx" + when 2024 + "/files/bulk-upload-sales-specification-2024-25.xlsx" end end diff --git a/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2024.html.erb b/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2024.html.erb index 618c2ab4c..8bc375450 100644 --- a/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2024.html.erb +++ b/app/views/bulk_upload_lettings_logs/forms/prepare_your_file_2024.html.erb @@ -13,26 +13,17 @@
Use one of these templates to upload logs for 2024/25:
-There are 7 or 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.
+<%= govuk_link_to "Download the lettings bulk upload template (2024 to 2025)", @form.template_path %>
+There are 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.
Use one of these templates to upload logs for 2024/25:
-There are 7 or 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.
+<%= govuk_link_to "Download the sales bulk upload template (2024 to 2025)", @form.template_path %>: In this template, the questions are in the same order as the 2024/25 paper form and web form.
+There are 8 rows of content in the templates. These rows are called the ‘headers’. They contain the CORE form questions and guidance about which questions are required and how to format your answers.
For each collection year, we publish a bulk upload template and specification.
-The bulk upload templates contain 7 or 8 rows of ‘headers’ with information about how to fill in the template, including:
+ <% if @form.year == 2023 %> +The bulk upload templates contain 7 or 8 rows of ‘headers’ with information about how to fill in the template, including:
+ <% else %> +The bulk upload templates contain 8 rows of ‘headers’ with information about how to fill in the template, including:
+ <% end %>You can paste your data below the headers or copy the headers and insert them above the data in your file. The bulk upload fields start at column B. Leave column A blank.
Make sure that each column of data aligns with the corresponding question in the headers. We recommend ordering your data to match the headers, but you can also reorder the headers to match your data. When processing the file, we check what each column of data represents based on the headers above.
-For 2023/24 uploads, there are 2 templates to choose from, a new template and a legacy template. They outline suggested ways of ordering your data.
-You must include the headers in your file when you upload, unless your data matches the exact order of the legacy template. If you choose to remove the headers, you must also remove the blank column A.
+ <% if @form.year == 2023 %> +For 2023/24 uploads, there are 2 templates to choose from, a new template and a legacy template. They outline suggested ways of ordering your data.
+You must include the headers in your file when you upload, unless your data matches the exact order of the legacy template. If you choose to remove the headers, you must also remove the blank column A.
-New template: In this template, the questions are in the same order as the 2023/24 paper form and web form. Use this template if your organisation is new to bulk upload or if your housing management system matches the new column ordering.
-<%= govuk_link_to "Download the lettings bulk upload template (2023 to 2024) – New question ordering", @form.lettings_template_path %>
-<%= govuk_link_to "Download the sales bulk upload template (2023 to 2024) – New question ordering", @form.sales_template_path %>
+New template: In this template, the questions are in the same order as the 2023/24 paper form and web form. Use this template if your organisation is new to bulk upload or if your housing management system matches the new column ordering.
+<%= govuk_link_to "Download the lettings bulk upload template (2023 to 2024) – New question ordering", @form.lettings_template_path %>
+<%= govuk_link_to "Download the sales bulk upload template (2023 to 2024) – New question ordering", @form.sales_template_path %>
-Legacy template: In this template, the questions are in the same order as the 2022/23 template, with new questions added on to the end. Use this template if you have not updated your system to match the new template yet.
-<%= govuk_link_to "Download the lettings bulk upload template (2023 to 2024) - Legacy version", @form.lettings_legacy_template_path %>
-<%= govuk_link_to "Download the sales bulk upload template (2023 to 2024) – Legacy version", @form.sales_legacy_template_path %>
+Legacy template: In this template, the questions are in the same order as the 2022/23 template, with new questions added on to the end. Use this template if you have not updated your system to match the new template yet.
+<%= govuk_link_to "Download the lettings bulk upload template (2023 to 2024) - Legacy version", @form.lettings_legacy_template_path %>
+<%= govuk_link_to "Download the sales bulk upload template (2023 to 2024) – Legacy version", @form.sales_legacy_template_path %>
+ <% else %> +<%= govuk_link_to "Download the lettings bulk upload template (2024 to 2025)", @form.lettings_template_path %>
+<%= govuk_link_to "Download the sales bulk upload template (2024 to 2025)", @form.sales_template_path %>
+ <% end %> <% end %> <%= accordion.with_section(heading_text: "Using the bulk upload specification") do %>The bulk upload specification contains the same information as the template headers, as well as more details about the accepted responses for each question. For multiple-choice questions, we use number or letter codes to represent each option, and the specification shows what answer each code represents.
There is a separate specification for lettings and sales:
-<%= govuk_link_to "Download the lettings bulk upload specification (2023 to 2024)", @form.lettings_specification_path, target: "_blank" %>
-<%= govuk_link_to "Download the sales bulk upload specification (2023 to 2024)", @form.sales_specification_path, target: "_blank" %>
+<%= govuk_link_to "Download the lettings bulk upload specification (#{@form.year} to #{@form.year + 1})", @form.lettings_specification_path, target: "_blank" %>
+<%= govuk_link_to "Download the sales bulk upload specification (#{@form.year} to #{@form.year + 1})", @form.sales_specification_path, target: "_blank" %>
If your upload fails because there are errors in the data, you can use the specification to help correct the errors. Having your file, the error report, and the specification open at the same time will make it easy to cross-reference field numbers and check accepted responses.
<% end %> diff --git a/spec/requests/bulk_upload_lettings_logs_controller_spec.rb b/spec/requests/bulk_upload_lettings_logs_controller_spec.rb index f901cdb7e..afc5577c3 100644 --- a/spec/requests/bulk_upload_lettings_logs_controller_spec.rb +++ b/spec/requests/bulk_upload_lettings_logs_controller_spec.rb @@ -49,7 +49,7 @@ RSpec.describe BulkUploadLettingsLogsController, type: :request do it "shows guidance page with correct title" do Timecop.freeze(2022, 1, 1) do - get "/lettings-logs/bulk-upload-logs/guidance", params: {} + get "/lettings-logs/bulk-upload-logs/guidance?form%5Byear%5D=2022", params: {} expect(response.body).to include("How to upload logs in bulk") end @@ -59,7 +59,7 @@ RSpec.describe BulkUploadLettingsLogsController, type: :request do context "when in crossover period" do it "shows guidance page with correct title" do Timecop.freeze(2023, 6, 1) do - get "/lettings-logs/bulk-upload-logs/guidance", params: {} + get "/lettings-logs/bulk-upload-logs/guidance?form%5Byear%5D=2023", params: {} expect(response.body).to include("How to upload logs in bulk") end diff --git a/spec/requests/bulk_upload_sales_logs_controller_spec.rb b/spec/requests/bulk_upload_sales_logs_controller_spec.rb index 3220ff885..c603ec821 100644 --- a/spec/requests/bulk_upload_sales_logs_controller_spec.rb +++ b/spec/requests/bulk_upload_sales_logs_controller_spec.rb @@ -49,7 +49,7 @@ RSpec.describe BulkUploadSalesLogsController, type: :request do it "shows guidance page with correct title" do Timecop.freeze(2022, 1, 1) do - get "/sales-logs/bulk-upload-logs/guidance", params: {} + get "/sales-logs/bulk-upload-logs/guidance?form%5Byear%5D=2022", params: {} expect(response.body).to include("How to upload logs in bulk") end @@ -59,7 +59,7 @@ RSpec.describe BulkUploadSalesLogsController, type: :request do context "when in crossover period" do it "shows guidance page with correct title" do Timecop.freeze(2023, 6, 1) do - get "/sales-logs/bulk-upload-logs/guidance", params: {} + get "/sales-logs/bulk-upload-logs/guidance?form%5Byear%5D=2023", params: {} expect(response.body).to include("How to upload logs in bulk") end From a3fb5313c0299d5fb92fce195885435338f5c429 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:36:19 +0000 Subject: [PATCH 06/13] CLDC-3175 Add max stairbought validation (#2204) * Add max stairbought validation * refactor tests --- .../sales/sale_information_validations.rb | 19 +++++ config/locales/en.yml | 2 + .../sale_information_validations_spec.rb | 69 +++++++++++++++++++ 3 files changed, 90 insertions(+) diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index 54d49b7e0..17fbc95b4 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -64,4 +64,23 @@ module Validations::Sales::SaleInformationValidations record.errors.add :grant, I18n.t("validations.sale_information.grant.out_of_range") end end + + def validate_stairbought(record) + return unless record.stairbought && record.type + return unless record.saledate && record.form.start_year_after_2024? + + max_stairbought = case record.type + when 30, 16, 28, 31, 32 + 90 + when 2, 18 + 75 + when 24 + 50 + end + + if max_stairbought && record.stairbought > max_stairbought + record.errors.add :stairbought, I18n.t("validations.sale_information.stairbought.over_max", max_stairbought:, type: record.form.get_question("type", record).answer_label(record)) + record.errors.add :type, I18n.t("validations.sale_information.stairbought.over_max", max_stairbought:, type: record.form.get_question("type", record).answer_label(record)) + end + end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 7fc5f9d57..c7d8c9da2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -617,6 +617,8 @@ en: higher_than_expected: "Basic monthly rent must be between £0.00 and £9,999.00" grant: out_of_range: "Loan, grants or subsidies must be between £9,000 and £16,000" + stairbought: + over_max: "The percentage bought in this staircasing transaction cannot be higher than %{max_stairbought}% for %{type} sales." merge_request: organisation_part_of_another_merge: "This organisation is part of another merge - select a different one" organisation_not_selected: "Select an organisation from the search list" diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index c890afed1..25474e55b 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -539,4 +539,73 @@ RSpec.describe Validations::Sales::SaleInformationValidations do end end end + + describe "#validate_stairbought" do + let(:now) { Time.zone.local(2024, 4, 4) } + + before do + Timecop.freeze(now) + Singleton.__init__(FormHandler) + end + + after do + Timecop.return + Singleton.__init__(FormHandler) + end + + [ + ["Shared Ownership (new model lease)", 30, 90], + ["Home Ownership for people with Long-Term Disabilities (HOLD)", 16, 90], + ["Rent to Buy — Shared Ownership", 28, 90], + ["Right to Shared Ownership (RtSO)", 31, 90], + ["London Living Rent — Shared Ownership", 32, 90], + ["Shared Ownership (old model lease)", 2, 75], + ["Social HomeBuy — shared ownership purchase", 18, 75], + ["Older Persons Shared Ownership", 24, 50], + ].each do |label, type, max| + context "when ownership type is #{label}" do + let(:record) { build(:sales_log, ownershipsch: 1, type:, saledate: now) } + + it "does not add an error if stairbought is under #{max}%" do + record.stairbought = max - 1 + sale_information_validator.validate_stairbought(record) + + expect(record.errors).to be_empty + end + + it "does not add an error if stairbought is #{max}%" do + record.stairbought = max + sale_information_validator.validate_stairbought(record) + + expect(record.errors).to be_empty + end + + it "does not add an error if stairbought is not given" do + record.stairbought = nil + sale_information_validator.validate_stairbought(record) + + expect(record.errors).to be_empty + end + + it "adds an error if stairbought is over #{max}%" do + record.stairbought = max + 2 + sale_information_validator.validate_stairbought(record) + + expect(record.errors[:stairbought]).to include("The percentage bought in this staircasing transaction cannot be higher than #{max}% for #{label} sales.") + expect(record.errors[:type]).to include("The percentage bought in this staircasing transaction cannot be higher than #{max}% for #{label} sales.") + end + end + end + + context "when the collection year is before 2024" do + let(:record) { build(:sales_log, ownershipsch: 1, type: 24, saledate: now, stairbought: 90) } + let(:now) { Time.zone.local(2023, 4, 4) } + + it "does not add an error" do + sale_information_validator.validate_stairbought(record) + + expect(record.errors).to be_empty + end + end + end end From 7a9291dac957e0c8b42a28d9d1b2a16d89cdf270 Mon Sep 17 00:00:00 2001 From: kosiakkatrina <54268893+kosiakkatrina@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:05:30 +0000 Subject: [PATCH 07/13] CLDC-3172 Update routing for staircase transactions (#2203) * Update routing for LaNominations * Update routing for buyer previous * Extract a method * lint --- app/models/form/sales/pages/buyer_previous.rb | 6 ++ app/models/form/sales/pages/la_nominations.rb | 6 ++ app/models/sales_log.rb | 4 ++ .../form/sales/pages/buyer_previous_spec.rb | 57 +++++++++++++++++++ .../form/sales/pages/la_nominations_spec.rb | 53 +++++++++++++++++ 5 files changed, 126 insertions(+) diff --git a/app/models/form/sales/pages/buyer_previous.rb b/app/models/form/sales/pages/buyer_previous.rb index f37c6a847..ed28cea00 100644 --- a/app/models/form/sales/pages/buyer_previous.rb +++ b/app/models/form/sales/pages/buyer_previous.rb @@ -10,4 +10,10 @@ class Form::Sales::Pages::BuyerPrevious < ::Form::Page Form::Sales::Questions::BuyerPrevious.new(nil, nil, self, joint_purchase: @joint_purchase), ] end + + def routed_to?(log, _current_user) + return false if log.is_staircase? && log.form.start_year_after_2024? + + super + end end diff --git a/app/models/form/sales/pages/la_nominations.rb b/app/models/form/sales/pages/la_nominations.rb index e756e3071..0ac2cde75 100644 --- a/app/models/form/sales/pages/la_nominations.rb +++ b/app/models/form/sales/pages/la_nominations.rb @@ -9,4 +9,10 @@ class Form::Sales::Pages::LaNominations < ::Form::Page Form::Sales::Questions::LaNominations.new(nil, nil, self), ] end + + def routed_to?(log, _current_user) + return false if log.staircase == 1 && log.form.start_year_after_2024? + + super + end end diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb index 3f47dea80..c0202c1df 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -477,4 +477,8 @@ class SalesLog < Log def nationality2_uk_or_prefers_not_to_say? nationality_all_buyer2_group&.zero? || nationality_all_buyer2_group == 826 end + + def is_staircase? + staircase == 1 + end end diff --git a/spec/models/form/sales/pages/buyer_previous_spec.rb b/spec/models/form/sales/pages/buyer_previous_spec.rb index e6dda073e..4d7df21a6 100644 --- a/spec/models/form/sales/pages/buyer_previous_spec.rb +++ b/spec/models/form/sales/pages/buyer_previous_spec.rb @@ -3,11 +3,21 @@ require "rails_helper" RSpec.describe Form::Sales::Pages::BuyerPrevious, type: :model do subject(:page) { described_class.new(page_id, page_definition, subsection, joint_purchase:) } + let(:log) { create(:sales_log, :completed) } + let(:page_id) { "example" } let(:page_definition) { nil } let(:subsection) { instance_double(Form::Subsection) } + let(:form) { instance_double(Form) } let(:joint_purchase) { false } + before do + allow(subsection).to receive(:depends_on).and_return(nil) + allow(subsection).to receive(:enabled?).and_return(true) + allow(subsection).to receive(:form).and_return(form) + allow(form).to receive(:depends_on_met).and_return(true) + end + it "has correct subsection" do expect(page.subsection).to eq(subsection) end @@ -41,4 +51,51 @@ RSpec.describe Form::Sales::Pages::BuyerPrevious, type: :model do expect(page.depends_on).to eq([{ "joint_purchase?" => false }]) end end + + context "with 23/24 log" do + before do + Timecop.freeze(Time.zone.local(2023, 4, 2)) + Singleton.__init__(FormHandler) + end + + after do + Timecop.return + end + + it "has correct routed to" do + log.staircase = 1 + expect(page.routed_to?(log, nil)).to eq(true) + end + end + + context "with 24/25 log" do + before do + Timecop.freeze(Time.zone.local(2024, 4, 2)) + Singleton.__init__(FormHandler) + end + + after do + Timecop.return + end + + it "has correct routed to when staircase is yes" do + log.staircase = 1 + expect(page.routed_to?(log, nil)).to eq(false) + end + + it "has correct routed to when staircase is nil" do + log.staircase = nil + expect(page.routed_to?(log, nil)).to eq(true) + end + + it "has correct routed to when staircase is no" do + log.staircase = 2 + expect(page.routed_to?(log, nil)).to eq(true) + end + + it "has correct routed to when staircase is don't know" do + log.staircase = 3 + expect(page.routed_to?(log, nil)).to eq(true) + end + end end diff --git a/spec/models/form/sales/pages/la_nominations_spec.rb b/spec/models/form/sales/pages/la_nominations_spec.rb index b7b40c2dd..ab41d7f94 100644 --- a/spec/models/form/sales/pages/la_nominations_spec.rb +++ b/spec/models/form/sales/pages/la_nominations_spec.rb @@ -3,10 +3,16 @@ require "rails_helper" RSpec.describe Form::Sales::Pages::LaNominations, type: :model do subject(:page) { described_class.new(page_id, page_definition, subsection) } + let(:log) { create(:sales_log, :completed) } + let(:page_id) { nil } let(:page_definition) { nil } let(:subsection) { instance_double(Form::Subsection) } + before do + allow(subsection).to receive(:depends_on).and_return(nil) + end + it "has correct subsection" do expect(page.subsection).to eq(subsection) end @@ -26,4 +32,51 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do it "has the correct description" do expect(page.description).to be_nil end + + context "with 23/24 log" do + before do + Timecop.freeze(Time.zone.local(2023, 4, 2)) + Singleton.__init__(FormHandler) + end + + after do + Timecop.return + end + + it "has correct routed to" do + log.staircase = 1 + expect(page.routed_to?(log, nil)).to eq(true) + end + end + + context "with 24/25 log" do + before do + Timecop.freeze(Time.zone.local(2024, 4, 2)) + Singleton.__init__(FormHandler) + end + + after do + Timecop.return + end + + it "has correct routed to when staircase is yes" do + log.staircase = 1 + expect(page.routed_to?(log, nil)).to eq(false) + end + + it "has correct routed to when staircase is nil" do + log.staircase = nil + expect(page.routed_to?(log, nil)).to eq(true) + end + + it "has correct routed to when staircase is no" do + log.staircase = 2 + expect(page.routed_to?(log, nil)).to eq(true) + end + + it "has correct routed to when staircase is don't know" do + log.staircase = 3 + expect(page.routed_to?(log, nil)).to eq(true) + end + end end From 9fdb4cee93a2d67f29485afcf172e09cbf71bb36 Mon Sep 17 00:00:00 2001 From: Rachael Booth