Browse Source

CLDC-4151: Split Referral into three questions (#3150)

* CLDC-4151: Note deprecations of existing referral questions

* CLDC-4151: Add new cols to lettings log model

* CLDC-4151: Add new referrals questions

* CLDC-4151: Remove referral value check

* CLDC-4151: Add new fields to bulk upload

use new fields as presented in bulk upload

* CLDC-4151: Update tests

also add bulk upload file to test with

* CLDC-4151: Ignore tests failing for later tickets

* fixup! CLDC-4151: Add new referrals questions

start q nums from 2026

* CLDC-4151: Add model tests for new questions

* fixup! CLDC-4151: Add new fields to bulk upload

export old_visible_id

set MAX_COLUMNS correctly

check .prp? for prp cols

* fixup! CLDC-4151: Update tests

clarify tests that may update

* fixup! CLDC-4151: Add new fields to bulk upload

handle the old_visible_id not existing

use override org ID only for the output owning ID. it's only passed as eg ORG1

* CLDC-4151: Add new questions to log factory

* fixup! CLDC-4151: Add new fields to bulk upload

leave field_131 validations till later

* CLDC-4188: Add LA flow

splits the referral_register question and pages into two, as its not easy to have the answers be dependent

if the owning organisation changes type, reset the referral register question. the other questions do not need to be reset as they are no longer routed to

* CLDC-4188: Infer referral_register for renewals

needs a new dependencies array for 2026

this handles inferring as well as clearing inferred answers if the prior answer changes

* CLDC-4188: Add validation between prevten and referral_register

block two other validations from previous years

* CLDC-4188: Update tests

* CLDC-4188: Ignore tests failing for future tickets

* CLDC-4188: Update existing tests

needed as should_reset_referral_register? calls a .find()

* fixup! CLDC-4188: Add validation between prevten and referral_register

use .prp?

improve grammar

* fixup! CLDC-4188: Infer referral_register for renewals

extract dependencies to common list

* fixup! CLDC-4188: Update tests

use before and context blocks better

* fixup! CLDC-4188: Update tests

lint

* fixup! CLDC-4188: Update tests

remove unneeded referral_type set

* CLDC-4189: Add PRP flow

* CLDC-4189: Update validation between prevten and referral_register

* CLDC-4189: Add tests

* fixup! CLDC-4189: Add PRP flow

fix typo

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>

* fixup! CLDC-4189: Add tests

fix typo

* fixup! CLDC-4189: Add tests

fix missing cases in page specs

use a loop and before blocks for household validation tests

* CLDC-4189: Ensure log is not classed as generan needs if prevten isnt answered

* fixup! CLDC-4189: Add tests

add cases for other internal transfer flow

* CLDC-4151: Add final question numbers

* fixup! CLDC-4189: Update validation between prevten and referral_register

include new code 40 from CLDC-4149

* fixup! CLDC-4151: Add final question numbers

reinstate fallback

* CLDC-4190: Q84 Referral BU validations (#3155)

* CLDC-4151: Note deprecations of existing referral questions

* CLDC-4151: Add new cols to lettings log model

* CLDC-4151: Add new referrals questions

* CLDC-4151: Remove referral value check

* CLDC-4151: Add new fields to bulk upload

use new fields as presented in bulk upload

* CLDC-4151: Update tests

also add bulk upload file to test with

* CLDC-4151: Ignore tests failing for later tickets

* fixup! CLDC-4151: Add new referrals questions

start q nums from 2026

* CLDC-4151: Add model tests for new questions

* fixup! CLDC-4151: Add new fields to bulk upload

export old_visible_id

set MAX_COLUMNS correctly

check .prp? for prp cols

* fixup! CLDC-4151: Update tests

clarify tests that may update

* fixup! CLDC-4151: Add new fields to bulk upload

handle the old_visible_id not existing

use override org ID only for the output owning ID. it's only passed as eg ORG1

* CLDC-4151: Add new questions to log factory

* fixup! CLDC-4151: Add new fields to bulk upload

leave field_131 validations till later

* CLDC-4188: Add LA flow

splits the referral_register question and pages into two, as its not easy to have the answers be dependent

if the owning organisation changes type, reset the referral register question. the other questions do not need to be reset as they are no longer routed to

* CLDC-4188: Infer referral_register for renewals

needs a new dependencies array for 2026

this handles inferring as well as clearing inferred answers if the prior answer changes

* CLDC-4188: Add validation between prevten and referral_register

block two other validations from previous years

* CLDC-4188: Update tests

* CLDC-4188: Ignore tests failing for future tickets

* CLDC-4188: Update existing tests

needed as should_reset_referral_register? calls a .find()

* fixup! CLDC-4188: Add validation between prevten and referral_register

use .prp?

improve grammar

* fixup! CLDC-4188: Infer referral_register for renewals

extract dependencies to common list

* fixup! CLDC-4188: Update tests

use before and context blocks better

* fixup! CLDC-4188: Update tests

lint

* fixup! CLDC-4188: Update tests

remove unneeded referral_type set

* CLDC-4189: Add PRP flow

* CLDC-4189: Update validation between prevten and referral_register

* CLDC-4189: Add tests

* fixup! CLDC-4189: Add PRP flow

fix typo

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>

* fixup! CLDC-4189: Add tests

fix typo

* fixup! CLDC-4189: Add tests

fix missing cases in page specs

use a loop and before blocks for household validation tests

* CLDC-4189: Ensure log is not classed as generan needs if prevten isnt answered

* fixup! CLDC-4189: Add tests

add cases for other internal transfer flow

* CLDC-4190: Invalidate all referral fields if any are wrong

* CLDC-4190: Remove other validations on referral fields

* CLDC-4190: Ignore referral validation if BU is renewal

* CLDC-4190: Add tests

* fixup! CLDC-4190: Invalidate all referral fields if any are wrong

add punctuation to comment

name validation fields better

* fixup! CLDC-4190: Add tests

make test names clearer

* CLDC-4190: Final field fixes

---------

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>

* CLDC-4191: Q84 Referral CSV and XML export (#3157)

* CLDC-4151: Note deprecations of existing referral questions

* CLDC-4151: Add new cols to lettings log model

* CLDC-4151: Add new referrals questions

* CLDC-4151: Remove referral value check

* CLDC-4151: Add new fields to bulk upload

use new fields as presented in bulk upload

* CLDC-4151: Update tests

also add bulk upload file to test with

* CLDC-4151: Ignore tests failing for later tickets

* fixup! CLDC-4151: Add new referrals questions

start q nums from 2026

* CLDC-4151: Add model tests for new questions

* fixup! CLDC-4151: Add new fields to bulk upload

export old_visible_id

set MAX_COLUMNS correctly

check .prp? for prp cols

* fixup! CLDC-4151: Update tests

clarify tests that may update

* fixup! CLDC-4151: Add new fields to bulk upload

handle the old_visible_id not existing

use override org ID only for the output owning ID. it's only passed as eg ORG1

* CLDC-4151: Add new questions to log factory

* fixup! CLDC-4151: Add new fields to bulk upload

leave field_131 validations till later

* CLDC-4188: Add LA flow

splits the referral_register question and pages into two, as its not easy to have the answers be dependent

if the owning organisation changes type, reset the referral register question. the other questions do not need to be reset as they are no longer routed to

* CLDC-4188: Infer referral_register for renewals

needs a new dependencies array for 2026

this handles inferring as well as clearing inferred answers if the prior answer changes

* CLDC-4188: Add validation between prevten and referral_register

block two other validations from previous years

* CLDC-4188: Update tests

* CLDC-4188: Ignore tests failing for future tickets

* CLDC-4188: Update existing tests

needed as should_reset_referral_register? calls a .find()

* fixup! CLDC-4188: Add validation between prevten and referral_register

use .prp?

improve grammar

* fixup! CLDC-4188: Infer referral_register for renewals

extract dependencies to common list

* fixup! CLDC-4188: Update tests

use before and context blocks better

* fixup! CLDC-4188: Update tests

lint

* fixup! CLDC-4188: Update tests

remove unneeded referral_type set

* CLDC-4189: Add PRP flow

* CLDC-4189: Update validation between prevten and referral_register

* CLDC-4189: Add tests

* fixup! CLDC-4189: Add PRP flow

fix typo

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>

* fixup! CLDC-4189: Add tests

fix typo

* fixup! CLDC-4189: Add tests

fix missing cases in page specs

use a loop and before blocks for household validation tests

* CLDC-4189: Ensure log is not classed as generan needs if prevten isnt answered

* fixup! CLDC-4189: Add tests

add cases for other internal transfer flow

* CLDC-4190: Invalidate all referral fields if any are wrong

* CLDC-4190: Remove other validations on referral fields

* CLDC-4190: Ignore referral validation if BU is renewal

* CLDC-4190: Add tests

* fixup! CLDC-4190: Invalidate all referral fields if any are wrong

add punctuation to comment

name validation fields better

* fixup! CLDC-4190: Add tests

make test names clearer

* CLDC-4191: Update CSV export tests

the export happens by default, no changes needed here

* CLDC-4191: Add new referral fields to 2026 exports

remove old referral fields from 2026 exports

ensure new referral fields don't show in pre 2026 exports

* CLDC-4190: Final field fixes

---------

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>

---------

Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
pull/3180/head^2
Samuel Young 2 months ago committed by GitHub
parent
commit
7821742b5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 7
      app/helpers/bulk_upload/lettings_log_to_csv.rb
  2. 60
      app/models/derived_variables/lettings_log_variables.rb
  3. 2
      app/models/form/lettings/pages/referral_direct.rb
  4. 1
      app/models/form/lettings/pages/referral_general_needs.rb
  5. 1
      app/models/form/lettings/pages/referral_general_needs_prp.rb
  6. 2
      app/models/form/lettings/pages/referral_hsc.rb
  7. 2
      app/models/form/lettings/pages/referral_justice.rb
  8. 2
      app/models/form/lettings/pages/referral_la.rb
  9. 15
      app/models/form/lettings/pages/referral_noms_hr.rb
  10. 15
      app/models/form/lettings/pages/referral_noms_la_hr.rb
  11. 15
      app/models/form/lettings/pages/referral_org_directly_referred.rb
  12. 15
      app/models/form/lettings/pages/referral_org_nominated.rb
  13. 2
      app/models/form/lettings/pages/referral_prp.rb
  14. 15
      app/models/form/lettings/pages/referral_register_la.rb
  15. 15
      app/models/form/lettings/pages/referral_register_prp.rb
  16. 1
      app/models/form/lettings/pages/referral_supported_housing.rb
  17. 1
      app/models/form/lettings/pages/referral_supported_housing_prp.rb
  18. 2
      app/models/form/lettings/pages/referral_type.rb
  19. 1
      app/models/form/lettings/pages/referral_value_check.rb
  20. 2
      app/models/form/lettings/questions/referral_direct.rb
  21. 1
      app/models/form/lettings/questions/referral_general_needs.rb
  22. 1
      app/models/form/lettings/questions/referral_general_needs_prp.rb
  23. 2
      app/models/form/lettings/questions/referral_hsc.rb
  24. 2
      app/models/form/lettings/questions/referral_justice.rb
  25. 2
      app/models/form/lettings/questions/referral_la.rb
  26. 49
      app/models/form/lettings/questions/referral_noms.rb
  27. 85
      app/models/form/lettings/questions/referral_org.rb
  28. 2
      app/models/form/lettings/questions/referral_prp.rb
  29. 56
      app/models/form/lettings/questions/referral_register.rb
  30. 1
      app/models/form/lettings/questions/referral_supported_housing.rb
  31. 1
      app/models/form/lettings/questions/referral_supported_housing_prp.rb
  32. 2
      app/models/form/lettings/questions/referral_type.rb
  33. 14
      app/models/form/lettings/subsections/household_situation.rb
  34. 7
      app/models/form/question.rb
  35. 43
      app/models/lettings_log.rb
  36. 1
      app/models/organisation.rb
  37. 11
      app/models/validations/household_validations.rb
  38. 4
      app/services/bulk_upload/lettings/year2026/csv_parser.rb
  39. 131
      app/services/bulk_upload/lettings/year2026/row_parser.rb
  40. 9
      app/services/exports/lettings_log_export_constants.rb
  41. 24
      config/locales/forms/2026/lettings/household_situation.en.yml
  42. 9
      config/locales/forms/2026/lettings/soft_validations.en.yml
  43. 3
      config/locales/validations/lettings/2026/bulk_upload.en.yml
  44. 4
      config/locales/validations/lettings/household.en.yml
  45. 9
      db/migrate/20260123150201_add2026_referral_fields.rb
  46. 3
      db/schema.rb
  47. 3
      spec/factories/lettings_log.rb
  48. 4
      spec/fixtures/exports/general_needs_log_26_27.xml
  49. 18
      spec/fixtures/files/2026_27_lettings_bulk_upload.csv
  50. 6
      spec/fixtures/files/lettings_log_csv_export_codes_26.csv
  51. 6
      spec/fixtures/files/lettings_log_csv_export_labels_26.csv
  52. 6
      spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv
  53. 6
      spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv
  54. 3
      spec/fixtures/variable_definitions/lettings_download_26_27.csv
  55. 2
      spec/lib/tasks/log_variable_definitions_spec.rb
  56. 79
      spec/models/form/lettings/pages/referral_noms_hr_spec.rb
  57. 79
      spec/models/form/lettings/pages/referral_noms_la_hr_spec.rb
  58. 79
      spec/models/form/lettings/pages/referral_org_directly_referred_spec.rb
  59. 79
      spec/models/form/lettings/pages/referral_org_nominated_spec.rb
  60. 78
      spec/models/form/lettings/pages/referral_register_la_spec.rb
  61. 78
      spec/models/form/lettings/pages/referral_register_prp_spec.rb
  62. 83
      spec/models/form/lettings/questions/referral_noms_spec.rb
  63. 119
      spec/models/form/lettings/questions/referral_org_spec.rb
  64. 104
      spec/models/form/lettings/questions/referral_register_spec.rb
  65. 37
      spec/models/form/lettings/subsections/household_situation_spec.rb
  66. 204
      spec/models/validations/household_validations_spec.rb
  67. 8
      spec/services/bulk_upload/lettings/validator_spec.rb
  68. 6
      spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb
  69. 249
      spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb
  70. 4
      spec/services/csv/lettings_log_csv_service_spec.rb
  71. 20
      spec/services/merge/merge_organisations_service_spec.rb

7
app/helpers/bulk_upload/lettings_log_to_csv.rb

@ -224,7 +224,7 @@ class BulkUpload::LettingsLogToCsv
chr,
cap,
accessible_register,
log.referral,
log.owning_organisation.la? ? log.referral_register : nil,
net_income_known,
log.incfreq,
log.earnings,
@ -263,7 +263,10 @@ class BulkUpload::LettingsLogToCsv
log.gender_same_as_sex7, # 150
log.gender_description7,
log.gender_same_as_sex8,
log.gender_description8, # 153
log.gender_description8,
log.owning_organisation.prp? ? log.referral_register : nil,
log.referral_noms,
log.referral_org, # 156
]
end

60
app/models/derived_variables/lettings_log_variables.rb

@ -33,7 +33,7 @@ module DerivedVariables::LettingsLogVariables
def set_derived_fields!
clear_inapplicable_derived_values!
set_encoded_derived_values!(DEPENDENCIES)
set_encoded_derived_values!(dependencies)
if rsnvac.present?
self.newprop = has_first_let_vacancy_reason? ? 1 : 2
@ -184,20 +184,15 @@ module DerivedVariables::LettingsLogVariables
private
DEPENDENCIES = [
{
conditions: {
renewal: 1,
},
derived_values: {
referral: 1,
referral_type: 3,
waityear: 2,
offered: 0,
rsnvac: 14,
first_time_property_let_as_social_housing: 0,
},
},
def dependencies
if form.start_year_2026_or_later?
DEPENDENCIES_2026
else
DEPENDENCIES_2025_2024
end
end
COMMON_DEPENDENCIES = [
{
conditions: {
net_income_known: 2,
@ -224,8 +219,41 @@ private
},
].freeze
DEPENDENCIES_2026 = [
{
conditions: {
renewal: 1,
},
derived_values: {
referral_register: 1,
waityear: 2,
offered: 0,
rsnvac: 14,
first_time_property_let_as_social_housing: 0,
},
},
*COMMON_DEPENDENCIES,
].freeze
DEPENDENCIES_2025_2024 = [
{
conditions: {
renewal: 1,
},
derived_values: {
referral: 1,
referral_type: 3,
waityear: 2,
offered: 0,
rsnvac: 14,
first_time_property_let_as_social_housing: 0,
},
},
*COMMON_DEPENDENCIES,
].freeze
def clear_inapplicable_derived_values!
reset_invalidated_derived_values!(DEPENDENCIES)
reset_invalidated_derived_values!(dependencies)
if (startdate_changed? || renewal_changed?) && (renewal_was == 1 && startdate_was&.between?(Time.zone.local(2021, 4, 1), Time.zone.local(2022, 3, 31)))
self.underoccupation_benefitcap = nil
end

2
app/models/form/lettings/pages/referral_direct.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralDirect < ::Form::Page
def initialize(id, hsh, subsection)
super

1
app/models/form/lettings/pages/referral_general_needs.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Pages::ReferralGeneralNeeds < ::Form::Page
def initialize(id, hsh, subsection)
super

1
app/models/form/lettings/pages/referral_general_needs_prp.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Pages::ReferralGeneralNeedsPrp < ::Form::Page
def initialize(id, hsh, subsection)
super

2
app/models/form/lettings/pages/referral_hsc.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralHsc < ::Form::Page
def initialize(id, hsh, subsection)
super

2
app/models/form/lettings/pages/referral_justice.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralJustice < ::Form::Page
def initialize(id, hsh, subsection)
super

2
app/models/form/lettings/pages/referral_la.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralLa < ::Form::Page
def initialize(id, hsh, subsection)
super

15
app/models/form/lettings/pages/referral_noms_hr.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralNomsHr < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_noms_hr"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralNoms.new(nil, nil, self, 7)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.prp? && !log.is_renewal? && log.referral_is_from_housing_register?
end
end

15
app/models/form/lettings/pages/referral_noms_la_hr.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralNomsLaHr < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_noms_la_hr"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralNoms.new(nil, nil, self, 6)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.prp? && !log.is_renewal? && log.referral_is_from_local_authority_housing_register?
end
end

15
app/models/form/lettings/pages/referral_org_directly_referred.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralOrgDirectlyReferred < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_org_directly_referred"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralOrg.new(nil, nil, self, 7)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.prp? && !log.is_renewal? && log.referral_is_directly_referred?
end
end

15
app/models/form/lettings/pages/referral_org_nominated.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralOrgNominated < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_org_nominated"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralOrg.new(nil, nil, self, 1)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.prp? && !log.is_renewal? && log.referral_is_nominated_by_local_authority?
end
end

2
app/models/form/lettings/pages/referral_prp.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralPrp < ::Form::Page
def initialize(id, hsh, subsection)
super

15
app/models/form/lettings/pages/referral_register_la.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralRegisterLa < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_register_la"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralRegister.new(nil, nil, self, :la)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.la? && !log.is_renewal?
end
end

15
app/models/form/lettings/pages/referral_register_prp.rb

@ -0,0 +1,15 @@
# added in 2026
class Form::Lettings::Pages::ReferralRegisterPrp < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "referral_register_prp"
end
def questions
@questions ||= [Form::Lettings::Questions::ReferralRegister.new(nil, nil, self, :prp)]
end
def routed_to?(log, _current_user)
log.owning_organisation&.prp? && !log.is_renewal?
end
end

1
app/models/form/lettings/pages/referral_supported_housing.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Pages::ReferralSupportedHousing < ::Form::Page
def initialize(id, hsh, subsection)
super

1
app/models/form/lettings/pages/referral_supported_housing_prp.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Pages::ReferralSupportedHousingPrp < ::Form::Page
def initialize(id, hsh, subsection)
super

2
app/models/form/lettings/pages/referral_type.rb

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Pages::ReferralType < ::Form::Page
def initialize(id, hsh, subsection)
super

1
app/models/form/lettings/pages/referral_value_check.rb

@ -1,3 +1,4 @@
# removed in 2026
class Form::Lettings::Pages::ReferralValueCheck < ::Form::Page
def initialize(id, hsh, subsection)
super

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralDirect < ::Form::Question
def initialize(id, hsh, page)
super

1
app/models/form/lettings/questions/referral_general_needs.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Questions::ReferralGeneralNeeds < ::Form::Question
def initialize(id, hsh, page)
super

1
app/models/form/lettings/questions/referral_general_needs_prp.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Questions::ReferralGeneralNeedsPrp < ::Form::Question
def initialize(id, hsh, page)
super

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralHsc < ::Form::Question
def initialize(id, hsh, page)
super

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralJustice < ::Form::Question
def initialize(id, hsh, page)
super

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralLa < ::Form::Question
def initialize(id, hsh, page)
super

49
app/models/form/lettings/questions/referral_noms.rb

@ -0,0 +1,49 @@
# added in 2026
class Form::Lettings::Questions::ReferralNoms < ::Form::Question
def initialize(id, hsh, page, referral_register)
super(id, hsh, page)
@id = "referral_noms"
@copy_key = "lettings.household_situation.referral.noms"
@type = "radio"
@check_answers_card_number = 0
@question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@referral_register = referral_register
end
def answer_options
case @referral_register
when 6
{
"1" => {
"value" => "Nominated by a local authority to a PRP",
},
"2" => {
"value" => "Supported housing only - referred by a local authority to a PRP",
},
"3" => {
"value" => "Internal transfer from another property owned by the same PRP landlord - for existing social tenants only",
},
"4" => {
"value" => "Other",
},
}.freeze
when 7
{
"5" => {
"value" => "Internal transfer from another property owned by the same PRP landlord - for existing social tenants only",
},
"6" => {
"value" => " A different PRP landlord - for existing social tenants only",
},
"7" => {
"value" => "Directly referred by a third party",
},
"8" => {
"value" => "Other",
},
}.freeze
end
end
QUESTION_NUMBER_FROM_YEAR = { 2026 => 92 }.freeze
end

85
app/models/form/lettings/questions/referral_org.rb

@ -0,0 +1,85 @@
# added in 2026
class Form::Lettings::Questions::ReferralOrg < ::Form::Question
def initialize(id, hsh, page, referral_noms)
super(id, hsh, page)
@id = "referral_org"
@copy_key = "lettings.household_situation.referral.org"
@type = "radio"
@check_answers_card_number = 0
@question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@referral_noms = referral_noms
end
def answer_options
case @referral_noms
when 1
{
"1" => {
"value" => "Referred to LA by health service",
},
"2" => {
"value" => "Referred to LA by community learning disability team",
},
"3" => {
"value" => "Referred to LA by community mental health team",
},
"4" => {
"value" => "Referred to LA by adult social services",
},
"5" => {
"value" => "Referred to LA by children's social care",
},
"6" => {
"value" => "Referred to LA by police, probation, prison or youth offending team following a custodial sentence",
},
"7" => {
"value" => "Referred to LA by police, probation, prison or youth offending team without a custodial sentence",
},
"8" => {
"value" => "Referred to LA by a voluntary agency",
},
"9" => {
"value" => "Other referral",
},
"10" => {
"value" => "Don't know",
},
}.freeze
when 7
{
"11" => {
"value" => "Health service",
},
"12" => {
"value" => "Community learning disability team",
},
"13" => {
"value" => "Community mental health team",
},
"14" => {
"value" => "Adult social services",
},
"15" => {
"value" => "Children's social care",
},
"16" => {
"value" => "Police, probation, prison or youth offending team following a custodial sentence",
},
"17" => {
"value" => "Police, probation, prison or youth offending team without a custodial sentence",
},
"18" => {
"value" => "Voluntary agency",
},
"19" => {
"value" => "Other third party",
},
"20" => {
"value" => "Don't know",
},
}.freeze
end
end
QUESTION_NUMBER_FROM_YEAR = { 2026 => 92 }.freeze
end

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralPrp < ::Form::Question
def initialize(id, hsh, page)
super

56
app/models/form/lettings/questions/referral_register.rb

@ -0,0 +1,56 @@
# added in 2026
class Form::Lettings::Questions::ReferralRegister < ::Form::Question
def initialize(id, hsh, page, provider_type)
super(id, hsh, page)
@id = "referral_register"
@copy_key = "lettings.household_situation.referral.register"
@type = "radio"
@check_answers_card_number = 0
@provider_type = provider_type
@question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@question_number += 1 if @provider_type == :prp
end
def answer_options
if @provider_type == :la
{
"1" => {
"value" => "Renewal to the same tenant in the same property",
},
"2" => {
"value" => "Internal transfer from another property owned by the same local authority - for existing social tenants only",
},
"3" => {
"value" => "From a housing register (waiting list)",
},
"4" => {
"value" => "Tenant applied directly (not via a nomination or housing register)",
},
}.freeze
else
{
"5" => {
"value" => "Renewal to the same tenant in the same property",
},
"6" => {
"value" => "From a local authority housing register (waiting list) or a register with local authority involvement",
},
"7" => {
"value" => "From a housing register (waiting list) with no local authority involvement",
},
"8" => {
"value" => "Tenant applied directly (not via a nomination or waiting list)",
},
"9" => {
"value" => "Don't know",
},
}.freeze
end
end
def derived?(log)
log.is_renewal?
end
QUESTION_NUMBER_FROM_YEAR = { 2026 => 91 }.freeze
end

1
app/models/form/lettings/questions/referral_supported_housing.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Questions::ReferralSupportedHousing < ::Form::Question
def initialize(id, hsh, page)
super

1
app/models/form/lettings/questions/referral_supported_housing_prp.rb

@ -1,3 +1,4 @@
# removed in 2025
class Form::Lettings::Questions::ReferralSupportedHousingPrp < ::Form::Question
def initialize(id, hsh, page)
super

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

@ -1,3 +1,5 @@
# added in 2025
# removed in 2026
class Form::Lettings::Questions::ReferralType < ::Form::Question
def initialize(id, hsh, page)
super

14
app/models/form/lettings/subsections/household_situation.rb

@ -22,12 +22,20 @@ class Form::Lettings::Subsections::HouseholdSituation < ::Form::Subsection
Form::Lettings::Pages::ReasonablePreferenceReason.new(nil, nil, self),
Form::Lettings::Pages::AllocationSystem.new("allocation_system", nil, self),
referral_questions,
Form::Lettings::Pages::ReferralValueCheck.new(nil, nil, self),
].flatten.compact
end
def referral_questions
if form.start_year_2025_or_later?
if form.start_year_2026_or_later?
[
Form::Lettings::Pages::ReferralRegisterLa.new(nil, nil, self),
Form::Lettings::Pages::ReferralRegisterPrp.new(nil, nil, self),
Form::Lettings::Pages::ReferralNomsLaHr.new(nil, nil, self),
Form::Lettings::Pages::ReferralNomsHr.new(nil, nil, self),
Form::Lettings::Pages::ReferralOrgNominated.new(nil, nil, self),
Form::Lettings::Pages::ReferralOrgDirectlyReferred.new(nil, nil, self),
]
elsif form.start_year_2025_or_later?
[
Form::Lettings::Pages::ReferralType.new(nil, nil, self),
Form::Lettings::Pages::ReferralDirect.new(nil, nil, self),
@ -35,6 +43,7 @@ class Form::Lettings::Subsections::HouseholdSituation < ::Form::Subsection
Form::Lettings::Pages::ReferralPrp.new(nil, nil, self),
Form::Lettings::Pages::ReferralHsc.new(nil, nil, self),
Form::Lettings::Pages::ReferralJustice.new(nil, nil, self),
Form::Lettings::Pages::ReferralValueCheck.new(nil, nil, self),
]
else
[
@ -42,6 +51,7 @@ class Form::Lettings::Subsections::HouseholdSituation < ::Form::Subsection
Form::Lettings::Pages::ReferralGeneralNeedsPrp.new(nil, nil, self),
Form::Lettings::Pages::ReferralSupportedHousing.new(nil, nil, self),
Form::Lettings::Pages::ReferralSupportedHousingPrp.new(nil, nil, self),
Form::Lettings::Pages::ReferralValueCheck.new(nil, nil, self),
]
end
end

7
app/models/form/question.rb

@ -362,6 +362,13 @@ private
inferred_answer["value"] if inferred_answer.present?
end
# every year currently visible should be specified.
# however, form_handler.rb will still initialise the next form even if its not visible.
# so we have a fallback to the latest year for these future years so all question have a question number.
def get_question_number_from_hash(hash)
hash[form.start_date.year] || hash[hash.keys.max]
end
RADIO_YES_VALUE = {
renewal: [1],
postcode_known: [1],

43
app/models/lettings_log.rb

@ -35,6 +35,7 @@ class LettingsLog < Log
before_validation :set_derived_fields!
before_validation :process_uprn_change!, if: :should_process_uprn_change?
before_validation :process_address_change!, if: :should_process_address_change?
before_validation :reset_referral_register!, if: :should_reset_referral_register?
belongs_to :scheme, optional: true
belongs_to :location, optional: true
@ -376,8 +377,12 @@ class LettingsLog < Log
end
def is_internal_transfer?
# 1: Internal Transfer
referral == 1
if form.start_year_2026_or_later?
referral_register == 2 || (referral_register == 6 && referral_noms == 3) || (referral_register == 7 && referral_noms == 5)
else
# 1: Internal Transfer
referral == 1
end
end
def is_from_prp_only_housing_register_or_waiting_list?
@ -544,6 +549,12 @@ class LettingsLog < Log
[30, 31].any?(prevten)
end
def is_prevten_general_needs?
return false unless prevten
![30, 31, 32, 33, 35, 38, 40, 6].include?(prevten)
end
def owning_organisation_name
owning_organisation&.name
end
@ -776,6 +787,22 @@ class LettingsLog < Log
form.start_year_2026_or_later? || !is_supported_housing?
end
def referral_is_from_local_authority_housing_register?
referral_register == 6
end
def referral_is_from_housing_register?
referral_register == 7
end
def referral_is_nominated_by_local_authority?
referral_is_from_local_authority_housing_register? && referral_noms == 1
end
def referral_is_directly_referred?
referral_is_from_housing_register? && referral_noms == 7
end
private
def reset_invalid_unresolved_log_fields!
@ -947,4 +974,16 @@ private
uprn_selection_changed? || startdate_changed?
end
end
def reset_referral_register!
self.referral_register = nil
end
def should_reset_referral_register?
return unless owning_organisation_id_changed? && owning_organisation_id && owning_organisation_id_was
old_owning_organisation = Organisation.find(owning_organisation_id_was)
old_owning_organisation.provider_type != owning_organisation.provider_type
end
end

1
app/models/organisation.rb

@ -74,6 +74,7 @@ class Organisation < ApplicationRecord
before_save :clear_group_member_fields_if_not_group_member
alias_method :la?, :LA?
alias_method :prp?, :PRP?
validates :name, presence: { message: I18n.t("validations.organisation.name_missing") }
validates :name, uniqueness: { case_sensitive: false, message: I18n.t("validations.organisation.name_not_unique") }

11
app/models/validations/household_validations.rb

@ -162,7 +162,7 @@ module Validations::HouseholdValidations
# 27 Owner occupation (low-cost home ownership)
# 28 Living with Friends or Family
# 29 Prison / Approved Probation Hostel
if record.is_internal_transfer? && [3, 4, 7, 10, 13, 14, 19, 23, 24, 25, 26, 27, 28, 29].include?(record.prevten)
if record.is_internal_transfer? && [3, 4, 7, 10, 13, 14, 19, 23, 24, 25, 26, 27, 28, 29].include?(record.prevten) && !record.form.start_year_2026_or_later?
label = record.form.get_question("prevten", record).present? ? record.form.get_question("prevten", record).label_from_value(record.prevten) : ""
record.errors.add :prevten, :internal_transfer_non_social_housing, message: I18n.t("validations.lettings.household.prevten.internal_transfer", prevten: label)
record.errors.add :referral, :internal_transfer_non_social_housing, message: I18n.t("validations.lettings.household.referral.prevten_invalid", prevten: label)
@ -172,7 +172,14 @@ module Validations::HouseholdValidations
def validate_referral(record)
return unless record.owning_organisation
if record.is_internal_transfer? && record.owning_organisation.provider_type == "PRP" && record.is_prevten_la_general_needs?
if record.form.start_year_2026_or_later?
if record.is_internal_transfer? && record.is_prevten_general_needs?
label = record.form.get_question("prevten", record).present? ? record.form.get_question("prevten", record).label_from_value(record.prevten) : ""
record.errors.add :prevten, message: I18n.t("validations.lettings.household.prevten.general_needs.internal_transfer", prevten: label)
record.errors.add :referral_register, message: I18n.t("validations.lettings.household.referral.general_needs.internal_transfer", prevten: label)
record.errors.add :referral_noms, message: I18n.t("validations.lettings.household.referral.general_needs.internal_transfer", prevten: label)
end
elsif record.is_internal_transfer? && record.owning_organisation.prp? && record.is_prevten_la_general_needs?
record.errors.add :prevten, :internal_transfer_fixed_or_lifetime, message: I18n.t("validations.lettings.household.prevten.la_general_needs.internal_transfer")
record.errors.add :referral, :internal_transfer_fixed_or_lifetime, message: I18n.t("validations.lettings.household.referral.la_general_needs.internal_transfer")
end

4
app/services/bulk_upload/lettings/year2026/csv_parser.rb

@ -4,7 +4,7 @@ class BulkUpload::Lettings::Year2026::CsvParser
include CollectionTimeHelper
# TODO: CLDC-4162: Update when 2026 format is known
FIELDS = 153
FIELDS = 156
FORM_YEAR = 2026
attr_reader :path
@ -27,7 +27,7 @@ class BulkUpload::Lettings::Year2026::CsvParser
def cols
# TODO: CLDC-4162: Update when 2026 format is known
@cols ||= ("A".."EX").to_a
@cols ||= ("A".."FA").to_a
end
def row_parsers

131
app/services/bulk_upload/lettings/year2026/row_parser.rb

@ -120,7 +120,7 @@ class BulkUpload::Lettings::Year2026::RowParser
field_113: "Was the letting made under the Common Allocation Policy (CAP)?",
field_114: "Was the letting made under the Common Housing Register (CHR)?",
field_115: "Was the letting made under the Accessible Register?",
field_116: "What was the source of referral for this letting?",
field_116: "What was the source of referral for this letting? - LA properties",
field_117: "Do you know the household’s combined total income after tax?",
field_118: "How often does the household receive income?",
field_119: "How much income does the household have in total?",
@ -159,6 +159,10 @@ class BulkUpload::Lettings::Year2026::RowParser
field_151: "If 'No', enter person 7's gender identity",
field_152: "Is the gender person 8 identifies with the same as their sex registered at birth?",
field_153: "If 'No', enter person 8's gender identity",
field_154: "What was the source of referral for this letting? - PRP properties part 1",
field_155: "What was the source of referral for this letting? - PRP properties part 2",
field_156: "What was the source of referral for this letting? - PRP properties part 3",
}.freeze
RENT_TYPE_BU_MAPPING = {
@ -333,6 +337,10 @@ class BulkUpload::Lettings::Year2026::RowParser
attribute :field_152, :integer
attribute :field_153, :string
attribute :field_154, :integer
attribute :field_155, :integer
attribute :field_156, :integer
validate :validate_valid_radio_option, on: :before_log
validates :field_11,
@ -458,8 +466,6 @@ class BulkUpload::Lettings::Year2026::RowParser
validate :validate_needs_type_present, on: :after_log
validate :validate_data_types, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
validate :validate_la_with_local_housing_referral, on: :after_log
validate :validate_cannot_be_la_referral_if_general_needs_and_la, on: :after_log
validate :validate_leaving_reason_for_renewal, on: :after_log
validate :validate_only_one_housing_needs_type, on: :after_log
validate :validate_no_disabled_needs_conjunction, on: :after_log
@ -470,6 +476,7 @@ class BulkUpload::Lettings::Year2026::RowParser
validate :validate_reasonable_preference_dont_know, on: :after_log
validate :validate_condition_effects, on: :after_log
validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? }
validate :validate_referral_fields, on: :after_log
validate :validate_owning_org_data_given, on: :after_log
validate :validate_owning_org_exists, on: :after_log
@ -730,7 +737,7 @@ private
end
def validate_prevten_value_when_renewal
return unless field_7 == 1
return unless renewal?
return if field_100.blank? || [6, 30, 31, 32, 33, 34, 35, 38].include?(field_100)
errors.add(:field_100, I18n.t("#{ERROR_BASE_KEY}.prevten.invalid"))
@ -837,7 +844,7 @@ private
end
def validate_leaving_reason_for_renewal
if field_7 == 1 && ![50, 51, 52, 53].include?(field_98)
if renewal? && ![50, 51, 52, 53].include?(field_98)
errors.add(:field_98, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed"))
end
end
@ -850,16 +857,8 @@ private
field_4 == 2
end
def validate_cannot_be_la_referral_if_general_needs_and_la
if field_116 == 4 && general_needs? && owning_organisation && owning_organisation.la?
errors.add :field_116, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la")
end
end
def validate_la_with_local_housing_referral
if field_116 == 3 && owning_organisation && owning_organisation.la?
errors.add(:field_116, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la"))
end
def renewal?
field_7 == 1
end
def validate_relevant_collection_window
@ -1042,6 +1041,57 @@ private
end
end
def field_referral_register_la_valid?
if owning_organisation&.la?
[1, 2, 3, 4].include?(field_116)
else
field_116.blank?
end
end
def field_referral_register_prp_valid?
if owning_organisation&.prp?
[5, 6, 7, 8, 9].include?(field_154)
else
field_154.blank?
end
end
def field_referral_noms_valid?
case field_154
when 6
[1, 2, 3, 4].include?(field_155)
when 7
[5, 6, 7, 8].include?(field_155)
else
field_155.blank?
end
end
def field_referral_org_valid?
case field_155
when 1
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].include?(field_156)
when 7
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20].include?(field_156)
else
field_156.blank?
end
end
def referral_fields_valid?
field_referral_register_la_valid? && field_referral_register_prp_valid? && field_referral_noms_valid? && field_referral_org_valid?
end
def validate_referral_fields
return if renewal?
return if referral_fields_valid?
%i[field_116 field_154 field_155 field_156].each do |field|
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.referral.invalid_option"))
end
end
def field_mapping_for_errors
{
lettype: [:field_11],
@ -1154,8 +1204,9 @@ private
accessible_register: %i[field_115],
letting_allocation: %i[field_112 field_113 field_114 field_115],
referral_type: %i[field_116],
referral: %i[field_116],
referral_register: %i[field_116 field_154],
referral_noms: %i[field_155],
referral_org: %i[field_156],
net_income_known: %i[field_117],
incfreq: %i[field_118],
@ -1349,8 +1400,9 @@ private
attributes["accessible_register"] = accessible_register
attributes["letting_allocation_unknown"] = letting_allocation_unknown
attributes["referral_type"] = referral_type
attributes["referral"] = field_116
attributes["referral_register"] = referral_register
attributes["referral_noms"] = referral_noms
attributes["referral_org"] = referral_org
attributes["net_income_known"] = net_income_known
attributes["earnings"] = earnings
@ -1768,21 +1820,36 @@ private
false
end
def referral_type
mapping = {
1 => [20, 2, 8],
2 => [21, 3, 4, 22],
3 => [1, 10, 23],
4 => [15, 9, 14, 24, 17],
5 => [18, 19],
6 => [7],
7 => [16],
}
def referral_register
return unless owning_organisation
# by default CORE will ingest all these fields and nil questions that aren't asked.
# here, we specifically want the log to be invalid if any of the referral fields are wrong.
# BU will only consider a log invalid if its incomplete.
# so, nil these fields if any are invalid.
return unless referral_fields_valid?
if owning_organisation.la?
field_116
else
field_154
end
end
def referral_noms
return unless owning_organisation
return unless referral_fields_valid?
mapping.each do |key, values|
return key if values.include?(field_116)
if owning_organisation.prp?
field_155
end
end
0
def referral_org
return unless owning_organisation
return unless referral_fields_valid?
if owning_organisation.prp?
field_156
end
end
end

9
app/services/exports/lettings_log_export_constants.rb

@ -77,7 +77,6 @@ module Exports::LettingsLogExportConstants
"reason",
"reasonother",
"reasonpref",
"referral",
"refused",
"reghome",
"renttype",
@ -158,6 +157,7 @@ module Exports::LettingsLogExportConstants
"chcharge",
"national",
"offered",
"referral",
]
YEAR_2022_EXPORT_FIELDS = Set[
@ -165,6 +165,7 @@ module Exports::LettingsLogExportConstants
"chcharge",
"national",
"offered",
"referral",
]
YEAR_2023_EXPORT_FIELDS = Set[
@ -172,6 +173,7 @@ module Exports::LettingsLogExportConstants
"chcharge",
"national",
"offered",
"referral",
]
YEAR_2024_EXPORT_FIELDS = Set[
@ -192,6 +194,7 @@ module Exports::LettingsLogExportConstants
"pscharge_value_check",
"supcharg_value_check",
"carehome_charges_value_check",
"referral",
]
YEAR_2025_EXPORT_FIELDS = Set[
@ -210,6 +213,7 @@ module Exports::LettingsLogExportConstants
"scharge_value_check",
"pscharge_value_check",
"supcharg_value_check",
"referral",
]
YEAR_2026_EXPORT_FIELDS = Set[
@ -227,6 +231,9 @@ module Exports::LettingsLogExportConstants
"scharge_value_check",
"pscharge_value_check",
"supcharg_value_check",
"referral_register",
"referral_noms",
"referral_org",
]
(1..8).each do |index|

24
config/locales/forms/2026/lettings/household_situation.en.yml

@ -112,37 +112,19 @@ en:
question_text: "How was this letting allocated?"
referral:
type:
register:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"
hint_text: ""
question_text: "What was the source of referral for this letting?"
direct:
noms:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"
hint_text: ""
question_text: "What was the source of referral for this letting?"
la:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"
hint_text: ""
question_text: "What was the source of referral for this letting?"
prp:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"
hint_text: ""
question_text: "What was the source of referral for this letting?"
hsc:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"
hint_text: ""
question_text: "What was the source of referral for this letting?"
justice:
org:
page_header: ""
check_answer_label: "Source of referral for letting"
check_answer_prompt: "Select source of referral"

9
config/locales/forms/2026/lettings/soft_validations.en.yml

@ -57,15 +57,6 @@ en:
title_text: "You told us that the tenant’s main reason for leaving their last settled home was %{reasonother}."
informative_text: "The reason you have entered looks very similar to one of the existing response categories. Please check the categories and select the appropriate one. If the existing categories are not suitable, please confirm here to move onto the next question."
referral_value_check:
page_header: ""
check_answer_label: "Referral confirmation"
check_answer_prompt: "Confirm referral type"
hint_text: ""
question_text: "Are you sure?"
title_text: "Are you sure?"
informative_text: "This is a general needs log, and this referral type is for supported housing."
net_income_value_check:
page_header: ""
check_answer_label: "Net income confirmation"

3
config/locales/validations/lettings/2026/bulk_upload.en.yml

@ -40,8 +40,7 @@ en:
reason:
renewal_reason_needed: "The reason for leaving must be \"End of social or private sector tenancy - no fault\", \"End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)\", \"End of social or private sector tenancy - evicted due to rent arrears\" or \"End of social or private sector tenancy - evicted for any other reason\"."
referral:
general_needs_prp_referred_by_la: "The source of the referral cannot be referred by local authority housing department for a general needs log."
nominated_by_local_ha_but_la: "The source of the referral cannot be Nominated by local housing authority as your organisation is a local authority."
invalid_option: "Your answers for each part of \"What is the source of referral for this letting?\" are incompatible with each other. Use the bulk upload specification or paper form to see which combinations are valid (available from ‘Collection resources’ on the homepage)."
scheme:
must_relate_to_org: "This scheme code does not belong to the owning organisation or managing organisation."
location:

4
config/locales/validations/lettings/household.en.yml

@ -98,8 +98,12 @@ en:
internal_transfer: "Answer cannot be %{prevten} as this tenancy is an internal transfer."
la_general_needs:
internal_transfer: "Answer cannot be a fixed-term or lifetime local authority general needs tenancy as it’s an internal transfer and a private registered provider is on the tenancy agreement."
general_needs:
internal_transfer: "Answer cannot be %{prevten} as this tenancy is an internal transfer. Internal transfers are for existing social tenants only; your answer to where the household was immediately before this letting shows the tenant was not in the social sector immediately prior to this letting."
referral:
prevten_invalid: "Answer cannot be internal transfer as the household situation immediately before this letting was %{prevten}."
la_general_needs:
internal_transfer: "Answer cannot be internal transfer as it’s the same landlord on the tenancy agreement and the household had either a fixed-term or lifetime local authority general needs tenancy immediately before this letting."
general_needs:
internal_transfer: "Answer cannot be internal transfer as the household situation immediately before this letting was %{prevten}. Internal transfers are for existing social tenants only; your answer to where the household was immediately before this letting shows the tenant was not in the social sector immediately prior to this letting."

9
db/migrate/20260123150201_add2026_referral_fields.rb

@ -0,0 +1,9 @@
class Add2026ReferralFields < ActiveRecord::Migration[7.2]
def change
change_table :lettings_logs, bulk: true do |t|
t.integer :referral_register
t.integer :referral_noms
t.integer :referral_org
end
end
end

3
db/schema.rb

@ -400,6 +400,9 @@ ActiveRecord::Schema[7.2].define(version: 2026_02_04_100051) do
t.string "gender_description6"
t.string "gender_description7"
t.string "gender_description8"
t.integer "referral_register"
t.integer "referral_noms"
t.integer "referral_org"
t.index ["assigned_to_id"], name: "index_lettings_logs_on_assigned_to_id"
t.index ["bulk_upload_id"], name: "index_lettings_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_lettings_logs_on_created_by_id"

3
spec/factories/lettings_log.rb

@ -168,6 +168,9 @@ FactoryBot.define do
first_time_property_let_as_social_housing { 0 }
referral_type { 1 }
referral { 2 }
referral_register { 1 }
referral_noms { 1 }
referral_org { 1 }
uprn_known { 0 }
joint { 3 }
address_line1 { "Address line 1" }

4
spec/fixtures/exports/general_needs_log_26_27.xml vendored

@ -123,7 +123,9 @@
<totelder>0</totelder>
<totadult>2</totadult>
<nocharge/>
<referral>2</referral>
<referral_register>1</referral_register>
<referral_noms/>
<referral_org/>
<brent>200.0</brent>
<scharge>50.0</scharge>
<pscharge>40.0</pscharge>

18
spec/fixtures/files/2026_27_lettings_bulk_upload.csv vendored

@ -1,4 +1,4 @@
Section,Setting up this lettings log,,,,,,,,,,,,,,,Property information,,,,,,,,,,,,,,,,,,,,,Tenancy information,,,,,Household characteristics,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Household needs,,,,,,,,,,,,,,,,,,,,,Household situation,,,,,,,,,,,,,,,,,,,,,"Income, benefits and outgoings",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Section,Setting up this lettings log,,,,,,,,,,,,,,,Property information,,,,,,,,,,,,,,,,,,,,,Tenancy information,,,,,Household characteristics,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Household needs,,,,,,,,,,,,,,,,,,,,,Household situation,,,,,,,,,,,,,,,,,,,,,"Income, benefits and outgoings",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Question,Which organisation owns this property?,Which organisation manages this letting?,What is the CORE username of the account this letting log should be assigned to? ,What is the needs type?,What scheme does this letting belong to?,Which location is this letting for?,Is this letting a renewal of social housing to the same tenant in the same property?,What is the tenancy start date? - day DD,What is the tenancy start date? - month MM,What is the tenancy start date? - year YY,What is the rent type?,Which 'Other' type of Intermediate Rent is this letting?,What is the tenant code?,What is the property reference?,Has the tenant seen or been given access to the MHCLG privacy notice?,What is the reason for the property being vacant?,What type was the property most recently let as?,"If known, provide this property’s UPRN",Address Line 1,Address Line 2,Town or city,County,Part 1 of the property's postcode,Part 2 of the property's postcode,What is the property's local authority?,What type of unit is the property?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date? - day DD,What is the void date? - month MM,What is the void date? - year YY,What date were any major repairs completed on? - day DD,What date were any major repairs completed on? - month MM,What date were any major repairs completed on? - year YY,Is this property older people's housing?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,What is the lead tenant’s age?,Which of these best describes the lead tenant’s gender identity? ,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant’s nationality?,Which of these best describes the lead tenant’s working situation?,Is person 2 the partner of the lead tenant?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,Is person 3 the partner of the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,Is person 4 the partner of the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,Is person 5 the partner of the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,Is person 6 the partner of the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,Is person 7 the partner of the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,Is person 8 the partner of the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,"Disabled access needs
a) Fully wheelchair-accessible housing","Disabled access needs
@ -29,7 +29,7 @@ Common Allocations Policy (CAP)","How was this letting allocated?
Common Housing Register (CHR)","How was this letting allocated?
Accessible Housing Register",What was the source of referral for this letting?,Do you know the household's combined total income after tax?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",What do you expect the outstanding amount to be?,What was the lead tenant's sex at birth?,What was person 2's sex registered at birth?,What was person 3's sex registered at birth?,What was person 4's sex registered at birth?,What was person 5's sex registered at birth?,What was person 6's sex registered at birth?,What was person 7's sex registered at birth?,What was person 8's sex registered at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter lead tenant's gender identity",Is the gender the person 2 identifies with the same as their sex registered at birth?,"If 'No', enter person 2's gender identity",Is the gender the person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",Is the gender the person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",Is the gender the person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",Is the gender the person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity",Is the gender the person 7 identifies with the same as their sex registered at birth?,"If 'No', enter person 7's gender identity",Is the gender the person 8 identifies with the same as their sex registered at birth?,"If 'No', enter person 8's gender identity"
Accessible Housing Register",What was the source of referral for this letting? - LA properties,Do you know the household's combined total income after tax?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",What do you expect the outstanding amount to be?,What was the lead tenant's sex at birth?,What was person 2's sex registered at birth?,What was person 3's sex registered at birth?,What was person 4's sex registered at birth?,What was person 5's sex registered at birth?,What was person 6's sex registered at birth?,What was person 7's sex registered at birth?,What was person 8's sex registered at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter lead tenant's gender identity",Is the gender the person 2 identifies with the same as their sex registered at birth?,"If 'No', enter person 2's gender identity",Is the gender the person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",Is the gender the person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",Is the gender the person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",Is the gender the person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity",Is the gender the person 7 identifies with the same as their sex registered at birth?,"If 'No', enter person 7's gender identity",Is the gender the person 8 identifies with the same as their sex registered at birth?,"If 'No', enter person 8's gender identity",What was the source of referral for this letting? - PRP properties part 1,What was the source of referral for this letting? - PRP properties part 2,What was the source of referral for this letting? - PRP properties part 3
Additional info,"You can find the org ID on the CORE service under 'Stock owners' or, if your organisation is the stock owner, under 'About your organisation'","You can find the org ID on the CORE service under 'Managing agents' or, if your organisation is the managing agent, under 'About your organisation'","If left empty, the letting log will be assigned to the account used to upload the log.","General needs housing includes both self-contained and shared housing without support or specific adaptations. Supported housing includes direct access hostels, group homes, residential care and nursing homes.","Scheme code. Include the 'S' at the beginning if it has one.
You can find the scheme code on the CORE service under 'Schemes', either by searching for the specific scheme or downloading a csv.","Location code.
@ -45,7 +45,7 @@ The UPRN may not be the same as the property reference assigned by your organisa
Extra care housing is for tenants with medium to high care and support needs, often with 24 hour access to support staff provided by an agency registered with the Care Quality Commission.",This is where two or more people are named on the tenancy agreement.,"If the tenancy has an ‘introductory period’ answer ‘yes’.
You should submit a CORE log at the beginning of the starter tenancy or introductory period, with the best information you have at the time. You do not need to submit a log when a tenant later rolls onto the main tenancy.",This is about the main tenancy after any starter or introductory period. See specification for definitions.,,Do not include the starter or introductory period. The minimum period is 2 years for social or affordable rent general needs logs. You do not need to submit CORE logs for these types of tenancies if they are shorter than 2 years.,"This is the household member who does the most paid work. If several people do the same amount of paid work, it's the oldest household member.",This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,"If the lead tenant is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, the tenant should decide which country to enter.","This is the household member who does the most paid work. If several people do the same amount of paid work, it's the oldest household member.",,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,,Answer 1 for children aged under 1 year old,This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth.,,"This excludes national service.
If several household members have these links, answer for regular first. If no regular, answer for reserve. If no reserve, answer for spouses or civil partners.",,,,,,,,,,,"For example, lifting and carrying objects, or using a keyboard",,"For example, deafness or partial hearing",,"For example, depression or anxiety","For example, walking short distances or climbing stairs","For example, anything associated with autism spectrum disorder (ASD), including Asperger’s or attention deficit hyperactivity disorder (ADHD)",,"For example, blindness or partial sight",,,,"The tenant's ‘last settled home' is their last long-standing home. For tenants who had temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously.",,,,"This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless.","Combined with field 104, it should be a postcode which lies within the local authority given in field 105.","Combined with field 103, it should be a postcode which lies within the local authority given in field 105.","This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless.",Households may be given ‘reasonable preference’ for social housing under one or more specific category by the local authority. This is also known as ‘priority need’.,,,,,,Where available vacant properties are advertised and applicants are able to bid for specific properties.,Where a common system agreed between a group of housing providers is used to determine applicants' priority for housing.,Where a single waiting list is used by a group of housing providers to receive and process housing applications. Providers may use different approaches to determine priority.,Where the 'access category' or another descriptor of whether an available vacant property meets a range of access needs is displayed to applicants during the allocations process.,,,,"Include any income after tax from employment, pensions, and Universal Credit. Don't include National Insurance (NI) contributions and tax, housing benefit, child benefit, or council tax support.","This is about when the tenant is in their new let. If they are unsure about the situation for their new let and their financial and working situation hasn’t changed significantly, answer based on what housing-related benefits they currently receive.",,"If rent is charged on the property then answer Yes, even if tenants do not pay it themselves.",,"This is the amount paid before any charges are added for services (for example, hot water or cleaning). Households may receive housing benefit or Universal Credit towards basic rent.","For example, cleaning. Households may get household benefits towards the service charge.",For example heating or hot water. This doesn’t include housing benefit or Universal Credit.,Any charges made to fund support services included in the tenancy agreement.,Also known as the 'outstanding amount',You only need to give an approximate figure.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,,,,,,,,,,,,,,,,
If several household members have these links, answer for regular first. If no regular, answer for reserve. If no reserve, answer for spouses or civil partners.",,,,,,,,,,,"For example, lifting and carrying objects, or using a keyboard",,"For example, deafness or partial hearing",,"For example, depression or anxiety","For example, walking short distances or climbing stairs","For example, anything associated with autism spectrum disorder (ASD), including Asperger’s or attention deficit hyperactivity disorder (ADHD)",,"For example, blindness or partial sight",,,,"The tenant's ‘last settled home' is their last long-standing home. For tenants who had temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously.",,,,"This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless.","Combined with field 104, it should be a postcode which lies within the local authority given in field 105.","Combined with field 103, it should be a postcode which lies within the local authority given in field 105.","This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless.",Households may be given ‘reasonable preference’ for social housing under one or more specific category by the local authority. This is also known as ‘priority need’.,,,,,,Where available vacant properties are advertised and applicants are able to bid for specific properties.,Where a common system agreed between a group of housing providers is used to determine applicants' priority for housing.,Where a single waiting list is used by a group of housing providers to receive and process housing applications. Providers may use different approaches to determine priority.,Where the 'access category' or another descriptor of whether an available vacant property meets a range of access needs is displayed to applicants during the allocations process.,,,,"Include any income after tax from employment, pensions, and Universal Credit. Don't include National Insurance (NI) contributions and tax, housing benefit, child benefit, or council tax support.","This is about when the tenant is in their new let. If they are unsure about the situation for their new let and their financial and working situation hasn’t changed significantly, answer based on what housing-related benefits they currently receive.",,"If rent is charged on the property then answer Yes, even if tenants do not pay it themselves.",,"This is the amount paid before any charges are added for services (for example, hot water or cleaning). Households may receive housing benefit or Universal Credit towards basic rent.","For example, cleaning. Households may get household benefits towards the service charge.",For example heating or hot water. This doesn’t include housing benefit or Universal Credit.,Any charges made to fund support services included in the tenancy agreement.,Also known as the 'outstanding amount',You only need to give an approximate figure.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,This is the sex that was registered at birth.,,,,,,,,,,,,,,,,,,,
Values,Alphanumeric,,Email format,01-Feb,Alphanumeric,Numeric,01-Feb,Jan-31,01-Dec,25 - 26,01-Jul,Text,"Alphanumeric, max 13 characters","Alphanumeric, max 12 characters",1,"5 - 6, or 8 - 22",1 - 3 or 5 - 9,Numeric,Alphanumeric,,Text,,"Alphanumeric,
2 - 4 characters","Alphanumeric,
3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ","1 - 2, 4 or 6 - 10",01-Feb,01-Feb,01-Jul,Jan-31,01-Dec,Jun-26,Jan-31,01-Dec,Jun-26,"2 - 4, 7 - 8",01-Mar,01-Feb,02-Aug,Text,"1 - 99, see specification for more detail",16 - 120 or R,"F, M, X or R",Jan-20,"3 digit ISO country code, see specification",0 - 10,01-Mar,"Numeric, range 1 - 120 or text (upper case 'R')
@ -77,11 +77,11 @@ Must be >= 16 if working situation = 1 - 8 or 0
Must be <16 if working situation = 9","F, M, X or R","0 - 10
Must be 9 if age <16",01-Jun,03-Jun,01-Mar,,1 or empty,,,,,,01-Mar,1 or empty,,,,,,,,,,1 - 2 or 6 - 12,2 or 6 - 13,"1 - 2, 4, 8 - 14, 16 - 20, 28 - 31, 34 or 44 - 55",Text,"3 - 4, 6 - 7, 9 - 10, 13 - 14, 18 - 19, 21, 23 - 33, 35, 37 - 39 ",1 or 11,01-Feb,"Alphanumeric, 2 - 4 characters","Alphanumeric,
3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ",01-Mar,1 or empty,,,,,01-Feb,,,,"1 - 4, 7 - 10, 14 - 24",01-Mar,01-Mar,0 - 99999,"1, 3, 6, 9 or 10",01-Apr,0 - 1,01-Oct,xxxx.xx,,,,01-Mar,xxxx.xx,"F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R",1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text
3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ",01-Mar,1 or empty,,,,,01-Feb,,,,,01-Mar,01-Mar,0 - 99999,"1, 3, 6, 9 or 10",01-Apr,0 - 1,01-Oct,xxxx.xx,,,,01-Mar,xxxx.xx,"F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R","F, M or R",1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,1 - 3,Text,,,
Can be empty?,No,,Yes,No,"Yes, if letting is general needs (if field 4 = 1)","Yes, if letting is general needs (if field 4 = 1)",No,,,,,"Yes, if letting is not 'Other intermediate rent product' (if field 11 is not 6)",Yes,,No,"Yes, if letting is a renewal (if field 7 = 1)","Yes, if letting is a renewal (if field 7 = 1) or a first-time let (if field 16 = 15 - 17)","Yes, if letting is supported housing (if field 4 = 2) or if the property's postcode is not empty (if fields 23 and 24 contain full and valid entries)","Yes, if letting is supported housing (if field 4 = 2) or if property's UPRN and local authority are known (if fields 18 and 25 are not empty)",Yes,"Yes, if letting is supported housing (if field 4 = 2) or if property's UPRN and local authority are known (if fields 18 and 25 are not empty)",Yes,"Yes, if letting is supported housing (if field 4 = 2) or if property's UPRN and local authority are known (if fields 18 and 25 are not empty)",,"Yes, if letting is supported housing (if field 4 = 2)",,,,,"Yes, if letting is a renewal (if field 7 = 1)",,,Yes,,,"Yes, if letting is general needs (if field 4 = 1)",No,,,"Yes, if 'Other' is not selected for tenancy type (if field 39 is not 3)","Yes, if letting is not a fixed-term tenancy (if field 39 is not 4 or 6)",No,,,,,"Yes, if all fields about person 2 are empty (fields 47 - 50)",,,,"Yes, if all fields about person 3 are empty (fields 51 - 54)",,,,"Yes, if all fields about person 4 are empty (fields 55 - 58)",,,,"Yes, if all fields about person 5 are empty (fields 59 - 62)",,,,"Yes, if all fields about person 6 are empty (fields 63 - 66)",,,,"Yes, if all fields about person 7 are empty (fields 67 - 70)",,,,"Yes, if all fields about person 8 are empty (fields 71 - 74)",,,,No,"Yes, if no one in the household is a current or former regular (if field 75 is not 1)","Yes, if no one in the household is a current or former regular or reserve (if field 75 is not 1 or 4)",No,"Yes, if no household members have access needs or if it is unknown (if field 83 or 84 = 1)",,,,"Yes, if a household member has an access need (if at least one of fields 79 to 82 = 1)",,No,"Yes, if a household member has an access need (if at least one of fields 79 to 82 = 1)
If someone in the household does have such a condition (if field 89 = 1), then at least 1 of these fields must be 1.",,,,,,,,,,No,"Yes, if letting is a renewal (if field 7 = 1)",No,"Yes, if 'Other' is not selected for reason for leaving last settled home (if field 98 is not 20)",No,No,,"Yes, if postcode of household's last settled home is not known (if 102 = 2)",,Yes,No,"If household was given 'reasonable preference' (if field 107 = 1), at least one of these fields must be 1
If household was not given 'reasonable preference' (if field 106 = 2 or 3), these fields will be ignored.",,,,,No,,,,"Yes, if letting is a renewal (if field 7 = 1)",No,"Yes, if household's income is unknown (if field 117 = 2 or 3)",,No,,"Yes, if letting is supported housing (if field 4 = 2)",No,"Yes, if the household does not pay rent (if field 122 = 1)",,,,"Yes, if the household doesn't receive housing benefits, or if it is unknown (if field 120 = 3, 9 or 10)","Yes, if the household does not need to pay rent or charges after receiving housing benefits (if field 128 is not 1)",,,,,,,,,,,,,,,,,,,,,,,,
Type of letting the question applies to,,,,,Supported housing only,,,,,,,Other Intermediate Rent only,,,,,,General needs only,,,,,,,,,,,,,,,,,,Supported housing only,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Supported housing only,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Duplicate check field?,Yes,,,,Yes,,,Yes,,,,,Yes,,,,,,,,,,Yes,,,,,,,,,,,,,,,,,,,Yes,,,,Yes,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Field number,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153
,ORG1,ORG1,support@example.com,1,,,2,1,4,26,1,,1,1,1,5,1,,a,a,a,a,a1,1aa,E09000001,1,1,1,1,1,4,25,,,,,3,1,2,,,20,F,1,GBR,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,6,3,1,1,,,,,,1,1,,,,,,,,,,1,2,50,,30,1,2,,,,1,1,,,,,1,1,1,1,7,2,,,1,2,1,1,50,0,0,0,3,,F,,,,,,,,1,,,,,,,,,,,,,,,
If household was not given 'reasonable preference' (if field 106 = 2 or 3), these fields will be ignored.",,,,,No,,,,,No,"Yes, if household's income is unknown (if field 117 = 2 or 3)",,No,,"Yes, if letting is supported housing (if field 4 = 2)",No,"Yes, if the household does not pay rent (if field 122 = 1)",,,,"Yes, if the household doesn't receive housing benefits, or if it is unknown (if field 120 = 3, 9 or 10)","Yes, if the household does not need to pay rent or charges after receiving housing benefits (if field 128 is not 1)",,,,,,,,,,,,,,,,,,,,,,,,,,,
Type of letting the question applies to,,,,,Supported housing only,,,,,,,Other Intermediate Rent only,,,,,,General needs only,,,,,,,,,,,,,,,,,,Supported housing only,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Supported housing only,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Duplicate check field?,Yes,,,,Yes,,,Yes,,,,,Yes,,,,,,,,,,Yes,,,,,,,,,,,,,,,,,,,Yes,,,,Yes,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
Field number,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156
,ORG1,ORG1,support@example.com,1,,,2,1,4,26,1,,1,1,1,5,1,,a,a,a,a,a1,1aa,E09000001,1,1,1,1,1,4,25,,,,,3,1,2,,,20,F,1,GBR,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,6,3,1,1,,,,,,1,1,,,,,,,,,,1,2,50,,30,1,2,,,,1,1,,,,,1,1,1,1,1,2,,,1,2,1,1,50,0,0,0,3,,F,,,,,,,,1,,,,,,,,,,,,,,,,,,

1 Section Setting up this lettings log Property information Tenancy information Household characteristics Household needs Household situation Income, benefits and outgoings
2 Question Which organisation owns this property? Which organisation manages this letting? What is the CORE username of the account this letting log should be assigned to? What is the needs type? What scheme does this letting belong to? Which location is this letting for? Is this letting a renewal of social housing to the same tenant in the same property? What is the tenancy start date? - day DD What is the tenancy start date? - month MM What is the tenancy start date? - year YY What is the rent type? Which 'Other' type of Intermediate Rent is this letting? What is the tenant code? What is the property reference? Has the tenant seen or been given access to the MHCLG privacy notice? What is the reason for the property being vacant? What type was the property most recently let as? If known, provide this property’s UPRN Address Line 1 Address Line 2 Town or city County Part 1 of the property's postcode Part 2 of the property's postcode What is the property's local authority? What type of unit is the property? Which type of building is the property? Is the property built or adapted to wheelchair-user standards? How many bedrooms does the property have? What is the void date? - day DD What is the void date? - month MM What is the void date? - year YY What date were any major repairs completed on? - day DD What date were any major repairs completed on? - month MM What date were any major repairs completed on? - year YY Is this property older people's housing? Is this a joint tenancy? Is this a starter tenancy? What is the type of tenancy? If 'Other', what is the type of tenancy? What is the length of the fixed-term tenancy to the nearest year? What is the lead tenant’s age? Which of these best describes the lead tenant’s gender identity? Which of these best describes the lead tenant's ethnic background? What is the lead tenant’s nationality? Which of these best describes the lead tenant’s working situation? Is person 2 the partner of the lead tenant? What is person 2's age? Which of these best describes person 2's gender identity? Which of these best describes person 2's working situation? Is person 3 the partner of the lead tenant? What is person 3's age? Which of these best describes person 3's gender identity? Which of these best describes person 3's working situation? Is person 4 the partner of the lead tenant? What is person 4's age? Which of these best describes person 4's gender identity? Which of these best describes person 4's working situation? Is person 5 the partner of the lead tenant? What is person 5's age? Which of these best describes person 5's gender identity? Which of these best describes person 5's working situation? Is person 6 the partner of the lead tenant? What is person 6's age? Which of these best describes person 6's gender identity? Which of these best describes person 6's working situation? Is person 7 the partner of the lead tenant? What is person 7's age? Which of these best describes person 7's gender identity? Which of these best describes person 7's working situation? Is person 8 the partner of the lead tenant? What is person 8's age? Which of these best describes person 8's gender identity? Which of these best describes person 8's working situation? Does anybody in the household have links to the UK armed forces? Is this person still serving in the UK armed forces? Was this person seriously injured or ill as a result of serving in the UK armed forces? Is anybody in the household pregnant? Disabled access needs a) Fully wheelchair-accessible housing Disabled access needs b) Wheelchair access to essential rooms Disabled access needs c) Level access housing Disabled access needs f) Other disabled access needs Disabled access needs g) No disabled access needs Disabled access needs h) Don’t know Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more? Does this person's condition affect their dexterity? Does this person's condition affect their learning or understanding or concentrating? Does this person's condition affect their hearing? Does this person's condition affect their memory? Does this person's condition affect their mental health? Does this person's condition affect their mobility? Does this person's condition affect them socially or behaviourally? Does this person's condition affect their stamina or breathing or fatigue? Does this person's condition affect their vision? Does this person's condition affect them in another way? How long has the household continuously lived in the local authority area of the new letting? How long has the household been on the local authority housing register (or waiting list) for the area of the new letting? What is the tenant’s main reason for the household leaving their last settled home? If 'Other', what was the main reason for leaving their last settled home? Where was the household immediately before this letting? Did the household experience homelessness immediately before this letting? Do you know the postcode of the household's last settled home? Part 1 of postcode of last settled home Part 2 of postcode of last settled home What is the local authority of the household's last settled home? Was the household given 'reasonable preference' by the local authority? Reasonable preference reason They were homeless or about to lose their home (within 56 days) Reasonable preference reason They were living in unsanitary, overcrowded or unsatisfactory housing Reasonable preference reason They needed to move due to medical and welfare reasons (including disability) Reasonable preference reason They needed to move to avoid hardship to themselves or others Reasonable preference reason Don't know How was this letting allocated? Choice based Lettings (CBL) How was this letting allocated? Common Allocations Policy (CAP) How was this letting allocated? Common Housing Register (CHR) How was this letting allocated? Accessible Housing Register What was the source of referral for this letting? What was the source of referral for this letting? - LA properties Do you know the household's combined total income after tax? How often does the household receive income? How much income does the household have in total? Is the tenant likely to be receiving any of these housing-related benefits? How much of the household's income is from Universal Credit, state pensions or benefits? Does the household pay rent or other charges for the accommodation? How often does the household pay rent and other charges? What is the basic rent? What is the service charge? What is the personal service charge? What is the support charge? After the household has received any housing-related benefits, will they still need to pay for rent and charges? What do you expect the outstanding amount to be? What was the lead tenant's sex at birth? What was person 2's sex registered at birth? What was person 3's sex registered at birth? What was person 4's sex registered at birth? What was person 5's sex registered at birth? What was person 6's sex registered at birth? What was person 7's sex registered at birth? What was person 8's sex registered at birth? Is the gender the lead tenant identifies with the same as their sex registered at birth? If 'No', enter lead tenant's gender identity Is the gender the person 2 identifies with the same as their sex registered at birth? If 'No', enter person 2's gender identity Is the gender the person 3 identifies with the same as their sex registered at birth? If 'No', enter person 3's gender identity Is the gender the person 4 identifies with the same as their sex registered at birth? If 'No', enter person 4's gender identity Is the gender the person 5 identifies with the same as their sex registered at birth? If 'No', enter person 5's gender identity Is the gender the person 6 identifies with the same as their sex registered at birth? If 'No', enter person 6's gender identity Is the gender the person 7 identifies with the same as their sex registered at birth? If 'No', enter person 7's gender identity Is the gender the person 8 identifies with the same as their sex registered at birth? If 'No', enter person 8's gender identity What was the source of referral for this letting? - PRP properties part 1 What was the source of referral for this letting? - PRP properties part 2 What was the source of referral for this letting? - PRP properties part 3
3 Additional info You can find the org ID on the CORE service under 'Stock owners' or, if your organisation is the stock owner, under 'About your organisation' You can find the org ID on the CORE service under 'Managing agents' or, if your organisation is the managing agent, under 'About your organisation' If left empty, the letting log will be assigned to the account used to upload the log. General needs housing includes both self-contained and shared housing without support or specific adaptations. Supported housing includes direct access hostels, group homes, residential care and nursing homes. Scheme code. Include the 'S' at the beginning if it has one. You can find the scheme code on the CORE service under 'Schemes', either by searching for the specific scheme or downloading a csv. Location code. You can find the location code on the CORE service under 'Schemes', either by searching for the specific location or downloading a csv. If the property was previously being used as temporary accommodation, then answer 'no'. See specification for definitions This is how you usually refer to this tenancy on your own systems. This is how you usually refer to this property on your own systems. Make sure the lead tenant has seen or been given access to the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice before completing this log. This is a legal requirement under data protection legislation. Internal transfer - Where a tenant moved from one social housing property to another property. Their landlord may be the same or may have changed. Renewal of a fixed term tenancy - to the same tenant in the same property, except if was previously used as temporary accommodation. This is the rent type of the previous tenancy in this property. The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and various industries across the UK. An example UPRN is 10010457355. The UPRN may not be the same as the property reference assigned by your organisation. Combined with field 22 it should be a postcode which lies within the local authority given in field 25. Combined with field 21 it should be a postcode which lies within the local authority given in field 25. This is whether someone who uses a wheelchair is able to make full use of all of the property’s rooms and facilities, including use of both inside and outside space, and entering and exiting the property. If shared accommodation, enter the number of bedrooms occupied by this household. A bedsit has 1 bedroom. Date the property was (legally/contractually) available to let, or for: - re-lets: the day after previous tenant’s contract end - new-builds: the day the landlord legally owned the property ('completion date’) - new conversions or acquisitions: the completion date, or the day after any rehabilitation work ended - new leases: the day the landlord got contractual property rights, and could let it out to tenants. Major repairs are works that could not be reasonably carried out with a tenant living at the property. For example, structural repairs. This includes retirement living, sheltered housing and extra care housing. There is no national set limit for “older people”, please answer based on your own policies. Extra care housing is for tenants with medium to high care and support needs, often with 24 hour access to support staff provided by an agency registered with the Care Quality Commission. This is where two or more people are named on the tenancy agreement. If the tenancy has an ‘introductory period’ answer ‘yes’. You should submit a CORE log at the beginning of the starter tenancy or introductory period, with the best information you have at the time. You do not need to submit a log when a tenant later rolls onto the main tenancy. This is about the main tenancy after any starter or introductory period. See specification for definitions. Do not include the starter or introductory period. The minimum period is 2 years for social or affordable rent general needs logs. You do not need to submit CORE logs for these types of tenancies if they are shorter than 2 years. This is the household member who does the most paid work. If several people do the same amount of paid work, it's the oldest household member. This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. If the lead tenant is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, the tenant should decide which country to enter. This is the household member who does the most paid work. If several people do the same amount of paid work, it's the oldest household member. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. Answer 1 for children aged under 1 year old This should be however they personally choose to identify from the options below. This may or may not be the same as their biological sex or the sex they were assigned at birth. This excludes national service. If several household members have these links, answer for regular first. If no regular, answer for reserve. If no reserve, answer for spouses or civil partners. For example, lifting and carrying objects, or using a keyboard For example, deafness or partial hearing For example, depression or anxiety For example, walking short distances or climbing stairs For example, anything associated with autism spectrum disorder (ASD), including Asperger’s or attention deficit hyperactivity disorder (ADHD) For example, blindness or partial sight The tenant's ‘last settled home' is their last long-standing home. For tenants who had temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously. This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless. Combined with field 104, it should be a postcode which lies within the local authority given in field 105. Combined with field 103, it should be a postcode which lies within the local authority given in field 105. This is the tenant’s last long-standing home. It is where the tenant was living before any period in temporary accommodation, sleeping rough or otherwise homeless. Households may be given ‘reasonable preference’ for social housing under one or more specific category by the local authority. This is also known as ‘priority need’. Where available vacant properties are advertised and applicants are able to bid for specific properties. Where a common system agreed between a group of housing providers is used to determine applicants' priority for housing. Where a single waiting list is used by a group of housing providers to receive and process housing applications. Providers may use different approaches to determine priority. Where the 'access category' or another descriptor of whether an available vacant property meets a range of access needs is displayed to applicants during the allocations process. Include any income after tax from employment, pensions, and Universal Credit. Don't include National Insurance (NI) contributions and tax, housing benefit, child benefit, or council tax support. This is about when the tenant is in their new let. If they are unsure about the situation for their new let and their financial and working situation hasn’t changed significantly, answer based on what housing-related benefits they currently receive. If rent is charged on the property then answer Yes, even if tenants do not pay it themselves. This is the amount paid before any charges are added for services (for example, hot water or cleaning). Households may receive housing benefit or Universal Credit towards basic rent. For example, cleaning. Households may get household benefits towards the service charge. For example heating or hot water. This doesn’t include housing benefit or Universal Credit. Any charges made to fund support services included in the tenancy agreement. Also known as the 'outstanding amount' You only need to give an approximate figure. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth. This is the sex that was registered at birth.
4 Values Alphanumeric Email format 01-Feb Alphanumeric Numeric 01-Feb Jan-31 01-Dec 25 - 26 01-Jul Text Alphanumeric, max 13 characters Alphanumeric, max 12 characters 1 5 - 6, or 8 - 22 1 - 3 or 5 - 9 Numeric Alphanumeric Text Alphanumeric, 2 - 4 characters Alphanumeric, 3 characters 9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) 1 - 2, 4 or 6 - 10 01-Feb 01-Feb 01-Jul Jan-31 01-Dec Jun-26 Jan-31 01-Dec Jun-26 2 - 4, 7 - 8 01-Mar 01-Feb 02-Aug Text 1 - 99, see specification for more detail 16 - 120 or R F, M, X or R Jan-20 3 digit ISO country code, see specification 0 - 10 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Mar Numeric, range 1 - 120 or text (upper case 'R') Must be >= 16 if working situation = 1 - 8 or 0 Must be <16 if working situation = 9 F, M, X or R 0 - 10 Must be 9 if age <16 01-Jun 03-Jun 01-Mar 1 or empty 01-Mar 1 or empty 1 - 2 or 6 - 12 2 or 6 - 13 1 - 2, 4, 8 - 14, 16 - 20, 28 - 31, 34 or 44 - 55 Text 3 - 4, 6 - 7, 9 - 10, 13 - 14, 18 - 19, 21, 23 - 33, 35, 37 - 39 1 or 11 01-Feb Alphanumeric, 2 - 4 characters Alphanumeric, 3 characters 9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) 01-Mar 1 or empty 01-Feb 1 - 4, 7 - 10, 14 - 24 01-Mar 01-Mar 0 - 99999 1, 3, 6, 9 or 10 01-Apr 0 - 1 01-Oct xxxx.xx 01-Mar xxxx.xx F, M or R F, M or R F, M or R F, M or R F, M or R F, M or R F, M or R F, M or R 1 - 3 Text 1 - 3 Text 1 - 3 Text 1 - 3 Text 1 - 3 Text 1 - 3 Text 1 - 3 Text 1 - 3 Text
29
30
31
32
33
34
35
45
46
47
48
49
50
51
77
78
79
80
81
82
83
84
85
86
87

