Browse Source

Merge branch 'main' into Fix-change-address-query-logic

pull/2998/head
Manny Dinssa 5 months ago
parent
commit
3b2302048a
  1. 2
      app/models/derived_variables/lettings_log_variables.rb
  2. 2
      app/models/form/lettings/questions/previous_let_type.rb
  3. 7
      app/models/validations/soft_validations.rb
  4. 52
      app/services/bulk_upload/sales/year2025/row_parser.rb
  5. 3
      spec/fixtures/files/lettings_log_csv_export_codes_25.csv
  6. 3
      spec/fixtures/files/lettings_log_csv_export_labels_25.csv
  7. 3
      spec/fixtures/files/lettings_log_csv_export_non_support_codes_25.csv
  8. 3
      spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv
  9. 2
      spec/models/form/lettings/questions/previous_let_type_spec.rb
  10. 36
      spec/models/validations/soft_validations_spec.rb
  11. 48
      spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
  12. 193
      spec/services/csv/lettings_log_csv_service_spec.rb

2
app/models/derived_variables/lettings_log_variables.rb

@ -18,7 +18,7 @@ module DerivedVariables::LettingsLogVariables
3 => 6, # "Rent to Buy" => "Rent to Buy basis" 3 => 6, # "Rent to Buy" => "Rent to Buy basis"
4 => 7, # "London Living Rent" => "London Living Rent basis" 4 => 7, # "London Living Rent" => "London Living Rent basis"
5 => 8, # "Other intermediate rent product" => "Another Intermediate Rent basis" 5 => 8, # "Other intermediate rent product" => "Another Intermediate Rent basis"
6 => 9, # "Specified accommodation - exempt accommodation, managed properties, refuges and local authority hostels" => "Specified accommodation - exempt accommodation, manged properties, refuges and local authority hostels" 6 => 9, # "Specified accommodation - exempt accommodation, managed properties, refuges and local authority hostels" => "Specified accommodation - exempt accommodation, managed properties, refuges and local authority hostels"
}.freeze }.freeze
RENTTYPE_DETAIL_MAPPING = { RENTTYPE_DETAIL_MAPPING = {

2
app/models/form/lettings/questions/previous_let_type.rb

@ -36,7 +36,7 @@ class Form::Lettings::Questions::PreviousLetType < ::Form::Question
"6" => { "value" => "Rent to Buy basis" }, "6" => { "value" => "Rent to Buy basis" },
"7" => { "value" => "London Living Rent basis" }, "7" => { "value" => "London Living Rent basis" },
"8" => { "value" => "Another Intermediate Rent basis" }, "8" => { "value" => "Another Intermediate Rent basis" },
"9" => { "value" => "Specified accommodation - exempt accommodation, manged properties, refuges and local authority hostels" }, "9" => { "value" => "Specified accommodation - exempt accommodation, managed properties, refuges and local authority hostels" },
"divider" => { "value" => true }, "divider" => { "value" => true },
"3" => { "value" => "Don’t know" }, "3" => { "value" => "Don’t know" },
}.freeze }.freeze

7
app/models/validations/soft_validations.rb

@ -103,13 +103,16 @@ module Validations::SoftValidations
TWO_YEARS_IN_DAYS = 730 TWO_YEARS_IN_DAYS = 730
TEN_YEARS_IN_DAYS = 3650 TEN_YEARS_IN_DAYS = 3650
TWENTY_YEARS_IN_DAYS = 7300
def major_repairs_date_in_soft_range? def major_repairs_date_in_soft_range?
mrcdate.present? && startdate.present? && mrcdate.between?(startdate.to_date - TEN_YEARS_IN_DAYS, startdate.to_date - TWO_YEARS_IN_DAYS) upper_limit = form.start_year_2025_or_later? ? TWENTY_YEARS_IN_DAYS : TEN_YEARS_IN_DAYS
mrcdate.present? && startdate.present? && mrcdate.between?(startdate.to_date - upper_limit, startdate.to_date - TWO_YEARS_IN_DAYS)
end end
def voiddate_in_soft_range? def voiddate_in_soft_range?
voiddate.present? && startdate.present? && voiddate.between?(startdate.to_date - TEN_YEARS_IN_DAYS, startdate.to_date - TWO_YEARS_IN_DAYS) upper_limit = form.start_year_2025_or_later? ? TWENTY_YEARS_IN_DAYS : TEN_YEARS_IN_DAYS
voiddate.present? && startdate.present? && voiddate.between?(startdate.to_date - upper_limit, startdate.to_date - TWO_YEARS_IN_DAYS)
end end
def net_income_higher_or_lower_text def net_income_higher_or_lower_text

