You can continue without the UPRN, but it means we will need you to enter the address of the property."
+ @conditional_for = { "uprn" => [1] }
+ @hidden_in_check_answers = true
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/lettings/subsections/property_information.rb b/app/models/form/lettings/subsections/property_information.rb
index f2dba28e5..0f921d4a5 100644
--- a/app/models/form/lettings/subsections/property_information.rb
+++ b/app/models/form/lettings/subsections/property_information.rb
@@ -34,7 +34,6 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions
if form.start_date.year >= 2023
[
- Form::Lettings::Pages::UprnKnown.new(nil, nil, self),
Form::Lettings::Pages::Uprn.new(nil, nil, self),
Form::Lettings::Pages::UprnConfirmation.new(nil, nil, self),
Form::Lettings::Pages::Address.new(nil, nil, self),
diff --git a/app/models/form/question.rb b/app/models/form/question.rb
index 19b9de163..8e8c26739 100644
--- a/app/models/form/question.rb
+++ b/app/models/form/question.rb
@@ -226,24 +226,6 @@ class Form::Question
label
end
- def answer_option_synonyms(resource)
- return unless resource.respond_to?(:synonyms)
-
- resource.synonyms
- end
-
- def answer_option_append(resource)
- return unless resource.respond_to?(:appended_text)
-
- resource.appended_text
- end
-
- def answer_option_hint(resource)
- return unless resource.respond_to?(:hint)
-
- resource.hint
- end
-
def answer_selected?(log, answer)
return false unless type == "select"
@@ -317,7 +299,11 @@ private
end
def enabled_inferred_answers(inferred_answers, log)
- inferred_answers.filter { |_key, value| value.all? { |condition_key, condition_value| log[condition_key] == condition_value } }
+ inferred_answers.filter do |_attribute, condition|
+ condition.all? do |condition_key, condition_value|
+ log.public_send(condition_key) == condition_value
+ end
+ end
end
def inferred_answer_value(log)
diff --git a/app/models/form/sales/pages/buyer_live_in_value_check.rb b/app/models/form/sales/pages/buyer_live_in_value_check.rb
new file mode 100644
index 000000000..067ba96ca
--- /dev/null
+++ b/app/models/form/sales/pages/buyer_live_in_value_check.rb
@@ -0,0 +1,21 @@
+class Form::Sales::Pages::BuyerLiveInValueCheck < Form::Sales::Pages::Person
+ def initialize(id, hsh, subsection, person_index:)
+ super
+ @depends_on = [
+ {
+ "buyer#{person_index}_livein_wrong_for_ownership_type?" => true,
+ },
+ ]
+ @title_text = {
+ "translation" => "soft_validations.buyer#{person_index}_livein_wrong_for_ownership_type.title_text",
+ "arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
+ }
+ @informative_text = {}
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::BuyerLiveInValueCheck.new(nil, nil, self, person_index: @person_index),
+ ]
+ end
+end
diff --git a/app/models/form/sales/pages/discounted_sale_value_check.rb b/app/models/form/sales/pages/discounted_sale_value_check.rb
index 8ff48a0bd..3c1b010f2 100644
--- a/app/models/form/sales/pages/discounted_sale_value_check.rb
+++ b/app/models/form/sales/pages/discounted_sale_value_check.rb
@@ -4,11 +4,23 @@ class Form::Sales::Pages::DiscountedSaleValueCheck < ::Form::Page
@depends_on = depends_on
@title_text = {
"translation" => "soft_validations.discounted_sale_value.title_text",
- "arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }],
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "value_with_discount",
+ "i18n_template" => "value_with_discount",
+ },
+ ],
}
@informative_text = {
"translation" => "soft_validations.discounted_sale_value.informative_text",
- "arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }],
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "mortgage_deposit_and_grant_total",
+ "i18n_template" => "mortgage_deposit_and_grant_total",
+ },
+ ],
}
@person_index = person_index
@depends_on = [
diff --git a/app/models/form/sales/pages/percentage_discount_value_check.rb b/app/models/form/sales/pages/percentage_discount_value_check.rb
new file mode 100644
index 000000000..1e3beb3e6
--- /dev/null
+++ b/app/models/form/sales/pages/percentage_discount_value_check.rb
@@ -0,0 +1,15 @@
+class Form::Sales::Pages::PercentageDiscountValueCheck < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @title_text = {
+ "translation" => "soft_validations.percentage_discount_value.title_text",
+ "arguments" => [{ "key" => "discount", "label" => true, "i18n_template" => "discount" }],
+ }
+ @informative_text = {}
+ @depends_on = [{ "percentage_discount_invalid?" => true }]
+ end
+
+ def questions
+ @questions ||= [Form::Sales::Questions::PercentageDiscountValueCheck.new(nil, nil, self)]
+ end
+end
diff --git a/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb b/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
index be2126482..4730248ed 100644
--- a/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
+++ b/app/models/form/sales/pages/shared_ownership_deposit_value_check.rb
@@ -11,8 +11,8 @@ class Form::Sales::Pages::SharedOwnershipDepositValueCheck < ::Form::Page
"translation" => "soft_validations.shared_ownership_deposit.title_text",
"arguments" => [
{
- "key" => "expected_shared_ownership_deposit_value",
- "label" => false,
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "expected_shared_ownership_deposit_value",
"i18n_template" => "expected_shared_ownership_deposit_value",
},
],
diff --git a/app/models/form/sales/pages/uprn.rb b/app/models/form/sales/pages/uprn.rb
index e1835f8ca..ad247207f 100644
--- a/app/models/form/sales/pages/uprn.rb
+++ b/app/models/form/sales/pages/uprn.rb
@@ -6,6 +6,7 @@ class Form::Sales::Pages::Uprn < ::Form::Page
def questions
@questions ||= [
+ Form::Sales::Questions::UprnKnown.new(nil, nil, self),
Form::Sales::Questions::Uprn.new(nil, nil, self),
]
end
diff --git a/app/models/form/sales/pages/uprn_known.rb b/app/models/form/sales/pages/uprn_known.rb
deleted file mode 100644
index e2cbfe63f..000000000
--- a/app/models/form/sales/pages/uprn_known.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class Form::Sales::Pages::UprnKnown < ::Form::Page
- def initialize(id, hsh, subsection)
- super
- @id = "uprn_known"
- end
-
- def questions
- @questions ||= [
- Form::Sales::Questions::UprnKnown.new(nil, nil, self),
- ]
- end
-end
diff --git a/app/models/form/sales/questions/buyer_live_in_value_check.rb b/app/models/form/sales/questions/buyer_live_in_value_check.rb
new file mode 100644
index 000000000..a4209c38c
--- /dev/null
+++ b/app/models/form/sales/questions/buyer_live_in_value_check.rb
@@ -0,0 +1,24 @@
+class Form::Sales::Questions::BuyerLiveInValueCheck < ::Form::Question
+ def initialize(id, hsh, page, person_index:)
+ super(id, hsh, page)
+ @id = "buyer_livein_value_check"
+ @check_answer_label = "Buyer live in confirmation"
+ @type = "interruption_screen"
+ @answer_options = {
+ "0" => { "value" => "Yes" },
+ "1" => { "value" => "No" },
+ }
+ @hidden_in_check_answers = {
+ "depends_on" => [
+ {
+ "buyer_livein_value_check" => 0,
+ },
+ {
+ "buyer_livein_value_check" => 1,
+ },
+ ],
+ }
+ @check_answers_card_number = person_index
+ @header = "Are you sure this is correct?"
+ end
+end
diff --git a/app/models/form/sales/questions/percentage_discount_value_check.rb b/app/models/form/sales/questions/percentage_discount_value_check.rb
new file mode 100644
index 000000000..9ac5547b4
--- /dev/null
+++ b/app/models/form/sales/questions/percentage_discount_value_check.rb
@@ -0,0 +1,23 @@
+class Form::Sales::Questions::PercentageDiscountValueCheck < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "percentage_discount_value_check"
+ @check_answer_label = "Percentage discount confirmation"
+ @header = "Are you sure this is correct?"
+ @type = "interruption_screen"
+ @answer_options = {
+ "0" => { "value" => "Yes" },
+ "1" => { "value" => "No" },
+ }
+ @hidden_in_check_answers = {
+ "depends_on" => [
+ {
+ "percentage_discount_value_check" => 0,
+ },
+ {
+ "percentage_discount_value_check" => 1,
+ },
+ ],
+ }
+ end
+end
diff --git a/app/models/form/sales/questions/uprn.rb b/app/models/form/sales/questions/uprn.rb
index 7967a2035..6b51260a7 100644
--- a/app/models/form/sales/questions/uprn.rb
+++ b/app/models/form/sales/questions/uprn.rb
@@ -5,9 +5,14 @@ class Form::Sales::Questions::Uprn < ::Form::Question
@check_answer_label = "UPRN"
@header = "What is the property's UPRN"
@type = "text"
- @hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355."
@width = 10
@question_number = 14
+ @inferred_check_answers_value = [
+ {
+ "condition" => { "uprn_known" => 0 },
+ "value" => "Not known",
+ },
+ ]
end
def unanswered_error_message
@@ -15,6 +20,8 @@ class Form::Sales::Questions::Uprn < ::Form::Question
end
def get_extra_check_answer_value(log)
+ return unless log.uprn_known == 1
+
value = [
log.address_line1,
log.address_line2,
@@ -28,8 +35,4 @@ class Form::Sales::Questions::Uprn < ::Form::Question
"\n\n#{value.join("\n")}"
end
-
- def hidden_in_check_answers?(log, _current_user = nil)
- log.uprn_known != 1
- end
end
diff --git a/app/models/form/sales/questions/uprn_known.rb b/app/models/form/sales/questions/uprn_known.rb
index b07b0b7d7..22438e662 100644
--- a/app/models/form/sales/questions/uprn_known.rb
+++ b/app/models/form/sales/questions/uprn_known.rb
@@ -8,6 +8,14 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question
@answer_options = ANSWER_OPTIONS
@hint_text = "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.
You can continue without the UPRN, but it means we will need you to enter the address of the property."
+ @conditional_for = { "uprn" => [1] }
+ @inferred_check_answers_value = [
+ {
+ "condition" => { "uprn_known" => 0 },
+ "value" => "Not known",
+ },
+ ]
+ @hidden_in_check_answers = true
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/sales/subsections/discounted_ownership_scheme.rb b/app/models/form/sales/subsections/discounted_ownership_scheme.rb
index 09813339d..52ee9e95c 100644
--- a/app/models/form/sales/subsections/discounted_ownership_scheme.rb
+++ b/app/models/form/sales/subsections/discounted_ownership_scheme.rb
@@ -11,6 +11,7 @@ class Form::Sales::Subsections::DiscountedOwnershipScheme < ::Form::Subsection
Form::Sales::Pages::LivingBeforePurchase.new("living_before_purchase_discounted_ownership", nil, self, ownershipsch: 2),
Form::Sales::Pages::AboutPriceRtb.new(nil, nil, self),
Form::Sales::Pages::ExtraBorrowingValueCheck.new("extra_borrowing_price_value_check", nil, self),
+ Form::Sales::Pages::PercentageDiscountValueCheck.new("percentage_discount_value_check", nil, self),
Form::Sales::Pages::AboutPriceNotRtb.new(nil, nil, self),
Form::Sales::Pages::GrantValueCheck.new(nil, nil, self),
Form::Sales::Pages::PurchasePriceOutrightOwnership.new("purchase_price_discounted_ownership", nil, self, ownershipsch: 2),
diff --git a/app/models/form/sales/subsections/household_characteristics.rb b/app/models/form/sales/subsections/household_characteristics.rb
index 922d95edd..64b0b95ea 100644
--- a/app/models/form/sales/subsections/household_characteristics.rb
+++ b/app/models/form/sales/subsections/household_characteristics.rb
@@ -26,6 +26,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::RetirementValueCheck.new("working_situation_1_retirement_value_check", nil, self, person_index: 1),
Form::Sales::Pages::Buyer1IncomeValueCheck.new("working_situation_buyer_1_income_value_check", nil, self),
Form::Sales::Pages::Buyer1LiveInProperty.new(nil, nil, self),
+ Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_1_live_in_property_value_check", nil, self, person_index: 1),
Form::Sales::Pages::Buyer2RelationshipToBuyer1.new(nil, nil, self),
Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_relationship_student_not_child_value_check", nil, self, person_index: 2),
Form::Sales::Pages::Age2.new(nil, nil, self),
@@ -40,6 +41,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::Buyer2IncomeValueCheck.new("working_situation_buyer_2_income_value_check", nil, self),
Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_working_situation_student_not_child_value_check", nil, self, person_index: 2),
Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self),
+ Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_2_live_in_property_value_check", nil, self, person_index: 2),
Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property", nil, self, joint_purchase: false),
Form::Sales::Pages::NumberOfOthersInProperty.new("number_of_others_in_property_joint_purchase", nil, self, joint_purchase: true),
Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 2),
diff --git a/app/models/form/sales/subsections/property_information.rb b/app/models/form/sales/subsections/property_information.rb
index cca34a764..74a064dca 100644
--- a/app/models/form/sales/subsections/property_information.rb
+++ b/app/models/form/sales/subsections/property_information.rb
@@ -13,6 +13,7 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_bedrooms_value_check", nil, self),
Form::Sales::Pages::PropertyUnitType.new(nil, nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_property_type_value_check", nil, self),
+ Form::Sales::Pages::PercentageDiscountValueCheck.new("percentage_discount_proptype_value_check", nil, self),
Form::Sales::Pages::PropertyBuildingType.new(nil, nil, self),
postcode_and_la_questions,
Form::Sales::Pages::AboutPriceValueCheck.new("about_price_la_value_check", nil, self),
@@ -23,7 +24,6 @@ class Form::Sales::Subsections::PropertyInformation < ::Form::Subsection
def uprn_questions
if form.start_date.year >= 2023
[
- Form::Sales::Pages::UprnKnown.new(nil, nil, self),
Form::Sales::Pages::Uprn.new(nil, nil, self),
Form::Sales::Pages::UprnConfirmation.new(nil, nil, self),
Form::Sales::Pages::Address.new(nil, nil, self),
diff --git a/app/models/form/sales/subsections/setup.rb b/app/models/form/sales/subsections/setup.rb
index d1bb9dd6b..c723b732c 100644
--- a/app/models/form/sales/subsections/setup.rb
+++ b/app/models/form/sales/subsections/setup.rb
@@ -19,6 +19,8 @@ class Form::Sales::Subsections::Setup < ::Form::Subsection
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("ownership_type_old_persons_shared_ownership_value_check", nil, self),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_type_value_check", nil, self),
Form::Sales::Pages::DiscountedSaleValueCheck.new("discounted_sale_type_value_check", nil, self),
+ Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_1_live_in_property_type_value_check", nil, self, person_index: 1),
+ Form::Sales::Pages::BuyerLiveInValueCheck.new("buyer_2_live_in_property_type_value_check", nil, self, person_index: 2),
Form::Sales::Pages::BuyerCompany.new(nil, nil, self),
Form::Sales::Pages::BuyerLive.new(nil, nil, self),
Form::Sales::Pages::JointPurchase.new(nil, nil, self),
diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb
index 43db4ed81..6ea58e339 100644
--- a/app/models/lettings_log.rb
+++ b/app/models/lettings_log.rb
@@ -58,7 +58,7 @@ class LettingsLog < Log
OPTIONAL_FIELDS = %w[rent_value_check first_time_property_let_as_social_housing tenancycode propcode chcharge].freeze
RENT_TYPE_MAPPING_LABELS = { 1 => "Social Rent", 2 => "Affordable Rent", 3 => "Intermediate Rent" }.freeze
HAS_BENEFITS_OPTIONS = [1, 6, 8, 7].freeze
- NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52 }.freeze
+ NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 1 => 52, 10 => 53 }.freeze
SUFFIX_FROM_PERIOD = { 2 => "every 2 weeks", 3 => "every 4 weeks", 4 => "every month" }.freeze
RETIREMENT_AGES = { "M" => 67, "F" => 60, "X" => 67 }.freeze
@@ -203,7 +203,7 @@ class LettingsLog < Log
needstype == 2
end
- def has_hbrentshortfall?
+ def has_housing_benefit_rent_shortfall?
# 1: Yes
hbrentshortfall == 1
end
@@ -506,7 +506,27 @@ class LettingsLog < Log
end
def care_home_charge_expected_not_provided?
- is_carehome == 1 && chcharge.blank?
+ is_carehome? && chcharge.blank?
+ end
+
+ def rent_and_charges_paid_weekly?
+ [1, 5, 6, 7, 8, 9, 10].include? period
+ end
+
+ def rent_and_charges_paid_every_4_weeks?
+ period == 3
+ end
+
+ def rent_and_charges_paid_every_2_weeks?
+ period == 2
+ end
+
+ def rent_and_charges_paid_monthly?
+ period == 4
+ end
+
+ def is_carehome?
+ is_carehome == 1
end
private
diff --git a/app/models/location.rb b/app/models/location.rb
index c2c2e5b4d..57393d9fb 100644
--- a/app/models/location.rb
+++ b/app/models/location.rb
@@ -24,6 +24,7 @@ class Location < ApplicationRecord
scope :started, -> { where("startdate <= ?", Time.zone.today).or(where(startdate: nil)) }
scope :active, -> { where(confirmed: true).and(started) }
scope :confirmed, -> { where(confirmed: true) }
+ scope :unconfirmed, -> { where.not(confirmed: true) }
LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h
diff --git a/app/models/log.rb b/app/models/log.rb
index 6a36b948d..33d3c4547 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -1,4 +1,6 @@
class Log < ApplicationRecord
+ include CollectionTimeHelper
+
self.abstract_class = true
belongs_to :owning_organisation, class_name: "Organisation", optional: true
@@ -50,6 +52,7 @@ class Log < ApplicationRecord
presenter = UprnDataPresenter.new(service.result)
+ self.uprn_known = 1
self.uprn_confirmed = nil
self.address_line1 = presenter.address_line1
self.address_line2 = presenter.address_line2
@@ -87,6 +90,8 @@ class Log < ApplicationRecord
end
def collection_period_open?
+ return false if older_than_previous_collection_year?
+
form.end_date > Time.zone.today
end
@@ -126,8 +131,20 @@ class Log < ApplicationRecord
end
end
+ def field_formatted_as_currency(field_name)
+ field_value = public_send(field_name)
+ format_as_currency(field_value)
+ end
+
private
+ # Handle logs that are older than previous collection start date
+ def older_than_previous_collection_year?
+ return false unless startdate
+
+ startdate < previous_collection_start_date
+ end
+
def plural_gender_for_person(person_num)
gender = public_send("sex#{person_num}".to_sym)
return unless gender
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
index 38beb850f..ebb3ef4e3 100644
--- a/app/models/sales_log.rb
+++ b/app/models/sales_log.rb
@@ -43,7 +43,7 @@ class SalesLog < Log
}
scope :filter_by_organisation, ->(org, _user = nil) { where(owning_organisation: org) }
- OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check].freeze
+ OPTIONAL_FIELDS = %w[saledate_check purchid monthly_charges_value_check old_persons_shared_ownership_value_check othtype discounted_sale_value_check buyer_livein_value_check].freeze
RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze
def lettings?
@@ -216,7 +216,7 @@ class SalesLog < Log
def expected_shared_ownership_deposit_value
return unless value && equity
- format_as_currency(value * equity / 100)
+ value * equity / 100
end
def process_postcode(postcode, postcode_known_key, la_inferred_key, la_key)
@@ -323,11 +323,6 @@ class SalesLog < Log
format_as_currency(soft_min)
end
- def field_formatted_as_currency(field_name)
- field_value = public_send(field_name)
- format_as_currency(field_value)
- end
-
def should_process_uprn_change?
uprn_changed? && saledate && saledate.year >= 2023
end
@@ -350,4 +345,15 @@ class SalesLog < Log
def beds_for_la_sale_range
beds.nil? ? nil : [beds, LaSaleRange::MAX_BEDS].min
end
+
+ def ownership_scheme
+ case ownershipsch
+ when 1
+ "shared ownership"
+ when 2
+ "discounted ownership"
+ when 3
+ "outright sale"
+ end
+ end
end
diff --git a/app/models/scheme.rb b/app/models/scheme.rb
index 8418f9393..75b37dec6 100644
--- a/app/models/scheme.rb
+++ b/app/models/scheme.rb
@@ -161,18 +161,6 @@ class Scheme < ApplicationRecord
]
end
- def synonyms
- locations.map(&:postcode).join(",")
- end
-
- def appended_text
- "#{locations.count { |location| location.startdate.blank? || location.startdate <= Time.zone.today }} locations"
- end
-
- def hint
- [primary_client_group, secondary_client_group].filter(&:present?).join(", ")
- end
-
def care_acts_options_with_hints
hints = { "Yes – part registered as a care home": "A proportion of units are registered as being a care home." }
diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb
index 7c684c4dd..857c4e193 100644
--- a/app/models/validations/financial_validations.rb
+++ b/app/models/validations/financial_validations.rb
@@ -4,7 +4,7 @@ module Validations::FinancialValidations
# Validations methods need to be called 'validate_' to run on model save
# or 'validate_' to run on submit as well
def validate_outstanding_rent_amount(record)
- if !record.has_hbrentshortfall? && record.tshortfall.present?
+ if !record.has_housing_benefit_rent_shortfall? && record.tshortfall.present?
record.errors.add :tshortfall, :no_outstanding_charges, message: I18n.t("validations.financial.tshortfall.outstanding_amount_not_required")
end
end
@@ -69,7 +69,7 @@ module Validations::FinancialValidations
end
def validate_tshortfall(record)
- if record.has_hbrentshortfall? && no_known_benefits?(record)
+ if record.has_housing_benefit_rent_shortfall? && no_known_benefits?(record)
record.errors.add :tshortfall, I18n.t("validations.financial.hbrentshortfall.outstanding_no_benefits")
end
end
@@ -99,7 +99,7 @@ module Validations::FinancialValidations
end
if record.tcharge.present? && weekly_value_in_range(record, "tcharge", 0, 9.99)
- record.errors.add :tcharge, I18n.t("validations.financial.tcharge.under_10")
+ record.errors.add :tcharge, :under_10, message: I18n.t("validations.financial.tcharge.under_10")
end
answered_questions = [record.tcharge, record.chcharge].concat(record.household_charge && record.household_charge == 1 ? [record.household_charge] : [])
@@ -224,7 +224,7 @@ private
end
if record.weekly_value(record["brent"]) > rent_range.hard_max
- record.errors.add :brent, I18n.t("validations.financial.brent.above_hard_max")
+ record.errors.add :brent, :over_hard_max, message: I18n.t("validations.financial.brent.above_hard_max")
record.errors.add :beds, I18n.t("validations.financial.brent.beds.above_hard_max")
record.errors.add :la, I18n.t("validations.financial.brent.la.above_hard_max")
record.errors.add :postcode_known, I18n.t("validations.financial.brent.postcode_known.above_hard_max")
diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb
index e4714e81a..42dbde2a5 100644
--- a/app/models/validations/sales/sale_information_validations.rb
+++ b/app/models/validations/sales/sale_information_validations.rb
@@ -48,7 +48,7 @@ module Validations::Sales::SaleInformationValidations
end
def validate_discounted_ownership_value(record)
- return unless record.saledate && collection_start_year(record.saledate) >= 2024
+ return unless record.saledate && collection_start_year_for_date(record.saledate) >= 2024
return unless record.value && record.deposit && record.ownershipsch
return unless record.mortgage || record.mortgageused == 2
return unless record.discount || record.grant || record.type == 29
diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb
index d72118d05..19d150c7e 100644
--- a/app/models/validations/sales/soft_validations.rb
+++ b/app/models/validations/sales/soft_validations.rb
@@ -123,6 +123,30 @@ module Validations::Sales::SoftValidations
mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale?
end
+ def buyer1_livein_wrong_for_ownership_type?
+ return unless ownershipsch && buy1livein
+
+ (discounted_ownership_sale? || shared_ownership_scheme?) && buy1livein == 2
+ end
+
+ def buyer2_livein_wrong_for_ownership_type?
+ return unless ownershipsch && buy2livein
+ return unless joint_purchase?
+
+ (discounted_ownership_sale? || shared_ownership_scheme?) && buy2livein == 2
+ end
+
+ def percentage_discount_invalid?
+ return unless discount && proptype
+
+ case proptype
+ when 1, 2
+ discount > 50
+ when 3, 4, 9
+ discount > 35
+ end
+ end
+
private
def sale_range
diff --git a/app/models/validations/setup_validations.rb b/app/models/validations/setup_validations.rb
index 0865ebae6..bd12d3249 100644
--- a/app/models/validations/setup_validations.rb
+++ b/app/models/validations/setup_validations.rb
@@ -20,6 +20,14 @@ module Validations::SetupValidations
location_during_startdate_validation(record, :location_id)
end
+ def validate_scheme_has_confirmed_locations_validation(record)
+ return unless record.scheme
+
+ unless record.scheme.locations.confirmed.any?
+ record.errors.add :scheme_id, I18n.t("validations.scheme.no_completed_locations")
+ end
+ end
+
def validate_scheme(record)
location_during_startdate_validation(record, :scheme_id)
scheme_during_startdate_validation(record, :scheme_id)
diff --git a/app/models/validations/shared_validations.rb b/app/models/validations/shared_validations.rb
index 57e1d05c6..f032a089c 100644
--- a/app/models/validations/shared_validations.rb
+++ b/app/models/validations/shared_validations.rb
@@ -7,6 +7,7 @@ module Validations::SharedValidations
main_field_label = main_label || main_field.to_s.humanize(capitalize: false)
other_field_label = other_label || other_field.to_s.humanize(capitalize: false)
if record[main_field] == value_other && record[other_field].blank?
+ record.errors.add main_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:)
end
diff --git a/app/services/bulk_upload/lettings/year2022/row_parser.rb b/app/services/bulk_upload/lettings/year2022/row_parser.rb
index 255aabe97..bfb7940ed 100644
--- a/app/services/bulk_upload/lettings/year2022/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2022/row_parser.rb
@@ -14,37 +14,37 @@ class BulkUpload::Lettings::Year2022::RowParser
field_9: "What is the tenancy type?",
field_10: "If 'Other', what is the tenancy type?",
field_11: "What is the length of the fixed-term tenancy to the nearest year?",
- field_12: "Age of Person 1",
- field_13: "Age of Person 2",
- field_14: "Age of Person 3",
- field_15: "Age of Person 4",
- field_16: "Age of Person 5",
- field_17: "Age of Person 6",
- field_18: "Age of Person 7",
- field_19: "Age of Person 8",
- field_20: "Gender identity of Person 1",
- field_21: "Gender identity of Person 2",
- field_22: "Gender identity of Person 3",
- field_23: "Gender identity of Person 4",
- field_24: "Gender identity of Person 5",
- field_25: "Gender identity of Person 6",
- field_26: "Gender identity of Person 7",
- field_27: "Gender identity of Person 8",
- field_28: "Relationship to Person 1 for Person 2",
- field_29: "Relationship to Person 1 for Person 3",
- field_30: "Relationship to Person 1 for Person 4",
- field_31: "Relationship to Person 1 for Person 5",
- field_32: "Relationship to Person 1 for Person 6",
- field_33: "Relationship to Person 1 for Person 7",
- field_34: "Relationship to Person 1 for Person 8",
- field_35: "Working situation of Person 1",
- field_36: "Working situation of Person 2",
- field_37: "Working situation of Person 3",
- field_38: "Working situation of Person 4",
- field_39: "Working situation of Person 5",
- field_40: "Working situation of Person 6",
- field_41: "Working situation of Person 7",
- field_42: "Working situation of Person 8",
+ field_12: "Age of person 1",
+ field_13: "Age of person 2",
+ field_14: "Age of person 3",
+ field_15: "Age of person 4",
+ field_16: "Age of person 5",
+ field_17: "Age of person 6",
+ field_18: "Age of person 7",
+ field_19: "Age of person 8",
+ field_20: "Gender identity of person 1",
+ field_21: "Gender identity of person 2",
+ field_22: "Gender identity of person 3",
+ field_23: "Gender identity of person 4",
+ field_24: "Gender identity of person 5",
+ field_25: "Gender identity of person 6",
+ field_26: "Gender identity of person 7",
+ field_27: "Gender identity of person 8",
+ field_28: "Relationship to person 1 for person 2",
+ field_29: "Relationship to person 1 for person 3",
+ field_30: "Relationship to person 1 for person 4",
+ field_31: "Relationship to person 1 for person 5",
+ field_32: "Relationship to person 1 for person 6",
+ field_33: "Relationship to person 1 for person 7",
+ field_34: "Relationship to person 1 for person 8",
+ field_35: "Working situation of person 1",
+ field_36: "Working situation of person 2",
+ field_37: "Working situation of person 3",
+ field_38: "Working situation of person 4",
+ field_39: "Working situation of person 5",
+ field_40: "Working situation of person 6",
+ field_41: "Working situation of person 7",
+ field_42: "Working situation of person 8",
field_43: "What is the lead tenant's ethnic group?",
field_44: "What is the lead tenant's nationality?",
field_45: "Does anybody in the household have links to the UK armed forces?",
@@ -340,10 +340,10 @@ class BulkUpload::Lettings::Year2022::RowParser
return true if blank_row?
- super
-
log.valid?
+ super
+
log.errors.each do |error|
fields = field_mapping_for_errors[error.attribute] || []
@@ -650,7 +650,7 @@ private
end
def questions
- log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
+ @questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
end
def validate_nulls
diff --git a/app/services/bulk_upload/lettings/year2023/row_parser.rb b/app/services/bulk_upload/lettings/year2023/row_parser.rb
index 60b5477ce..43b229aa3 100644
--- a/app/services/bulk_upload/lettings/year2023/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2023/row_parser.rb
@@ -292,6 +292,7 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, allow_blank: true
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, allow_blank: true
+ validates :field_6, presence: { message: I18n.t("validations.not_answered", question: "property renewal") }
validates :field_7, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (day)") }
validates :field_8, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (month)") }
validates :field_9, presence: { message: I18n.t("validations.not_answered", question: "tenancy start date (year)") }
@@ -342,10 +343,10 @@ class BulkUpload::Lettings::Year2023::RowParser
return true if blank_row?
- super
-
log.valid?
+ super
+
log.errors.each do |error|
fields = field_mapping_for_errors[error.attribute] || []
@@ -826,7 +827,7 @@ private
end
def questions
- log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
+ @questions ||= log.form.subsections.flat_map { |ss| ss.applicable_questions(log) }
end
def attributes_for_log
@@ -1050,8 +1051,6 @@ private
1
when 2
0
- when nil
- rsnvac == 14 ? 1 : 0
else
field_6
end
diff --git a/app/services/bulk_upload/sales/year2022/row_parser.rb b/app/services/bulk_upload/sales/year2022/row_parser.rb
index 965c3547a..6f38654e6 100644
--- a/app/services/bulk_upload/sales/year2022/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2022/row_parser.rb
@@ -9,29 +9,29 @@ class BulkUpload::Sales::Year2022::RowParser
field_4: "What is the year of the sale completion date? - YY",
field_5: "This question has been removed",
field_6: "Was the buyer interviewed for any of the answers you will provide on this log?",
- field_7: "Age of Buyer 1",
- field_8: "Age of Person 2",
- field_9: "Age of Person 3",
- field_10: "Age of Person 4",
- field_11: "Age of Person 5",
- field_12: "Age of Person 6",
- field_13: "Gender identity of Buyer 1",
- field_14: "Gender identity of Person 2",
- field_15: "Gender identity of Person 3",
- field_16: "Gender identity of Person 4",
- field_17: "Gender identity of Person 5",
- field_18: "Gender identity of Person 6",
- field_19: "Relationship to Buyer 1 for Person 2",
- field_20: "Relationship to Buyer 1 for Person 3",
- field_21: "Relationship to Buyer 1 for Person 4",
- field_22: "Relationship to Buyer 1 for Person 5",
- field_23: "Relationship to Buyer 1 for Person 6",
- field_24: "Working situation of Buyer 1",
- field_25: "Working situation of Person 2",
- field_26: "Working situation of Person 3",
- field_27: "Working situation of Person 4",
- field_28: "Working situation of Person 5",
- field_29: "Working situation of Person 6",
+ field_7: "Age of buyer 1",
+ field_8: "Age of person 2",
+ field_9: "Age of person 3",
+ field_10: "Age of person 4",
+ field_11: "Age of person 5",
+ field_12: "Age of person 6",
+ field_13: "Gender identity of buyer 1",
+ field_14: "Gender identity of person 2",
+ field_15: "Gender identity of person 3",
+ field_16: "Gender identity of person 4",
+ field_17: "Gender identity of person 5",
+ field_18: "Gender identity of person 6",
+ field_19: "Relationship to buyer 1 for person 2",
+ field_20: "Relationship to buyer 1 for person 3",
+ field_21: "Relationship to buyer 1 for person 4",
+ field_22: "Relationship to buyer 1 for person 5",
+ field_23: "Relationship to buyer 1 for person 6",
+ field_24: "Working situation of buyer 1",
+ field_25: "Working situation of person 2",
+ field_26: "Working situation of person 3",
+ field_27: "Working situation of person 4",
+ field_28: "Working situation of person 5",
+ field_29: "Working situation of person 6",
field_30: "What is buyer 1's ethnic group?",
field_31: "What is buyer 1's nationality?",
field_32: "What is buyer 1's gross annual income?",
diff --git a/app/services/exports/lettings_log_export_service.rb b/app/services/exports/lettings_log_export_service.rb
index 1592f545d..429361913 100644
--- a/app/services/exports/lettings_log_export_service.rb
+++ b/app/services/exports/lettings_log_export_service.rb
@@ -12,19 +12,20 @@ module Exports
start_time = Time.zone.now
logs_by_collection = retrieve_lettings_logs(start_time, full_update).group_by(&:collection_start_year)
daily_run_number = get_daily_run_number
- archives_for_manifest = []
+ archives_for_manifest = {}
base_number = LogsExport.where(empty_export: false).maximum(:base_number) || 1
available_collection_years.each do |collection|
lettings_logs = logs_by_collection.fetch(collection, LettingsLog.none)
export = build_export_run(collection, start_time, base_number, full_update)
archives = write_export_archive(export, lettings_logs)
- archives_for_manifest << archives if archives.any?
+ archives_for_manifest.merge!(archives)
+
export.empty_export = archives.empty?
export.save!
end
- write_master_manifest(daily_run_number, archives_for_manifest.flatten)
+ write_master_manifest(daily_run_number, archives_for_manifest)
end
private
@@ -129,7 +130,7 @@ module Exports
headers = ["zip-name", "date-time zipped folder generated", "zip-file-uri"]
csv_string = CSV.generate do |csv|
csv << headers
- archive_datetimes.each do |archive, datetime|
+ archive_datetimes.each do |(archive, datetime)|
csv << [archive, datetime, "#{archive}.zip"]
end
end
diff --git a/config/initializers/feature_toggle.rb b/app/services/feature_toggle.rb
similarity index 86%
rename from config/initializers/feature_toggle.rb
rename to app/services/feature_toggle.rb
index 125aa6770..eed6244d1 100644
--- a/config/initializers/feature_toggle.rb
+++ b/app/services/feature_toggle.rb
@@ -36,7 +36,11 @@ class FeatureToggle
true
end
- def self.bulk_upload_logs?
+ def self.bulk_upload_lettings_logs?
+ !Rails.env.production?
+ end
+
+ def self.bulk_upload_sales_logs?
!Rails.env.production?
end
@@ -53,4 +57,8 @@ class FeatureToggle
def self.collection_2023_2024_year_enabled?
true
end
+
+ def self.merge_organisations_enabled?
+ !Rails.env.production?
+ end
end
diff --git a/app/services/imports/lettings_logs_import_service.rb b/app/services/imports/lettings_logs_import_service.rb
index 94fb2ec3e..01c71faef 100644
--- a/app/services/imports/lettings_logs_import_service.rb
+++ b/app/services/imports/lettings_logs_import_service.rb
@@ -302,6 +302,8 @@ module Imports
%i[supcharg outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
%i[scharge outside_the_range] => %w[brent scharge pscharge supcharg tcharge],
%i[location_id not_active] => %w[location_id scheme_id],
+ %i[tcharge under_10] => %w[brent scharge pscharge supcharg tcharge],
+ %i[brent over_hard_max] => %w[brent scharge pscharge supcharg tcharge],
}
(2..8).each do |person|
diff --git a/app/services/imports/sales_logs_import_service.rb b/app/services/imports/sales_logs_import_service.rb
index 2fb619619..2d6551189 100644
--- a/app/services/imports/sales_logs_import_service.rb
+++ b/app/services/imports/sales_logs_import_service.rb
@@ -155,6 +155,8 @@ module Imports
attributes["monthly_charges_value_check"] = 0
attributes["student_not_child_value_check"] = 0
attributes["discounted_sale_value_check"] = 0
+ attributes["buyer_livein_value_check"] = 0
+ attributes["percentage_discount_value_check"] = 0
# Sets the log creator
owner_id = meta_field_value(xml_doc, "owner-user-id").strip
@@ -278,7 +280,9 @@ module Imports
hodate_check
saledate_check
student_not_child_value_check
- discounted_sale_value_check]
+ discounted_sale_value_check
+ buyer_livein_value_check
+ percentage_discount_value_check]
end
def check_status_completed(sales_log, previous_status)
diff --git a/app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb b/app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb
index f38178b7e..7524072a5 100644
--- a/app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb
+++ b/app/views/bulk_upload_lettings_logs/forms/checking_file.html.erb
@@ -10,14 +10,14 @@
Upload lettings logs in bulk (<%= @form.year_combo %>)
We’re checking the file
-
Once this is done, we’ll email you the outcome.
+
Once this is done, we’ll email you the outcome.
- We’re checking for any missing data, issues or errors. Depending on the file size, this could take a few minutes.
+ We’re checking for any missing data, issues or errors. Depending on file size, this could take a few minutes.
- If there are errors we will email you a link to view all the errors.
+ If there are errors, we will email you to let you know how to fix them.
Fill in the template with CORE data from your housing management system according to the <%= govuk_link_to "Lettings #{@form.year_combo} Bulk Upload Specification", @form.specification_path %>
+
Username field: To assign a log to someone else, enter the email address they use to log into CORE
If you have to manually enter large volumes of data into the bulk upload template, we recommend creating logs directly in the service instead. <%= govuk_link_to "Find out more about exporting your data", bulk_upload_lettings_log_path(id: "guidance", form: { year: @form.year }) %>
- We’re checking for any missing data, issues or errors. Depending on the file size, this could take a few minutes.
+ We’re checking for any missing data, issues or errors. Depending on file size, this could take a few minutes.
- If there are errors we will email you a link to view all the errors.
+ If there are errors, we will email you to let you know how to fix them.
Fill in the template with CORE data from your housing management system according to the <%= govuk_link_to "Sales #{@form.year_combo} Bulk Upload Specification", @form.specification_path %>
+
Username field: To assign a log to someone else, enter the email address they use to log into CORE
If you have to manually enter large volumes of data into the bulk upload template, we recommend creating logs directly in the service instead. <%= govuk_link_to "Find out more about exporting your data", bulk_upload_sales_log_path(id: "guidance", form: { year: @form.year }) %>
<% end %>
diff --git a/app/views/organisations/merge.html.erb b/app/views/organisations/merge.html.erb
new file mode 100644
index 000000000..7d72d08b7
--- /dev/null
+++ b/app/views/organisations/merge.html.erb
@@ -0,0 +1,48 @@
+<% content_for :before_content do %>
+ <% title = "Tell us if your organisation is merging" %>
+ <% content_for :title, title %>
+
+ <%= govuk_back_link href: organisation_path %>
+<% end %>
+
Tell us if your organisation is merging
+
+
+
+
+ Use this service to tell us if your organisation is merging with one or more other organisations. You can also use it to tell us about past merges that have not yet been reported to CORE.
+
+
+
Before you start
+
Regardless of the merge type, you’ll be asked for:
+
+
the organisations merging in CORE
+
the merge type: for example one organisation absorbing the rest, or them all creating a new organisation
+
to confirm or update the telephone number
+
the merge date
+
if user email addresses will change with this merge
+
+
+
If email addresses are changing
+ <%= govuk_inset_text(text: "Update all user email addresses on CORE as soon as they change, so that everyone can still access their CORE account. ") %>
+
+ Users must have access to their old email address, so they can confirm their new one.
+
+
+
If merging into a new organisation
+
You'll also be asked for the new organisation’s:
+
+
name
+
address
+
telephone number
+
housing provider type
+
Regulator of Social Housing registration number
+
held stock details
+
+
+ <%= govuk_warning_text text: "You will not be able to submit your request without the above information. Do not start the form until you have obtained all of the information. " %>
+ <%= govuk_start_button(
+ text: "Start now",
+ href: "#",
+ ) %>
+
+
diff --git a/app/views/organisations/show.html.erb b/app/views/organisations/show.html.erb
index bbe9ae67a..4561e985b 100644
--- a/app/views/organisations/show.html.erb
+++ b/app/views/organisations/show.html.erb
@@ -35,6 +35,9 @@
<% end %>
<% end %>
+ <% if FeatureToggle.merge_organisations_enabled? %>
+
Is your organisation merging with another? <%= govuk_link_to "Let us know using this form", merge_organisation_path %>
diff --git a/app/views/schemes/primary_client_group.html.erb b/app/views/schemes/primary_client_group.html.erb
index 610e916f4..8fe852c89 100644
--- a/app/views/schemes/primary_client_group.html.erb
+++ b/app/views/schemes/primary_client_group.html.erb
@@ -7,10 +7,7 @@
<% end %>
<% content_for :before_content do %>
- <%= govuk_back_link(
- text: "Back",
- href: back_button_path,
- ) %>
+ <%= govuk_back_link(href: back_button_path) %>
<% end %>
<%= form_for(@scheme, method: :patch) do |f| %>
diff --git a/app/views/schemes/secondary_client_group.html.erb b/app/views/schemes/secondary_client_group.html.erb
index 4f48dab00..fe292b1c2 100644
--- a/app/views/schemes/secondary_client_group.html.erb
+++ b/app/views/schemes/secondary_client_group.html.erb
@@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
- text: "Back",
href: request.query_parameters["check_answers"] ? "/schemes/#{@scheme.id}/check-answers" : "/schemes/#{@scheme.id}/confirm-secondary-client-group",
) %>
<% end %>
diff --git a/app/views/schemes/show.html.erb b/app/views/schemes/show.html.erb
index 5ef55f9f4..beb4508e0 100644
--- a/app/views/schemes/show.html.erb
+++ b/app/views/schemes/show.html.erb
@@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
- text: "Back",
href: "/schemes",
) %>
<% end %>
diff --git a/app/views/schemes/support.html.erb b/app/views/schemes/support.html.erb
index 0c06a059f..23948978b 100644
--- a/app/views/schemes/support.html.erb
+++ b/app/views/schemes/support.html.erb
@@ -2,7 +2,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
- text: "Back",
href: request.query_parameters["check_answers"] ? "/schemes/#{@scheme.id}/check-answers" : "/schemes/#{@scheme.id}/secondary-client-group",
) %>
<% end %>
diff --git a/app/views/schemes/toggle_active.html.erb b/app/views/schemes/toggle_active.html.erb
index f2ecc4a1a..e989be995 100644
--- a/app/views/schemes/toggle_active.html.erb
+++ b/app/views/schemes/toggle_active.html.erb
@@ -3,7 +3,6 @@
<% content_for :before_content do %>
<%= govuk_back_link(
- text: "Back",
href: scheme_details_path(@scheme),
) %>
<% end %>
diff --git a/config/forms/2022_2023.json b/config/forms/2022_2023.json
index e13ce5516..9b5aa6bb8 100644
--- a/config/forms/2022_2023.json
+++ b/config/forms/2022_2023.json
@@ -7492,23 +7492,26 @@
"4": {
"value": "Every calendar month"
},
- "5": {
- "value": "Weekly for 50 weeks"
+ "9": {
+ "value": "Weekly for 46 weeks"
},
- "6": {
- "value": "Weekly for 49 weeks"
+ "8": {
+ "value": "Weekly for 47 weeks"
},
"7": {
"value": "Weekly for 48 weeks"
},
- "8": {
- "value": "Weekly for 47 weeks"
+ "6": {
+ "value": "Weekly for 49 weeks"
},
- "9": {
- "value": "Weekly for 46 weeks"
+ "5": {
+ "value": "Weekly for 50 weeks"
},
"1": {
"value": "Weekly for 52 weeks"
+ },
+ "10": {
+ "value": "Weekly for 53 weeks"
}
}
}
@@ -7558,63 +7561,13 @@
},
"depends_on": [
{
- "period": 1,
- "needstype": 2,
+ "rent_and_charges_paid_weekly?": true,
+ "is_supported_housing?": true,
"household_charge": 0
},
{
- "period": 1,
- "needstype": 2,
- "household_charge": null
- },
- {
- "period": 5,
- "needstype": 2,
- "household_charge": 0
- },
- {
- "period": 5,
- "needstype": 2,
- "household_charge": null
- },
- {
- "period": 6,
- "needstype": 2,
- "household_charge": 0
- },
- {
- "period": 6,
- "needstype": 2,
- "household_charge": null
- },
- {
- "period": 7,
- "needstype": 2,
- "household_charge": 0
- },
- {
- "period": 7,
- "needstype": 2,
- "household_charge": null
- },
- {
- "period": 8,
- "needstype": 2,
- "household_charge": 0
- },
- {
- "period": 8,
- "needstype": 2,
- "household_charge": null
- },
- {
- "period": 9,
- "needstype": 2,
- "household_charge": 0
- },
- {
- "period": 9,
- "needstype": 2,
+ "rent_and_charges_paid_weekly?": true,
+ "is_supported_housing?": true,
"household_charge": null
}
]
@@ -7898,124 +7851,14 @@
},
"depends_on": [
{
- "period": 1,
- "household_charge": 0,
- "is_carehome": 0
- },
- {
- "period": 1,
- "household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 5,
- "household_charge": 0,
- "is_carehome": 0
- },
- {
- "period": 5,
- "household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 6,
- "household_charge": 0,
- "is_carehome": 0
- },
- {
- "period": 6,
- "household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 7,
- "household_charge": 0,
- "is_carehome": 0
- },
- {
- "period": 7,
- "household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 8,
+ "rent_and_charges_paid_weekly?": true,
"household_charge": 0,
- "is_carehome": 0
+ "is_carehome?": false
},
{
- "period": 8,
+ "rent_and_charges_paid_weekly?": true,
"household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 9,
- "household_charge": 0,
- "is_carehome": 0
- },
- {
- "period": 9,
- "household_charge": null,
- "is_carehome": 0
- },
- {
- "period": 1,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 1,
- "household_charge": null,
- "is_carehome": null
- },
- {
- "period": 5,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 5,
- "household_charge": null,
- "is_carehome": null
- },
- {
- "period": 6,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 6,
- "household_charge": null,
- "is_carehome": null
- },
- {
- "period": 7,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 7,
- "household_charge": null,
- "is_carehome": null
- },
- {
- "period": 8,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 8,
- "household_charge": null,
- "is_carehome": null
- },
- {
- "period": 9,
- "household_charge": 0,
- "is_carehome": null
- },
- {
- "period": 9,
- "household_charge": null,
- "is_carehome": null
+ "is_carehome?": false
}
]
},
@@ -8602,6 +8445,12 @@
"depends_on": {
"period": 1
}
+ },
+ {
+ "label": " every week for 53 weeks",
+ "depends_on": {
+ "period": 10
+ }
}
]
}
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
index 71d184ad6..928c8f671 100644
--- a/config/initializers/filter_parameter_logging.rb
+++ b/config/initializers/filter_parameter_logging.rb
@@ -2,5 +2,5 @@
# Configure sensitive parameters which will be filtered from the log file.
Rails.application.config.filter_parameters += %i[
- passw secret token crypt salt certificate otp ssn
+ passw secret token crypt salt certificate otp ssn reset_password_token
]
diff --git a/config/locales/en.yml b/config/locales/en.yml
index e223c7fc9..eef342674 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -190,11 +190,11 @@ en:
reactivating_soon: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date"
activating_soon: "%{name} is not available until %{date}. Enter a tenancy start date after %{date}"
owning_organisation:
- invalid: "Please select owning organisation or managing organisation that you belong to"
+ invalid: "Please select the owning organisation or managing organisation that you belong to"
managing_organisation:
- invalid: "Please select owning organisation or managing organisation that you belong to"
+ invalid: "Please select the owning organisation or managing organisation that you belong to"
created_by:
- invalid: "Please select owning organisation or managing organisation that you belong to"
+ invalid: "Please select the owning organisation or managing organisation that you belong to"
lettype:
general_needs_mismatch: Lettings type must be a general needs type because you selected general needs when uploading the file
supported_housing_mismatch: Lettings type must be a supported housing type because you selected supported housing when uploading the file
@@ -253,10 +253,10 @@ en:
freq_missing: "Select how often the household receives income"
earnings_missing: "Enter how much income the household has in total"
income:
- over_hard_max_for_london: "Income must not exceed £90,000.00 for properties within London local authorities"
- over_hard_max_for_outside_london: "Income must not exceed £80,000.00 for properties outside London local authorities"
- combined_over_hard_max_for_london: "Combined income must not exceed £90,000.00 for properties within London local authorities"
- combined_over_hard_max_for_outside_london: "Combined income must not exceed £80,000.00 for properties outside London local authorities"
+ over_hard_max_for_london: "Income must be £90,000 or lower for properties within a London local authority"
+ over_hard_max_for_outside_london: "Income must be £80,000 or lower for properties outside London local authority"
+ combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority"
+ combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities"
child_has_income: "Child's income must be £0"
negative_currency: "Enter an amount above 0"
rent:
@@ -283,7 +283,7 @@ en:
general_needs: "Enter a value for the support charge between £0 and £60 per week if the landlord is a local authority and it is a general needs letting"
supported_housing: "Enter a value for the support charge between £0 and £120 per week if the landlord is a local authority and it is a supported housing letting"
ecstat:
- over_hard_max: "Net income of £%{hard_max} per week is too high for given the tenant’s working situation"
+ over_hard_max: "Net income of %{hard_max} per week is too high given the tenant’s working situation"
brent:
below_hard_min: "Rent is below the absolute minimum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms"
@@ -314,7 +314,7 @@ en:
charges:
complete_1_of_3: "Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’"
tcharge:
- under_10: "Enter a total charge that is at least £10 per week"
+ under_10: "Enter a total charge that is at least £10.00 per week"
rent_period:
invalid_for_org: "%{org_name} does not charge rent %{rent_period}"
carehome:
@@ -466,6 +466,7 @@ en:
during_deactivated_period: "The scheme is already deactivated during this date, please enter a different date"
owning_organisation:
does_not_own_stock: "Enter an organisation that owns housing stock"
+ no_completed_locations: "This scheme cannot be chosen as it has no completed locations"
location:
postcode_blank: "Enter a postcode"
@@ -516,8 +517,8 @@ en:
under_soft_min_for_economic_status: "You said income was %{income}, which is below this working situation's minimum (%{minimum})"
rent:
outside_range_title: "You told us the rent is %{brent}"
- min_hint_text: "The minimum rent expected for this type of property in this local authority is £%{soft_min_for_period}."
- max_hint_text: "The maximum rent expected for this type of property in this local authority is £%{soft_max_for_period}."
+ min_hint_text: "The minimum rent expected for this type of property in this local authority is %{soft_min_for_period}."
+ max_hint_text: "The maximum rent expected for this type of property in this local authority is %{soft_max_for_period}."
purchase_price:
title_text: "You told us the purchase price is %{value}"
hint_text: "The %{min_or_max} purchase price expected for this type of property in this local authority is %{soft_min_or_soft_max}"
@@ -539,7 +540,7 @@ en:
void_date:
title_text: "You told us the time between the start of the tenancy and the void date is more than 2 years"
shared_ownership_deposit:
- title_text: "Mortgage, deposit and cash discount total should equal £%{expected_shared_ownership_deposit_value}"
+ title_text: "Mortgage, deposit and cash discount total should equal %{expected_shared_ownership_deposit_value}"
old_persons_shared_ownership: "At least one buyer should be aged over 64 for Older persons’ shared ownership scheme"
staircase_bought_seems_high: "You said %{percentage}% was bought in this staircasing transaction, which seems high. Are you sure?"
monthly_charges_over_soft_max:
@@ -547,10 +548,16 @@ en:
student_not_child:
title_text: "You told us this person is a student aged beween 16 and 19"
discounted_sale_value:
- title_text: "Mortgage, deposit, and grant total must equal £%{value_with_discount}"
- informative_text: "Your given mortgage, deposit and grant total is £%{mortgage_deposit_and_grant_total}"
+ title_text: "Mortgage, deposit, and grant total must equal %{value_with_discount}"
+ informative_text: "Your given mortgage, deposit and grant total is %{mortgage_deposit_and_grant_total}"
care_home_charges:
title_text: "Care home charges should be provided if this is a care home accommodation"
+ buyer1_livein_wrong_for_ownership_type:
+ title_text: "You told us that buyer 1 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
+ buyer2_livein_wrong_for_ownership_type:
+ title_text: "You told us that buyer 2 will not live in the property. For %{ownership_scheme} types, the buyer usually lives in the property."
+ percentage_discount_value:
+ title_text: "You told us that the percentage discount was %{discount}. This seems high for this type of property."
devise:
two_factor_authentication:
diff --git a/config/routes.rb b/config/routes.rb
index c01f38027..f6e00083b 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -119,6 +119,7 @@ Rails.application.routes.draw do
get "managing-agents/remove", to: "organisation_relationships#remove_managing_agent"
post "managing-agents", to: "organisation_relationships#create_managing_agent"
delete "managing-agents", to: "organisation_relationships#delete_managing_agent"
+ get "merge", to: "organisations#merge"
end
end
diff --git a/db/migrate/20230405074138_add_percentage_discount_value_check.rb b/db/migrate/20230405074138_add_percentage_discount_value_check.rb
new file mode 100644
index 000000000..adce0fe58
--- /dev/null
+++ b/db/migrate/20230405074138_add_percentage_discount_value_check.rb
@@ -0,0 +1,5 @@
+class AddPercentageDiscountValueCheck < ActiveRecord::Migration[7.0]
+ def change
+ add_column :sales_logs, :percentage_discount_value_check, :integer
+ end
+end
diff --git a/db/migrate/20230405140343_add_buyer_livin_value_check.rb b/db/migrate/20230405140343_add_buyer_livin_value_check.rb
new file mode 100644
index 000000000..feafc610b
--- /dev/null
+++ b/db/migrate/20230405140343_add_buyer_livin_value_check.rb
@@ -0,0 +1,5 @@
+class AddBuyerLivinValueCheck < ActiveRecord::Migration[7.0]
+ def change
+ add_column :sales_logs, :buyer_livein_value_check, :integer
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 53dbf448b..12dfe0481 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -573,6 +573,8 @@ ActiveRecord::Schema[7.0].define(version: 2023_04_12_143245) do
t.integer "nationalbuy2"
t.integer "discounted_sale_value_check"
t.integer "student_not_child_value_check"
+ t.integer "buyer_livein_value_check"
+ t.integer "percentage_discount_value_check"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"
t.index ["old_id"], name: "index_sales_logs_on_old_id", unique: true
diff --git a/public/files/bulk-upload-lettings-specification-2023-24.xlsx b/public/files/bulk-upload-lettings-specification-2023-24.xlsx
index 819fdaee0..6d964c8dd 100644
Binary files a/public/files/bulk-upload-lettings-specification-2023-24.xlsx and b/public/files/bulk-upload-lettings-specification-2023-24.xlsx differ
diff --git a/public/files/bulk-upload-lettings-template-2023-24.xlsx b/public/files/bulk-upload-lettings-template-2023-24.xlsx
index e97e67d25..e2c6cc27f 100644
Binary files a/public/files/bulk-upload-lettings-template-2023-24.xlsx and b/public/files/bulk-upload-lettings-template-2023-24.xlsx differ
diff --git a/public/files/bulk-upload-sales-specification-2023-24.xlsx b/public/files/bulk-upload-sales-specification-2023-24.xlsx
index d1927d275..a7122e397 100644
Binary files a/public/files/bulk-upload-sales-specification-2023-24.xlsx and b/public/files/bulk-upload-sales-specification-2023-24.xlsx differ
diff --git a/public/files/bulk-upload-sales-template-2023-24.xlsx b/public/files/bulk-upload-sales-template-2023-24.xlsx
index 59fce8b6f..de79ac6d6 100644
Binary files a/public/files/bulk-upload-sales-template-2023-24.xlsx and b/public/files/bulk-upload-sales-template-2023-24.xlsx differ
diff --git a/spec/components/bulk_upload_error_row_component_spec.rb b/spec/components/bulk_upload_error_row_component_spec.rb
index 665a630c8..85b2fe522 100644
--- a/spec/components/bulk_upload_error_row_component_spec.rb
+++ b/spec/components/bulk_upload_error_row_component_spec.rb
@@ -78,22 +78,6 @@ RSpec.describe BulkUploadErrorRowComponent, type: :component do
end
end
- context "when multiple errors for a row" do
- subject(:component) { described_class.new(bulk_upload_errors:) }
-
- let(:bulk_upload_errors) do
- [
- build(:bulk_upload_error, cell: "Z1"),
- build(:bulk_upload_error, cell: "AB1"),
- build(:bulk_upload_error, cell: "A1"),
- ]
- end
-
- it "is sorted by cell" do
- expect(component.bulk_upload_errors.map(&:cell)).to eql(%w[A1 Z1 AB1])
- end
- end
-
context "when a sales bulk upload" do
let(:bulk_upload) { create(:bulk_upload, :sales) }
let(:field) { :field_87 }
diff --git a/spec/features/form/accessible_autocomplete_spec.rb b/spec/features/form/accessible_autocomplete_spec.rb
index 15d23fe32..0ff03ec03 100644
--- a/spec/features/form/accessible_autocomplete_spec.rb
+++ b/spec/features/form/accessible_autocomplete_spec.rb
@@ -75,6 +75,7 @@ RSpec.describe "Accessible Autocomplete" do
before do
FactoryBot.create(:location, scheme:, postcode: "W6 0ST", startdate: Time.zone.local(2022, 1, 1))
FactoryBot.create(:location, scheme:, postcode: "SE6 1LB", startdate: Time.zone.local(2022, 1, 1))
+ FactoryBot.create(:location, scheme:, postcode: nil, startdate: Time.zone.local(2022, 1, 1), confirmed: false)
lettings_log.update!(needstype: 2)
visit("/lettings-logs/#{lettings_log.id}/scheme")
end
@@ -87,7 +88,7 @@ RSpec.describe "Accessible Autocomplete" do
it "displays appended text next to the options", js: true do
find("#lettings-log-scheme-id-field").click.native.send_keys("w", "6", :down, :enter)
expect(find(".autocomplete__option", visible: :hidden, text: scheme.service_name)).to be_present
- expect(find("span", visible: :hidden, text: "2 locations")).to be_present
+ expect(find("span", visible: :hidden, text: "2 completed locations, 1 incomplete location")).to be_present
end
it "displays hint text under the options", js: true do
diff --git a/spec/features/form/form_navigation_spec.rb b/spec/features/form/form_navigation_spec.rb
index aa0223616..6fdec8366 100644
--- a/spec/features/form/form_navigation_spec.rb
+++ b/spec/features/form/form_navigation_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe "Form Navigation" do
click_button("Save and continue")
click_link(text: "Back")
click_link(text: "Back")
- expect(page).to have_current_path("/lettings-logs")
+ expect(page).to have_current_path("/lettings-logs/#{id}")
end
context "when changing an answer from the check answers page", js: true do
diff --git a/spec/features/organisation_spec.rb b/spec/features/organisation_spec.rb
index bc6aa243a..7e25fe933 100644
--- a/spec/features/organisation_spec.rb
+++ b/spec/features/organisation_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe "User Features" do
expect(page).to have_current_path("/organisations/#{org_id}/details")
end
- context "when the user is a coordinator and the organisation does not hold housing stock" do
+ context "and the organisation does not hold housing stock" do
before do
organisation.update(holds_own_stock: false)
end
@@ -51,7 +51,7 @@ RSpec.describe "User Features" do
end
end
- context "when the user is a coordinator and the organisation holds housing stock" do
+ context "and the organisation holds housing stock" do
before do
organisation.update(holds_own_stock: true)
end
@@ -61,18 +61,6 @@ RSpec.describe "User Features" do
expect(page).to have_link("Schemes", href: "/schemes")
end
end
-
- context "when the user is support and the organisation does not hold housing stock" do
- before do
- organisation.update!(holds_own_stock: false)
- user.update!(role: "support")
- end
-
- it "does not show schemes in the primary or secondary navigation bar on the organisations page" do
- visit("/organisations")
- expect(page).not_to have_link("Schemes", href: "/schemes", count: 2)
- end
- end
end
context "when users are part of organisation" do
@@ -321,5 +309,16 @@ RSpec.describe "User Features" do
end
end
end
+
+ context "and the organisation does not hold housing stock" do
+ before do
+ organisation.update!(holds_own_stock: false)
+ end
+
+ it "does not show schemes in the primary or secondary navigation bar on the organisations page" do
+ visit("/organisations")
+ expect(page).not_to have_link("Schemes", href: "/schemes", count: 2)
+ end
+ end
end
end
diff --git a/spec/fixtures/forms/2021_2022.json b/spec/fixtures/forms/2021_2022.json
index ec13bdabb..97999d8a3 100644
--- a/spec/fixtures/forms/2021_2022.json
+++ b/spec/fixtures/forms/2021_2022.json
@@ -879,23 +879,26 @@
"4": {
"value": "Every calendar month"
},
- "5": {
- "value": "Weekly for 50 weeks"
+ "9": {
+ "value": "Weekly for 46 weeks"
},
- "6": {
- "value": "Weekly for 49 weeks"
+ "8": {
+ "value": "Weekly for 47 weeks"
},
"7": {
"value": "Weekly for 48 weeks"
},
- "8": {
- "value": "Weekly for 47 weeks"
+ "6": {
+ "value": "Weekly for 49 weeks"
},
- "9": {
- "value": "Weekly for 46 weeks"
+ "5": {
+ "value": "Weekly for 50 weeks"
},
"1": {
"value": "Weekly for 52 weeks"
+ },
+ "10": {
+ "value": "Weekly for 53 weeks"
}
}
},
diff --git a/spec/helpers/collection_time_helper_spec.rb b/spec/helpers/collection_time_helper_spec.rb
index 1537926ab..e9ec52292 100644
--- a/spec/helpers/collection_time_helper_spec.rb
+++ b/spec/helpers/collection_time_helper_spec.rb
@@ -50,7 +50,7 @@ RSpec.describe CollectionTimeHelper do
let(:now) { Time.utc(2022, 8, 3) }
it "returns the same year as the current start year" do
- expect(collection_start_year(now)).to eq(2022)
+ expect(collection_start_year_for_date(now)).to eq(2022)
end
it "returns the correct current start date" do
@@ -66,7 +66,7 @@ RSpec.describe CollectionTimeHelper do
let(:now) { Time.utc(2022, 2, 3) }
it "returns the previous year as the current start year" do
- expect(collection_start_year(now)).to eq(2021)
+ expect(collection_start_year_for_date(now)).to eq(2021)
end
it "returns the correct current start date" do
diff --git a/spec/helpers/interruption_screen_helper_spec.rb b/spec/helpers/interruption_screen_helper_spec.rb
index fba8782da..33553f39f 100644
--- a/spec/helpers/interruption_screen_helper_spec.rb
+++ b/spec/helpers/interruption_screen_helper_spec.rb
@@ -4,9 +4,9 @@ RSpec.describe InterruptionScreenHelper do
form_handler = FormHandler.instance
let(:form) { form_handler.get_form("test_form") }
let(:subsection) { form.get_subsection("household_characteristics") }
- let(:user) { FactoryBot.create(:user) }
+ let(:user) { create(:user) }
let(:lettings_log) do
- FactoryBot.create(
+ create(
:lettings_log,
:in_progress,
ecstat1: 1,
@@ -14,6 +14,7 @@ RSpec.describe InterruptionScreenHelper do
incfreq: 1,
created_by: user,
sex1: "F",
+ brent: 12_345,
)
end
@@ -45,7 +46,13 @@ RSpec.describe InterruptionScreenHelper do
],
}
expect(display_informative_text(informative_text, lettings_log))
- .to eq(I18n.t("soft_validations.net_income.hint_text", ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase, earnings: lettings_log.form.get_question("earnings", lettings_log).answer_label(lettings_log)))
+ .to eq(
+ I18n.t(
+ "soft_validations.net_income.hint_text",
+ ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase,
+ earnings: lettings_log.form.get_question("earnings", lettings_log).answer_label(lettings_log),
+ ),
+ )
end
end
@@ -62,7 +69,12 @@ RSpec.describe InterruptionScreenHelper do
],
}
expect(display_informative_text(informative_text, lettings_log))
- .to eq(I18n.t("test.one_argument", ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase))
+ .to eq(
+ I18n.t(
+ "test.one_argument",
+ ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase,
+ ),
+ )
end
end
@@ -84,7 +96,12 @@ RSpec.describe InterruptionScreenHelper do
],
}
expect(display_informative_text(informative_text, lettings_log))
- .to eq(I18n.t("test.one_argument", ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase))
+ .to eq(
+ I18n.t(
+ "test.one_argument",
+ ecstat1: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase,
+ ),
+ )
end
end
@@ -126,15 +143,15 @@ RSpec.describe InterruptionScreenHelper do
informative_text_hash = {
"arguments" => [
{
- "key" => "retirement_age_for_person",
- "arguments_for_key" => 1,
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "brent",
"i18n_template" => "argument",
},
],
}
- allow(lettings_log).to receive(:retirement_age_for_person)
+ allow(lettings_log).to receive(:field_formatted_as_currency)
display_informative_text(informative_text_hash, lettings_log)
- expect(lettings_log).to have_received(:retirement_age_for_person).with(1)
+ expect(lettings_log).to have_received(:field_formatted_as_currency).with("brent")
end
it "returns the correct text" do
@@ -143,13 +160,13 @@ RSpec.describe InterruptionScreenHelper do
"translation" => translation,
"arguments" => [
{
- "key" => "retirement_age_for_person",
- "arguments_for_key" => 1,
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "brent",
"i18n_template" => "argument",
},
],
}
- expect(display_informative_text(informative_text_hash, lettings_log)).to eq(I18n.t(translation, argument: lettings_log.retirement_age_for_person(1)))
+ expect(display_informative_text(informative_text_hash, lettings_log)).to eq("You said this: £12,345.00")
end
end
end
@@ -178,6 +195,38 @@ RSpec.describe InterruptionScreenHelper do
expect(display_title_text(title_text, lettings_log))
.to eq(I18n.t("test.title_text.one_argument", argument: lettings_log.form.get_question("ecstat1", lettings_log).answer_label(lettings_log).downcase))
end
+
+ context "when and argument is given with a key and arguments for the key" do
+ it "makes the correct method call" do
+ title_text = {
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "brent",
+ "i18n_template" => "argument",
+ },
+ ],
+ }
+ allow(lettings_log).to receive(:field_formatted_as_currency)
+ display_title_text(title_text, lettings_log)
+ expect(lettings_log).to have_received(:field_formatted_as_currency).with("brent")
+ end
+
+ it "returns the correct text" do
+ translation = "test.title_text.one_argument"
+ title_text = {
+ "translation" => translation,
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "brent",
+ "i18n_template" => "argument",
+ },
+ ],
+ }
+ expect(display_title_text(title_text, lettings_log)).to eq("You said this: £12,345.00")
+ end
+ end
end
context "when title text is not defined" do
diff --git a/spec/helpers/locations_helper_spec.rb b/spec/helpers/locations_helper_spec.rb
index 7926854ec..354b948d4 100644
--- a/spec/helpers/locations_helper_spec.rb
+++ b/spec/helpers/locations_helper_spec.rb
@@ -178,7 +178,7 @@ RSpec.describe LocationsHelper do
context "when location has no local authority" do
before do
LocalAuthorityLink.create!(local_authority_id: LocalAuthority.find_by(code: "E07000030").id, linked_local_authority_id: LocalAuthority.find_by(code: "E06000063").id)
- location.update!(location_code: nil)
+ location.update!(location_code: nil, confirmed: false)
end
it "returns correct display attributes" do
diff --git a/spec/models/form/lettings/pages/max_rent_value_check_spec.rb b/spec/models/form/lettings/pages/max_rent_value_check_spec.rb
new file mode 100644
index 000000000..7a3a5544f
--- /dev/null
+++ b/spec/models/form/lettings/pages/max_rent_value_check_spec.rb
@@ -0,0 +1,37 @@
+require "rails_helper"
+
+RSpec.describe Form::Lettings::Pages::MaxRentValueCheck, type: :model do
+ subject(:page) { described_class.new(page_id, page_definition, subsection) }
+
+ let(:page_id) { "shared_ownership_deposit_value_check" }
+ let(:page_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ 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[rent_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("max_rent_value_check")
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be_nil
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([{ "rent_in_soft_max_range?" => true }])
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({ "arguments" => [{ "i18n_template" => "brent", "key" => "brent", "label" => true }], "translation" => "soft_validations.rent.outside_range_title" })
+ end
+
+ it "has the correct informative_text" do
+ expect(page.informative_text).to eq({ "arguments" => [{ "arguments_for_key" => "soft_max_for_period", "i18n_template" => "soft_max_for_period", "key" => "field_formatted_as_currency" }], "translation" => "soft_validations.rent.max_hint_text" })
+ end
+end
diff --git a/spec/models/form/lettings/pages/min_rent_value_check_spec.rb b/spec/models/form/lettings/pages/min_rent_value_check_spec.rb
new file mode 100644
index 000000000..4e68a09c7
--- /dev/null
+++ b/spec/models/form/lettings/pages/min_rent_value_check_spec.rb
@@ -0,0 +1,48 @@
+require "rails_helper"
+
+RSpec.describe Form::Lettings::Pages::MinRentValueCheck, type: :model do
+ subject(:page) { described_class.new(nil, page_definition, subsection) }
+
+ let(:page_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ it "has correct subsection" do
+ expect(page.subsection).to eq(subsection)
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be nil
+ end
+
+ it "has the correct description" do
+ expect(page.description).to be nil
+ end
+
+ it "has correct questions" do
+ expect(page.questions.map(&:id)).to eq(%w[rent_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("min_rent_value_check")
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq(
+ [{ "rent_in_soft_min_range?" => true }],
+ )
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({
+ "translation" => "soft_validations.rent.outside_range_title",
+ "arguments" => [{ "i18n_template" => "brent", "key" => "brent", "label" => true }],
+ })
+ end
+
+ it "has the correct informative_text" do
+ expect(page.informative_text).to eq({
+ "arguments" => [{ "arguments_for_key" => "soft_min_for_period", "i18n_template" => "soft_min_for_period", "key" => "field_formatted_as_currency" }],
+ "translation" => "soft_validations.rent.min_hint_text",
+ })
+ end
+end
diff --git a/spec/models/form/lettings/pages/net_income_value_check_spec.rb b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
new file mode 100644
index 000000000..c43eb3381
--- /dev/null
+++ b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
@@ -0,0 +1,40 @@
+require "rails_helper"
+
+RSpec.describe Form::Lettings::Pages::NetIncomeValueCheck, type: :model do
+ subject(:page) { described_class.new(page_id, page_definition, subsection) }
+
+ let(:page_id) { "shared_ownership_deposit_value_check" }
+ let(:page_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ 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[net_income_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("net_income_value_check")
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be_nil
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([{ "net_income_soft_validation_triggered?" => true }])
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({ "translation" => "soft_validations.net_income.title_text" })
+ end
+
+ it "has the correct informative_text" do
+ expect(page.informative_text).to eq({
+ "arguments" => [{ "arguments_for_key" => "ecstat1", "i18n_template" => "ecstat1", "key" => "field_formatted_as_currency" }, { "arguments_for_key" => "earnings", "i18n_template" => "earnings", "key" => "field_formatted_as_currency" }],
+ "translation" => "soft_validations.net_income.hint_text",
+ })
+ end
+end
diff --git a/spec/models/form/lettings/pages/uprn_known_spec.rb b/spec/models/form/lettings/pages/uprn_known_spec.rb
deleted file mode 100644
index 27b893a5c..000000000
--- a/spec/models/form/lettings/pages/uprn_known_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-require "rails_helper"
-
-RSpec.describe Form::Lettings::Pages::UprnKnown, 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) }
-
- 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[uprn_known])
- end
-
- it "has the correct id" do
- expect(page.id).to eq("uprn_known")
- end
-
- it "has the correct header" do
- expect(page.header).to be_nil
- end
-
- it "has the correct description" do
- expect(page.description).to be_nil
- end
-
- it "has correct depends_on" do
- expect(page.depends_on).to be_nil
- end
-
- describe "has correct routed_to?" do
- context "when needstype != 2" do
- let(:log) { create(:lettings_log, needstype: nil) }
-
- it "returns true" do
- expect(page.routed_to?(log)).to eq(true)
- end
- end
-
- context "when needstype == 2" do
- let(:log) { create(:lettings_log, needstype: 2) }
-
- it "returns true" do
- expect(page.routed_to?(log)).to eq(false)
- end
- end
- end
-end
diff --git a/spec/models/form/lettings/pages/uprn_spec.rb b/spec/models/form/lettings/pages/uprn_spec.rb
index 7b480b6b2..d7ddec73f 100644
--- a/spec/models/form/lettings/pages/uprn_spec.rb
+++ b/spec/models/form/lettings/pages/uprn_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Form::Lettings::Pages::Uprn, type: :model do
end
it "has correct questions" do
- expect(page.questions.map(&:id)).to eq(%w[uprn])
+ expect(page.questions.map(&:id)).to eq(%w[uprn_known uprn])
end
it "has the correct id" do
@@ -36,14 +36,6 @@ RSpec.describe Form::Lettings::Pages::Uprn, type: :model do
end
describe "has correct routed_to?" do
- context "when uprn_known != 1" do
- let(:log) { create(:lettings_log, uprn_known: 0) }
-
- it "returns false" do
- expect(page.routed_to?(log)).to eq(false)
- end
- end
-
context "when uprn_known == 1" do
let(:log) { create(:lettings_log, uprn_known: 1) }
diff --git a/spec/models/form/lettings/questions/address_line1_spec.rb b/spec/models/form/lettings/questions/address_line1_spec.rb
index e2600f0cc..2c13aef48 100644
--- a/spec/models/form/lettings/questions/address_line1_spec.rb
+++ b/spec/models/form/lettings/questions/address_line1_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Form::Lettings::Questions::AddressLine1, type: :model do
end
end
- context "when la is present but inferred" do
+ context "when la is present and inferred" do
let(:log) { create(:lettings_log, la: "E09000003") }
before do
diff --git a/spec/models/form/lettings/questions/location_id_spec.rb b/spec/models/form/lettings/questions/location_id_spec.rb
index afb39ce11..fbe580970 100644
--- a/spec/models/form/lettings/questions/location_id_spec.rb
+++ b/spec/models/form/lettings/questions/location_id_spec.rb
@@ -48,11 +48,13 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
context "when getting available locations" do
let(:scheme) { FactoryBot.create(:scheme) }
let!(:lettings_log) do
- FactoryBot.create(:lettings_log, owning_organisation: scheme.owning_organisation, scheme:, needstype: 2)
+ FactoryBot.create(:lettings_log, owning_organisation: scheme.owning_organisation, needstype: 2)
end
context "when there are no locations" do
- it "the displayed_answer_options is an empty hash" do
+ it "the displayed_answer_options is an empty hash (the scheme should have failed validation anyway so don't validate here)" do
+ lettings_log.scheme = scheme
+ lettings_log.save!(validate: false)
expect(question.displayed_answer_options(lettings_log)).to eq({})
end
end
@@ -70,6 +72,7 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
before do
FactoryBot.create(:location, scheme:, startdate: Time.utc(2022, 5, 13))
FactoryBot.create(:location, scheme:, startdate: Time.utc(2023, 1, 1))
+ lettings_log.update!(scheme:)
end
it "the displayed_answer_options is an empty hash" do
@@ -77,10 +80,11 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
end
end
- context "and the locations have a no startdate" do
+ context "and the locations have no startdate" do
before do
FactoryBot.create(:location, scheme:, startdate: nil)
FactoryBot.create(:location, scheme:, startdate: nil)
+ lettings_log.update!(scheme:)
end
it "the displayed_answer_options shows the locations" do
@@ -92,6 +96,7 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
before do
FactoryBot.create(:location, scheme:, startdate: Time.utc(2022, 4, 10))
FactoryBot.create(:location, scheme:, startdate: Time.utc(2022, 5, 12))
+ lettings_log.update!(scheme:)
end
it "the displayed_answer_options shows the locations" do
@@ -103,9 +108,22 @@ RSpec.describe Form::Lettings::Questions::LocationId, type: :model do
before do
FactoryBot.create(:location, scheme:, startdate: Time.utc(2022, 10, 10))
FactoryBot.create(:location, scheme:, startdate: Time.utc(2022, 5, 12))
+ lettings_log.update!(scheme:)
end
- it "the displayed_answer_options shows the active location" do
+ it "the displayed_answer_options shows only the active location" do
+ expect(question.displayed_answer_options(lettings_log).count).to eq(1)
+ end
+ end
+
+ context "and some locations are not confirmed" do
+ before do
+ FactoryBot.create(:location, scheme:, postcode: nil)
+ FactoryBot.create(:location, scheme:)
+ lettings_log.update!(scheme:)
+ end
+
+ it "the displayed_answer_options shows only the confirmed location" do
expect(question.displayed_answer_options(lettings_log).count).to eq(1)
end
end
diff --git a/spec/models/form/lettings/questions/scheme_id_spec.rb b/spec/models/form/lettings/questions/scheme_id_spec.rb
index 7e88e3139..0b7c8da96 100644
--- a/spec/models/form/lettings/questions/scheme_id_spec.rb
+++ b/spec/models/form/lettings/questions/scheme_id_spec.rb
@@ -39,6 +39,45 @@ RSpec.describe Form::Lettings::Questions::SchemeId, type: :model do
expect(question.derived?).to be false
end
+ it "has the correct inferred_answers" do
+ expect(question.inferred_answers).to eq({
+ "location.name": {
+ "scheme_has_multiple_locations?": false,
+ },
+ })
+ end
+
+ describe "has the correct get_extra_check_answer_value" do
+ let(:scheme) { create(:scheme) }
+
+ context "when locations are present but not inferred" do
+ let(:lettings_log) { create(:lettings_log) }
+
+ before do
+ allow(lettings_log).to receive(:scheme_has_multiple_locations?).and_return(true)
+ end
+
+ it "returns nil" do
+ expect(question.get_extra_check_answer_value(lettings_log)).to be_nil
+ end
+ end
+
+ context "when location is present and inferred" do
+ let!(:location) { create(:location, scheme:) }
+ let!(:lettings_log) { create(:lettings_log, scheme:, location:) }
+ let(:real_2022_2023_form) { Form.new("config/forms/2022_2023.json") }
+
+ before do
+ allow(lettings_log).to receive(:scheme_has_multiple_locations?).and_return(false)
+ allow(lettings_log).to receive(:form).and_return(real_2022_2023_form)
+ end
+
+ it "returns the postcode" do
+ expect(question.get_extra_check_answer_value(lettings_log)).to eq(location.postcode)
+ end
+ end
+ end
+
context "when a user is signed in" do
let(:organisation) { FactoryBot.create(:organisation) }
let(:organisation_2) { FactoryBot.create(:organisation) }
@@ -84,13 +123,17 @@ RSpec.describe Form::Lettings::Questions::SchemeId, type: :model do
end
context "when the question is answered" do
- it "returns 'select an option' as selected answer" do
+ before do
+ FactoryBot.create(:location, scheme:)
+ end
+
+ it "returns scheme as selected answer" do
lettings_log.update!(scheme:)
answers = question.displayed_answer_options(lettings_log).map do |key, value|
OpenStruct.new(id: key, name: value.respond_to?(:service_name) ? value.service_name : nil, resource: value)
end
answers.each do |answer|
- if answer.id == scheme.id
+ if answer.id.to_i == scheme.id
expect(question.answer_selected?(lettings_log, answer)).to eq(true)
else
expect(question.answer_selected?(lettings_log, answer)).to eq(false)
diff --git a/spec/models/form/lettings/questions/uprn_known_spec.rb b/spec/models/form/lettings/questions/uprn_known_spec.rb
index 07eb72f8d..a79185462 100644
--- a/spec/models/form/lettings/questions/uprn_known_spec.rb
+++ b/spec/models/form/lettings/questions/uprn_known_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Form::Lettings::Questions::UprnKnown, type: :model do
end
it "has correct conditional for" do
- expect(question.conditional_for).to be_nil
+ expect(question.conditional_for).to eq({ "uprn" => [1] })
end
it "has the correct unanswered_error_message" do
@@ -54,6 +54,6 @@ RSpec.describe Form::Lettings::Questions::UprnKnown, type: :model do
end
it "has the correct hidden_in_check_answers" do
- expect(question.hidden_in_check_answers).to be_nil
+ expect(question.hidden_in_check_answers).to eq(true)
end
end
diff --git a/spec/models/form/lettings/questions/uprn_spec.rb b/spec/models/form/lettings/questions/uprn_spec.rb
index 8f6ba047a..5e0be655b 100644
--- a/spec/models/form/lettings/questions/uprn_spec.rb
+++ b/spec/models/form/lettings/questions/uprn_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Form::Lettings::Questions::Uprn, type: :model do
end
it "has the correct hint" do
- expect(question.hint_text).to eq("The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.")
+ expect(question.hint_text).to be_nil
end
it "has the correct unanswered_error_message" do
@@ -61,32 +61,44 @@ RSpec.describe Form::Lettings::Questions::Uprn, type: :model do
county: "Test County",
postcode_full: "AA1 1AA",
la: "E09000003",
+ uprn_known:,
)
end
- it "returns formatted value" do
- expect(question.get_extra_check_answer_value(log)).to eq(
- "\n\n1, Test Street\nTest Town\nTest County\nAA1 1AA\nWestminster",
- )
+ context "when uprn known nil" do
+ let(:uprn_known) { nil }
+
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to be_nil
+ end
end
- end
- end
- describe "has the correct hidden_in_check_answers" do
- context "when uprn_known == 1" do
- let(:log) { create(:lettings_log, uprn_known: 1) }
+ context "when uprn known" do
+ let(:uprn_known) { 1 }
- it "returns false" do
- expect(question.hidden_in_check_answers?(log)).to eq(false)
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to eq(
+ "\n\n1, Test Street\nTest Town\nTest County\nAA1 1AA\nWestminster",
+ )
+ end
end
- end
- context "when uprn_known != 1" do
- let(:log) { create(:lettings_log, uprn_known: 0) }
+ context "when uprn not known" do
+ let(:uprn_known) { 0 }
- it "returns false" do
- expect(question.hidden_in_check_answers?(log)).to eq(true)
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to be_nil
+ end
end
end
end
+
+ it "has the correct inferred_check_answers_value" do
+ expect(question.inferred_check_answers_value).to eq([{
+ "condition" => {
+ "uprn_known" => 0,
+ },
+ "value" => "Not known",
+ }])
+ end
end
diff --git a/spec/models/form/lettings/subsections/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb
index b66761125..0eac3a27a 100644
--- a/spec/models/form/lettings/subsections/property_information_spec.rb
+++ b/spec/models/form/lettings/subsections/property_information_spec.rb
@@ -49,7 +49,6 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do
it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq(
%w[
- uprn_known
uprn
uprn_confirmation
address
diff --git a/spec/models/form/sales/pages/about_price_value_check_spec.rb b/spec/models/form/sales/pages/about_price_value_check_spec.rb
new file mode 100644
index 000000000..6c8d27463
--- /dev/null
+++ b/spec/models/form/sales/pages/about_price_value_check_spec.rb
@@ -0,0 +1,54 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Pages::AboutPriceValueCheck, type: :model do
+ subject(:page) { described_class.new(page_id, page_definition, subsection) }
+
+ let(:page_id) { "savings_value_check" }
+ let(:page_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ 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[value_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("savings_value_check")
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be_nil
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([{ "purchase_price_out_of_soft_range?" => true }])
+ end
+
+ it "is interruption screen page" do
+ expect(page.interruption_screen?).to eq(true)
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({ "arguments" => [{ "i18n_template" => "value", "key" => "value", "label" => true }], "translation" => "soft_validations.purchase_price.title_text" })
+ end
+
+ it "has the correct informative_text" do
+ expect(page.informative_text).to eq({
+ "translation" => "soft_validations.purchase_price.hint_text",
+ "arguments" => [
+ {
+ "key" => "field_formatted_as_currency",
+ "arguments_for_key" => "purchase_price_soft_min_or_soft_max",
+ "i18n_template" => "soft_min_or_soft_max",
+ },
+ {
+ "key" => "purchase_price_min_or_max_text",
+ "i18n_template" => "min_or_max",
+ },
+ ],
+ })
+ end
+end
diff --git a/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb b/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb
new file mode 100644
index 000000000..9d00b086b
--- /dev/null
+++ b/spec/models/form/sales/pages/buyer_live_in_value_check_spec.rb
@@ -0,0 +1,64 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Pages::BuyerLiveInValueCheck, type: :model do
+ subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
+
+ let(:page_id) { "buyer_1_live_in_value_check" }
+ let(:page_definition) { nil }
+ let(:person_index) { 1 }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ 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[buyer_livein_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("buyer_1_live_in_value_check")
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be_nil
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "buyer1_livein_wrong_for_ownership_type?" => true,
+ },
+ ])
+ end
+
+ it "is interruption screen page" do
+ expect(page.interruption_screen?).to eq(true)
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({
+ "translation" => "soft_validations.buyer1_livein_wrong_for_ownership_type.title_text",
+ "arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
+ })
+ end
+
+ context "with buyer 2" do
+ let(:person_index) { 2 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "buyer2_livein_wrong_for_ownership_type?" => true,
+ },
+ ])
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({
+ "translation" => "soft_validations.buyer2_livein_wrong_for_ownership_type.title_text",
+ "arguments" => [{ "key" => "ownership_scheme", "label" => false, "i18n_template" => "ownership_scheme" }],
+ })
+ end
+ end
+end
diff --git a/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb b/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
index ddd4bc33c..d086542dc 100644
--- a/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
+++ b/spec/models/form/sales/pages/discounted_sale_value_check_spec.rb
@@ -27,14 +27,14 @@ RSpec.describe Form::Sales::Pages::DiscountedSaleValueCheck, type: :model do
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.discounted_sale_value.title_text",
- "arguments" => [{ "key" => "value_with_discount", "label" => false, "i18n_template" => "value_with_discount" }],
+ "arguments" => [{ "arguments_for_key" => "value_with_discount", "i18n_template" => "value_with_discount", "key" => "field_formatted_as_currency" }],
})
end
it "has the correct informative_text" do
expect(page.informative_text).to eq({
"translation" => "soft_validations.discounted_sale_value.informative_text",
- "arguments" => [{ "key" => "mortgage_deposit_and_grant_total", "label" => false, "i18n_template" => "mortgage_deposit_and_grant_total" }],
+ "arguments" => [{ "arguments_for_key" => "mortgage_deposit_and_grant_total", "i18n_template" => "mortgage_deposit_and_grant_total", "key" => "field_formatted_as_currency" }],
})
end
diff --git a/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb b/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb
new file mode 100644
index 000000000..d933e3278
--- /dev/null
+++ b/spec/models/form/sales/pages/percentage_discount_value_check_spec.rb
@@ -0,0 +1,48 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Pages::PercentageDiscountValueCheck, type: :model do
+ subject(:page) { described_class.new(page_id, page_definition, subsection) }
+
+ let(:page_id) { "percentage_discount_value_check" }
+ let(:page_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection) }
+
+ 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[percentage_discount_value_check])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("percentage_discount_value_check")
+ end
+
+ it "has the correct header" do
+ expect(page.header).to be_nil
+ end
+
+ it "has the correct title_text" do
+ expect(page.title_text).to eq({
+ "translation" => "soft_validations.percentage_discount_value.title_text",
+ "arguments" => [{ "key" => "discount", "label" => true, "i18n_template" => "discount" }],
+ })
+ end
+
+ it "has the correct informative_text" do
+ expect(page.informative_text).to eq({})
+ end
+
+ it "is interruption screen page" do
+ expect(page.interruption_screen?).to eq(true)
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "percentage_discount_invalid?" => true,
+ },
+ ])
+ end
+end
diff --git a/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb b/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
index 893a5cb5b..45744cde4 100644
--- a/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
+++ b/spec/models/form/sales/pages/shared_ownership_deposit_value_check_spec.rb
@@ -34,13 +34,7 @@ RSpec.describe Form::Sales::Pages::SharedOwnershipDepositValueCheck, type: :mode
it "has the correct title_text" do
expect(page.title_text).to eq({
"translation" => "soft_validations.shared_ownership_deposit.title_text",
- "arguments" => [
- {
- "key" => "expected_shared_ownership_deposit_value",
- "label" => false,
- "i18n_template" => "expected_shared_ownership_deposit_value",
- },
- ],
+ "arguments" => [{ "arguments_for_key" => "expected_shared_ownership_deposit_value", "i18n_template" => "expected_shared_ownership_deposit_value", "key" => "field_formatted_as_currency" }],
})
end
diff --git a/spec/models/form/sales/pages/uprn_known_spec.rb b/spec/models/form/sales/pages/uprn_known_spec.rb
deleted file mode 100644
index 9c18cfa21..000000000
--- a/spec/models/form/sales/pages/uprn_known_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "rails_helper"
-
-RSpec.describe Form::Sales::Pages::UprnKnown, 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) }
-
- 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[uprn_known])
- end
-
- it "has the correct id" do
- expect(page.id).to eq("uprn_known")
- end
-
- it "has the correct header" do
- expect(page.header).to be_nil
- end
-
- it "has the correct description" do
- expect(page.description).to be_nil
- end
-
- it "has correct depends_on" do
- expect(page.depends_on).to be_nil
- end
-end
diff --git a/spec/models/form/sales/pages/uprn_spec.rb b/spec/models/form/sales/pages/uprn_spec.rb
index 5573caf5a..a0cd5b7bc 100644
--- a/spec/models/form/sales/pages/uprn_spec.rb
+++ b/spec/models/form/sales/pages/uprn_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Form::Sales::Pages::Uprn, type: :model do
end
it "has correct questions" do
- expect(page.questions.map(&:id)).to eq(%w[uprn])
+ expect(page.questions.map(&:id)).to eq(%w[uprn_known uprn])
end
it "has the correct id" do
diff --git a/spec/models/form/sales/questions/address_line1_spec.rb b/spec/models/form/sales/questions/address_line1_spec.rb
index f037f41cd..8c73feef2 100644
--- a/spec/models/form/sales/questions/address_line1_spec.rb
+++ b/spec/models/form/sales/questions/address_line1_spec.rb
@@ -64,7 +64,7 @@ RSpec.describe Form::Sales::Questions::AddressLine1, type: :model do
end
end
- context "when la is present but inferred" do
+ context "when la is present and inferred" do
let(:log) { create(:sales_log, la: "E09000003") }
before do
diff --git a/spec/models/form/sales/questions/buyer_live_in_value_check_spec.rb b/spec/models/form/sales/questions/buyer_live_in_value_check_spec.rb
new file mode 100644
index 000000000..0409f4f2e
--- /dev/null
+++ b/spec/models/form/sales/questions/buyer_live_in_value_check_spec.rb
@@ -0,0 +1,62 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Questions::BuyerLiveInValueCheck, type: :model do
+ subject(:question) { described_class.new(question_id, question_definition, page, person_index:) }
+
+ let(:question_id) { nil }
+ let(:question_definition) { nil }
+ let(:person_index) { 1 }
+ let(:page) { instance_double(Form::Page) }
+
+ it "has correct page" do
+ expect(question.page).to eq(page)
+ end
+
+ it "has the correct id" do
+ expect(question.id).to eq("buyer_livein_value_check")
+ end
+
+ it "has the correct header" do
+ expect(question.header).to eq("Are you sure this is correct?")
+ end
+
+ it "has the correct check_answer_label" do
+ expect(question.check_answer_label).to eq("Buyer live in confirmation")
+ end
+
+ it "has the correct type" do
+ expect(question.type).to eq("interruption_screen")
+ end
+
+ it "is not marked as derived" do
+ expect(question.derived?).to be false
+ end
+
+ it "has the correct hint" do
+ expect(question.hint_text).to be_nil
+ end
+
+ it "has a correct check_answers_card_number" do
+ expect(question.check_answers_card_number).to eq(1)
+ end
+
+ it "has the correct answer_options" do
+ expect(question.answer_options).to eq({
+ "0" => { "value" => "Yes" },
+ "1" => { "value" => "No" },
+ })
+ end
+
+ it "has the correct hidden_in_check_answers" do
+ expect(question.hidden_in_check_answers).to eq({
+ "depends_on" => [
+ {
+ "buyer_livein_value_check" => 0,
+ },
+ {
+ "buyer_livein_value_check" => 1,
+ },
+ ],
+ })
+ end
+end
diff --git a/spec/models/form/sales/questions/percentage_discount_value_check_spec.rb b/spec/models/form/sales/questions/percentage_discount_value_check_spec.rb
new file mode 100644
index 000000000..72f4f0cbb
--- /dev/null
+++ b/spec/models/form/sales/questions/percentage_discount_value_check_spec.rb
@@ -0,0 +1,57 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Questions::PercentageDiscountValueCheck, type: :model do
+ subject(:question) { described_class.new(question_id, question_definition, page) }
+
+ let(:question_id) { nil }
+ let(:question_definition) { nil }
+ let(:page) { instance_double(Form::Page) }
+
+ it "has correct page" do
+ expect(question.page).to eq(page)
+ end
+
+ it "has the correct id" do
+ expect(question.id).to eq("percentage_discount_value_check")
+ end
+
+ it "has the correct header" do
+ expect(question.header).to eq("Are you sure this is correct?")
+ end
+
+ it "has the correct check_answer_label" do
+ expect(question.check_answer_label).to eq("Percentage discount confirmation")
+ end
+
+ it "has the correct type" do
+ expect(question.type).to eq("interruption_screen")
+ end
+
+ it "is not marked as derived" do
+ expect(question.derived?).to be false
+ end
+
+ it "has the correct hint" do
+ expect(question.hint_text).to be_nil
+ end
+
+ it "has the correct answer_options" do
+ expect(question.answer_options).to eq({
+ "0" => { "value" => "Yes" },
+ "1" => { "value" => "No" },
+ })
+ end
+
+ it "has the correct hidden_in_check_answers" do
+ expect(question.hidden_in_check_answers).to eq({
+ "depends_on" => [
+ {
+ "percentage_discount_value_check" => 0,
+ },
+ {
+ "percentage_discount_value_check" => 1,
+ },
+ ],
+ })
+ end
+end
diff --git a/spec/models/form/sales/questions/uprn_known_spec.rb b/spec/models/form/sales/questions/uprn_known_spec.rb
index 457471568..4016b6e8d 100644
--- a/spec/models/form/sales/questions/uprn_known_spec.rb
+++ b/spec/models/form/sales/questions/uprn_known_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Form::Sales::Questions::UprnKnown, type: :model do
end
it "has correct conditional for" do
- expect(question.conditional_for).to be_nil
+ expect(question.conditional_for).to eq({ "uprn" => [1] })
end
it "has the correct unanswered_error_message" do
@@ -54,6 +54,6 @@ RSpec.describe Form::Sales::Questions::UprnKnown, type: :model do
end
it "has the correct hidden_in_check_answers" do
- expect(question.hidden_in_check_answers).to be_nil
+ expect(question.hidden_in_check_answers).to eq(true)
end
end
diff --git a/spec/models/form/sales/questions/uprn_spec.rb b/spec/models/form/sales/questions/uprn_spec.rb
index f8fd75942..46e635868 100644
--- a/spec/models/form/sales/questions/uprn_spec.rb
+++ b/spec/models/form/sales/questions/uprn_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Form::Sales::Questions::Uprn, type: :model do
end
it "has the correct hint" do
- expect(question.hint_text).to eq("The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and sectors UK-wide. For example 10010457355.")
+ expect(question.hint_text).to be_nil
end
it "has the correct unanswered_error_message" do
@@ -61,33 +61,44 @@ RSpec.describe Form::Sales::Questions::Uprn, type: :model do
county: "Test County",
postcode_full: "AA1 1AA",
la: "E09000003",
+ uprn_known:,
)
end
- it "returns formatted value" do
- expect(question.get_extra_check_answer_value(log)).to eq(
- "\n\n1, Test Street\nTest Town\nTest County\nAA1 1AA\nWestminster",
- )
+ context "when uprn known nil" do
+ let(:uprn_known) { nil }
+
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to be_nil
+ end
end
- end
- end
- describe "has the correct hidden_in_check_answers" do
- context "when uprn_known == 1" do
- let(:log) { create(:sales_log) }
+ context "when uprn known" do
+ let(:uprn_known) { 1 }
- it "returns false" do
- log.uprn_known = 1
- expect(question.hidden_in_check_answers?(log)).to eq(false)
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to eq(
+ "\n\n1, Test Street\nTest Town\nTest County\nAA1 1AA\nWestminster",
+ )
+ end
end
- end
- context "when uprn_known != 1" do
- let(:log) { create(:sales_log, uprn_known: 0) }
+ context "when uprn not known" do
+ let(:uprn_known) { 0 }
- it "returns false" do
- expect(question.hidden_in_check_answers?(log)).to eq(true)
+ it "returns formatted value" do
+ expect(question.get_extra_check_answer_value(log)).to be_nil
+ end
end
end
end
+
+ it "has the correct inferred_check_answers_value" do
+ expect(question.inferred_check_answers_value).to eq([{
+ "condition" => {
+ "uprn_known" => 0,
+ },
+ "value" => "Not known",
+ }])
+ end
end
diff --git a/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb b/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
index 5c0dbfea0..9aa0aa102 100644
--- a/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
+++ b/spec/models/form/sales/subsections/discounted_ownership_scheme_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe Form::Sales::Subsections::DiscountedOwnershipScheme, type: :model
living_before_purchase_discounted_ownership
about_price_rtb
extra_borrowing_price_value_check
+ percentage_discount_value_check
about_price_not_rtb
grant_value_check
purchase_price_discounted_ownership
diff --git a/spec/models/form/sales/subsections/household_characteristics_spec.rb b/spec/models/form/sales/subsections/household_characteristics_spec.rb
index 57a9ce019..c926baa08 100644
--- a/spec/models/form/sales/subsections/household_characteristics_spec.rb
+++ b/spec/models/form/sales/subsections/household_characteristics_spec.rb
@@ -39,6 +39,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_1_retirement_value_check
working_situation_buyer_1_income_value_check
buyer_1_live_in_property
+ buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
buyer_2_relationship_student_not_child_value_check
buyer_2_age
@@ -52,6 +53,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_buyer_2_income_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
+ buyer_2_live_in_property_value_check
number_of_others_in_property
number_of_others_in_property_joint_purchase
person_2_known
@@ -141,6 +143,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_1_retirement_value_check
working_situation_buyer_1_income_value_check
buyer_1_live_in_property
+ buyer_1_live_in_property_value_check
buyer_2_relationship_to_buyer_1
buyer_2_relationship_student_not_child_value_check
buyer_2_age
@@ -161,6 +164,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
working_situation_buyer_2_income_value_check
buyer_2_working_situation_student_not_child_value_check
buyer_2_live_in_property
+ buyer_2_live_in_property_value_check
number_of_others_in_property
number_of_others_in_property_joint_purchase
person_2_known
diff --git a/spec/models/form/sales/subsections/property_information_spec.rb b/spec/models/form/sales/subsections/property_information_spec.rb
index 1c049ea97..559db5ea6 100644
--- a/spec/models/form/sales/subsections/property_information_spec.rb
+++ b/spec/models/form/sales/subsections/property_information_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
about_price_bedrooms_value_check
property_unit_type
monthly_charges_property_type_value_check
+ percentage_discount_proptype_value_check
property_building_type
property_postcode
property_local_authority
@@ -40,7 +41,6 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
it "has correct pages" do
expect(property_information.pages.map(&:id)).to eq(
%w[
- uprn_known
uprn
uprn_confirmation
address
@@ -49,6 +49,7 @@ RSpec.describe Form::Sales::Subsections::PropertyInformation, type: :model do
about_price_bedrooms_value_check
property_unit_type
monthly_charges_property_type_value_check
+ percentage_discount_proptype_value_check
property_building_type
about_price_la_value_check
property_wheelchair_accessible
diff --git a/spec/models/form/sales/subsections/setup_spec.rb b/spec/models/form/sales/subsections/setup_spec.rb
index 92271ba25..7f12a8498 100644
--- a/spec/models/form/sales/subsections/setup_spec.rb
+++ b/spec/models/form/sales/subsections/setup_spec.rb
@@ -26,6 +26,8 @@ RSpec.describe Form::Sales::Subsections::Setup, type: :model do
ownership_type_old_persons_shared_ownership_value_check
monthly_charges_type_value_check
discounted_sale_type_value_check
+ buyer_1_live_in_property_type_value_check
+ buyer_2_live_in_property_type_value_check
buyer_company
buyer_live
joint_purchase
diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb
index e3123ad41..908fcab17 100644
--- a/spec/models/form_spec.rb
+++ b/spec/models/form_spec.rb
@@ -17,11 +17,11 @@ RSpec.describe Form, type: :model do
let(:conditional_section_complete_lettings_log) { FactoryBot.build(:lettings_log, :conditional_section_complete) }
describe ".next_page" do
- let(:previous_page) { form.get_page("person_1_age") }
+ let(:previous_page_id) { form.get_page("person_1_age") }
let(:value_check_previous_page) { form.get_page("net_income_value_check") }
it "returns the next page given the previous" do
- expect(form.next_page(previous_page, lettings_log, user)).to eq("person_1_gender")
+ expect(form.next_page_id(previous_page_id, lettings_log, user)).to eq("person_1_gender")
end
context "when the current page is a value check page" do
@@ -33,12 +33,12 @@ RSpec.describe Form, type: :model do
it "returns the previous page if answer is `No` and the page is routed to" do
lettings_log.net_income_value_check = 1
- expect(form.next_page(value_check_previous_page, lettings_log, user)).to eq("net_income")
+ expect(form.next_page_id(value_check_previous_page, lettings_log, user)).to eq("net_income")
end
it "returns the next page if answer is `Yes` answer and the page is routed to" do
lettings_log.net_income_value_check = 0
- expect(form.next_page(value_check_previous_page, lettings_log, user)).to eq("net_income_uc_proportion")
+ expect(form.next_page_id(value_check_previous_page, lettings_log, user)).to eq("net_income_uc_proportion")
end
end
end
@@ -46,31 +46,30 @@ RSpec.describe Form, type: :model do
describe ".previous_page" do
context "when the current page is not a value check page" do
let!(:subsection) { form.get_subsection("conditional_question") }
- let!(:page_ids) { subsection.pages.map(&:id) }
before do
lettings_log.preg_occ = 2
end
it "returns the previous page if the page is routed to" do
- page_index = page_ids.index("conditional_question_no_second_page")
- expect(form.previous_page(page_ids, page_index, lettings_log, user)).to eq("conditional_question_no_page")
+ page = subsection.pages.find { |p| p.id == "conditional_question_no_second_page" }
+ expect(form.previous_page_id(page, lettings_log, user)).to eq("conditional_question_no_page")
end
it "returns the page before the previous one if the previous page is not routed to" do
- page_index = page_ids.index("conditional_question_no_page")
- expect(form.previous_page(page_ids, page_index, lettings_log, user)).to eq("conditional_question")
+ page = subsection.pages.find { |p| p.id == "conditional_question_no_page" }
+ expect(form.previous_page_id(page, lettings_log, user)).to eq("conditional_question")
end
end
end
describe "next_page_redirect_path" do
- let(:previous_page) { form.get_page("net_income") }
+ let(:previous_page_id) { form.get_page("net_income") }
let(:last_previous_page) { form.get_page("housing_benefit") }
let(:previous_conditional_page) { form.get_page("conditional_question") }
it "returns a correct page path if there is no conditional routing" do
- expect(form.next_page_redirect_path(previous_page, lettings_log, user)).to eq("lettings_log_net_income_uc_proportion_path")
+ expect(form.next_page_redirect_path(previous_page_id, lettings_log, user)).to eq("lettings_log_net_income_uc_proportion_path")
end
it "returns a check answers page if previous page is the last page" do
@@ -247,9 +246,9 @@ RSpec.describe Form, type: :model do
expect(form.sections[0].class).to eq(Form::Sales::Sections::Setup)
expect(form.subsections.count).to eq(1)
expect(form.subsections.first.id).to eq("setup")
- expect(form.pages.count).to eq(16)
+ expect(form.pages.count).to eq(18)
expect(form.pages.first.id).to eq("organisation")
- expect(form.questions.count).to eq(17)
+ expect(form.questions.count).to eq(19)
expect(form.questions.first.id).to eq("owning_organisation_id")
expect(form.start_date).to eq(Time.zone.parse("2022-04-01"))
expect(form.end_date).to eq(Time.zone.parse("2023-06-07"))
diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb
index ea771af6b..c7968b9ee 100644
--- a/spec/models/lettings_log_spec.rb
+++ b/spec/models/lettings_log_spec.rb
@@ -1,13 +1,13 @@
require "rails_helper"
require "shared/shared_examples_for_derived_fields"
+# rubocop:disable RSpec/MessageChain
# rubocop:disable RSpec/AnyInstance
RSpec.describe LettingsLog do
let(:different_managing_organisation) { create(:organisation) }
let(:created_by_user) { create(:user) }
let(:owning_organisation) { created_by_user.organisation }
let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
- let(:fake_2022_2023_form) { Form.new("spec/fixtures/forms/2022_2023.json") }
around do |example|
Timecop.freeze(Time.utc(2022, 1, 1)) do
@@ -1084,6 +1084,87 @@ RSpec.describe LettingsLog do
expect(record_from_db["wtcharge"]).to eq(187.2)
end
end
+
+ context "when rent is paid weekly for 53 weeks" do
+ it "correctly derives and saves weekly rent" do
+ lettings_log.update!(brent: 130, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wrent from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wrent).to eq(132.5)
+ expect(record_from_db["wrent"]).to eq(132.5)
+ end
+
+ it "correctly derives and saves weekly service charge" do
+ lettings_log.update!(scharge: 30, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wscharge from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wscharge).to eq(30.58)
+ expect(record_from_db["wscharge"]).to eq(30.58)
+ end
+
+ it "correctly derives and saves weekly personal service charge" do
+ lettings_log.update!(pscharge: 30, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wpschrge from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wpschrge).to eq(30.58)
+ expect(record_from_db["wpschrge"]).to eq(30.58)
+ end
+
+ it "correctly derives and saves weekly support charge" do
+ lettings_log.update!(supcharg: 30, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wsupchrg from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wsupchrg).to eq(30.58)
+ expect(record_from_db["wsupchrg"]).to eq(30.58)
+ end
+
+ it "correctly derives and saves weekly total charge" do
+ lettings_log.update!(tcharge: 30, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wtcharge from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wtcharge).to eq(30.58)
+ expect(record_from_db["wtcharge"]).to eq(30.58)
+ end
+
+ context "when the tenant has an outstanding amount after benefits" do
+ context "when tenant is in receipt of housing benefit" do
+ it "correctly derives and saves weekly total shortfall" do
+ lettings_log.update!(hbrentshortfall: 1, tshortfall: 130, period: 10, hb: 1)
+ record_from_db = ActiveRecord::Base.connection.execute("select wtshortfall from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wtshortfall).to eq(132.5)
+ expect(record_from_db["wtshortfall"]).to eq(132.5)
+ end
+ end
+
+ context "when tenant is in receipt of universal credit with housing element exc. housing benefit" do
+ it "correctly derives and saves weekly total shortfall" do
+ lettings_log.update!(hbrentshortfall: 1, tshortfall: 130, period: 10, hb: 6)
+ record_from_db = ActiveRecord::Base.connection.execute("select wtshortfall from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wtshortfall).to eq(132.5)
+ expect(record_from_db["wtshortfall"]).to eq(132.5)
+ end
+ end
+
+ context "when tenant is in receipt of housing benefit and universal credit" do
+ it "correctly derives and saves weekly total shortfall" do
+ lettings_log.update!(hbrentshortfall: 1, tshortfall: 130, period: 10, hb: 8)
+ record_from_db = ActiveRecord::Base.connection.execute("select wtshortfall from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wtshortfall).to eq(132.5)
+ expect(record_from_db["wtshortfall"]).to eq(132.5)
+ end
+ end
+ end
+
+ it "correctly derives floats" do
+ lettings_log.update!(supcharg: 30.12, pscharge: 25.13, scharge: 30.98, brent: 100.97, period: 10)
+ record_from_db = ActiveRecord::Base.connection.execute("select wtcharge, wsupchrg, wpschrge, wscharge, wrent from lettings_logs where id=#{lettings_log.id}").to_a[0]
+ expect(lettings_log.wsupchrg).to eq(30.7)
+ expect(lettings_log.wpschrge).to eq(25.61)
+ expect(lettings_log.wscharge).to eq(31.58)
+ expect(lettings_log.wrent).to eq(102.91)
+ expect(lettings_log.wtcharge).to eq(190.8)
+ expect(record_from_db["wsupchrg"]).to eq(30.7)
+ expect(record_from_db["wpschrge"]).to eq(25.61)
+ expect(record_from_db["wscharge"]).to eq(31.58)
+ expect(record_from_db["wrent"]).to eq(102.91)
+ expect(record_from_db["wtcharge"]).to eq(190.8)
+ end
+ end
end
context "when the owning organisation is a LA" do
@@ -2264,7 +2345,7 @@ RSpec.describe LettingsLog do
describe "resetting invalidated fields" do
let(:scheme) { create(:scheme, owning_organisation: created_by_user.organisation) }
- let(:location) { create(:location, location_code: "E07000223", scheme:) }
+ let!(:location) { create(:location, location_code: "E07000223", scheme:) }
let(:lettings_log) do
create(
:lettings_log,
@@ -3065,6 +3146,7 @@ RSpec.describe LettingsLog do
.and change(lettings_log, :postcode_full).from(nil).to("POSTCODE")
.and change(lettings_log, :uprn_confirmed).from(1).to(nil)
.and change(lettings_log, :county).from("county").to(nil)
+ .and change(lettings_log, :uprn_known).from(nil).to(1)
end
end
@@ -3114,5 +3196,55 @@ RSpec.describe LettingsLog do
end
end
end
+
+ describe "#collection_period_open?" do
+ let(:log) { build(:lettings_log, startdate:) }
+
+ context "when startdate is nil" do
+ let(:startdate) { nil }
+
+ it "returns false" do
+ expect(log.collection_period_open?).to eq(true)
+ end
+ end
+
+ context "when older_than_previous_collection_year" do
+ let(:previous_collection_start_date) { Time.zone.local(2050, 4, 1) }
+ let(:startdate) { previous_collection_start_date - 1.day }
+
+ before do
+ allow(log).to receive(:previous_collection_start_date).and_return(previous_collection_start_date)
+ end
+
+ it "returns true" do
+ expect(log.collection_period_open?).to eq(false)
+ end
+ end
+
+ context "when form end date is in the future" do
+ let(:startdate) { nil }
+
+ before do
+ allow(log).to receive_message_chain(:form, :end_date).and_return(Time.zone.now + 1.day)
+ end
+
+ it "returns true" do
+ expect(log.collection_period_open?).to eq(true)
+ end
+ end
+
+ context "when form end date is in the past" do
+ let(:startdate) { Time.zone.local(2020, 4, 1) }
+
+ before do
+ allow(log).to receive_message_chain(:form, :end_date).and_return(Time.zone.now - 1.day)
+ end
+
+ it "returns false" do
+ expect(log.collection_period_open?).to eq(false)
+ end
+ end
+ end
end
# rubocop:enable RSpec/AnyInstance
+# rubocop:enable RSpec/MessageChain
diff --git a/spec/models/location_spec.rb b/spec/models/location_spec.rb
index 3d10ec777..1fe359136 100644
--- a/spec/models/location_spec.rb
+++ b/spec/models/location_spec.rb
@@ -788,7 +788,7 @@ RSpec.describe Location, type: :model do
before do
FactoryBot.create(:location, name: "ABC", postcode: "NW1 8RR", startdate: Time.zone.today)
FactoryBot.create(:location, name: "XYZ", postcode: "SE1 6HJ", startdate: Time.zone.today + 1.day)
- FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: Time.zone.today - 1.day, units: nil)
+ FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: Time.zone.today - 1.day, units: nil, confirmed: false)
FactoryBot.create(:location, name: "GHQ", postcode: "EW1 7JK", startdate: nil)
end
diff --git a/spec/models/sales_log_spec.rb b/spec/models/sales_log_spec.rb
index 0632af547..c008269ea 100644
--- a/spec/models/sales_log_spec.rb
+++ b/spec/models/sales_log_spec.rb
@@ -1,6 +1,7 @@
require "rails_helper"
require "shared/shared_examples_for_derived_fields"
+# rubocop:disable RSpec/MessageChain
# rubocop:disable RSpec/AnyInstance
RSpec.describe SalesLog, type: :model do
let(:owning_organisation) { create(:organisation) }
@@ -61,6 +62,7 @@ RSpec.describe SalesLog, type: :model do
old_persons_shared_ownership_value_check
othtype
discounted_sale_value_check
+ buyer_livein_value_check
proplen
mortlen
frombeds
@@ -79,6 +81,7 @@ RSpec.describe SalesLog, type: :model do
old_persons_shared_ownership_value_check
othtype
discounted_sale_value_check
+ buyer_livein_value_check
address_line2
county
postcode_full
@@ -498,7 +501,7 @@ RSpec.describe SalesLog, type: :model do
let!(:completed_sales_log) { create(:sales_log, :completed, ownershipsch: 1, type: 2, value: 1000, equity: 50) }
it "is set to completed for a completed sales log" do
- expect(completed_sales_log.expected_shared_ownership_deposit_value).to eq("£500.00")
+ expect(completed_sales_log.expected_shared_ownership_deposit_value).to eq(500)
end
end
@@ -556,6 +559,7 @@ RSpec.describe SalesLog, type: :model do
.and change(sales_log, :postcode_full).from(nil).to("POSTCODE")
.and change(sales_log, :uprn_confirmed).from(1).to(nil)
.and change(sales_log, :county).from("county").to(nil)
+ .and change(sales_log, :uprn_known).from(nil).to(1)
end
end
@@ -605,5 +609,55 @@ RSpec.describe SalesLog, type: :model do
end
end
end
+
+ describe "#collection_period_open?" do
+ let(:log) { build(:sales_log, saledate:) }
+
+ context "when saledate is nil" do
+ let(:saledate) { nil }
+
+ it "returns false" do
+ expect(log.collection_period_open?).to eq(true)
+ end
+ end
+
+ context "when older_than_previous_collection_year" do
+ let(:previous_collection_start_date) { Time.zone.local(2050, 4, 1) }
+ let(:saledate) { previous_collection_start_date - 1.day }
+
+ before do
+ allow(log).to receive(:previous_collection_start_date).and_return(previous_collection_start_date)
+ end
+
+ it "returns true" do
+ expect(log.collection_period_open?).to eq(false)
+ end
+ end
+
+ context "when form end date is in the future" do
+ let(:saledate) { nil }
+
+ before do
+ allow(log).to receive_message_chain(:form, :end_date).and_return(Time.zone.now + 1.day)
+ end
+
+ it "returns true" do
+ expect(log.collection_period_open?).to eq(true)
+ end
+ end
+
+ context "when form end date is in the past" do
+ let(:saledate) { Time.zone.local(2020, 4, 1) }
+
+ before do
+ allow(log).to receive_message_chain(:form, :end_date).and_return(Time.zone.now - 1.day)
+ end
+
+ it "returns false" do
+ expect(log.collection_period_open?).to eq(false)
+ end
+ end
+ end
end
# rubocop:enable RSpec/AnyInstance
+# rubocop:enable RSpec/MessageChain
diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb
index 239be2853..b9c747e9c 100644
--- a/spec/models/validations/date_validations_spec.rb
+++ b/spec/models/validations/date_validations_spec.rb
@@ -4,9 +4,9 @@ RSpec.describe Validations::DateValidations do
subject(:date_validator) { validator_class.new }
let(:validator_class) { Class.new { include Validations::DateValidations } }
- let(:record) { FactoryBot.create(:lettings_log) }
- let(:scheme) { FactoryBot.create(:scheme, end_date: Time.zone.today - 5.days) }
- let(:scheme_no_end_date) { FactoryBot.create(:scheme, end_date: nil) }
+ let(:record) { create(:lettings_log) }
+ let(:scheme) { create(:scheme, end_date: Time.zone.today - 5.days) }
+ let(:scheme_no_end_date) { create(:scheme, end_date: nil) }
describe "tenancy start date" do
it "must be a valid date" do
@@ -165,7 +165,7 @@ RSpec.describe Validations::DateValidations do
let(:scheme) { create(:scheme) }
before do
- FactoryBot.create(:location, scheme:)
+ create(:location, scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:)
scheme.reload
end
@@ -190,7 +190,7 @@ RSpec.describe Validations::DateValidations do
let(:scheme) { create(:scheme) }
before do
- FactoryBot.create(:location, scheme:)
+ create(:location, scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 2), reactivation_date: Time.zone.local(2022, 8, 3), scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 1), reactivation_date: Time.zone.local(2022, 9, 4), scheme:)
diff --git a/spec/models/validations/sales/soft_validations_spec.rb b/spec/models/validations/sales/soft_validations_spec.rb
index 712e53965..f63f6fbcc 100644
--- a/spec/models/validations/sales/soft_validations_spec.rb
+++ b/spec/models/validations/sales/soft_validations_spec.rb
@@ -913,4 +913,325 @@ RSpec.describe Validations::Sales::SoftValidations do
end
end
end
+
+ describe "#buyer1_livein_wrong_for_ownership_type?" do
+ context "when it's a shared ownership" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 1) }
+
+ context "and buy1livein is no" do
+ before do
+ record.buy1livein = 2
+ end
+
+ it "returns true" do
+ expect(record).to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy1livein is yes" do
+ before do
+ record.buy1livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+ end
+ end
+
+ describe "#percentage_discount_invalid?" do
+ context "when property type is Flat (1)" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 1) }
+
+ context "and discount is under 50%" do
+ before do
+ record.discount = 49
+ end
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "and discount is over 50%" do
+ before do
+ record.discount = 51
+ end
+
+ it "returns true" do
+ expect(record).to be_percentage_discount_invalid
+ end
+ end
+ end
+
+ context "when it's a discounted ownership" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 2) }
+
+ context "and buy1livein is no" do
+ before do
+ record.buy1livein = 2
+ end
+
+ it "returns true" do
+ expect(record).to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy1livein is yes" do
+ before do
+ record.buy1livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ context "when property type is masionette or bedsit (2)" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 2) }
+
+ context "and discount is under 50%" do
+ before do
+ record.discount = 49
+ end
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "and discount is over 50%" do
+ before do
+ record.discount = 51
+ end
+
+ it "returns true" do
+ expect(record).to be_percentage_discount_invalid
+ end
+ end
+ end
+
+ context "when it's a outright sale" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 3) }
+
+ context "and buy1livein is no" do
+ before do
+ record.buy1livein = 2
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy1livein is yes" do
+ before do
+ record.buy1livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ context "when property type is House (3)" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 3) }
+
+ context "and discount is under 35%" do
+ before do
+ record.discount = 34
+ end
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "and discount is over 35%" do
+ before do
+ record.discount = 36
+ end
+
+ it "returns true" do
+ expect(record).to be_percentage_discount_invalid
+ end
+ end
+ end
+
+ context "when ownership is not given" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 3) }
+
+ before do
+ record.ownershipsch = nil
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer1_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ describe "#buyer2_livein_wrong_for_ownership_type?" do
+ context "when it's a shared ownership" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 1, jointpur: 1) }
+
+ context "and buy2livein is no" do
+ before do
+ record.buy2livein = 2
+ end
+
+ it "returns true" do
+ expect(record).to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy2livein is yes" do
+ before do
+ record.buy2livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and not a joint purchase" do
+ before do
+ record.buy2livein = 2
+ record.jointpur = 2
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ context "when it's a discounted ownership" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 2, jointpur: 1) }
+
+ context "and buy2livein is no" do
+ before do
+ record.buy2livein = 2
+ end
+
+ it "returns true" do
+ expect(record).to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy2livein is yes" do
+ before do
+ record.buy2livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ context "when it's a outright sale" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 3, jointpur: 1) }
+
+ context "and buy2livein is no" do
+ before do
+ record.buy2livein = 2
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "and buy2livein is yes" do
+ before do
+ record.buy2livein = 1
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+ end
+
+ context "when ownership is not given" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 3, jointpur: 1) }
+
+ before do
+ record.ownershipsch = nil
+ end
+
+ it "returns false" do
+ expect(record).not_to be_buyer2_livein_wrong_for_ownership_type
+ end
+ end
+
+ context "when property type is Bungalow (4)" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 4) }
+
+ context "and discount is under 35%" do
+ before do
+ record.discount = 34
+ end
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "and discount is over 35%" do
+ before do
+ record.discount = 36
+ end
+
+ it "returns true" do
+ expect(record).to be_percentage_discount_invalid
+ end
+ end
+ end
+
+ context "when property type is Other (9)" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 9) }
+
+ context "and discount is under 35%" do
+ before do
+ record.discount = 34
+ end
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "and discount is over 35%" do
+ before do
+ record.discount = 36
+ end
+
+ it "returns true" do
+ expect(record).to be_percentage_discount_invalid
+ end
+ end
+ end
+
+ context "when discount is not given" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: 1, discount: nil) }
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+
+ context "when property type is not given" do
+ let(:record) { FactoryBot.build(:sales_log, proptype: nil, discount: 51) }
+
+ it "returns false" do
+ expect(record).not_to be_percentage_discount_invalid
+ end
+ end
+ end
end
diff --git a/spec/models/validations/setup_validations_spec.rb b/spec/models/validations/setup_validations_spec.rb
index 16d52fb07..5bb180aa2 100644
--- a/spec/models/validations/setup_validations_spec.rb
+++ b/spec/models/validations/setup_validations_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Validations::SetupValidations do
subject(:setup_validator) { setup_validator_class.new }
let(:setup_validator_class) { Class.new { include Validations::SetupValidations } }
- let(:record) { FactoryBot.create(:lettings_log) }
+ let(:record) { create(:lettings_log) }
describe "tenancy start date" do
context "when in 22/23 collection" do
@@ -188,7 +188,7 @@ RSpec.describe Validations::SetupValidations do
let(:scheme) { create(:scheme, created_at: Time.zone.local(2022, 4, 1)) }
before do
- FactoryBot.create(:location, scheme:)
+ create(:location, scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:)
scheme.reload
end
@@ -213,7 +213,7 @@ RSpec.describe Validations::SetupValidations do
let(:scheme) { create(:scheme, created_at: Time.zone.local(2022, 4, 1)) }
before do
- FactoryBot.create(:location, scheme:)
+ create(:location, scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 4), reactivation_date: Time.zone.local(2022, 8, 4), scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 2), reactivation_date: Time.zone.local(2022, 8, 3), scheme:)
create(:scheme_deactivation_period, deactivation_date: Time.zone.local(2022, 6, 1), reactivation_date: Time.zone.local(2022, 9, 4), scheme:)
@@ -310,8 +310,8 @@ RSpec.describe Validations::SetupValidations do
end
describe "#validate_organisation" do
- let(:user) { FactoryBot.create(:user) }
- let(:other_organisation) { FactoryBot.create(:organisation) }
+ let(:user) { create(:user) }
+ let(:other_organisation) { create(:organisation) }
it "validates if neither managing nor owning organisation is the same as created_by user organisation" do
record.created_by = user
@@ -368,4 +368,36 @@ RSpec.describe Validations::SetupValidations do
expect(record.errors["managing_organisation_id"]).to be_empty
end
end
+
+ describe "#validate_scheme_has_confirmed_locations_validation" do
+ let(:scheme) { create(:scheme) }
+
+ context "with a scheme that has no confirmed locations" do
+ before do
+ create(:location, scheme:, postcode: nil)
+ scheme.reload
+ end
+
+ it "produces an error" do
+ record.scheme = scheme
+ setup_validator.validate_scheme_has_confirmed_locations_validation(record)
+ expect(record.errors["scheme_id"])
+ .to include(match I18n.t("validations.scheme.no_completed_locations"))
+ end
+ end
+
+ context "with a scheme that has confirmed locations" do
+ before do
+ create(:location, scheme:)
+ scheme.reload
+ end
+
+ it "does not produce an error" do
+ record.scheme = scheme
+ setup_validator.validate_scheme_has_confirmed_locations_validation(record)
+ expect(record.errors["scheme_id"])
+ .to be_empty
+ end
+ end
+ end
end
diff --git a/spec/requests/form_controller_spec.rb b/spec/requests/form_controller_spec.rb
index c60448e4e..de2e0b571 100644
--- a/spec/requests/form_controller_spec.rb
+++ b/spec/requests/form_controller_spec.rb
@@ -201,25 +201,27 @@ RSpec.describe FormController, type: :request do
describe "GET" do
context "with form pages" do
- context "when forms exist for multiple years" do
- let(:lettings_log_year_1) { create(:lettings_log, owning_organisation: organisation, created_by: user) }
- let(:lettings_log_year_2) { create(:lettings_log, :setup_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) }
+ context "when forms exist" do
+ let(:lettings_log) { create(:lettings_log, :setup_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) }
- before do
- Timecop.freeze(Time.zone.local(2021, 5, 1))
- lettings_log_year_1.update!(startdate: Time.zone.local(2021, 5, 1))
- Timecop.unfreeze
- allow(lettings_log_year_1.form).to receive(:end_date).and_return(Time.zone.today + 1.day)
- end
+ it "displays the question details" do
+ get "/lettings-logs/#{lettings_log.id}/tenant-code-test", headers: headers, params: {}
- it "displays the correct question details for each lettings log based on form year" do
- get "/lettings-logs/#{lettings_log_year_1.id}/tenant-code-test", headers: headers, params: {}
- expect(response.body).to include("What is the tenant code?")
- get "/lettings-logs/#{lettings_log_year_2.id}/tenant-code-test", headers: headers, params: {}
+ expect(response).to be_ok
expect(response.body).to match("Different question header text for this year - 2023")
end
end
+ context "when question not routed to" do
+ let(:lettings_log) { create(:lettings_log, :setup_completed, startdate: Time.zone.local(2022, 5, 1), owning_organisation: organisation, created_by: user) }
+
+ it "redirects to log" do
+ get "/lettings-logs/#{lettings_log.id}/scheme", headers: headers, params: {}
+
+ expect(response).to redirect_to("/lettings-logs/#{lettings_log.id}")
+ end
+ end
+
context "when lettings logs are not owned or managed by your organisation" do
it "does not show form pages for lettings logs you don't have access to" do
get "/lettings-logs/#{unauthorized_lettings_log.id}/person-1-age", headers: headers, params: {}
diff --git a/spec/requests/locations_controller_spec.rb b/spec/requests/locations_controller_spec.rb
index 154d18735..ab9dcd268 100644
--- a/spec/requests/locations_controller_spec.rb
+++ b/spec/requests/locations_controller_spec.rb
@@ -1263,14 +1263,30 @@ RSpec.describe LocationsController, type: :request do
patch "/schemes/#{scheme.id}/locations/#{location.id}/confirm", params:
end
- it "confirms location" do
- expect(Location.last.confirmed).to eq(true)
+ context "when location is complete" do
+ it "confirms location" do
+ expect(Location.last.confirmed).to eq(true)
+ end
+
+ it "redirects correctly and displays success banner" do
+ follow_redirect!
+ expect(page).to have_content("Success")
+ expect(page).to have_content("added to this scheme")
+ end
end
- it "redirects correctly and displays success banner" do
- follow_redirect!
- expect(page).to have_content("Success")
- expect(page).to have_content("added to this scheme")
+ context "when location is not complete" do
+ let(:location) { FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2000, 1, 1), postcode: nil) }
+
+ it "does not confirm location" do
+ expect(Location.last.confirmed).to eq(false)
+ end
+
+ it "redirects correctly and does not display success banner" do
+ follow_redirect!
+ expect(page).not_to have_content("Success")
+ expect(page).not_to have_content("added to this scheme")
+ end
end
end
@@ -1308,14 +1324,30 @@ RSpec.describe LocationsController, type: :request do
patch "/schemes/#{scheme.id}/locations/#{location.id}/confirm", params:
end
- it "confirms location" do
- expect(Location.last.confirmed).to eq(true)
+ context "when location is complete" do
+ it "confirms location" do
+ expect(Location.last.confirmed).to eq(true)
+ end
+
+ it "redirects correctly and displays success banner" do
+ follow_redirect!
+ expect(page).to have_content("Success")
+ expect(page).to have_content("added to this scheme")
+ end
end
- it "redirects correctly and displays success banner" do
- follow_redirect!
- expect(page).to have_content("Success")
- expect(page).to have_content("added to this scheme")
+ context "when location is not complete" do
+ let(:location) { FactoryBot.create(:location, scheme:, startdate: Time.zone.local(2000, 1, 1), postcode: nil) }
+
+ it "does not confirm location" do
+ expect(Location.last.confirmed).to eq(false)
+ end
+
+ it "redirects correctly and does not display success banner" do
+ follow_redirect!
+ expect(page).not_to have_content("Success")
+ expect(page).not_to have_content("added to this scheme")
+ end
end
end
diff --git a/spec/requests/organisations_controller_spec.rb b/spec/requests/organisations_controller_spec.rb
index 15cfba390..459987fdc 100644
--- a/spec/requests/organisations_controller_spec.rb
+++ b/spec/requests/organisations_controller_spec.rb
@@ -227,6 +227,11 @@ RSpec.describe OrganisationsController, type: :request do
expected_html = "data-qa=\"change-name\" href=\"/organisations/#{organisation.id}/edit\""
expect(response.body).to include(expected_html)
end
+
+ it "displays a link to merge organisations" do
+ expect(page).to have_content("Is your organisation merging with another?")
+ expect(page).to have_link("Let us know using this form", href: "/organisations/#{organisation.id}/merge")
+ end
end
context "with organisation that are not in scope for the user, i.e. that they do not belong to" do
@@ -435,6 +440,36 @@ RSpec.describe OrganisationsController, type: :request do
expect { request }.not_to change(Organisation, :count)
end
end
+
+ describe "#merge" do
+ context "with an organisation that the user belongs to" do
+ before do
+ get "/organisations/#{organisation.id}/merge", headers:, params: {}
+ end
+
+ it "shows the correct content" do
+ expect(page).to have_content("Tell us if your organisation is merging")
+ end
+
+ it "has a correct back link" do
+ expect(page).to have_link("Back", href: "/organisations/#{organisation.id}")
+ end
+
+ it "has a correct start no button" do
+ expect(page).to have_link("Start now", href: "#")
+ end
+ end
+
+ context "with organisation that are not in scope for the user, i.e. that they do not belong to" do
+ before do
+ get "/organisations/#{unauthorised_organisation.id}/merge", headers:, params: {}
+ end
+
+ it "returns not found 404 from org details route" do
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+ end
end
context "with a data provider user" do
diff --git a/spec/requests/schemes_controller_spec.rb b/spec/requests/schemes_controller_spec.rb
index fb9150940..1a450a922 100644
--- a/spec/requests/schemes_controller_spec.rb
+++ b/spec/requests/schemes_controller_spec.rb
@@ -658,6 +658,26 @@ RSpec.describe SchemesController, type: :request do
end
end
+ context "when scheme is completed but not yet confirmed" do
+ let(:params) { { scheme: { page: "check-answers" } } }
+
+ it "is not confirmed" do
+ expect(scheme_to_update.confirmed).to eq(nil)
+ end
+
+ context "when confirming finished scheme" do
+ let(:params) { { scheme: { confirmed: true, page: "check-answers" } } }
+
+ before do
+ scheme_to_update.reload
+ end
+
+ it "confirms scheme" do
+ expect(scheme_to_update.confirmed).to eq(true)
+ end
+ end
+ end
+
context "when required params are missing" do
let(:params) do
{ scheme: {
@@ -921,6 +941,35 @@ RSpec.describe SchemesController, type: :request do
patch "/schemes/#{scheme_to_update.id}", params:
end
+ context "when confirming unfinished scheme" do
+ let(:params) { { scheme: { owning_organisation_id: user.organisation.id, arrangement_type: nil, confirmed: true, page: "check-answers" } } }
+
+ it "does not allow the scheme to be confirmed" do
+ expect(response).to have_http_status(:unprocessable_entity)
+ expect(page).to have_content(I18n.t("activerecord.errors.models.scheme.attributes.arrangement_type.invalid"))
+ end
+ end
+
+ context "when scheme is completed but not yet confirmed" do
+ let(:params) { { scheme: { page: "check-answers" } } }
+
+ it "is not confirmed" do
+ expect(scheme_to_update.confirmed).to eq(nil)
+ end
+
+ context "when confirming finished scheme" do
+ let(:params) { { scheme: { confirmed: true, page: "check-answers" } } }
+
+ before do
+ scheme_to_update.reload
+ end
+
+ it "confirms scheme" do
+ expect(scheme_to_update.confirmed).to eq(true)
+ end
+ end
+ end
+
context "when required params are missing" do
let(:params) do
{ scheme: {
diff --git a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
index b79ee9f88..37d8e24a5 100644
--- a/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
@@ -242,9 +242,9 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_13: "123" } }
it "has errors on setup fields" do
- errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute)
+ errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort
- expect(errors).to eql(%i[field_4 field_5 field_7 field_8 field_9 field_1 field_2])
+ expect(errors).to eql(%i[field_1 field_2 field_4 field_5 field_6 field_7 field_8 field_9])
end
end
@@ -792,7 +792,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
end
- describe "#field_6" do
+ describe "#field_6" do # renewal
context "when an unpermitted value" do
let(:attributes) { { bulk_upload:, field_6: "3" } }
@@ -800,6 +800,14 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_6]).to be_present
end
end
+
+ context "when blank" do
+ let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_6: "" } }
+
+ it "has errors on the field" do
+ expect(parser.errors[:field_6]).to include("You must answer property renewal")
+ end
+ end
end
describe "#field_18" do # UPRN
@@ -844,12 +852,12 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
end
end
- describe "#field_56" do # age3
+ describe "#field_52" do # age2
context "when null but gender given" do
- let(:attributes) { setup_section_params.merge({ field_56: "", field_57: "F" }) }
+ let(:attributes) { setup_section_params.merge({ field_52: "", field_53: "F" }) }
it "returns an error" do
- expect(parser.errors[:field_56]).to be_present
+ expect(parser.errors[:field_52]).to be_present
end
end
end
@@ -1103,14 +1111,6 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.log.renewal).to eq(0)
end
end
-
- context "when field_6 is null but rsnvac/field_27 is 14" do
- let(:attributes) { { bulk_upload:, field_6: "", field_27: "14" } }
-
- it "sets renewal to 1" do
- expect(parser.log.renewal).to eq(1)
- end
- end
end
describe "#sexN fields" do
diff --git a/spec/services/exports/lettings_log_export_service_spec.rb b/spec/services/exports/lettings_log_export_service_spec.rb
index b2aaace1a..349d2fc84 100644
--- a/spec/services/exports/lettings_log_export_service_spec.rb
+++ b/spec/services/exports/lettings_log_export_service_spec.rb
@@ -135,6 +135,15 @@ RSpec.describe Exports::LettingsLogExportService do
export_service.export_xml_lettings_logs
end
+
+ it "generates a master manifest with CSV headers" do
+ actual_content = nil
+ expected_content = "zip-name,date-time zipped folder generated,zip-file-uri\ncore_2021_2022_apr_mar_f0001_inc0001,2022-05-01 00:00:00 +0100,#{expected_zip_filename}\n"
+ allow(storage_service).to receive(:write_file).with(expected_master_manifest_filename, any_args) { |_, arg2| actual_content = arg2&.string }
+
+ export_service.export_xml_lettings_logs
+ expect(actual_content).to eq(expected_content)
+ end
end
context "with 23/24 collection period" do
diff --git a/spec/services/imports/lettings_logs_import_service_spec.rb b/spec/services/imports/lettings_logs_import_service_spec.rb
index deccde0c0..4621afb2f 100644
--- a/spec/services/imports/lettings_logs_import_service_spec.rb
+++ b/spec/services/imports/lettings_logs_import_service_spec.rb
@@ -323,6 +323,34 @@ RSpec.describe Imports::LettingsLogsImportService do
end
end
+ context "and is a other tenancy but missing tenancyother" do
+ let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
+
+ before do
+ lettings_log_xml.at_xpath("//meta:status").content = "saved"
+ lettings_log_xml.at_xpath("//xmlns:Q2b").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q2ba").content = ""
+ end
+
+ it "intercepts the relevant validation error" do
+ allow(logger).to receive(:warn)
+
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the invalid answers" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.tenancy).to be_nil
+ expect(lettings_log.tenancyother).to be_nil
+ end
+ end
+
context "and this is an internal transfer from a non social housing" do
before do
lettings_log_xml.at_xpath("//xmlns:Q11").content = "9 Residential care home"
@@ -532,11 +560,11 @@ RSpec.describe Imports::LettingsLogsImportService do
end
it "intercepts the relevant validation error" do
- expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing brent with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10 per week")
- expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing scharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10 per week")
- expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing pscharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10 per week")
- expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing supcharg with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10 per week")
- expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing tcharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10 per week")
+ expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing brent with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing scharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing pscharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing supcharg with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0b4a68df-30cc-474a-93c0-a56ce8fdad3b: Removing tcharge with error: Answer either the ‘household rent and charges’ question or ‘is this accommodation a care home‘, or select ‘no’ for ‘does the household pay rent or charges for the accommodation?’, Enter a total charge that is at least £10.00 per week")
expect { lettings_log_service.send(:create_log, lettings_log_xml) }
.not_to raise_error
end
@@ -719,6 +747,78 @@ RSpec.describe Imports::LettingsLogsImportService do
end
end
+ context "and tcharge is less than £10 per week" do
+ before do
+ lettings_log_xml.at_xpath("//xmlns:Q18ai").content = "1"
+ lettings_log_xml.at_xpath("//xmlns:Q18aii").content = "2"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiii").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiv").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18av").content = "9"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing brent with error: Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing scharge with error: Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing pscharge with error: Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing supcharg with error: Enter a total charge that is at least £10.00 per week")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing tcharge with error: Enter a total charge that is at least £10.00 per week")
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the charges answers" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.tcharge).to be_nil
+ end
+ end
+
+ context "and rent is higher than the absolute maximum expected for a property " do
+ before do
+ LaRentRange.create!(
+ ranges_rent_id: "2",
+ la: "E08000035",
+ beds: 2,
+ lettype: 1,
+ soft_min: 12.41,
+ soft_max: 89.54,
+ hard_min: 9.87,
+ hard_max: 100.99,
+ start_year: 2021,
+ )
+
+ lettings_log_xml.at_xpath("//xmlns:Q18ai").content = "500"
+ lettings_log_xml.at_xpath("//xmlns:Q18aii").content = "2"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiii").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18aiv").content = "3"
+ lettings_log_xml.at_xpath("//xmlns:Q18av").content = "508"
+ end
+
+ it "intercepts the relevant validation error" do
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing brent with error: Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing scharge with error: Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing pscharge with error: Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing supcharg with error: Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms")
+ expect(logger).to receive(:warn).with("Log 0ead17cb-1668-442d-898c-0d52879ff592: Removing tcharge with error: Rent is higher than the absolute maximum expected for a property of this type. Please check the rent, rent period, local authority and (if general needs) number of bedrooms")
+ expect { lettings_log_service.send(:create_log, lettings_log_xml) }
+ .not_to raise_error
+ end
+
+ it "clears out the charges answers" do
+ allow(logger).to receive(:warn)
+
+ lettings_log_service.send(:create_log, lettings_log_xml)
+ lettings_log = LettingsLog.find_by(old_id: lettings_log_id)
+
+ expect(lettings_log).not_to be_nil
+ expect(lettings_log.tcharge).to be_nil
+ end
+ end
+
context "and location is not active during the period" do
let(:lettings_log_id) { "0b4a68df-30cc-474a-93c0-a56ce8fdad3b" }
diff --git a/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb b/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb
new file mode 100644
index 000000000..286e1e279
--- /dev/null
+++ b/spec/views/bulk_upload_lettings_results/show.html.erb_spec.rb
@@ -0,0 +1,20 @@
+require "rails_helper"
+
+RSpec.describe "bulk_upload_lettings_results/show.html.erb" do
+ let(:bulk_upload) { create(:bulk_upload, :lettings) }
+
+ before do
+ create(:bulk_upload_error, bulk_upload:, cell: "AA100", row: "100", col: "AA")
+ create(:bulk_upload_error, bulk_upload:, cell: "Z100", row: "100", col: "Z")
+ end
+
+ it "renders errors ordered by cell" do
+ assign(:bulk_upload, bulk_upload)
+
+ render
+
+ fragment = Capybara::Node::Simple.new(rendered)
+
+ expect(fragment.find_css("table tbody th").map(&:inner_text)).to eql(%w[Z100 AA100])
+ end
+end