6
spec/fixtures/files/lettings_log_csv_export_codes_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/lettings_log_csv_export_labels_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv vendored

File diff suppressed because one or more lines are too long

3
spec/fixtures/variable_definitions/lettings_download_26_27.csv vendored

@ -23,3 +23,6 @@ gender_description5,If 'No', enter person 5's gender identity
gender_description6,If 'No', enter person 6's gender identity
gender_description7,If 'No', enter person 7's gender identity
gender_description8,If 'No', enter person 8's gender identity
referral_register,What was the source of referral for this letting?
referral_noms,What was the source of referral for this letting?
referral_org,What was the source of referral for this letting?

Can't render this file because it has a wrong number of fields in line 18.

2
spec/lib/tasks/log_variable_definitions_spec.rb

@ -6,7 +6,7 @@ RSpec.describe "log_variable_definitions" do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
let(:path) { "spec/fixtures/variable_definitions" }
let(:total_variable_definitions_count) { 447 }
let(:total_variable_definitions_count) { 450 }
before do
Rake.application.rake_require("tasks/log_variable_definitions")

79
spec/models/form/lettings/pages/referral_noms_hr_spec.rb

@ -0,0 +1,79 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralNomsHr, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:prp?) { nil }
let(:organisation) { instance_double(Organisation, prp?: prp?) }
let(:is_renewal?) { nil }
let(:referral_is_from_housing_register?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation, referral_is_from_housing_register?: referral_is_from_housing_register?) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_noms])
end
it "has the correct id" do
expect(page.id).to eq("referral_noms_hr")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is prp" do
let(:prp?) { true }
context "when log is a renewal" do
let(:is_renewal?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log is not a renewal" do
let(:is_renewal?) { false }
context "and log referral is not from housing register" do
let(:referral_is_from_housing_register?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log referral is from housing register" do
let(:referral_is_from_housing_register?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
end
end
end

79
spec/models/form/lettings/pages/referral_noms_la_hr_spec.rb

@ -0,0 +1,79 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralNomsLaHr, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:prp?) { nil }
let(:organisation) { instance_double(Organisation, prp?: prp?) }
let(:is_renewal?) { nil }
let(:referral_is_from_local_authority_housing_register?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation, referral_is_from_local_authority_housing_register?: referral_is_from_local_authority_housing_register?) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_noms])
end
it "has the correct id" do
expect(page.id).to eq("referral_noms_la_hr")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is prp" do
let(:prp?) { true }
context "when log is a renewal" do
let(:is_renewal?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log is not a renewal" do
let(:is_renewal?) { false }
context "and log referral is not from local authority housing register" do
let(:referral_is_from_local_authority_housing_register?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log referral is from local authority housing register" do
let(:referral_is_from_local_authority_housing_register?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
end
end
end

79
spec/models/form/lettings/pages/referral_org_directly_referred_spec.rb

@ -0,0 +1,79 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralOrgDirectlyReferred, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:prp?) { nil }
let(:organisation) { instance_double(Organisation, prp?: prp?) }
let(:is_renewal?) { nil }
let(:referral_is_directly_referred?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation, referral_is_directly_referred?: referral_is_directly_referred?) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_org])
end
it "has the correct id" do
expect(page.id).to eq("referral_org_directly_referred")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is prp" do
let(:prp?) { true }
context "when log is a renewal" do
let(:is_renewal?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log is not a renewal" do
let(:is_renewal?) { false }
context "and log referral is not nominated by local authority" do
let(:referral_is_directly_referred?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log referral is nominated by local authority" do
let(:referral_is_directly_referred?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
end
end
end

79
spec/models/form/lettings/pages/referral_org_nominated_spec.rb

@ -0,0 +1,79 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralOrgNominated, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:prp?) { nil }
let(:organisation) { instance_double(Organisation, prp?: prp?) }
let(:is_renewal?) { nil }
let(:referral_is_nominated_by_local_authority?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation, referral_is_nominated_by_local_authority?: referral_is_nominated_by_local_authority?) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_org])
end
it "has the correct id" do
expect(page.id).to eq("referral_org_nominated")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is prp" do
let(:prp?) { true }
context "when log is a renewal" do
let(:is_renewal?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log is not a renewal" do
let(:is_renewal?) { false }
context "and log referral is not nominated by local authority" do
let(:referral_is_nominated_by_local_authority?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log referral is nominated by local authority" do
let(:referral_is_nominated_by_local_authority?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
end
end
end

78
spec/models/form/lettings/pages/referral_register_la_spec.rb

@ -0,0 +1,78 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralRegisterLa, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:la?) { nil }
let(:organisation) { instance_double(Organisation, la?: la?) }
let(:is_renewal?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_register])
end
it "has the correct id" do
expect(page.id).to eq("referral_register_la")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "when log is a renewal" do
let(:is_renewal?) { true }
context "and log owning organisation is la" do
let(:la?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is not an la" do
let(:la?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
end
context "when log is not a renewal" do
let(:is_renewal?) { false }
context "and log owning organisation is la" do
let(:la?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
context "and log owning organisation is not an la" do
let(:la?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
end
end

78
spec/models/form/lettings/pages/referral_register_prp_spec.rb

@ -0,0 +1,78 @@
require "rails_helper"
RSpec.describe Form::Lettings::Pages::ReferralRegisterPrp, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
let(:subsection) { instance_double(Form::Subsection, form:) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:prp?) { nil }
let(:organisation) { instance_double(Organisation, prp?: prp?) }
let(:is_renewal?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?, owning_organisation: organisation) }
before do
allow(subsection).to receive(:form).and_return(form)
end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[referral_register])
end
it "has the correct id" do
expect(page.id).to eq("referral_register_prp")
end
it "has the correct description" do
expect(page.description).to be_nil
end
it "has the correct depends_on" do
expect(page.depends_on).to be nil
end
context "when log is a renewal" do
let(:is_renewal?) { true }
context "and log owning organisation is prp" do
let(:prp?) { true }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
end
context "when log is not a renewal" do
let(:is_renewal?) { false }
context "and log owning organisation is prp" do
let(:prp?) { true }
it "is routed to" do
expect(page.routed_to?(log, nil)).to be true
end
end
context "and log owning organisation is not prp" do
let(:prp?) { false }
it "is not routed to" do
expect(page.routed_to?(log, nil)).to be false
end
end
end
end

83
spec/models/form/lettings/questions/referral_noms_spec.rb

@ -0,0 +1,83 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::ReferralNoms, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page, referral_register) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:referral_register) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
before do
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("referral_noms")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
context "when referral_register is 6" do
let(:referral_register) { 6 }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"1" => {
"value" => "Nominated by a local authority to a PRP",
},
"2" => {
"value" => "Supported housing only - referred by a local authority to a PRP",
},
"3" => {
"value" => "Internal transfer from another property owned by the same PRP landlord - for existing social tenants only",
},
"4" => {
"value" => "Other",
},
}.freeze,
)
end
end
context "when referral_register is 7" do
let(:referral_register) { 7 }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"5" => {
"value" => "Internal transfer from another property owned by the same PRP landlord - for existing social tenants only",
},
"6" => {
"value" => " A different PRP landlord - for existing social tenants only",
},
"7" => {
"value" => "Directly referred by a third party",
},
"8" => {
"value" => "Other",
},
}.freeze,
)
end
end
it "has the correct question_number" do
expect(question.question_number).to eq(92)
end
end