52
app/services/bulk_upload/sales/year2025/row_parser.rb

@ -815,31 +815,11 @@ private
attributes["sex5"] = field_52 attributes["sex5"] = field_52
attributes["sex6"] = field_56 attributes["sex6"] = field_56
attributes["relat2"] = if field_34 == 1 attributes["relat2"] = relationship_from_is_partner(field_34)
"P" attributes["relat3"] = relationship_from_is_partner(field_42)
else attributes["relat4"] = relationship_from_is_partner(field_46)
(field_34 == 2 ? "X" : "R") attributes["relat5"] = relationship_from_is_partner(field_50)
end attributes["relat6"] = relationship_from_is_partner(field_54)
attributes["relat3"] = if field_42 == 1
"P"
else
(field_42 == 2 ? "X" : "R")
end
attributes["relat4"] = if field_46 == 1
"P"
else
(field_46 == 2 ? "X" : "R")
end
attributes["relat5"] = if field_50 == 1
"P"
else
(field_50 == 2 ? "X" : "R")
end
attributes["relat6"] = if field_54 == 1
"P"
else
(field_54 == 2 ? "X" : "R")
end
attributes["ecstat1"] = field_32 attributes["ecstat1"] = field_32
attributes["ecstat2"] = field_39 attributes["ecstat2"] = field_39
@ -1052,6 +1032,17 @@ private
field_55.present? || field_56.present? || field_54.present? field_55.present? || field_56.present? || field_54.present?
end end
def relationship_from_is_partner(is_partner)
case is_partner
when 1
"P"
when 2
"X"
when 3
"R"
end
end
def details_known?(person_n) def details_known?(person_n)
send("person_#{person_n}_present?") ? 1 : 2 send("person_#{person_n}_present?") ? 1 : 2
end end
@ -1491,6 +1482,17 @@ private
%w[0] + GlobalConstants::COUNTRIES_ANSWER_OPTIONS.keys # 0 is "Prefers not to say" %w[0] + GlobalConstants::COUNTRIES_ANSWER_OPTIONS.keys # 0 is "Prefers not to say"
end end
def validate_relat_fields
%i[field_34 field_42 field_46 field_50 field_54].each do |field|
value = send(field)
next if value.blank?
unless (1..3).cover?(value)
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])))
end
end
end
def bulk_upload_organisation def bulk_upload_organisation
Organisation.find(bulk_upload.organisation_id) Organisation.find(bulk_upload.organisation_id)
end end

3
spec/fixtures/files/lettings_log_csv_export_codes_25.csv vendored

File diff suppressed because one or more lines are too long

3
spec/fixtures/files/lettings_log_csv_export_labels_25.csv vendored

File diff suppressed because one or more lines are too long

3
spec/fixtures/files/lettings_log_csv_export_non_support_codes_25.csv vendored

File diff suppressed because one or more lines are too long

3
spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv vendored

File diff suppressed because one or more lines are too long

2
spec/models/form/lettings/questions/previous_let_type_spec.rb

@ -83,7 +83,7 @@ RSpec.describe Form::Lettings::Questions::PreviousLetType, type: :model do
"6" => { "value" => "Rent to Buy basis" }, "6" => { "value" => "Rent to Buy basis" },
"7" => { "value" => "London Living Rent basis" }, "7" => { "value" => "London Living Rent basis" },
"8" => { "value" => "Another Intermediate Rent basis" }, "8" => { "value" => "Another Intermediate Rent basis" },
"9" => { "value" => "Specified accommodation - exempt accommodation, manged properties, refuges and local authority hostels" }, "9" => { "value" => "Specified accommodation - exempt accommodation, managed properties, refuges and local authority hostels" },
"divider" => { "value" => true }, "divider" => { "value" => true },
"3" => { "value" => "Don’t know" }, "3" => { "value" => "Don’t know" },
}) })