119
spec/models/form/lettings/questions/referral_org_spec.rb

@ -0,0 +1,119 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::ReferralOrg, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page, referral_noms) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:referral_noms) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
before do
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("referral_org")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?(nil)).to be false
end
context "when referral_noms is 1" do
let(:referral_noms) { 1 }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"1" => {
"value" => "Referred to LA by health service",
},
"2" => {
"value" => "Referred to LA by community learning disability team",
},
"3" => {
"value" => "Referred to LA by community mental health team",
},
"4" => {
"value" => "Referred to LA by adult social services",
},
"5" => {
"value" => "Referred to LA by children's social care",
},
"6" => {
"value" => "Referred to LA by police, probation, prison or youth offending team following a custodial sentence",
},
"7" => {
"value" => "Referred to LA by police, probation, prison or youth offending team without a custodial sentence",
},
"8" => {
"value" => "Referred to LA by a voluntary agency",
},
"9" => {
"value" => "Other referral",
},
"10" => {
"value" => "Don't know",
},
}.freeze,
)
end
end
context "when referral_noms is 7" do
let(:referral_noms) { 7 }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"11" => {
"value" => "Health service",
},
"12" => {
"value" => "Community learning disability team",
},
"13" => {
"value" => "Community mental health team",
},
"14" => {
"value" => "Adult social services",
},
"15" => {
"value" => "Children's social care",
},
"16" => {
"value" => "Police, probation, prison or youth offending team following a custodial sentence",
},
"17" => {
"value" => "Police, probation, prison or youth offending team without a custodial sentence",
},
"18" => {
"value" => "Voluntary agency",
},
"19" => {
"value" => "Other third party",
},
"20" => {
"value" => "Don't know",
},
}.freeze,
)
end
end
it "has the correct question_number" do
expect(question.question_number).to eq(92)
end
end

104
spec/models/form/lettings/questions/referral_register_spec.rb

@ -0,0 +1,104 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::ReferralRegister, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page, provider_type) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page) }
let(:provider_type) { nil }
let(:subsection) { instance_double(Form::Subsection) }
let(:form) { instance_double(Form, start_date: Time.zone.today) }
let(:is_renewal?) { nil }
let(:log) { instance_double(LettingsLog, is_renewal?: is_renewal?) }
before do
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("referral_register")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
context "when log is a renewal" do
let(:is_renewal?) { true }
it "is marked as derived" do
expect(question.derived?(log)).to be true
end
end
context "when log is not a renewal" do
let(:is_renewal?) { false }
it "is not marked as derived" do
expect(question.derived?(log)).to be false
end
end
context "when log is owned by an LA" do
let(:provider_type) { :la }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"1" => {
"value" => "Renewal to the same tenant in the same property",
},
"2" => {
"value" => "Internal transfer from another property owned by the same local authority - for existing social tenants only",
},
"3" => {
"value" => "From a housing register (waiting list)",
},
"4" => {
"value" => "Tenant applied directly (not via a nomination or housing register)",
},
}.freeze,
)
end
it "has the correct question_number" do
expect(question.question_number).to eq(91)
end
end
context "when log is owned by an PRP" do
let(:provider_type) { :prp }
it "has the correct answer_options" do
expect(question.answer_options).to eq(
{
"5" => {
"value" => "Renewal to the same tenant in the same property",
},
"6" => {
"value" => "From a local authority housing register (waiting list) or a register with local authority involvement",
},
"7" => {
"value" => "From a housing register (waiting list) with no local authority involvement",
},
"8" => {
"value" => "Tenant applied directly (not via a nomination or waiting list)",
},
"9" => {
"value" => "Don't know",
},
}.freeze,
)
end
it "has the correct question_number" do
expect(question.question_number).to eq(92)
end
end
end