36
spec/models/validations/soft_validations_spec.rb

@ -265,6 +265,24 @@ RSpec.describe Validations::SoftValidations do
expect(record.major_repairs_date_in_soft_range?).to be false expect(record.major_repairs_date_in_soft_range?).to be false
end end
end end
context "with 2025 logs" do
context "when the void date is within 20 years of the tenancy start date" do
it "shows the interruption screen" do
record.startdate = Time.zone.local(2026, 2, 1)
record.mrcdate = Time.zone.local(2007, 2, 1)
expect(record.major_repairs_date_in_soft_range?).to be true
end
end
context "when the void date is less than 2 years before the tenancy start date" do
it "does not show the interruption screen" do
record.startdate = Time.zone.local(2026, 2, 1)
record.mrcdate = Time.zone.local(2025, 2, 1)
expect(record.major_repairs_date_in_soft_range?).to be false
end
end
end
end end
describe "void date soft validations" do describe "void date soft validations" do
@ -283,6 +301,24 @@ RSpec.describe Validations::SoftValidations do
expect(record.voiddate_in_soft_range?).to be false expect(record.voiddate_in_soft_range?).to be false
end end
end end
context "with 2025 logs" do
context "when the void date is within 20 years of the tenancy start date" do
it "shows the interruption screen" do
record.startdate = Time.zone.local(2026, 2, 1)
record.voiddate = Time.zone.local(2007, 2, 1)
expect(record.voiddate_in_soft_range?).to be true
end
end
context "when the void date is less than 2 years before the tenancy start date" do
it "does not show the interruption screen" do
record.startdate = Time.zone.local(2026, 2, 1)
record.voiddate = Time.zone.local(2025, 2, 1)
expect(record.voiddate_in_soft_range?).to be false
end
end
end
end end
describe "old persons shared ownership soft validations" do describe "old persons shared ownership soft validations" do

48
spec/services/bulk_upload/sales/year2025/row_parser_spec.rb

@ -60,7 +60,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
field_31: "28", field_31: "28",
field_32: "1", field_32: "1",
field_33: "1", field_33: "1",
field_34: "R", field_34: "3",
field_35: "32", field_35: "32",
field_36: "F", field_36: "F",
field_37: "17", field_37: "17",
@ -1145,6 +1145,52 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
end end
describe "relationship field mappings" do
[
%w[field_34 relat2 2],
%w[field_42 relat3 3],
%w[field_46 relat4 4],
%w[field_50 relat5 5],
%w[field_54 relat6 6],
].each do |input_field, relationship_attribute, person_num|
describe input_field.to_s do
context "when #{input_field} is 1" do
let(:attributes) { setup_section_params.merge({ input_field.to_sym => "1", field_41: "5" }) }
it "sets relationship to P" do
expect(parser.log.public_send(relationship_attribute)).to eq("P")
end
end
context "when #{input_field} is 2" do
let(:attributes) { setup_section_params.merge({ input_field.to_sym => "2", field_41: "5" }) }
it "sets relationship to X" do
expect(parser.log.public_send(relationship_attribute)).to eq("X")
end
end
context "when #{input_field} is 3" do
let(:attributes) { setup_section_params.merge({ input_field.to_sym => "3", field_41: "5" }) }
it "sets relationship to R" do
expect(parser.log.public_send(relationship_attribute)).to eq("R")
end
end
context "when #{input_field} is 4" do
let(:attributes) { setup_section_params.merge({ input_field.to_sym => "4", field_41: "5" }) }
it "gives a validation error" do
parser.valid?
validation_message = "You must answer person #{person_num} is the partner of buyer 1."
expect(parser.errors[input_field]).to include validation_message
end
end
end
end
end
describe "field_39" do # ecstat2 describe "field_39" do # ecstat2
context "when buyer 2 has no age but has ecstat as child" do context "when buyer 2 has no age but has ecstat as child" do
let(:attributes) { valid_attributes.merge({ field_35: nil, field_39: "9" }) } let(:attributes) { valid_attributes.merge({ field_35: nil, field_39: "9" }) }

193
spec/services/csv/lettings_log_csv_service_spec.rb