37
spec/models/form/lettings/subsections/household_situation_spec.rb

@ -10,16 +10,18 @@ RSpec.describe Form::Lettings::Subsections::HouseholdSituation, type: :model do
before do
allow(section).to receive(:form).and_return(form)
allow(form).to receive(:start_year_2024_or_later?).and_return(false)
allow(form).to receive(:start_year_2025_or_later?).and_return(false)
allow(form).to receive(:start_year_2026_or_later?).and_return(false)
end
it "has correct section" do
expect(household_situation.section).to eq(section)
end
context "with form year before 2024" do
context "with form year is 2024", metadata: { year: 24 } do
before do
allow(form).to receive(:start_year_2024_or_later?).and_return(false)
allow(form).to receive(:start_year_2025_or_later?).and_return(false)
allow(form).to receive(:start_year_2024_or_later?).and_return(true)
end
it "has correct pages" do
@ -29,6 +31,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdSituation, type: :model do
time_on_waiting_list
reason_for_leaving_last_settled_home
reason_for_leaving_last_settled_home_renewal
reasonother_value_check
previous_housing_situation
previous_housing_situation_renewal
homelessness
@ -47,10 +50,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdSituation, type: :model do
end
end
context "with form year is 2024" do
context "with form year is 2025", metadata: { year: 25 } do
before do
allow(form).to receive(:start_year_2024_or_later?).and_return(true)
allow(form).to receive(:start_year_2025_or_later?).and_return(false)
allow(form).to receive(:start_year_2025_or_later?).and_return(true)
end
it "has correct pages" do
@ -69,20 +72,23 @@ RSpec.describe Form::Lettings::Subsections::HouseholdSituation, type: :model do
reasonable_preference
reasonable_preference_reason
allocation_system
referral
referral_type
referral_direct
referral_la
referral_prp
referral_supported_housing
referral_supported_housing_prp
referral_hsc
referral_justice
referral_value_check
],
)
end
end
context "with form year is 2025" do
context "with form year is 2026", metadata: { year: 26 } do
before do
allow(form).to receive(:start_year_2024_or_later?).and_return(true)
allow(form).to receive(:start_year_2025_or_later?).and_return(true)
allow(form).to receive(:start_year_2026_or_later?).and_return(true)
end
it "has correct pages" do
@ -101,13 +107,12 @@ RSpec.describe Form::Lettings::Subsections::HouseholdSituation, type: :model do
reasonable_preference
reasonable_preference_reason
allocation_system
referral_type
referral_direct
referral_la
referral_prp
referral_hsc
referral_justice
referral_value_check
referral_register_la
referral_register_prp
referral_noms_la_hr
referral_noms_hr
referral_org_nominated
referral_org_directly_referred
],
)
end

204
spec/models/validations/household_validations_spec.rb

@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Validations::HouseholdValidations do
include CollectionTimeHelper
subject(:household_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::HouseholdValidations } }
@ -488,6 +490,141 @@ RSpec.describe Validations::HouseholdValidations do
expect(record.errors["homeless"]).to be_empty
end
end
context "when start year is 2026" do
let(:startdate) { collection_start_date_for_year(2026) }
[
{
internal_transfer: true,
label: "LA",
referral_register: 2,
referral_noms: nil,
},
{
internal_transfer: true,
label: "PRP",
referral_register: 6,
referral_noms: 3,
},
{
internal_transfer: true,
label: "PRP",
referral_register: 7,
referral_noms: 5,
},
{
internal_transfer: false,
label: "LA",
referral_register: 1,
referral_noms: nil,
},
{
internal_transfer: false,
label: "PRP",
referral_register: 6,
referral_noms: 2,
},
{
internal_transfer: false,
label: "PRP",
referral_register: 7,
referral_noms: 6,
},
]
.each do |scenario|
context "and record #{scenario[:internal_transfer] ? 'is ' : 'is not '}internal transfer via #{scenario[:label]} path" do
before do
record.owning_organisation.provider_type = scenario[:label]
record.referral_register = scenario[:referral_register]
record.referral_noms = scenario[:referral_noms]
end
context "and prevten is nil" do
before do
record.prevten = nil
end
it "does not add an error" do
household_validator.validate_referral(record)
expect(record.errors["prevten"]).to be_empty
expect(record.errors["referral_register"]).to be_empty
expect(record.errors["referral_noms"]).to be_empty
end
end
[
{ code: 3, label: "Private sector tenancy" },
{ code: 27, label: "Owner occupation (low-cost home ownership)" },
{ code: 26, label: "Owner occupation (private)" },
{ code: 28, label: "Living with friends or family (long-term)" },
{ code: 39, label: "Sofa surfing (moving regularly between family or friends, no permanent bed)" },
{ code: 14, label: "Bed and breakfast" },
{ code: 7, label: "Direct access hostel" },
{ code: 10, label: "Hospital" },
{ code: 29, label: "Prison or approved probation hostel" },
{ code: 19, label: "Rough sleeping" },
{ code: 18, label: "Any other temporary accommodation" },
{ code: 13, label: "Children’s home or foster care" },
{ code: 24, label: "Home Office Asylum Support" },
{ code: 37, label: "Host family or similar refugee accommodation" },
{ code: 23, label: "Mobile home or caravan" },
{ code: 21, label: "Refuge" },
{ code: 9, label: "Residential care home" },
{ code: 4, label: "Tied housing or rented with job" },
{ code: 25, label: "Any other accommodation" },
].each do |prevten|
context "and prevten is #{prevten[:code]}" do
before do
record.prevten = prevten[:code]
end
if scenario[:internal_transfer]
it "adds an error" do
household_validator.validate_referral(record)
expect(record.errors["prevten"])
.to include(match I18n.t("validations.lettings.household.prevten.general_needs.internal_transfer", prevten: prevten[:label]))
expect(record.errors["referral_register"])
.to include(match I18n.t("validations.lettings.household.referral.general_needs.internal_transfer", prevten: prevten[:label]))
expect(record.errors["referral_noms"])
.to include(match I18n.t("validations.lettings.household.referral.general_needs.internal_transfer", prevten: prevten[:label]))
end
else
it "does not add an error" do
household_validator.validate_referral(record)
expect(record.errors["prevten"]).to be_empty
expect(record.errors["referral_register"]).to be_empty
expect(record.errors["referral_noms"]).to be_empty
end
end
end
end
[
{ code: 30, label: "Fixed-term local authority general needs tenancy" },
{ code: 31, label: "Lifetime local authority general needs tenancy" },
{ code: 32, label: "Fixed-term private registered provider (PRP) general needs tenancy" },
{ code: 33, label: "Lifetime private registered provider (PRP) general needs tenancy" },
{ code: 35, label: "Extra care housing" },
{ code: 38, label: "Older people’s housing for tenants with low support needs" },
{ code: 6, label: "Other supported housing" },
].each do |prevten|
context "and prevten is #{prevten[:code]}" do
before do
record.prevten = prevten[:code]
end
it "does not add an error" do
household_validator.validate_referral(record)
expect(record.errors["prevten"]).to be_empty
expect(record.errors["referral_register"]).to be_empty
expect(record.errors["referral_noms"]).to be_empty
end
end
end
end
end
end
end
describe "la validations" do
@ -564,10 +701,14 @@ RSpec.describe Validations::HouseholdValidations do
end
end
context "when the referral is internal transfer" do
it "prevten can be 9" do
record.referral_type = 3
context "when the referral is internal transfer for 2025" do
let(:startdate) { collection_start_date_for_year(2025) }
before do
record.referral = 1
end
it "prevten can be 9" do
record.prevten = 9
household_validator.validate_previous_housing_situation(record)
expect(record.errors["prevten"])
@ -593,16 +734,53 @@ RSpec.describe Validations::HouseholdValidations do
{ code: 28, label: "Living with friends or family" },
{ code: 29, label: "Prison or approved probation hostel" },
].each do |prevten|
it "prevten cannot be #{prevten[:code]}" do
record.referral_type = 3
record.referral = 1
record.prevten = prevten[:code]
household_validator.validate_previous_housing_situation(record)
label = record.form.start_year_2025_or_later? && prevten[:code] == 28 ? "Living with friends or family (long-term)" : prevten[:label]
expect(record.errors["prevten"])
.to include(match I18n.t("validations.lettings.household.prevten.internal_transfer", prevten: label))
expect(record.errors["referral"])
.to include(match I18n.t("validations.lettings.household.referral.prevten_invalid", prevten: ""))
context "and prevten is #{prevten}" do
it "adds an error" do
record.prevten = prevten[:code]
household_validator.validate_previous_housing_situation(record)
label = record.form.start_year_2025_or_later? && prevten[:code] == 28 ? "Living with friends or family (long-term)" : prevten[:label]
expect(record.errors["prevten"])
.to include(match I18n.t("validations.lettings.household.prevten.internal_transfer", prevten: label))
expect(record.errors["referral"])
.to include(match I18n.t("validations.lettings.household.referral.prevten_invalid", prevten: ""))
end
end
end
end
context "when the referral is internal transfer for 2026" do
let(:startdate) { collection_start_date_for_year(2026) }
before do
record.owning_organisation.provider_type = "LA"
record.referral_register = 2
end
[
{ code: 3, label: "Private sector tenancy" },
{ code: 4, label: "Tied housing or rented with job" },
{ code: 7, label: "Direct access hostel" },
{ code: 10, label: "Hospital" },
{ code: 13, label: "Children’s home or foster care" },
{ code: 14, label: "Bed and breakfast" },
{ code: 19, label: "Rough sleeping" },
{ code: 23, label: "Mobile home or caravan" },
{ code: 24, label: "Home Office Asylum Support" },
{ code: 25, label: "Any other accommodation" },
{ code: 26, label: "Owner occupation (private)" },
{ code: 28, label: "Living with friends or family" },
{ code: 29, label: "Prison or approved probation hostel" },
].each do |prevten|
context "and prevten is #{prevten}" do
before do
record.prevten = prevten[:code]
end
it "does not add an error" do
household_validator.validate_previous_housing_situation(record)
expect(record.errors["prevten"]).to be_empty
expect(record.errors["referral"]).to be_empty
end
end
end
end