@ -194,6 +194,199 @@ RSpec.describe Csv::LettingsLogCsvService do
end end
describe "the full CSV output" do describe "the full CSV output" do
context "when the requested log year is 2025" do
let(:year) { 2025 }
let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") }
let(:log) do
create(
:lettings_log,
:ignore_validation_errors,
created_by: user,
assigned_to: user,
created_at: Time.zone.local(2025, 4, 1),
updated_at: Time.zone.local(2025, 4, 1),
owning_organisation: organisation,
managing_organisation: organisation,
needstype: 1,
renewal: 0,
startdate: Time.zone.local(2025, 4, 1),
rent_type: 1,
tenancycode: "HIJKLMN",
propcode: "ABCDEFG",
declaration: 1,
address_line1: "Address line 1",
town_or_city: "London",
postcode_full: "NW9 5LL",
la: "E09000003",
is_la_inferred: false,
address_line1_as_entered: "address line 1 as entered",
address_line2_as_entered: "address line 2 as entered",
town_or_city_as_entered: "town or city as entered",
county_as_entered: "county as entered",
postcode_full_as_entered: "AB1 2CD",
la_as_entered: "la as entered",
first_time_property_let_as_social_housing: 0,
unitletas: 2,
rsnvac: 6,
unittype_gn: 7,
builtype: 1,
wchair: 1,
beds: 3,
voiddate: Time.zone.local(2025, 3, 30),
majorrepairs: 1,
mrcdate: Time.zone.local(2025, 3, 31),
joint: 3,
startertenancy: 1,
tenancy: 4,
tenancylength: 2,
hhmemb: 4,
age1_known: 0,
age1: 35,
sex1: "F",
ethnic_group: 0,
ethnic: 2,
nationality_all: 36,
ecstat1: 0,
details_known_2: 0,
relat2: "P",
age2_known: 0,
age2: 32,
sex2: "M",
ecstat2: 6,
details_known_3: 1,
details_known_4: 0,
relat4: "R",
age4_known: 1,
sex4: "R",
ecstat4: 10,
armedforces: 1,
leftreg: 4,
reservist: 1,
preg_occ: 2,
housingneeds: 1,
housingneeds_type: 0,
housingneeds_a: 1,
housingneeds_b: 0,
housingneeds_c: 0,
housingneeds_f: 0,
housingneeds_g: 0,
housingneeds_h: 0,
housingneeds_other: 0,
illness: 1,
illness_type_1: 0,
illness_type_2: 1,
illness_type_3: 0,
illness_type_4: 0,
illness_type_5: 0,
illness_type_6: 0,
illness_type_7: 0,
illness_type_8: 0,
illness_type_9: 0,
illness_type_10: 0,
layear: 2,
waityear: 7,
reason: 4,
prevten: 6,
homeless: 1,
ppcodenk: 1,
ppostcode_full: "TN23 6LZ",
previous_la_known: 1,
prevloc: "E07000105",
reasonpref: 1,
rp_homeless: 0,
rp_insan_unsat: 1,
rp_medwel: 0,
rp_hardship: 0,
rp_dontknow: 0,
cbl: 0,
chr: 1,
cap: 0,
accessible_register: 0,
referral: 2,
net_income_known: 0,
incref: 0,
incfreq: 1,
earnings: 268,
hb: 6,
has_benefits: 1,
benefits: 1,
period: 2,
brent: 200,
scharge: 50,
pscharge: 40,
supcharg: 35,
tcharge: 325,
hbrentshortfall: 1,
tshortfall_known: 1,
tshortfall: 12,
)
end
context "when exporting with human readable labels" do
let(:export_type) { "labels" }
context "when the current user is a support user" do
let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") }
it "exports the CSV with 2025 ordering and all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_25.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
context "when the current user is not a support user" do
let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
end
context "when exporting values as codes" do
let(:export_type) { "codes" }
context "when the current user is a support user" do
let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_25.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
context "when the current user is not a support user" do
let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") }
it "exports the CSV with all values correct" do
expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_25.csv")
values_to_delete = %w[id]
values_to_delete.each do |attribute|
index = attribute_line.index(attribute)
content_line[index] = nil
end
expect(csv).to eq expected_content
end
end
end
end
context "when the requested log year is 2024" do context "when the requested log year is 2024" do
let(:year) { 2024 } let(:year) { 2024 }
let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") } let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") }

Loading…
Cancel
Save