8
spec/services/bulk_upload/lettings/validator_spec.rb

@ -172,8 +172,8 @@ RSpec.describe BulkUpload::Lettings::Validator do
expect(error.tenant_code).to eql(log.tenancycode)
expect(error.property_ref).to eql(log.propcode)
expect(error.row).to eql("2")
expect(error.cell).to eql("CX2")
expect(error.col).to eql("CX")
expect(error.cell).to eql("CX2") # this may change when adding a new field as the cols are in a random order
expect(error.col).to eql("CX") # this may change when adding a new field as the cols are in a random order
end
end
@ -190,8 +190,8 @@ RSpec.describe BulkUpload::Lettings::Validator do
expect(error.tenant_code).to eql(log.tenancycode)
expect(error.property_ref).to eql(log.propcode)
expect(error.row).to eql("2")
expect(error.cell).to eql("EF2")
expect(error.col).to eql("EF")
expect(error.cell).to eql("EH2") # this may change when adding a new field as the cols are in a random order
expect(error.col).to eql("EH") # this may change when adding a new field as the cols are in a random order
end
end
end

6
spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb

@ -244,9 +244,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::CsvParser do
end
it "returns correct column" do
expect(service.column_for_field("field_5")).to eql("AG")
expect(service.column_for_field("field_22")).to eql("BO")
expect(service.column_for_field("field_26")).to eql("CD")
expect(service.column_for_field("field_5")).to eql("AI")
expect(service.column_for_field("field_22")).to eql("BR")
expect(service.column_for_field("field_26")).to eql("CG")
expect(service.column_for_field("field_25")).to eql("E")
end
end

249
spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb

@ -224,7 +224,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do
field_114: "2",
field_115: "2",
field_116: "2",
field_116: "1",
field_117: "1",
field_118: "2",
@ -648,12 +648,12 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do
end
context "when an invalid value error has been added" do
let(:attributes) { setup_section_params.merge({ field_116: "100" }) }
let(:attributes) { setup_section_params.merge({ field_115: "100" }) }
it "does not add an additional error" do
parser.valid?
expect(parser.errors[:field_116].length).to eq(1)
expect(parser.errors[:field_116]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: ""))
expect(parser.errors[:field_115].length).to eq(1)
expect(parser.errors[:field_115]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: ""))
end
end
end
@ -1160,43 +1160,236 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do
end
end
describe "#field_116" do # referral
context "when 3 ie PRP nominated by LA and owning org is LA" do
let(:attributes) { { bulk_upload:, field_116: "3", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } }
describe "#field_116, field_154, field_155, field_156" do # referral
context "when org is LA" do
let(:owning_org) { create(:organisation, :la, :with_old_visible_id) }
it "is not permitted" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
let(:org_attributes) { { bulk_upload:, field_1: owning_org.old_visible_id } }
context "and not renewal" do
let(:renewal_attributes) { org_attributes.merge({ field_7: nil }) }
context "and field_116 is valid" do
let(:attributes) { renewal_attributes.merge({ field_116: 1 }) }
it "does not add an error" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
end
context "and field_116 is invalid" do
let(:attributes) { renewal_attributes.merge({ field_116: 5 }) } # PRP option
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_116 is blank" do
let(:attributes) { renewal_attributes.merge({ field_116: nil }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and other fields are given" do
let(:attributes) { renewal_attributes.merge({ field_116: 1, field_154: 5, field_155: 1, field_152: 1 }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
end
end
context "when 4 ie referred by LA and is general needs and owning org is LA" do
let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "1" } }
context "and is renewal" do
let(:attributes) { org_attributes.merge({ field_7: 1, field_116: 1, field_154: 5, field_155: 1, field_156: 1 }) }
it "is not permitted" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
it "does not add an error for referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
end
end
context "when 4 ie referred by LA and is general needs and owning org is PRP" do
context "when org is PRP" do
let(:owning_org) { create(:organisation, :prp, :with_old_visible_id) }
let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } }
let(:org_attributes) { { bulk_upload:, field_1: owning_org.old_visible_id } }
it "is permitted" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
context "and not renewal" do
let(:renewal_attributes) { org_attributes.merge({ field_7: nil }) }
context "and field_154 is valid and does not expect an answer for field_155" do
let(:attributes) { renewal_attributes.merge({ field_154: 5 }) }
it "does not add an error" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
context "and later fields are given" do
let(:attributes) { renewal_attributes.merge({ field_154: 5, field_155: 1, field_156: 1 }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
end
context "and field_154 is invalid" do
let(:attributes) { renewal_attributes.merge({ field_154: 1 }) } # LA option
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_154 is blank" do
let(:attributes) { renewal_attributes.merge({ field_154: nil }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_154 is valid and expects an answer for field_155" do
let(:field_154_attributes) { renewal_attributes.merge({ field_154: 6 }) }
context "and field_155 is valid and does not expect an answer for field_156" do
let(:attributes) { field_154_attributes.merge({ field_155: 2 }) }
it "does not add an error" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
context "and later fields are given" do
let(:attributes) { field_154_attributes.merge({ field_155: 2, field_156: 1 }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
end
context "and field_155 is invalid" do
let(:attributes) { field_154_attributes.merge({ field_155: 5 }) } # needs field_154 to be 7
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_155 is blank" do
let(:attributes) { field_154_attributes.merge({ field_155: nil }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_155 is valid and expects an answer for field_156" do
let(:field_155_attributes) { field_154_attributes.merge({ field_155: 1 }) }
context "and field_156 is valid" do
let(:attributes) { field_155_attributes.merge({ field_156: 1 }) }
it "does not add an error" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
end
context "and field_156 is invalid" do
let(:attributes) { field_155_attributes.merge({ field_156: 11 }) } # needs field_155 to be 7
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
context "and field_156 is blank" do
let(:attributes) { field_155_attributes.merge({ field_156: nil }) }
it "adds errors to all referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_present
expect(parser.errors[:field_154]).to be_present
expect(parser.errors[:field_155]).to be_present
expect(parser.errors[:field_156]).to be_present
end
end
end
end
end
end
context "when 4 ie referred by LA and is not general needs" do
let(:bulk_upload) { create(:bulk_upload, :lettings, user:) }
let(:attributes) { { bulk_upload:, field_116: "4", field_4: "2" } }
context "and is renewal" do
let(:attributes) { org_attributes.merge({ field_7: 1, field_116: 1, field_154: 5, field_155: 1, field_156: 1 }) }
it "is permitted" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
it "does not add an error for referral fields" do
parser.valid?
expect(parser.errors[:field_116]).to be_blank
expect(parser.errors[:field_154]).to be_blank
expect(parser.errors[:field_155]).to be_blank
expect(parser.errors[:field_156]).to be_blank
end
end
end
end

4
spec/services/csv/lettings_log_csv_service_spec.rb

@ -308,7 +308,9 @@ RSpec.describe Csv::LettingsLogCsvService do
chr: 1,
cap: 0,
accessible_register: 0,
referral: 2,
referral_register: 1,
referral_noms: 1,
referral_org: 1,
net_income_known: 0,
incref: 0,
incfreq: 1,

20
spec/services/merge/merge_organisations_service_spec.rb

@ -56,6 +56,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -100,6 +101,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -137,6 +139,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -557,6 +560,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -590,6 +594,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -652,6 +657,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -688,6 +694,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -877,6 +884,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -996,6 +1004,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1121,6 +1130,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(absorbing_organisation.id).and_return(absorbing_organisation)
allow(absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1191,6 +1201,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1235,6 +1246,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1272,6 +1284,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1377,6 +1390,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1409,6 +1423,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1448,6 +1463,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1484,6 +1500,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1593,6 +1610,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1683,6 +1701,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")
@ -1725,6 +1744,7 @@ RSpec.describe Merge::MergeOrganisationsService do
it "rolls back if there's an error" do
allow(Organisation).to receive(:find).with(merging_organisation_ids).and_return(Organisation.find(merging_organisation_ids))
allow(Organisation).to receive(:find).with(merging_organisation.id).and_return(merging_organisation)
allow(Organisation).to receive(:find).with(new_absorbing_organisation.id).and_return(new_absorbing_organisation)
allow(new_absorbing_organisation).to receive(:save!).and_raise(ActiveRecord::RecordInvalid)
expect(Rails.logger).to receive(:error).with("Organisation merge failed with: Record invalid")

Loading…
Cancel
Save