diff --git a/app/models/validations/.yardoc/checksums b/app/models/validations/.yardoc/checksums new file mode 100644 index 000000000..556d95ee7 --- /dev/null +++ b/app/models/validations/.yardoc/checksums @@ -0,0 +1,15 @@ +sales/financial_validations.rb 6add021f45e5e9c88d0afec093421b0063212292 +sales/household_validations.rb 3a1cb5ed2c2d1ce2a1ce0cf15cee1f9f3b6b5f9d +sales/property_validations.rb 20246b8f4746379f02de744d5e946f2859174b93 +sales/sale_information_validations.rb 23d52b47f67fc5ef728e0d82b80e8d6f748d5205 +sales/setup_validations.rb ef71ce4e95490183dca7893b908f46afb003e91b +sales/soft_validations.rb 80f3e430dda865cf4256db8bb966f9fcd47773c9 +date_validations.rb 8a8d0c5640e5426441a46db20c82f8bbff864250 +financial_validations.rb a3996355854dfb5df4a39357ee074783c7f8e17e +household_validations.rb 3b54050ed5cfb80be6f4d920bb48780eff4e646f +local_authority_validations.rb a83a049b3b8ea90de2b629c071b5832705b6f0c1 +property_validations.rb f5f2ffe3e2d7c9a5deb31ba2618ad2641598d148 +setup_validations.rb 75dba754f71e631fd35c216cf5610a8cb13d8b6e +shared_validations.rb 5d408ca2ede983dd0e38a6dbfc1136b18c099ea9 +soft_validations.rb af5a959f496c7f509d784528896171abd7d726ee +tenancy_validations.rb 954d3c4bad2304cf656295a5e7a79d87f37a225e diff --git a/app/models/validations/.yardoc/complete b/app/models/validations/.yardoc/complete new file mode 100644 index 000000000..e69de29bb diff --git a/app/models/validations/.yardoc/object_types b/app/models/validations/.yardoc/object_types new file mode 100644 index 000000000..fa49e9f5c Binary files /dev/null and b/app/models/validations/.yardoc/object_types differ diff --git a/app/models/validations/.yardoc/objects/root.dat b/app/models/validations/.yardoc/objects/root.dat new file mode 100644 index 000000000..5d3e6caa5 Binary files /dev/null and b/app/models/validations/.yardoc/objects/root.dat differ diff --git a/app/models/validations/.yardoc/proxy_types b/app/models/validations/.yardoc/proxy_types new file mode 100644 index 000000000..beefda1ae Binary files /dev/null and b/app/models/validations/.yardoc/proxy_types differ diff --git a/app/models/validations/doc/Validations/DateValidations.html b/app/models/validations/doc/Validations/DateValidations.html new file mode 100644 index 000000000..aedff3786 --- /dev/null +++ b/app/models/validations/doc/Validations/DateValidations.html @@ -0,0 +1,360 @@ + + + + + + + Module: Validations::DateValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::DateValidations + + + +

+
+ + + + + + +
+
Includes:
+
SharedValidations
+
+ + + + + + +
+
Defined in:
+
date_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_property_major_repairs(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
+
# File 'date_validations.rb', line 4
+
+def validate_property_major_repairs(record)
+  date_valid?("mrcdate", record)
+  if record["startdate"].present? && record["mrcdate"].present? && record["startdate"] < record["mrcdate"]
+    record.errors.add :mrcdate, I18n.t("validations.property.mrcdate.before_tenancy_start")
+  end
+
+  if is_rsnvac_first_let?(record) && record["mrcdate"].present?
+    record.errors.add :mrcdate, I18n.t("validations.property.mrcdate.not_first_let")
+  end
+
+  if record["mrcdate"].present? && record["startdate"].present? && record["startdate"].to_date - record["mrcdate"].to_date > 3650
+    record.errors.add :mrcdate, I18n.t("validations.property.mrcdate.ten_years_before_tenancy_start")
+  end
+end
+
+
+ +
+

+ + #validate_property_void_date(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+
+
# File 'date_validations.rb', line 19
+
+def validate_property_void_date(record)
+  if record["voiddate"].present? && record["startdate"].present? && record["startdate"].to_date - record["voiddate"].to_date > 3650
+    record.errors.add :voiddate, I18n.t("validations.property.void_date.ten_years_before_tenancy_start")
+  end
+
+  if record["voiddate"].present? && record["startdate"].present? && record["startdate"].to_date < record["voiddate"].to_date
+    record.errors.add :voiddate, I18n.t("validations.property.void_date.before_tenancy_start")
+  end
+
+  if record["voiddate"].present? && record["mrcdate"].present? && record["mrcdate"].to_date < record["voiddate"].to_date
+    record.errors.add :voiddate, :after_mrcdate, message: I18n.t("validations.property.void_date.after_mrcdate")
+    record.errors.add :mrcdate, I18n.t("validations.property.mrcdate.before_void_date")
+  end
+end
+
+
+ +
+

+ + #validate_startdate(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+
+
# File 'date_validations.rb', line 34
+
+def validate_startdate(record)
+  return unless record.startdate && date_valid?("startdate", record)
+
+  if record["voiddate"].present? && record.startdate < record["voiddate"]
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.after_void_date")
+  end
+
+  if record["mrcdate"].present? && record.startdate < record["mrcdate"]
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.after_major_repair_date")
+  end
+
+  if record["voiddate"].present? && record["startdate"].to_date - record["voiddate"].to_date > 3650
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.ten_years_after_void_date")
+  end
+
+  if record["mrcdate"].present? && record["startdate"].to_date - record["mrcdate"].to_date > 3650
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.ten_years_after_mrc_date")
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/FinancialValidations.html b/app/models/validations/doc/Validations/FinancialValidations.html new file mode 100644 index 000000000..a73ca9e12 --- /dev/null +++ b/app/models/validations/doc/Validations/FinancialValidations.html @@ -0,0 +1,915 @@ + + + + + + + Module: Validations::FinancialValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::FinancialValidations + + + +

+
+ + + + + + +
+
Includes:
+
ChargesHelper, MoneyFormattingHelper, SharedValidations
+
+ + + + + + +
+
Defined in:
+
financial_validations.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
EMPLOYED_STATUSES = + +
+
[1, 0].freeze
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + +
+

Instance Method Details

+ + +
+

+ + #no_known_benefits?(record) ⇒ Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+
+
# File 'financial_validations.rb', line 108
+
+def no_known_benefits?(record)
+  return true unless record.collection_start_year
+
+  if record.collection_start_year <= 2021
+    record.benefits_unknown? ||
+      record.receives_no_benefits? ||
+      record.receives_universal_credit_but_no_housing_benefit?
+  else
+    record.benefits_unknown? ||
+      record.receives_no_benefits? ||
+      record.tenant_refuses_to_say_benefits?
+  end
+end
+
+
+ +
+

+ + #validate_care_home_charges(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+
+
# File 'financial_validations.rb', line 158
+
+def validate_care_home_charges(record)
+  if record.is_carehome?
+    period = record.form.get_question("period", record).label_from_value(record.period).downcase
+    # NOTE: This is a temporary change to allow `ccharge` values despite `is_carehome` being true. This value
+    # is going to be moved to a soft validation in CLDC-2074, so we can safely do this.
+    if record.chcharge.blank?
+      # record.errors.add :is_carehome, I18n.t("validations.financial.carehome.not_provided", period:)
+      # record.errors.add :chcharge, I18n.t("validations.financial.carehome.not_provided", period:)
+    elsif !weekly_value_in_range(record, "chcharge", 10, 5000)
+      max_chcharge = record.weekly_to_value_per_period(5000)
+      min_chcharge = record.weekly_to_value_per_period(10)
+      message = I18n.t("validations.financial.carehome.out_of_range", period:, min_chcharge:, max_chcharge:)
+
+      record.errors.add :period, message
+      record.errors.add :chcharge, :out_of_range, message:
+    end
+  end
+end
+
+
+ +
+

+ + #validate_negative_currency(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+93
+94
+95
+96
+97
+98
+99
+100
+
+
# File 'financial_validations.rb', line 93
+
+def validate_negative_currency(record)
+  t = %w[earnings brent scharge pscharge supcharg]
+  t.each do |x|
+    if record[x].present? && record[x].negative?
+      record.errors.add x.to_sym, I18n.t("validations.financial.negative_currency")
+    end
+  end
+end
+
+
+ +
+

+ + #validate_net_income(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+
+
# File 'financial_validations.rb', line 27
+
+def validate_net_income(record)
+  if record.ecstat1 && record.hhmemb && record.weekly_net_income && record.startdate && record.form.start_date.year >= 2023
+    if record.weekly_net_income > record.applicable_income_range.hard_max
+      frequency = record.form.get_question("incfreq", record).label_from_value(record.incfreq).downcase
+      hard_max = format_as_currency(record.applicable_income_range.hard_max)
+      record.errors.add(
+        :earnings,
+        :over_hard_max,
+        message: I18n.t("validations.financial.earnings.over_hard_max", hard_max:),
+      )
+      record.errors.add(
+        :hhmemb,
+        :over_hard_max,
+        message: I18n.t("validations.financial.hhmemb.earnings.over_hard_max", earnings: format_as_currency(record.earnings), frequency:),
+      )
+      (1..record.hhmemb).each do |n|
+        record.errors.add(
+          "ecstat#{n}",
+          :over_hard_max,
+          message: I18n.t("validations.financial.ecstat.over_hard_max", earnings: format_as_currency(record.earnings), frequency:),
+        )
+        next unless record["ecstat#{n}"] == 9
+
+        record.errors.add(
+          "age#{n}",
+          :over_hard_max,
+          message: I18n.t("validations.financial.age.earnings_over_hard_max", earnings: format_as_currency(record.earnings), frequency:),
+        )
+      end
+    end
+
+    if record.weekly_net_income < record.applicable_income_range.hard_min
+      hard_min = format_as_currency(record.applicable_income_range.hard_min)
+      frequency = record.form.get_question("incfreq", record).label_from_value(record.incfreq).downcase
+      record.errors.add(
+        :earnings,
+        :under_hard_min,
+        message: I18n.t("validations.financial.earnings.under_hard_min", hard_min:),
+      )
+      record.errors.add(
+        :hhmemb,
+        :under_hard_min,
+        message: I18n.t("validations.financial.hhmemb.earnings.under_hard_min", earnings: format_as_currency(record.earnings), frequency:),
+      )
+      (1..record.hhmemb).each do |n|
+        record.errors.add(
+          "ecstat#{n}",
+          :under_hard_min,
+          message: I18n.t("validations.financial.ecstat.under_hard_min", earnings: format_as_currency(record.earnings), frequency:),
+        )
+        # N.B. It is not possible for a change to an age field to increase the hard min
+      end
+    end
+  end
+
+  if record.earnings.present? && record.incfreq.blank?
+    record.errors.add :incfreq, I18n.t("validations.financial.earnings.freq_missing")
+    record.errors.add :earnings, I18n.t("validations.financial.earnings.freq_missing")
+  end
+
+  if record.incfreq.present? && record.earnings.blank?
+    record.errors.add :earnings, I18n.t("validations.financial.earnings.earnings_missing")
+    record.errors.add :incfreq, I18n.t("validations.financial.earnings.earnings_missing")
+  end
+end
+
+
+ +
+

+ + #validate_net_income_uc_proportion(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
+
# File 'financial_validations.rb', line 15
+
+def validate_net_income_uc_proportion(record)
+  (1..8).any? do |n|
+    economic_status = record["ecstat#{n}"]
+    is_employed = EMPLOYED_STATUSES.include?(economic_status)
+    relationship = record["relat#{n}"]
+    is_partner_or_main = relationship == "P" || (relationship.nil? && economic_status.present?)
+    if is_employed && is_partner_or_main && record.benefits&.zero?
+      record.errors.add :benefits, I18n.t("validations.financial.benefits.part_or_full_time")
+    end
+  end
+end
+
+
+ +
+

+ + #validate_outstanding_rent_amount(record) ⇒ Object + + + + + +

+
+ +

Validations methods need to be called ‘validate_<page_name>’ to run on model save or ‘validate_’ to run on submit as well

+ + +
+
+
+ + +
+ + + + +
+
+
+
+7
+8
+9
+10
+11
+12
+
+
# File 'financial_validations.rb', line 7
+
+def validate_outstanding_rent_amount(record)
+  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_expected")
+    record.errors.add :hbrentshortfall, :no_outstanding_charges, message: I18n.t("validations.financial.hbrentshortfall.outstanding_amount_not_expected")
+  end
+end
+
+
+ +
+

+ + #validate_rent_amount(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+
+
# File 'financial_validations.rb', line 122
+
+def validate_rent_amount(record)
+  if record.wtshortfall
+    if record.wrent && (record.wtshortfall > record.wrent)
+      record.errors.add :tshortfall, :more_than_rent, message: I18n.t("validations.financial.tshortfall.more_than_rent")
+      record.errors.add :brent, I18n.t("validations.financial.rent.less_than_shortfall")
+    elsif record.wtshortfall < 0.01
+      record.errors.add :tshortfall, :must_be_positive, message: I18n.t("validations.financial.tshortfall.must_be_positive")
+    end
+  end
+
+  if record.tcharge.present? && weekly_value_in_range(record, "tcharge", 0, 9.99)
+    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] : [])
+  if answered_questions.count(&:present?) > 1
+    record.errors.add :tcharge, :complete_1_of_3, message: I18n.t("validations.financial.charges.complete_1_of_3") if record.tcharge.present?
+    record.errors.add :chcharge, I18n.t("validations.financial.charges.complete_1_of_3") if record.chcharge.present?
+    record.errors.add :household_charge, I18n.t("validations.financial.charges.complete_1_of_3") if record.household_charge.present?
+  end
+
+  validate_charges(record)
+  validate_rent_range(record)
+end
+
+
+ +
+

+ + #validate_rent_period(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+
+
# File 'financial_validations.rb', line 147
+
+def validate_rent_period(record)
+  if record.managing_organisation.present? && record.managing_organisation.rent_periods.present? &&
+      record.period && !record.managing_organisation.rent_periods.include?(record.period)
+    record.errors.add :period, :wrong_rent_period, message: I18n.t(
+      "validations.financial.rent_period.invalid_for_org",
+      org_name: record.managing_organisation.name,
+      rent_period: record.form.get_question("period", record).label_from_value(record.period).downcase,
+    )
+  end
+end
+
+
+ +
+

+ + #validate_tshortfall(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+102
+103
+104
+105
+106
+
+
# File 'financial_validations.rb', line 102
+
+def validate_tshortfall(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
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/HouseholdValidations.html b/app/models/validations/doc/Validations/HouseholdValidations.html new file mode 100644 index 000000000..d3e28583e --- /dev/null +++ b/app/models/validations/doc/Validations/HouseholdValidations.html @@ -0,0 +1,1243 @@ + + + + + + + Module: Validations::HouseholdValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::HouseholdValidations + + + +

+
+ + + + + + +
+
Includes:
+
SharedValidations
+
+ + + + + + +
+
Defined in:
+
household_validations.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
PHRASES_INDICATING_HOMELESSNESS = + +
+
[
+  "Homeless",
+  "Homelessness",
+  "Temporary accommodation",
+  "Temp accommodation",
+  "TA",
+  "Sleeping rough",
+  "Rough sleeping",
+].freeze
+ +
PHRASES_INDICATING_HOMELESSNESS_REGEX = + +
+
Regexp.union(
+  PHRASES_INDICATING_HOMELESSNESS.map { |phrase| Regexp.new("\\A[^[:alpha:]]*#{phrase}[^[:alpha:]]*\\Z", Regexp::IGNORECASE) },
+)
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_armed_forces(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+46
+47
+48
+49
+50
+51
+52
+53
+
+
# File 'household_validations.rb', line 46
+
+def validate_armed_forces(record)
+  if (record.armed_forces_no? || record.armed_forces_refused?) && record.reservist.present?
+    record.errors.add :reservist, I18n.t("validations.household.reservist.injury_not_required")
+  end
+  if !record.armed_forces_regular? && record.leftreg.present?
+    record.errors.add :leftreg, I18n.t("validations.household.leftreg.question_not_required")
+  end
+end
+
+
+ +
+

+ + #validate_combination_of_housing_needs_responses(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+212
+213
+214
+215
+216
+217
+218
+
+
# File 'household_validations.rb', line 212
+
+def validate_combination_of_housing_needs_responses(record)
+  if record.has_housingneeds? && record.housingneeds_type_not_listed? && record.no_or_unknown_other_housing_needs?
+    record.errors.add :housingneeds, I18n.t("validations.household.housingneeds.invalid")
+    record.errors.add :housingneeds_type, I18n.t("validations.household.housingneeds.invalid")
+    record.errors.add :housingneeds_other, I18n.t("validations.household.housingneeds.invalid")
+  end
+end
+
+
+ +
+

+ + #validate_condition_effects(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+132
+133
+134
+135
+136
+137
+
+
# File 'household_validations.rb', line 132
+
+def validate_condition_effects(record)
+  all_options = [record.illness_type_1, record.illness_type_2, record.illness_type_3, record.illness_type_4, record.illness_type_5, record.illness_type_6, record.illness_type_7, record.illness_type_8, record.illness_type_9, record.illness_type_10]
+  if all_options.count(1) >= 1 && household_no_illness?(record)
+    record.errors.add :condition_effects, I18n.t("validations.household.condition_effects.no_choices")
+  end
+end
+
+
+ +
+

+ + #validate_layear(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+190
+191
+192
+193
+194
+195
+196
+197
+
+
# File 'household_validations.rb', line 190
+
+def validate_layear(record)
+  return unless record.layear && record.renewal
+
+  if record.is_renewal? && record.layear == 1
+    record.errors.add :layear, :renewal_just_moved, message: I18n.t("validations.household.renewal_just_moved_to_area.layear")
+    record.errors.add :renewal, I18n.t("validations.household.renewal_just_moved_to_area.renewal")
+  end
+end
+
+
+ +
+

+ + #validate_layear_and_prevloc(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+
+
# File 'household_validations.rb', line 199
+
+def validate_layear_and_prevloc(record)
+  return unless record.layear && record.la && record.prevloc && record.collection_start_year
+
+  if record.la == record.prevloc && record.layear == 1 && record.collection_start_year >= 2023
+    record.errors.add :layear, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.layear")
+    record.errors.add :la, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.current_la")
+    record.errors.add :postcode_full, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.current_la")
+    record.errors.add :uprn, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.current_la")
+    record.errors.add :ppostcode_full, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.previous_la")
+    record.errors.add :prevloc, :renewal_just_moved, message: I18n.t("validations.household.same_la_just_moved_to_area.previous_la")
+  end
+end
+
+
+ +
+

+ + #validate_partner_count(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+55
+56
+57
+
+
# File 'household_validations.rb', line 55
+
+def validate_partner_count(record)
+  shared_validate_partner_count(record, 8)
+end
+
+
+ +
+

+ + #validate_person_1_economic(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+
+
# File 'household_validations.rb', line 59
+
+def validate_person_1_economic(record)
+  return unless record.age1 && record.ecstat1 && !record.form.start_year_after_2024?
+
+  if record.age1 < 16 && !economic_status_is_child_other_or_refused?(record.ecstat1)
+    record.errors.add "ecstat1", I18n.t("validations.household.ecstat.child_under_16", person_num: 1)
+    record.errors.add "age1", I18n.t("validations.household.age.child_under_16_ecstat", person_num: 1)
+  end
+  if tenant_is_economic_child?(record.ecstat1) && record.age1 > 16
+    record.errors.add "ecstat1", I18n.t("validations.household.ecstat.child_over_16", person_num: 1)
+    record.errors.add "age1", I18n.t("validations.household.age.child_over_16", person_num: 1)
+  end
+end
+
+
+ +
+

+ + #validate_person_age_and_relationship_matches_economic_status(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+
+
# File 'household_validations.rb', line 104
+
+def validate_person_age_and_relationship_matches_economic_status(record)
+  return unless record.startdate && !record.form.start_year_after_2024?
+
+  (2..8).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    economic_status = record.public_send("ecstat#{person_num}")
+    relationship = record.public_send("relat#{person_num}")
+    next unless age && economic_status && relationship
+
+    age_between_16_19 = age.between?(16, 19)
+    student = tenant_is_fulltime_student?(economic_status)
+    economic_status_refused = tenant_economic_status_refused?(economic_status)
+    child = tenant_is_child?(relationship)
+
+    if age_between_16_19 && !(student || economic_status_refused) && child
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.must_be_student")
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.cannot_be_16_19.child_not_student")
+      record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.16_19_not_student")
+    end
+
+    next unless !age_between_16_19 && student && child
+
+    record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.must_be_16_19")
+    record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.cannot_be_student.child_not_16_19")
+    record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.student_not_16_19")
+  end
+end
+
+
+ +
+

+ + #validate_person_age_matches_economic_status(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+
+
# File 'household_validations.rb', line 72
+
+def validate_person_age_matches_economic_status(record)
+  (2..8).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    economic_status = record.public_send("ecstat#{person_num}")
+    next unless age && economic_status
+
+    if age < 16 && !economic_status_is_child_other_or_refused?(economic_status) && !record.form.start_year_after_2024?
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_under_16", person_num:)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_ecstat", person_num:)
+    end
+    if tenant_is_economic_child?(economic_status) && age > 16
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_over_16", person_num:)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_over_16", person_num:)
+    end
+  end
+end
+
+
+ +
+

+ + #validate_person_age_matches_relationship(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+
+
# File 'household_validations.rb', line 89
+
+def validate_person_age_matches_relationship(record)
+  return unless record.startdate && !record.form.start_year_after_2024?
+
+  (2..8).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    relationship = record.public_send("relat#{person_num}")
+    next unless age && relationship
+
+    if age < 16 && !relationship_is_child_other_or_refused?(relationship)
+      record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.child_under_16_lettings", person_num:)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_relat_lettings", person_num:)
+    end
+  end
+end
+
+
+ +
+

+ + #validate_previous_housing_situation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+
+
# File 'household_validations.rb', line 139
+
+def validate_previous_housing_situation(record)
+  if record.is_relet_to_temp_tenant? && !record.previous_tenancy_was_temporary?
+    record.errors.add :prevten, :non_temp_accommodation, message: I18n.t("validations.household.prevten.non_temp_accommodation")
+  end
+
+  if record.age1.present? && record.age1 > 25 && record.previous_tenancy_was_foster_care?
+    record.errors.add :prevten, :over_25_foster_care, message: I18n.t("validations.household.prevten.over_25_foster_care")
+    record.errors.add :age1, I18n.t("validations.household.age.lead.over_25")
+  end
+
+  if record.sex1 == "M" && record.previous_tenancy_was_refuge?
+    record.errors.add :prevten, I18n.t("validations.household.prevten.male_refuge")
+    record.errors.add :sex1, I18n.t("validations.household.gender.male_refuge")
+  end
+
+  # 3  Private Sector Tenancy
+  # 4  Tied housing or rented with job
+  # 7  Direct access hostel
+  # 10 Hospital
+  # 13 Children's home / Foster Care
+  # 14 Bed and breakfast
+  # 19 Rough Sleeping
+  # 23 Mobile home / Caravan
+  # 24 Home Office Asylum Support
+  # 25 Other
+  # 26 Owner Occupation
+  # 27 Owner occupation (low-cost home ownership)
+  # 28 Living with Friends or Family
+  # 29 Prison / Approved Probation Hostel
+  if record.is_internal_transfer? && [3, 4, 7, 10, 13, 14, 19, 23, 24, 25, 26, 27, 28, 29].include?(record.prevten)
+    label = record.form.get_question("prevten", record).present? ? record.form.get_question("prevten", record).label_from_value(record.prevten) : ""
+    record.errors.add :prevten, :internal_transfer_non_social_housing, message: I18n.t("validations.household.prevten.internal_transfer", prevten: label)
+    record.errors.add :referral, :internal_transfer_non_social_housing, message: I18n.t("validations.household.referral.prevten_invalid", prevten: label)
+  end
+end
+
+
+ +
+

+ + #validate_prevloc(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+184
+185
+186
+187
+188
+
+
# File 'household_validations.rb', line 184
+
+def validate_prevloc(record)
+  if record.previous_la_known? && record.prevloc.blank?
+    record.errors.add :prevloc, I18n.t("validations.household.previous_la_known")
+  end
+end
+
+
+ +
+

+ + #validate_reason_for_leaving_last_settled_home(record) ⇒ Object + + + + + +

+
+ +

describe everything this does here

+ + +
+
+
+ + +
+ + + + +
+
+
+
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+
# File 'household_validations.rb', line 27
+
+def validate_reason_for_leaving_last_settled_home(record)
+  if record.reason == 32 && record.underoccupation_benefitcap != 4
+    record.errors.add :underoccupation_benefitcap, I18n.t("validations.household.underoccupation_benefitcap.dont_know_required")
+    record.errors.add :reason, I18n.t("validations.household.underoccupation_benefitcap.dont_know_required")
+  end
+  validate_other_field(record, 20, :reason, :reasonother)
+
+  if record.is_reason_permanently_decanted? && record.referral.present? && !record.is_internal_transfer?
+    record.errors.add :referral, I18n.t("validations.household.referral.reason_permanently_decanted")
+    record.errors.add :reason, I18n.t("validations.household.reason.not_internal_transfer")
+  end
+
+  return unless record.form.start_year_after_2024?
+
+  if record.reason == 20 && PHRASES_INDICATING_HOMELESSNESS_REGEX.match?(record.reasonother)
+    record.errors.add :reason, I18n.t("validations.household.reason.other_not_settled")
+  end
+end
+
+
+ +
+

+ + #validate_reasonable_preference(record) ⇒ Object + + + + + +

+
+ +

Validations methods need to be called ‘validate_<page_name>’ to run on model save or ‘validate_’ to run on submit as well

+ + +
+
+
+ + +
+ + + + +
+
+
+
+6
+7
+8
+9
+10
+
+
# File 'household_validations.rb', line 6
+
+def validate_reasonable_preference(record)
+  if !record.given_reasonable_preference? && [record.rp_homeless, record.rp_insan_unsat, record.rp_medwel, record.rp_hardship, record.rp_dontknow].any? { |a| a == 1 }
+    record.errors.add :reasonable_preference_reason, I18n.t("validations.household.reasonable_preference_reason.reason_not_required")
+  end
+end
+
+
+ +
+

+ + #validate_referral(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+175
+176
+177
+178
+179
+180
+181
+182
+
+
# File 'household_validations.rb', line 175
+
+def validate_referral(record)
+  return unless record.owning_organisation
+
+  if record.is_internal_transfer? && record.owning_organisation.provider_type == "PRP" && record.is_prevten_la_general_needs?
+    record.errors.add :prevten, :internal_transfer_fixed_or_lifetime, message: I18n.t("validations.household.prevten.la_general_needs.internal_transfer")
+    record.errors.add :referral, :internal_transfer_fixed_or_lifetime, message: I18n.t("validations.household.referral.la_general_needs.internal_transfer")
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/LocalAuthorityValidations.html b/app/models/validations/doc/Validations/LocalAuthorityValidations.html new file mode 100644 index 000000000..5f00227c2 --- /dev/null +++ b/app/models/validations/doc/Validations/LocalAuthorityValidations.html @@ -0,0 +1,182 @@ + + + + + + + Module: Validations::LocalAuthorityValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::LocalAuthorityValidations + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
local_authority_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_previous_accommodation_postcode(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+2
+3
+4
+5
+6
+7
+8
+
+
# File 'local_authority_validations.rb', line 2
+
+def validate_previous_accommodation_postcode(record)
+  postcode = record.ppostcode_full
+  if record.previous_postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
+    error_message = I18n.t("validations.postcode")
+    record.errors.add :ppostcode_full, :wrong_format, message: error_message
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/PropertyValidations.html b/app/models/validations/doc/Validations/PropertyValidations.html new file mode 100644 index 000000000..bac65d187 --- /dev/null +++ b/app/models/validations/doc/Validations/PropertyValidations.html @@ -0,0 +1,435 @@ + + + + + + + Module: Validations::PropertyValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::PropertyValidations + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
property_validations.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
REFERRAL_INVALID_TMP = +
+
+ +

Validations methods need to be called ‘validate_<page_name>’ to run on model save or ‘validate_’ to run on submit as well

+ + +
+
+
+ + +
+
+
[8, 10, 12, 13, 14, 15].freeze
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_rsnvac(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+
+
# File 'property_validations.rb', line 6
+
+def validate_rsnvac(record)
+  if !record.first_time_property_let_as_social_housing? && record.has_first_let_vacancy_reason?
+    record.errors.add :rsnvac, I18n.t("validations.property.rsnvac.first_let_not_social")
+  end
+
+  if record.first_time_property_let_as_social_housing? && record.rsnvac.present? && !record.has_first_let_vacancy_reason?
+    record.errors.add :rsnvac, I18n.t("validations.property.rsnvac.first_let_social")
+  end
+
+  if record.is_relet_to_temp_tenant? && !record.previous_tenancy_was_temporary?
+    record.errors.add :rsnvac, I18n.t("validations.property.rsnvac.non_temp_accommodation")
+  end
+
+  if record.is_relet_to_temp_tenant? && REFERRAL_INVALID_TMP.include?(record.referral)
+    record.errors.add :rsnvac, I18n.t("validations.property.rsnvac.referral_invalid")
+    record.errors.add :referral, :referral_invalid, message: I18n.t("validations.household.referral.rsnvac_non_temp")
+  end
+
+  if record.renewal.present? && record.renewal.zero? && record.rsnvac == 14
+    record.errors.add :rsnvac, I18n.t("validations.property.rsnvac.not_a_renewal")
+  end
+end
+
+
+ +
+

+ + #validate_shared_housing_rooms(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+
+
# File 'property_validations.rb', line 35
+
+def validate_shared_housing_rooms(record)
+  unless record.unittype_gn.nil?
+    if record.is_bedsit? && record.beds != 1 && record.beds.present? && !record.form.start_year_after_2024?
+      record.errors.add :unittype_gn, I18n.t("validations.property.unittype_gn.one_bedroom_bedsit")
+      record.errors.add :beds, I18n.t("validations.property.unittype_gn.one_bedroom_bedsit")
+    end
+
+    if record.hhmemb == 1 && record.is_shared_housing? &&
+        !record.beds.to_i.between?(1, 3) && record.beds.present?
+      record.errors.add :unittype_gn, I18n.t("validations.property.unittype_gn.one_three_bedroom_single_tenant_shared")
+      record.errors.add :beds, :one_three_bedroom_single_tenant_shared, message: I18n.t("validations.property.unittype_gn.one_three_bedroom_single_tenant_shared")
+    elsif record.is_shared_housing? && record.beds.present? && !record.beds.to_i.between?(1, 7)
+      record.errors.add :unittype_gn, I18n.t("validations.property.unittype_gn.one_seven_bedroom_shared")
+      record.errors.add :beds, I18n.t("validations.property.unittype_gn.one_seven_bedroom_shared")
+    end
+  end
+end
+
+
+ +
+

+ + #validate_unitletas(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+29
+30
+31
+32
+33
+
+
# File 'property_validations.rb', line 29
+
+def validate_unitletas(record)
+  if record.first_time_property_let_as_social_housing? && record.unitletas.present?
+    record.errors.add :unitletas, I18n.t("validations.property.rsnvac.previous_let_social")
+  end
+end
+
+
+ +
+

+ + #validate_uprn(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+53
+54
+55
+56
+57
+58
+59
+
+
# File 'property_validations.rb', line 53
+
+def validate_uprn(record)
+  return unless record.uprn
+
+  return if record.uprn.match?(/^[0-9]{1,12}$/)
+
+  record.errors.add :uprn, I18n.t("validations.property.uprn.invalid")
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/FinancialValidations.html b/app/models/validations/doc/Validations/Sales/FinancialValidations.html new file mode 100644 index 000000000..9f08e7d18 --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/FinancialValidations.html @@ -0,0 +1,843 @@ + + + + + + + Module: Validations::Sales::FinancialValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::FinancialValidations + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
sales/financial_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_child_income(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+80
+81
+82
+83
+84
+85
+86
+87
+
+
# File 'sales/financial_validations.rb', line 80
+
+def validate_child_income(record)
+  return unless record.income2 && record.ecstat2
+
+  if record.income2.positive? && is_economic_status_child?(record.ecstat2) && record.form.start_date.year >= 2023
+    record.errors.add :ecstat2, I18n.t("validations.financial.income.child_has_income")
+    record.errors.add :income2, I18n.t("validations.financial.income.child_has_income")
+  end
+end
+
+
+ +
+

+ + #validate_combined_income(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+
+
# File 'sales/financial_validations.rb', line 27
+
+def validate_combined_income(record)
+  return unless record.income1 && record.income2 && record.la && record.shared_ownership_scheme?
+
+  combined_income = record.income1 + record.income2
+  relevant_fields = %i[income1 income2 ownershipsch uprn la postcode_full]
+  if record.london_property? && combined_income > 90_000
+    relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_london") }
+  elsif record.property_not_in_london? && combined_income > 80_000
+    relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_outside_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london") }
+  end
+end
+
+
+ +
+

+ + #validate_equity_in_range_for_year_and_type(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+
# File 'sales/financial_validations.rb', line 89
+
+def validate_equity_in_range_for_year_and_type(record)
+  return unless record.type && record.equity && record.collection_start_year
+
+  ranges = EQUITY_RANGES_BY_YEAR.fetch(record.collection_start_year, DEFAULT_EQUITY_RANGES)
+
+  return unless (range = ranges[record.type])
+
+  if record.equity < range.min
+    record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min)
+    record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min)
+  elsif record.equity > range.max
+    record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max)
+    record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max)
+  end
+end
+
+
+ +
+

+ + #validate_equity_less_than_staircase_difference(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+
+
# File 'sales/financial_validations.rb', line 105
+
+def validate_equity_less_than_staircase_difference(record)
+  return unless record.equity && record.stairbought && record.stairowned
+  return unless record.saledate && record.form.start_year_after_2024?
+
+  if record.equity > record.stairowned - record.stairbought
+    formatted_equity = sprintf("%g", record.equity)
+    record.errors.add :equity, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
+    record.errors.add :stairowned, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
+    record.errors.add :stairbought, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns")
+  end
+end
+
+
+ +
+

+ + #validate_income1(record) ⇒ Object + + + + + +

+
+ +

Validations methods need to be called ‘validate_<page_name>’ to run on model save or ‘validate_’ to run on submit as well

+ + +
+
+
+ + +
+ + + + +
+
+
+
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+
+
# File 'sales/financial_validations.rb', line 5
+
+def validate_income1(record)
+  return unless record.income1 && record.la && record.shared_ownership_scheme?
+
+  relevant_fields = %i[income1 ownershipsch uprn la postcode_full]
+  if record.london_property? && !record.income1.between?(0, 90_000)
+    relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") }
+  elsif record.property_not_in_london? && !record.income1.between?(0, 80_000)
+    relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") }
+  end
+end
+
+
+ +
+

+ + #validate_income2(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+
+
# File 'sales/financial_validations.rb', line 16
+
+def validate_income2(record)
+  return unless record.income2 && record.la && record.shared_ownership_scheme?
+
+  relevant_fields = %i[income2 ownershipsch uprn la postcode_full]
+  if record.london_property? && !record.income2.between?(0, 90_000)
+    relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") }
+  elsif record.property_not_in_london? && !record.income2.between?(0, 80_000)
+    relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") }
+  end
+end
+
+
+ +
+

+ + #validate_monthly_leasehold_charges(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+43
+44
+45
+
+
# File 'sales/financial_validations.rb', line 43
+
+def validate_monthly_leasehold_charges(record)
+  record.errors.add :mscharge, I18n.t("validations.financial.monthly_leasehold_charges.not_zero") if record.mscharge&.zero?
+end
+
+
+ +
+

+ + #validate_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+39
+40
+41
+
+
# File 'sales/financial_validations.rb', line 39
+
+def validate_mortgage(record)
+  record.errors.add :mortgage, :cannot_be_0, message: I18n.t("validations.financial.mortgage") if record.mortgage_used? && record.mortgage&.zero?
+end
+
+
+ +
+

+ + #validate_percentage_bought_at_least_threshold(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+
+
# File 'sales/financial_validations.rb', line 65
+
+def validate_percentage_bought_at_least_threshold(record)
+  return unless record.stairbought && record.type
+
+  threshold = if [2, 16, 18, 24].include? record.type
+                10
+              else
+                1
+              end
+
+  if threshold && record.stairbought < threshold
+    record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_must_be_at_least_threshold", threshold:)
+    record.errors.add :type, I18n.t("validations.setup.type.percentage_bought_must_be_at_least_threshold", threshold:)
+  end
+end
+
+
+ +
+

+ + #validate_percentage_bought_not_equal_percentage_owned(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+55
+56
+57
+58
+59
+60
+61
+62
+63
+
+
# File 'sales/financial_validations.rb', line 55
+
+def validate_percentage_bought_not_equal_percentage_owned(record)
+  return unless record.stairbought && record.stairowned
+  return unless record.saledate && record.form.start_year_after_2024?
+
+  if record.stairbought == record.stairowned
+    record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
+    record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned))
+  end
+end
+
+
+ +
+

+ + #validate_percentage_bought_not_greater_than_percentage_owned(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+47
+48
+49
+50
+51
+52
+53
+
+
# File 'sales/financial_validations.rb', line 47
+
+def validate_percentage_bought_not_greater_than_percentage_owned(record)
+  return unless record.stairbought && record.stairowned
+
+  if record.stairbought > record.stairowned
+    record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_must_be_greater_than_percentage_owned", buyer_now_owns: record.joint_purchase? ? "buyers now own" : "buyer now owns")
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/HouseholdValidations.html b/app/models/validations/doc/Validations/Sales/HouseholdValidations.html new file mode 100644 index 000000000..00e5308c0 --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/HouseholdValidations.html @@ -0,0 +1,702 @@ + + + + + + + Module: Validations::Sales::HouseholdValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::HouseholdValidations + + + +

+
+ + + + + + +
+
Includes:
+
Validations::SharedValidations
+
+ + + + + + +
+
Defined in:
+
sales/household_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_buyer1_previous_tenure(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+18
+19
+20
+21
+22
+23
+24
+25
+26
+
+
# File 'sales/household_validations.rb', line 18
+
+def validate_buyer1_previous_tenure(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.discounted_ownership_sale? && record.prevten
+
+  if [3, 4, 5, 6, 7, 9, 0].include?(record.prevten)
+    record.errors.add :prevten, I18n.t("validations.household.prevten.invalid_for_discounted_sale")
+    record.errors.add :ownershipsch, I18n.t("validations.household.prevten.invalid_for_discounted_sale")
+  end
+end
+
+
+ +
+

+ + #validate_buyer_not_child(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+108
+109
+110
+111
+112
+113
+
+
# File 'sales/household_validations.rb', line 108
+
+def validate_buyer_not_child(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+
+  record.errors.add "ecstat1", I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "1") if person_is_economic_child?(record.ecstat1)
+  record.errors.add "ecstat2", I18n.t("validations.household.ecstat.buyer_cannot_be_child", buyer_index: "2") if person_is_economic_child?(record.ecstat2) && record.joint_purchase?
+end
+
+
+ +
+

+ + #validate_buyers_living_in_property(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+8
+9
+10
+11
+12
+13
+14
+15
+16
+
+
# File 'sales/household_validations.rb', line 8
+
+def validate_buyers_living_in_property(record)
+  return unless record.form.start_date.year >= 2023
+
+  if record.buyers_will_live_in? && record.buyer_one_will_not_live_in_property? && record.buyer_two_will_not_live_in_property?
+    record.errors.add :buylivein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent_setup")
+    record.errors.add :buy1livein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
+    record.errors.add :buy2livein, I18n.t("validations.household.buylivein.buyers_will_live_in_property_values_inconsistent")
+  end
+end
+
+
+ +
+

+ + #validate_child_12_years_younger(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+
+
# File 'sales/household_validations.rb', line 91
+
+def validate_child_12_years_younger(record)
+  return unless record.saledate && !record.form.start_year_after_2024?
+
+  (2..6).each do |person_num|
+    buyer_1_age = record.public_send("age1")
+    person_age = record.public_send("age#{person_num}")
+    relationship = record.public_send("relat#{person_num}")
+    next unless buyer_1_age && person_age && relationship
+
+    next unless person_age > buyer_1_age - 12 && person_is_child?(relationship)
+
+    record.errors.add "age1", I18n.t("validations.household.age.child_12_years_younger")
+    record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_12_years_younger")
+    record.errors.add "relat#{person_num}", I18n.t("validations.household.age.child_12_years_younger")
+  end
+end
+
+
+ +
+

+ + #validate_partner_count(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+4
+5
+6
+
+
# File 'sales/household_validations.rb', line 4
+
+def validate_partner_count(record)
+  shared_validate_partner_count(record, 6)
+end
+
+
+ +
+

+ + #validate_person_age_and_relationship_matches_economic_status(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+
+
# File 'sales/household_validations.rb', line 46
+
+def validate_person_age_and_relationship_matches_economic_status(record)
+  return unless record.saledate && !record.form.start_year_after_2024?
+
+  (2..6).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    economic_status = record.public_send("ecstat#{person_num}")
+    relationship = record.public_send("relat#{person_num}")
+    next unless age && economic_status && relationship
+
+    age_between_16_19 = age.between?(16, 19)
+    student = person_is_fulltime_student?(economic_status)
+    economic_status_refused = person_economic_status_refused?(economic_status)
+    child = person_is_child?(relationship)
+
+    if age_between_16_19 && !(student || economic_status_refused) && child
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.must_be_student")
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.cannot_be_16_19.child_not_student")
+      record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.16_19_not_student")
+    end
+
+    next unless !age_between_16_19 && student && child
+
+    record.errors.add "age#{person_num}", I18n.t("validations.household.age.student_16_19.must_be_16_19")
+    record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.student_16_19.cannot_be_student.child_not_16_19")
+    record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.student_16_19.cannot_be_child.student_not_16_19")
+  end
+end
+
+
+ +
+

+ + #validate_person_age_matches_economic_status(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+
+
# File 'sales/household_validations.rb', line 74
+
+def validate_person_age_matches_economic_status(record)
+  (2..6).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    economic_status = record.public_send("ecstat#{person_num}")
+    next unless age && economic_status
+
+    if age < 16 && !economic_status_is_child_other_or_refused?(economic_status) && !record.form.start_year_after_2024?
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_under_16", person_num:)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_ecstat", person_num:)
+    end
+    if person_is_economic_child?(economic_status) && age > 16
+      record.errors.add "ecstat#{person_num}", I18n.t("validations.household.ecstat.child_over_16", person_num:)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_over_16", person_num:)
+    end
+  end
+end
+
+
+ +
+

+ + #validate_person_age_matches_relationship(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+
+
# File 'sales/household_validations.rb', line 28
+
+def validate_person_age_matches_relationship(record)
+  return unless record.saledate && !record.form.start_year_after_2024?
+
+  (2..6).each do |person_num|
+    age = record.public_send("age#{person_num}")
+    relationship = record.public_send("relat#{person_num}")
+    next unless age && relationship
+
+    if age < 16 && !relationship_is_child_other_or_refused?(relationship)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_under_16_relat_sales", person_num:)
+      record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.child_under_16_sales", person_num:)
+    elsif age >= 20 && person_is_child?(relationship)
+      record.errors.add "age#{person_num}", I18n.t("validations.household.age.child_over_20")
+      record.errors.add "relat#{person_num}", I18n.t("validations.household.relat.child_over_20")
+    end
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/PropertyValidations.html b/app/models/validations/doc/Validations/Sales/PropertyValidations.html new file mode 100644 index 000000000..3ff4c2d75 --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/PropertyValidations.html @@ -0,0 +1,312 @@ + + + + + + + Module: Validations::Sales::PropertyValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::PropertyValidations + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
sales/property_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_bedsit_number_of_beds(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+14
+15
+16
+17
+18
+19
+20
+21
+
+
# File 'sales/property_validations.rb', line 14
+
+def validate_bedsit_number_of_beds(record)
+  return unless record.proptype.present? && record.beds.present?
+
+  if record.is_bedsit? && record.beds > 1
+    record.errors.add :proptype, I18n.t("validations.property.proptype.bedsits_have_max_one_bedroom")
+    record.errors.add :beds, I18n.t("validations.property.beds.bedsits_have_max_one_bedroom")
+  end
+end
+
+
+ +
+

+ + #validate_postcodes_match_if_discounted_ownership(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+
+
# File 'sales/property_validations.rb', line 2
+
+def validate_postcodes_match_if_discounted_ownership(record)
+  return unless record.saledate && !record.form.start_year_after_2024?
+  return unless record.ppostcode_full.present? && record.postcode_full.present?
+
+  if record.discounted_ownership_sale? && record.ppostcode_full != record.postcode_full
+    record.errors.add :postcode_full, I18n.t("validations.property.postcode.must_match_previous", buyer_possessive: record.joint_purchase? ? "Buyers’" : "Buyer’s")
+    record.errors.add :ppostcode_full, I18n.t("validations.property.postcode.must_match_previous", buyer_possessive: record.joint_purchase? ? "Buyers’" : "Buyer’s")
+    record.errors.add :ownershipsch, I18n.t("validations.property.postcode.must_match_previous", buyer_possessive: record.joint_purchase? ? "Buyers’" : "Buyer’s")
+    record.errors.add :uprn, I18n.t("validations.property.postcode.must_match_previous", buyer_possessive: record.joint_purchase? ? "Buyers’" : "Buyer’s")
+  end
+end
+
+
+ +
+

+ + #validate_uprn(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+23
+24
+25
+26
+27
+28
+29
+
+
# File 'sales/property_validations.rb', line 23
+
+def validate_uprn(record)
+  return unless record.uprn
+
+  return if record.uprn.match?(/^[0-9]{1,12}$/)
+
+  record.errors.add :uprn, I18n.t("validations.property.uprn.invalid")
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/SaleInformationValidations.html b/app/models/validations/doc/Validations/Sales/SaleInformationValidations.html new file mode 100644 index 000000000..bef2d1288 --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/SaleInformationValidations.html @@ -0,0 +1,1445 @@ + + + + + + + Module: Validations::Sales::SaleInformationValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::SaleInformationValidations + + + +

+
+ + + + + + +
+
Includes:
+
CollectionTimeHelper, MoneyFormattingHelper, Validations::SharedValidations
+
+ + + + +
+
Included in:
+
SoftValidations
+
+ + + +
+
Defined in:
+
sales/sale_information_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + + + +
+

Instance Method Details

+ + +
+

+ + #check_non_staircasing_non_socialhomebuy_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+
+
# File 'sales/sale_information_validations.rb', line 178
+
+def check_non_staircasing_non_socialhomebuy_mortgage(record)
+  if record.mortgage_used?
+    return unless record.mortgage
+
+    if over_tolerance?(record.mortgage_and_deposit_total, record.expected_shared_ownership_deposit_value, 1)
+      %i[mortgage value deposit equity].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+    end
+  elsif record.mortgage_not_used?
+    if over_tolerance?(record.deposit, record.expected_shared_ownership_deposit_value, 1)
+      %i[mortgageused value deposit equity].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_not_used", deposit: record.field_formatted_as_currency("deposit"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_not_used", deposit: record.field_formatted_as_currency("deposit"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+    end
+  end
+end
+
+
+ +
+

+ + #check_non_staircasing_socialhomebuy_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+
+
# File 'sales/sale_information_validations.rb', line 156
+
+def check_non_staircasing_socialhomebuy_mortgage(record)
+  return unless record.cashdis
+
+  if record.mortgage_used?
+    return unless record.mortgage
+
+    if over_tolerance?(record.mortgage_deposit_and_discount_total, record.expected_shared_ownership_deposit_value, 1)
+      %i[mortgage value deposit cashdis equity].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used_socialhomebuy", mortgage_deposit_and_discount_total: record.field_formatted_as_currency("mortgage_deposit_and_discount_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_used_socialhomebuy", mortgage_deposit_and_discount_total: record.field_formatted_as_currency("mortgage_deposit_and_discount_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+    end
+  elsif record.mortgage_not_used?
+    if over_tolerance?(record.deposit_and_discount_total, record.expected_shared_ownership_deposit_value, 1)
+      %i[mortgageused value deposit cashdis equity].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_not_used_socialhomebuy", deposit_and_discount_total: record.field_formatted_as_currency("deposit_and_discount_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.non_staircasing_mortgage.mortgage_not_used_socialhomebuy", deposit_and_discount_total: record.field_formatted_as_currency("deposit_and_discount_total"), expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value"))
+    end
+  end
+end
+
+
+ +
+

+ + #check_staircasing_non_socialhomebuy_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+
+
# File 'sales/sale_information_validations.rb', line 218
+
+def check_staircasing_non_socialhomebuy_mortgage(record)
+  if record.mortgage_used?
+    return unless record.mortgage
+
+    if over_tolerance?(record.mortgage_and_deposit_total, record.stairbought_part_of_value, 1)
+      %i[mortgage value deposit stairbought type].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.staircasing_mortgage.mortgage_used", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.staircasing_mortgage.mortgage_used", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+    end
+  elsif over_tolerance?(record.deposit, record.stairbought_part_of_value, 1)
+    %i[mortgageused value deposit stairbought type].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.staircasing_mortgage.mortgage_not_used", deposit: record.field_formatted_as_currency("deposit"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+    end
+    record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.staircasing_mortgage.mortgage_not_used", deposit: record.field_formatted_as_currency("deposit"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+  end
+end
+
+
+ +
+

+ + #check_staircasing_socialhomebuy_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+
+
# File 'sales/sale_information_validations.rb', line 198
+
+def check_staircasing_socialhomebuy_mortgage(record)
+  return unless record.cashdis
+
+  if record.mortgage_used?
+    return unless record.mortgage
+
+    if over_tolerance?(record.mortgage_deposit_and_discount_total, record.stairbought_part_of_value, 1)
+      %i[mortgage value deposit cashdis stairbought].each do |field|
+        record.errors.add field, I18n.t("validations.sale_information.staircasing_mortgage.mortgage_used_socialhomebuy", mortgage_deposit_and_discount_total: record.field_formatted_as_currency("mortgage_deposit_and_discount_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+      end
+      record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.staircasing_mortgage.mortgage_used_socialhomebuy", mortgage_deposit_and_discount_total: record.field_formatted_as_currency("mortgage_deposit_and_discount_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+    end
+  elsif over_tolerance?(record.deposit_and_discount_total, record.stairbought_part_of_value, 1)
+    %i[mortgageused value deposit cashdis stairbought].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.staircasing_mortgage.mortgage_not_used_socialhomebuy", deposit_and_discount_total: record.field_formatted_as_currency("deposit_and_discount_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+    end
+    record.errors.add :type, :skip_bu_error, message: I18n.t("validations.sale_information.staircasing_mortgage.mortgage_not_used_socialhomebuy", deposit_and_discount_total: record.field_formatted_as_currency("deposit_and_discount_total"), stairbought_part_of_value: record.field_formatted_as_currency("stairbought_part_of_value"))
+  end
+end
+
+
+ +
+

+ + #over_tolerance?(expected, actual, tolerance) ⇒ Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+250
+251
+252
+
+
# File 'sales/sale_information_validations.rb', line 250
+
+def over_tolerance?(expected, actual, tolerance)
+  (expected - actual).abs >= tolerance
+end
+
+
+ +
+

+ + #validate_basic_monthly_rent(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+71
+72
+73
+74
+75
+76
+77
+78
+
+
# File 'sales/sale_information_validations.rb', line 71
+
+def validate_basic_monthly_rent(record)
+  return unless record.mrent && record.ownershipsch && record.type
+
+  if record.shared_ownership_scheme? && !record.old_persons_shared_ownership? && record.mrent > 9999
+    record.errors.add :mrent, I18n.t("validations.sale_information.monthly_rent.higher_than_expected")
+    record.errors.add :type, I18n.t("validations.sale_information.monthly_rent.higher_than_expected")
+  end
+end
+
+
+ +
+

+ + #validate_discount_and_value(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+
+
# File 'sales/sale_information_validations.rb', line 108
+
+def validate_discount_and_value(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.discount && record.value && record.la
+
+  if record.london_property? && record.discount_value > 136_400
+    %i[discount value la postcode_full uprn].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.value.over_discounted_london_max", discount_value: record.field_formatted_as_currency("discount_value"))
+    end
+  elsif record.property_not_in_london? && record.discount_value > 102_400
+    %i[discount value la postcode_full uprn].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.value.over_discounted_max", discount_value: record.field_formatted_as_currency("discount_value"))
+    end
+  end
+end
+
+
+ +
+

+ + #validate_discounted_ownership_value(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+
+
# File 'sales/sale_information_validations.rb', line 44
+
+def validate_discounted_ownership_value(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.value && record.deposit && record.ownershipsch
+  return unless record.mortgage || record.mortgageused == 2 || record.mortgageused == 3
+  return unless record.discount || record.grant || record.type == 29
+
+  if over_tolerance?(record.mortgage_deposit_and_grant_total, record.value_with_discount, 1) && record.discounted_ownership_sale?
+    %i[mortgageused mortgage value deposit ownershipsch discount grant].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.discounted_ownership_value", mortgage_deposit_and_grant_total: record.field_formatted_as_currency("mortgage_deposit_and_grant_total"), value_with_discount: record.field_formatted_as_currency("value_with_discount"))
+    end
+  end
+end
+
+
+ +
+

+ + #validate_exchange_date(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+
+
# File 'sales/sale_information_validations.rb', line 21
+
+def validate_exchange_date(record)
+  return unless record.exdate && record.saledate
+
+  if record.exdate > record.saledate
+    record.errors.add :exdate, I18n.t("validations.sale_information.exdate.must_be_before_saledate")
+    record.errors.add :saledate, I18n.t("validations.sale_information.saledate.must_be_after_exdate")
+  end
+
+  if record.saledate - record.exdate >= 1.year
+    record.errors.add :exdate, I18n.t("validations.sale_information.exdate.must_be_less_than_1_year_from_saledate")
+    record.errors.add :saledate, I18n.t("validations.sale_information.saledate.must_be_less_than_1_year_from_exdate")
+  end
+end
+
+
+ +
+

+ + #validate_grant_amount(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+80
+81
+82
+83
+84
+85
+86
+87
+
+
# File 'sales/sale_information_validations.rb', line 80
+
+def validate_grant_amount(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.grant && (record.type == 8 || record.type == 21)
+
+  unless record.grant.between?(9_000, 16_000)
+    record.errors.add :grant, I18n.t("validations.sale_information.grant.out_of_range")
+  end
+end
+
+
+ +
+

+ + #validate_mortgage_used_and_stairbought(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+147
+148
+149
+150
+151
+152
+153
+154
+
+
# File 'sales/sale_information_validations.rb', line 147
+
+def validate_mortgage_used_and_stairbought(record)
+  return unless record.stairowned && record.mortgageused
+
+  if !record.stairowned_100? && record.mortgageused == 3
+    record.errors.add :stairowned, I18n.t("validations.sale_information.stairowned.mortgageused_dont_know")
+    record.errors.add :mortgageused, I18n.t("validations.sale_information.stairowned.mortgageused_dont_know")
+  end
+end
+
+
+ +
+

+ + #validate_mortgage_used_dont_know(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+
+
# File 'sales/sale_information_validations.rb', line 236
+
+def validate_mortgage_used_dont_know(record)
+  return unless record.mortgageused == 3
+
+  if record.discounted_ownership_sale?
+    record.errors.add(:mortgageused, I18n.t("validations.invalid_option", question: "Was a mortgage used for the purchase of this property?"))
+  end
+  if record.outright_sale? && record.saledate && !record.form.start_year_after_2024?
+    record.errors.add(:mortgageused, I18n.t("validations.invalid_option", question: "Was a mortgage used for the purchase of this property?"))
+  end
+  if record.shared_ownership_scheme? && record.staircase && record.staircase != 1
+    record.errors.add(:mortgageused, I18n.t("validations.invalid_option", question: "Was a mortgage used for the purchase of this property?"))
+  end
+end
+
+
+ +
+

+ + #validate_non_staircasing_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+
+
# File 'sales/sale_information_validations.rb', line 123
+
+def validate_non_staircasing_mortgage(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.value && record.deposit && record.equity
+  return unless record.shared_ownership_scheme? && record.type && record.mortgageused && record.is_not_staircasing?
+
+  if record.social_homebuy?
+    check_non_staircasing_socialhomebuy_mortgage(record)
+  else
+    check_non_staircasing_non_socialhomebuy_mortgage(record)
+  end
+end
+
+
+ +
+

+ + #validate_outright_sale_value_matches_mortgage_plus_deposit(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+
+
# File 'sales/sale_information_validations.rb', line 57
+
+def validate_outright_sale_value_matches_mortgage_plus_deposit(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.outright_sale?
+  return unless record.mortgage_used? && record.mortgage
+  return unless record.deposit && record.value
+
+  if over_tolerance?(record.mortgage_and_deposit_total, record.value, 1)
+    %i[mortgageused mortgage value deposit].each do |field|
+      record.errors.add field, I18n.t("validations.sale_information.outright_sale_value", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), value: record.field_formatted_as_currency("value"))
+    end
+    record.errors.add :ownershipsch, :skip_bu_error, message: I18n.t("validations.sale_information.outright_sale_value", mortgage_and_deposit_total: record.field_formatted_as_currency("mortgage_and_deposit_total"), value: record.field_formatted_as_currency("value"))
+  end
+end
+
+
+ +
+

+ + #validate_practical_completion_date(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+
+
# File 'sales/sale_information_validations.rb', line 6
+
+def validate_practical_completion_date(record)
+  return unless record.hodate.present? && date_valid?("hodate", record)
+  return if record.saledate.blank?
+
+  if record.hodate > record.saledate
+    record.errors.add :hodate, I18n.t("validations.sale_information.hodate.must_be_before_saledate")
+    record.errors.add :saledate, I18n.t("validations.sale_information.saledate.must_be_after_hodate")
+  end
+
+  if record.saledate - record.hodate >= 3.years && record.form.start_year_after_2024?
+    record.errors.add :hodate, I18n.t("validations.sale_information.hodate.must_be_less_than_3_years_from_saledate")
+    record.errors.add :saledate, I18n.t("validations.sale_information.saledate.must_be_less_than_3_years_from_hodate")
+  end
+end
+
+
+ +
+

+ + #validate_previous_property_unit_type(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+35
+36
+37
+38
+39
+40
+41
+42
+
+
# File 'sales/sale_information_validations.rb', line 35
+
+def validate_previous_property_unit_type(record)
+  return unless record.fromprop && record.frombeds
+
+  if record.frombeds != 1 && record.fromprop == 2
+    record.errors.add :frombeds, I18n.t("validations.sale_information.previous_property_type.property_type_bedsit")
+    record.errors.add :fromprop, I18n.t("validations.sale_information.previous_property_type.property_type_bedsit")
+  end
+end
+
+
+ +
+

+ + #validate_stairbought(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+
+
# File 'sales/sale_information_validations.rb', line 89
+
+def validate_stairbought(record)
+  return unless record.stairbought && record.type
+  return unless record.saledate && record.form.start_year_after_2024?
+
+  max_stairbought = case record.type
+                    when 30, 16, 28, 31, 32
+                      90
+                    when 2, 18
+                      75
+                    when 24
+                      50
+                    end
+
+  if max_stairbought && record.stairbought > max_stairbought
+    record.errors.add :stairbought, I18n.t("validations.sale_information.stairbought.over_max", max_stairbought:, type: record.form.get_question("type", record).answer_label(record))
+    record.errors.add :type, I18n.t("validations.sale_information.stairbought.over_max", max_stairbought:, type: record.form.get_question("type", record).answer_label(record))
+  end
+end
+
+
+ +
+

+ + #validate_staircasing_mortgage(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+
+
# File 'sales/sale_information_validations.rb', line 135
+
+def validate_staircasing_mortgage(record)
+  return unless record.saledate && record.form.start_year_after_2024?
+  return unless record.value && record.deposit && record.stairbought
+  return unless record.shared_ownership_scheme? && record.type && record.mortgageused && record.is_staircase?
+
+  if record.social_homebuy?
+    check_staircasing_socialhomebuy_mortgage(record)
+  else
+    check_staircasing_non_socialhomebuy_mortgage(record)
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/SetupValidations.html b/app/models/validations/doc/Validations/Sales/SetupValidations.html new file mode 100644 index 000000000..4c5f4b7ba --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/SetupValidations.html @@ -0,0 +1,417 @@ + + + + + + + Module: Validations::Sales::SetupValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::SetupValidations + + + +

+
+ + + + + + +
+
Includes:
+
CollectionTimeHelper, Validations::SharedValidations
+
+ + + + + + +
+
Defined in:
+
sales/setup_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_merged_organisations_saledate(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+
# File 'sales/setup_validations.rb', line 27
+
+def validate_merged_organisations_saledate(record)
+  return unless record.saledate && date_valid?("saledate", record)
+
+  if merged_owning_organisation_inactive?(record)
+    record.errors.add :saledate, I18n.t("validations.setup.saledate.invalid_merged_organisations_saledate",
+                                        owning_organisation: record.owning_organisation.name,
+                                        owning_organisation_merge_date: record.owning_organisation.merge_date.to_formatted_s(:govuk_date),
+                                        owning_absorbing_organisation: record.owning_organisation.absorbing_organisation.name)
+  end
+
+  if absorbing_owning_organisation_inactive?(record)
+    record.errors.add :saledate, I18n.t("validations.setup.saledate.invalid_absorbing_organisations_saledate",
+                                        owning_organisation: record.owning_organisation.name,
+                                        owning_organisation_available_from: record.owning_organisation.available_from.to_formatted_s(:govuk_date))
+  end
+end
+
+
+ +
+

+ + #validate_organisation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+
+
# File 'sales/setup_validations.rb', line 44
+
+def validate_organisation(record)
+  return unless record.saledate && record.owning_organisation
+
+  if record.owning_organisation.present?
+    if record.owning_organisation&.merge_date.present? && record.owning_organisation.merge_date <= record.saledate
+      record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.inactive_merged_organisation_sales",
+                                                        owning_organisation: record.owning_organisation.name,
+                                                        owning_organisation_merge_date: record.owning_organisation.merge_date.to_formatted_s(:govuk_date),
+                                                        owning_absorbing_organisation: record.owning_organisation.absorbing_organisation.name)
+    elsif record.owning_organisation&.absorbed_organisations.present? && record.owning_organisation.available_from.present? && record.owning_organisation.available_from.to_date > record.saledate.to_date
+      record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.inactive_absorbing_organisation_sales",
+                                                        owning_organisation: record.owning_organisation.name,
+                                                        owning_organisation_available_from: record.owning_organisation.available_from.to_formatted_s(:govuk_date))
+    end
+  end
+end
+
+
+ +
+

+ + #validate_saledate_collection_year(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
+
# File 'sales/setup_validations.rb', line 5
+
+def validate_saledate_collection_year(record)
+  return unless record.saledate && date_valid?("saledate", record) && !FeatureToggle.allow_future_form_use?
+
+  first_collection_start_date = if record.saledate_was.present?
+                                  editable_collection_start_date
+                                else
+                                  active_collection_start_date
+                                end
+
+  unless record.saledate.between?(first_collection_start_date, current_collection_end_date)
+    record.errors.add :saledate, saledate_validation_error_message
+  end
+end
+
+
+ +
+

+ + #validate_saledate_two_weeks(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+19
+20
+21
+22
+23
+24
+25
+
+
# File 'sales/setup_validations.rb', line 19
+
+def validate_saledate_two_weeks(record)
+  return unless record.saledate && date_valid?("saledate", record) && !FeatureToggle.allow_future_form_use?
+
+  if record.saledate > Time.zone.today + 14.days
+    record.errors.add :saledate, I18n.t("validations.setup.saledate.later_than_14_days_after")
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/Sales/SoftValidations.html b/app/models/validations/doc/Validations/Sales/SoftValidations.html new file mode 100644 index 000000000..bc76c4854 --- /dev/null +++ b/app/models/validations/doc/Validations/Sales/SoftValidations.html @@ -0,0 +1,1996 @@ + + + + + + + Module: Validations::Sales::SoftValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::Sales::SoftValidations + + + +

+
+ + + + + + +
+
Includes:
+
SaleInformationValidations
+
+ + + + + + +
+
Defined in:
+
sales/soft_validations.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
ALLOWED_INCOME_RANGES_SALES = + +
+
{
+  1 => OpenStruct.new(soft_min: 5000),
+  2 => OpenStruct.new(soft_min: 1500),
+  3 => OpenStruct.new(soft_min: 1000),
+  5 => OpenStruct.new(soft_min: 2000),
+  0 => OpenStruct.new(soft_min: 2000),
+}.freeze
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #buyer1_livein_wrong_for_ownership_type?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+152
+153
+154
+155
+156
+
+
# File 'sales/soft_validations.rb', line 152
+
+def buyer1_livein_wrong_for_ownership_type?
+  return unless ownershipsch && buy1livein
+
+  (discounted_ownership_sale? || shared_ownership_scheme?) && buy1livein == 2
+end
+
+
+ +
+

+ + #buyer2_livein_wrong_for_ownership_type?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+158
+159
+160
+161
+162
+163
+
+
# File 'sales/soft_validations.rb', line 158
+
+def buyer2_livein_wrong_for_ownership_type?
+  return unless ownershipsch && buy2livein
+  return unless joint_purchase?
+
+  (discounted_ownership_sale? || shared_ownership_scheme?) && buy2livein == 2
+end
+
+
+ +
+

+ + #combined_income_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+36
+37
+38
+39
+40
+
+
# File 'sales/soft_validations.rb', line 36
+
+def combined_income_over_soft_max?
+  return unless income1 && income2 && la && discounted_ownership_sale?
+
+  income_over_soft_max?(income1 + income2)
+end
+
+
+ +
+

+ + #deposit_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+64
+65
+66
+67
+68
+
+
# File 'sales/soft_validations.rb', line 64
+
+def deposit_over_soft_max?
+  return unless savings && deposit && mortgage_used?
+
+  deposit > savings * 4 / 3
+end
+
+
+ +
+

+ + #discounted_ownership_value_invalid?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+143
+144
+145
+146
+147
+148
+149
+150
+
+
# File 'sales/soft_validations.rb', line 143
+
+def discounted_ownership_value_invalid?
+  return unless saledate && collection_start_year <= 2023
+  return unless value && deposit && ownershipsch
+  return unless mortgage || mortgageused == 2 || mortgageused == 3
+  return unless discount || grant || type == 29
+
+  mortgage_deposit_and_grant_total != value_with_discount && discounted_ownership_sale?
+end
+
+
+ +
+

+ + #extra_borrowing_expected_but_not_reported?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+70
+71
+72
+73
+74
+
+
# File 'sales/soft_validations.rb', line 70
+
+def extra_borrowing_expected_but_not_reported?
+  return unless extrabor && mortgage && deposit && value && discount
+
+  extrabor != 1 && mortgage + deposit > value - value * discount / 100
+end
+
+
+ +
+

+ + #grant_outside_common_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+118
+119
+120
+121
+122
+123
+
+
# File 'sales/soft_validations.rb', line 118
+
+def grant_outside_common_range?
+  return unless grant && type && saledate
+  return if form.start_year_after_2024? && (type == 21 || type == 8)
+
+  !grant.between?(9_000, 16_000)
+end
+
+
+ +
+

+ + #hodate_3_years_or_more_saledate?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+104
+105
+106
+107
+108
+
+
# File 'sales/soft_validations.rb', line 104
+
+def hodate_3_years_or_more_saledate?
+  return unless hodate && saledate
+
+  saledate - hodate >= 3.years
+end
+
+
+ +
+

+ + #income1_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+24
+25
+26
+27
+28
+
+
# File 'sales/soft_validations.rb', line 24
+
+def income1_over_soft_max?
+  return unless income1 && la && discounted_ownership_sale?
+
+  income_over_soft_max?(income1)
+end
+
+
+ +
+

+ + #income1_under_soft_min?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+12
+13
+14
+15
+16
+
+
# File 'sales/soft_validations.rb', line 12
+
+def income1_under_soft_min?
+  return false unless ecstat1 && income1 && ALLOWED_INCOME_RANGES_SALES[ecstat1]
+
+  income1 < ALLOWED_INCOME_RANGES_SALES[ecstat1][:soft_min]
+end
+
+
+ +
+

+ + #income2_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+30
+31
+32
+33
+34
+
+
# File 'sales/soft_validations.rb', line 30
+
+def income2_over_soft_max?
+  return unless income2 && la && discounted_ownership_sale?
+
+  income_over_soft_max?(income2)
+end
+
+
+ +
+

+ + #income2_under_soft_min?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+18
+19
+20
+21
+22
+
+
# File 'sales/soft_validations.rb', line 18
+
+def income2_under_soft_min?
+  return false unless ecstat2 && income2 && ALLOWED_INCOME_RANGES_SALES[ecstat2]
+
+  income2 < ALLOWED_INCOME_RANGES_SALES[ecstat2][:soft_min]
+end
+
+
+ +
+

+ + #monthly_charges_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+125
+126
+127
+128
+129
+130
+
+
# File 'sales/soft_validations.rb', line 125
+
+def monthly_charges_over_soft_max?
+  return unless type && mscharge && proptype
+
+  soft_max = old_persons_shared_ownership? ? 550 : 300
+  mscharge > soft_max
+end
+
+
+ +
+

+ + #mortgage_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+46
+47
+48
+49
+50
+51
+52
+
+
# File 'sales/soft_validations.rb', line 46
+
+def mortgage_over_soft_max?
+  return false unless mortgage && inc1mort && (inc2mort || not_joint_purchase?)
+  return false if income1_used_for_mortgage? && income1.blank? || income2_used_for_mortgage? && income2.blank?
+
+  income_used_for_mortgage = (income1_used_for_mortgage? ? income1 : 0) + (income2_used_for_mortgage? ? income2 : 0)
+  mortgage > income_used_for_mortgage * 5
+end
+
+
+ +
+

+ + #mortgage_plus_deposit_less_than_discounted_value?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+97
+98
+99
+100
+101
+102
+
+
# File 'sales/soft_validations.rb', line 97
+
+def mortgage_plus_deposit_less_than_discounted_value?
+  return unless mortgage && deposit && value && discount
+
+  discounted_value = value * (100 - discount) / 100
+  mortgage + deposit < discounted_value
+end
+
+
+ +
+

+ + #percentage_discount_invalid?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+
+
# File 'sales/soft_validations.rb', line 165
+
+def percentage_discount_invalid?
+  return unless discount && proptype
+
+  case proptype
+  when 1, 2
+    discount > 50
+  when 3, 4, 9
+    discount > 35
+  end
+end
+
+
+ +
+

+ + #purchase_price_higher_or_lower_textObject + + + + + +

+ + + + +
+
+
+
+110
+111
+112
+
+
# File 'sales/soft_validations.rb', line 110
+
+def purchase_price_higher_or_lower_text
+  value < sale_range.soft_min ? "lower" : "higher"
+end
+
+
+ +
+

+ + #purchase_price_out_of_soft_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+76
+77
+78
+79
+80
+
+
# File 'sales/soft_validations.rb', line 76
+
+def purchase_price_out_of_soft_range?
+  return unless value && beds && la && sale_range
+
+  !value.between?(sale_range.soft_min, sale_range.soft_max)
+end
+
+
+ +
+

+ + #purchase_price_soft_min_or_soft_maxObject + + + + + +

+ + + + +
+
+
+
+114
+115
+116
+
+
# File 'sales/soft_validations.rb', line 114
+
+def purchase_price_soft_min_or_soft_max
+  value < sale_range.soft_min ? sale_range.soft_min : sale_range.soft_max
+end
+
+
+ +
+

+ + #savings_over_soft_max?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+60
+61
+62
+
+
# File 'sales/soft_validations.rb', line 60
+
+def savings_over_soft_max?
+  savings && savings > 100_000
+end
+
+
+ +
+

+ + #shared_ownership_deposit_invalid?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+88
+89
+90
+91
+92
+93
+94
+95
+
+
# File 'sales/soft_validations.rb', line 88
+
+def shared_ownership_deposit_invalid?
+  return unless saledate && collection_start_year <= 2023
+  return unless mortgage || mortgageused == 2 || mortgageused == 3
+  return unless cashdis || !social_homebuy?
+  return unless deposit && value && equity
+
+  over_tolerance?(mortgage_deposit_and_discount_total, value * equity / 100, 1)
+end
+
+
+ +
+

+ + #staircase_bought_above_fifty?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+42
+43
+44
+
+
# File 'sales/soft_validations.rb', line 42
+
+def staircase_bought_above_fifty?
+  stairbought && stairbought > 50
+end
+
+
+ +
+

+ + #staircase_owned_out_of_soft_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+82
+83
+84
+85
+86
+
+
# File 'sales/soft_validations.rb', line 82
+
+def staircase_owned_out_of_soft_range?
+  return unless type && stairowned
+
+  type == 24 && stairowned.between?(76, 100)
+end
+
+
+ +
+

+ + #wheelchair_when_not_disabled?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+54
+55
+56
+57
+58
+
+
# File 'sales/soft_validations.rb', line 54
+
+def wheelchair_when_not_disabled?
+  return unless disabled && wheel
+
+  wheel == 1 && disabled == 2
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/SetupValidations.html b/app/models/validations/doc/Validations/SetupValidations.html new file mode 100644 index 000000000..60286aa16 --- /dev/null +++ b/app/models/validations/doc/Validations/SetupValidations.html @@ -0,0 +1,679 @@ + + + + + + + Module: Validations::SetupValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::SetupValidations + + + +

+
+ + + + + + +
+
Includes:
+
CollectionTimeHelper, SharedValidations
+
+ + + + + + +
+
Defined in:
+
setup_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_irproduct_other(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+69
+70
+71
+72
+73
+
+
# File 'setup_validations.rb', line 69
+
+def validate_irproduct_other(record)
+  if intermediate_product_rent_type?(record) && record.irproduct_other.blank?
+    record.errors.add :irproduct_other, I18n.t("validations.setup.intermediate_rent_product_name.blank")
+  end
+end
+
+
+ +
+

+ + #validate_location(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+75
+76
+77
+78
+79
+80
+81
+82
+
+
# File 'setup_validations.rb', line 75
+
+def validate_location(record)
+  location_during_startdate_validation(record)
+
+  if record.location&.status == :incomplete
+    record.errors.add :location_id, :incomplete, message: I18n.t("validations.setup.location.incomplete")
+    record.errors.add :scheme_id, :incomplete, message: I18n.t("validations.setup.location.incomplete")
+  end
+end
+
+
+ +
+

+ + #validate_managing_organisation_data_sharing_agremeent_signed(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+96
+97
+98
+99
+100
+101
+102
+
+
# File 'setup_validations.rb', line 96
+
+def validate_managing_organisation_data_sharing_agremeent_signed(record)
+  return if record.skip_dpo_validation
+
+  if record.managing_organisation_id_changed? && record.managing_organisation.present? && !record.managing_organisation.data_protection_confirmed?
+    record.errors.add :managing_organisation_id, I18n.t("validations.setup.managing_organisation.data_sharing_agreement_not_signed")
+  end
+end
+
+
+ +
+

+ + #validate_merged_organisations_start_date(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+59
+60
+61
+62
+63
+64
+65
+66
+67
+
+
# File 'setup_validations.rb', line 59
+
+def validate_merged_organisations_start_date(record)
+  return unless record.startdate && date_valid?("startdate", record)
+
+  return add_same_merge_organisation_error(record) if record.owning_organisation == record.managing_organisation
+  return add_same_merge_error(record) if organisations_belong_to_same_merge?(record.owning_organisation, record.managing_organisation)
+
+  add_merged_organisations_errors(record)
+  add_absorbing_organisations_errors(record)
+end
+
+
+ +
+

+ + #validate_organisation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+
# File 'setup_validations.rb', line 23
+
+def validate_organisation(record)
+  created_by, managing_organisation, owning_organisation = record.values_at("created_by", "managing_organisation", "owning_organisation")
+  unless [created_by, managing_organisation, owning_organisation].any?(&:blank?) || ((created_by.organisation.absorbed_organisations + [created_by.organisation]) & [managing_organisation, owning_organisation]).present?
+    record.errors.add :created_by, I18n.t("validations.setup.created_by.invalid")
+    record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.invalid")
+    record.errors.add :managing_organisation_id, I18n.t("validations.setup.managing_organisation.invalid")
+  end
+  return unless record.startdate
+
+  if owning_organisation.present?
+    if owning_organisation&.merge_date.present? && owning_organisation.merge_date <= record.startdate
+      record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.inactive_merged_organisation",
+                                                        owning_organisation: record.owning_organisation.name,
+                                                        owning_organisation_merge_date: record.owning_organisation.merge_date.to_formatted_s(:govuk_date),
+                                                        owning_absorbing_organisation: record.owning_organisation.absorbing_organisation.name)
+    elsif owning_organisation&.absorbed_organisations.present? && owning_organisation.available_from.present? && owning_organisation.available_from.to_date > record.startdate.to_date
+      record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.inactive_absorbing_organisation",
+                                                        owning_organisation: record.owning_organisation.name,
+                                                        owning_organisation_available_from: record.owning_organisation.available_from.to_formatted_s(:govuk_date))
+    end
+  end
+
+  if managing_organisation.present?
+    if managing_organisation&.merge_date.present? && managing_organisation.merge_date <= record.startdate
+      record.errors.add :managing_organisation_id, I18n.t("validations.setup.managing_organisation.inactive_merged_organisation",
+                                                          managing_organisation: record.managing_organisation.name,
+                                                          managing_organisation_merge_date: record.managing_organisation.merge_date.to_formatted_s(:govuk_date),
+                                                          managing_absorbing_organisation: record.managing_organisation.absorbing_organisation.name)
+    elsif managing_organisation&.absorbed_organisations.present? && managing_organisation.available_from.present? && managing_organisation.available_from.to_date > record.startdate.to_date
+      record.errors.add :managing_organisation_id, I18n.t("validations.setup.managing_organisation.inactive_absorbing_organisation",
+                                                          managing_organisation: record.managing_organisation.name,
+                                                          managing_organisation_available_from: record.managing_organisation.available_from.to_formatted_s(:govuk_date))
+    end
+  end
+end
+
+
+ +
+

+ + #validate_scheme(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+92
+93
+94
+
+
# File 'setup_validations.rb', line 92
+
+def validate_scheme(record)
+  scheme_during_startdate_validation(record)
+end
+
+
+ +
+

+ + #validate_scheme_has_confirmed_locations_validation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+84
+85
+86
+87
+88
+89
+90
+
+
# File 'setup_validations.rb', line 84
+
+def validate_scheme_has_confirmed_locations_validation(record)
+  return unless record.scheme
+
+  unless record.scheme.locations.confirmed.any?
+    record.errors.add :scheme_id, :no_completed_locations, message: I18n.t("validations.scheme.no_completed_locations")
+  end
+end
+
+
+ +
+

+ + #validate_startdate_setup(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+
+
# File 'setup_validations.rb', line 5
+
+def validate_startdate_setup(record)
+  return unless record.startdate && date_valid?("startdate", record) && !FeatureToggle.allow_future_form_use?
+
+  first_collection_start_date = if record.startdate_was.present?
+                                  editable_collection_start_date
+                                else
+                                  active_collection_start_date
+                                end
+
+  unless record.startdate.between?(first_collection_start_date, current_collection_end_date)
+    record.errors.add :startdate, startdate_validation_error_message
+  end
+
+  if record.startdate > Time.zone.today + 14.days
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.later_than_14_days_after")
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/SharedValidations.html b/app/models/validations/doc/Validations/SharedValidations.html new file mode 100644 index 000000000..6c9807b39 --- /dev/null +++ b/app/models/validations/doc/Validations/SharedValidations.html @@ -0,0 +1,853 @@ + + + + + + + Module: Validations::SharedValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::SharedValidations + + + +

+
+ + + + + + +
+
Includes:
+
ActionView::Helpers::NumberHelper
+
+ + + + +
+
Included in:
+
DateValidations, FinancialValidations, HouseholdValidations, Validations::Sales::HouseholdValidations, Validations::Sales::SaleInformationValidations, Validations::Sales::SetupValidations, SetupValidations, TenancyValidations
+
+ + + +
+
Defined in:
+
shared_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #date_valid?(question, record) ⇒ Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+116
+117
+118
+119
+120
+121
+122
+123
+
+
# File 'shared_validations.rb', line 116
+
+def date_valid?(question, record)
+  if record[question].is_a?(ActiveSupport::TimeWithZone) && record[question].year.zero?
+    record.errors.add question, I18n.t("validations.date.invalid_date")
+    false
+  else
+    true
+  end
+end
+
+
+ +
+

+ + #inactive_status(date, resource) ⇒ Object + + + + + +

+ + + + +
+
+
+
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+
+
# File 'shared_validations.rb', line 87
+
+def inactive_status(date, resource)
+  return if date.blank? || resource.blank?
+
+  status = resource.status_at(date)
+  return unless %i[reactivating_soon activating_soon deactivated].include?(status)
+
+  closest_reactivation = resource.last_deactivation_before(date)
+  open_deactivation = resource.open_deactivation
+
+  date = case status
+         when :reactivating_soon then closest_reactivation.reactivation_date
+         when :activating_soon then resource&.available_from
+         when :deactivated then open_deactivation.deactivation_date
+         end
+
+  { scope: status, date: date&.to_formatted_s(:govuk_date), deactivation_date: closest_reactivation&.deactivation_date&.to_formatted_s(:govuk_date) }
+end
+
+
+ +
+

+ + #location_during_startdate_validation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+
+
# File 'shared_validations.rb', line 67
+
+def location_during_startdate_validation(record)
+  location_inactive_status = inactive_status(record.startdate, record.location)
+
+  if location_inactive_status.present?
+    date, scope, deactivation_date = location_inactive_status.values_at(:date, :scope, :deactivation_date)
+    record.errors.add :startdate, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.startdate", postcode: record.location.postcode, date:, deactivation_date:)
+    record.errors.add :location_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
+    record.errors.add :scheme_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
+  end
+end
+
+
+ +
+

+ + #scheme_during_startdate_validation(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+78
+79
+80
+81
+82
+83
+84
+85
+
+
# File 'shared_validations.rb', line 78
+
+def scheme_during_startdate_validation(record)
+  scheme_inactive_status = inactive_status(record.startdate, record.scheme)
+  if scheme_inactive_status.present?
+    date, scope, deactivation_date = scheme_inactive_status.values_at(:date, :scope, :deactivation_date)
+    record.errors.add :startdate, I18n.t("validations.setup.startdate.scheme.#{scope}.startdate", name: record.scheme.service_name, date:, deactivation_date:)
+    record.errors.add :scheme_id, I18n.t("validations.setup.startdate.scheme.#{scope}.scheme_id", name: record.scheme.service_name, date:, deactivation_date:)
+  end
+end
+
+
+ +
+

+ + #shared_validate_partner_count(record, max_people) ⇒ Object + + + + + +

+ + + + +
+
+
+
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+
+
# File 'shared_validations.rb', line 105
+
+def shared_validate_partner_count(record, max_people)
+  return if record.form.start_year_after_2024?
+
+  partner_numbers = (2..max_people).select { |n| person_is_partner?(record["relat#{n}"]) }
+  if partner_numbers.count > 1
+    partner_numbers.each do |n|
+      record.errors.add "relat#{n}", I18n.t("validations.household.relat.one_partner")
+    end
+  end
+end
+
+
+ +
+

+ + #validate_numeric_min_max(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+
+
# File 'shared_validations.rb', line 19
+
+def validate_numeric_min_max(record)
+  record.form.numeric_questions.each do |question|
+    next unless question.min || question.max
+    next unless record[question.id] && question.page.routed_to?(record, nil)
+
+    begin
+      answer = Float(record.public_send("#{question.id}_before_type_cast"))
+    rescue ArgumentError
+      add_range_error(record, question)
+    end
+
+    next unless answer
+
+    if (question.min && question.min > answer) || (question.max && question.max < answer)
+      add_range_error(record, question)
+    end
+  end
+end
+
+
+ +
+

+ + #validate_numeric_step(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+
+
# File 'shared_validations.rb', line 38
+
+def validate_numeric_step(record)
+  record.form.numeric_questions.each do |question|
+    next unless question.step
+    next unless record[question.id] && question.page.routed_to?(record, nil)
+
+    value = record.public_send("#{question.id}_before_type_cast")
+    field = question.check_answer_label || question.id
+    incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0
+
+    if question.step < 1 && incorrect_accuracy
+      record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_hundredth", field:)
+    elsif incorrect_accuracy || value.to_d != value.to_i    # if the user enters a value in exponent notation (eg '4e1') the to_i method does not convert this to the correct value
+      field = question.check_answer_label || question.id
+      case question.step
+      when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.numeric.whole_number", field:)
+      when 10 then record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_ten", field:)
+      end
+    end
+  end
+end
+
+
+ +
+

+ + #validate_other_field(record, value_other = nil, main_field = nil, other_field = nil, main_label = nil, other_label = nil) ⇒ Object + + + + + +

+ + + + +
+
+
+
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
+
# File 'shared_validations.rb', line 4
+
+def validate_other_field(record, value_other = nil, main_field = nil, other_field = nil, main_label = nil, other_label = nil)
+  return unless main_field || other_field
+
+  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
+
+  if record[main_field] != value_other && record[other_field].present?
+    record.errors.add other_field.to_sym, I18n.t("validations.other_field_not_required", main_field_label:, other_field_label:)
+  end
+end
+
+
+ +
+

+ + #validate_owning_organisation_data_sharing_agremeent_signed(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+125
+126
+127
+128
+129
+130
+131
+
+
# File 'shared_validations.rb', line 125
+
+def validate_owning_organisation_data_sharing_agremeent_signed(record)
+  return if record.skip_dpo_validation
+
+  if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
+    record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.data_sharing_agreement_not_signed")
+  end
+end
+
+
+ +
+

+ + #validate_property_postcode(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+59
+60
+61
+62
+63
+64
+65
+
+
# File 'shared_validations.rb', line 59
+
+def validate_property_postcode(record)
+  postcode = record.postcode_full
+  if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
+    error_message = I18n.t("validations.postcode")
+    record.errors.add :postcode_full, :wrong_format, message: error_message
+  end
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/SoftValidations.html b/app/models/validations/doc/Validations/SoftValidations.html new file mode 100644 index 000000000..29e6114c2 --- /dev/null +++ b/app/models/validations/doc/Validations/SoftValidations.html @@ -0,0 +1,1516 @@ + + + + + + + Module: Validations::SoftValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::SoftValidations + + + +

+
+ + + + + + +
+
Includes:
+
ChargesHelper
+
+ + + + + + +
+
Defined in:
+
soft_validations.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
ALLOWED_INCOME_RANGES = + +
+
{
+  1 => OpenStruct.new(soft_min: 143, soft_max: 730, hard_min: 90, hard_max: 1230),
+  2 => OpenStruct.new(soft_min: 67, soft_max: 620, hard_min: 50, hard_max: 950),
+  3 => OpenStruct.new(soft_min: 80, soft_max: 480, hard_min: 40, hard_max: 990),
+  4 => OpenStruct.new(soft_min: 50, soft_max: 370, hard_min: 10, hard_max: 450),
+  5 => OpenStruct.new(soft_min: 50, soft_max: 380, hard_min: 10, hard_max: 690),
+  6 => OpenStruct.new(soft_min: 53, soft_max: 540, hard_min: 10, hard_max: 890),
+  7 => OpenStruct.new(soft_min: 47, soft_max: 460, hard_min: 10, hard_max: 1300),
+  8 => OpenStruct.new(soft_min: 54, soft_max: 460, hard_min: 10, hard_max: 2000),
+  9 => OpenStruct.new(soft_min: 50, soft_max: 450, hard_min: 10, hard_max: 750),
+  0 => OpenStruct.new(soft_min: 50, soft_max: 580, hard_min: 10, hard_max: 1040),
+  10 => OpenStruct.new(soft_min: 47, soft_max: 730, hard_min: 10, hard_max: 2000),
+}.freeze
+ +
TWO_YEARS_IN_DAYS = + +
+
730
+ +
TEN_YEARS_IN_DAYS = + +
+
3650
+ +
PHRASES_LIKELY_TO_INDICATE_EXISTING_REASON_CATEGORY = + +
+
[
+  "Decant",
+  "Decanted",
+  "Refugee",
+  "Asylum",
+  "Ukraine",
+  "Ukrainian",
+  "Army",
+  "Military",
+  "Domestic Abuse",
+  "Domestic Violence",
+  "DA",
+  "DV",
+  "Relationship breakdown",
+  "Overcrowding",
+  "Overcrowded",
+  "Too small",
+  "More space",
+  "Bigger property",
+  "Damp",
+  "Mould",
+  "Fire",
+  "Repossession",
+  "Death",
+  "Deceased",
+  "Passed away",
+  "Prison",
+  "Hospital",
+].freeze
+ +
PHRASES_LIKELY_TO_INDICATE_EXISTING_REASON_CATEGORY_REGEX = + +
+
Regexp.union(
+  PHRASES_LIKELY_TO_INDICATE_EXISTING_REASON_CATEGORY.map { |phrase| Regexp.new("\\b[^[:alpha]]*#{phrase}[^[:alpha:]]*\\b", Regexp::IGNORECASE) },
+)
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #all_tenants_age_and_gender_information_completed?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+78
+79
+80
+81
+82
+83
+84
+
+
# File 'soft_validations.rb', line 78
+
+def all_tenants_age_and_gender_information_completed?
+  person_count = hhmemb || 8
+
+  (1..person_count).all? do |n|
+    public_send("sex#{n}").present? && public_send("age#{n}").present? && details_known_or_lead_tenant?(n) && public_send("age#{n}_known").present? && public_send("age#{n}_known").zero?
+  end
+end
+
+
+ +
+

+ + #all_tenants_gender_information_completed?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+86
+87
+88
+89
+90
+91
+92
+
+
# File 'soft_validations.rb', line 86
+
+def all_tenants_gender_information_completed?
+  person_count = hhmemb || 8
+
+  (1..person_count).all? do |n|
+    public_send("sex#{n}").present? && details_known_or_lead_tenant?(n)
+  end
+end
+
+
+ +
+

+ + #female_in_pregnant_household_in_soft_validation_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+74
+75
+76
+
+
# File 'soft_validations.rb', line 74
+
+def female_in_pregnant_household_in_soft_validation_range?
+  all_tenants_age_and_gender_information_completed? && females_in_the_household? && !females_in_age_range(16, 50) && preg_occ == 1
+end
+
+
+ +
+

+ + #major_repairs_date_in_soft_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+97
+98
+99
+
+
# File 'soft_validations.rb', line 97
+
+def major_repairs_date_in_soft_range?
+  mrcdate.present? && startdate.present? && mrcdate.between?(startdate.to_date - TEN_YEARS_IN_DAYS, startdate.to_date - TWO_YEARS_IN_DAYS)
+end
+
+
+ +
+

+ + #multiple_partners?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+198
+199
+200
+201
+202
+203
+
+
# File 'soft_validations.rb', line 198
+
+def multiple_partners?
+  return unless hhmemb
+
+  max_person_with_details = sales? ? [hhmemb, 6].min : [hhmemb, 8].min
+  (2..max_person_with_details).many? { |n| public_send("relat#{n}") == "P" }
+end
+
+
+ +
+

+ + #net_income_higher_or_lower_textObject + + + + + +

+ + + + +
+
+
+
+105
+106
+107
+
+
# File 'soft_validations.rb', line 105
+
+def net_income_higher_or_lower_text
+  net_income_in_soft_max_range? ? "higher" : "lower"
+end
+
+
+ +
+

+ + #net_income_in_soft_max_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+18
+19
+20
+21
+22
+
+
# File 'soft_validations.rb', line 18
+
+def net_income_in_soft_max_range?
+  return unless weekly_net_income && ecstat1 && hhmemb
+
+  weekly_net_income.between?(applicable_income_range.soft_max, applicable_income_range.hard_max)
+end
+
+
+ +
+

+ + #net_income_in_soft_min_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+24
+25
+26
+27
+28
+
+
# File 'soft_validations.rb', line 24
+
+def net_income_in_soft_min_range?
+  return unless weekly_net_income && ecstat1 && hhmemb
+
+  weekly_net_income.between?(applicable_income_range.hard_min, applicable_income_range.soft_min)
+end
+
+
+ +
+

+ + #no_females_in_a_pregnant_household?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+70
+71
+72
+
+
# File 'soft_validations.rb', line 70
+
+def no_females_in_a_pregnant_household?
+  !females_in_the_household? && all_tenants_gender_information_completed? && preg_occ == 1
+end
+
+
+ +
+

+ + #pscharge_in_soft_max_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+
+
# File 'soft_validations.rb', line 126
+
+def pscharge_in_soft_max_range?
+  return unless pscharge && period && needstype && owning_organisation
+  return if weekly_value(pscharge).blank?
+
+  soft_max = if needstype == 1
+               owning_organisation.provider_type == "LA" ? 25 : 35
+             else
+               owning_organisation.provider_type == "LA" ? 75 : 100
+             end
+
+  provider_type = owning_organisation.provider_type_before_type_cast
+  hard_max = CHARGE_MAXIMA_PER_WEEK.dig(:pscharge, PROVIDER_TYPE[provider_type], NEEDSTYPE_VALUES[needstype])
+
+  weekly_pscharge = weekly_value(pscharge)
+  weekly_pscharge > soft_max && weekly_pscharge <= hard_max
+end
+
+
+ +
+

+ + #reasonother_might_be_existing_category?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+194
+195
+196
+
+
# File 'soft_validations.rb', line 194
+
+def reasonother_might_be_existing_category?
+  PHRASES_LIKELY_TO_INDICATE_EXISTING_REASON_CATEGORY_REGEX.match?(reasonother)
+end
+
+
+ +
+

+ + #rent_in_soft_max_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+
# File 'soft_validations.rb', line 42
+
+def rent_in_soft_max_range?
+  return unless brent && weekly_value(brent) && startdate
+
+  rent_range = LaRentRange.find_by(
+    start_year: collection_start_year,
+    la:,
+    beds: beds_for_la_rent_range,
+    lettype: get_lettype,
+  )
+  if beds.present? && rent_range.present? && beds > LaRentRange::MAX_BEDS
+    weekly_value(brent) > rent_range.soft_max
+  elsif rent_range.present?
+    weekly_value(brent).between?(rent_range.soft_max, rent_range.hard_max)
+  end
+end
+
+
+ +
+

+ + #rent_in_soft_min_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+
+
# File 'soft_validations.rb', line 30
+
+def rent_in_soft_min_range?
+  return unless brent && weekly_value(brent) && startdate
+
+  rent_range = LaRentRange.find_by(
+    start_year: collection_start_year,
+    la:,
+    beds: beds_for_la_rent_range,
+    lettype: get_lettype,
+  )
+  rent_range.present? && weekly_value(brent).between?(rent_range.hard_min, rent_range.soft_min)
+end
+
+
+ +
+

+ + #scharge_in_soft_max_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+
+
# File 'soft_validations.rb', line 109
+
+def scharge_in_soft_max_range?
+  return unless scharge && period && needstype && owning_organisation
+  return if weekly_value(scharge).blank?
+
+  soft_max = if needstype == 1
+               owning_organisation.provider_type == "LA" ? 25 : 35
+             else
+               owning_organisation.provider_type == "LA" ? 100 : 200
+             end
+
+  provider_type = owning_organisation.provider_type_before_type_cast
+  hard_max = CHARGE_MAXIMA_PER_WEEK.dig(:scharge, PROVIDER_TYPE[provider_type], NEEDSTYPE_VALUES[needstype])
+
+  weekly_scharge = weekly_value(scharge)
+  weekly_scharge > soft_max && weekly_scharge <= hard_max
+end
+
+
+ +
+

+ + #supcharg_in_soft_max_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+
+
# File 'soft_validations.rb', line 143
+
+def supcharg_in_soft_max_range?
+  return unless supcharg && period && needstype && owning_organisation
+  return if weekly_value(supcharg).blank?
+
+  soft_max = if needstype == 1
+               owning_organisation.provider_type == "LA" ? 25 : 35
+             else
+               owning_organisation.provider_type == "LA" ? 75 : 85
+             end
+
+  provider_type = owning_organisation.provider_type_before_type_cast
+  hard_max = CHARGE_MAXIMA_PER_WEEK.dig(:supcharg, PROVIDER_TYPE[provider_type], NEEDSTYPE_VALUES[needstype])
+
+  weekly_supcharg = weekly_value(supcharg)
+  weekly_supcharg > soft_max && weekly_supcharg <= hard_max
+end
+
+
+ +
+

+ + #voiddate_in_soft_range?Boolean + + + + + +

+
+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+101
+102
+103
+
+
# File 'soft_validations.rb', line 101
+
+def voiddate_in_soft_range?
+  voiddate.present? && startdate.present? && voiddate.between?(startdate.to_date - TEN_YEARS_IN_DAYS, startdate.to_date - TWO_YEARS_IN_DAYS)
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/Validations/TenancyValidations.html b/app/models/validations/doc/Validations/TenancyValidations.html new file mode 100644 index 000000000..812d2d626 --- /dev/null +++ b/app/models/validations/doc/Validations/TenancyValidations.html @@ -0,0 +1,584 @@ + + + + + + + Module: Validations::TenancyValidations + + — Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: Validations::TenancyValidations + + + +

+
+ + + + + + +
+
Includes:
+
SharedValidations
+
+ + + + + + +
+
Defined in:
+
tenancy_validations.rb
+
+ +
+ + + + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + + +
+

Instance Method Details

+ + +
+

+ + #validate_general_needs_fixed_tenancy_length_affordable_social_rent(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+
+
# File 'tenancy_validations.rb', line 19
+
+def validate_general_needs_fixed_tenancy_length_affordable_social_rent(record)
+  return unless record.tenancy_type_fixed_term? && record.affordable_or_social_rent? && record.is_general_needs?
+  return if record.tenancylength.blank?
+
+  min_tenancy_length = 2
+  return if record.tenancylength.to_i.between?(min_tenancy_length, 99)
+
+  message = I18n.t("validations.tenancy.length.invalid_fixed", min_tenancy_length:)
+  record.errors.add :needstype, message
+  record.errors.add :rent_type, message
+  record.errors.add :tenancylength, :tenancylength_invalid, message: message
+  record.errors.add :tenancy, message
+end
+
+
+ +
+

+ + #validate_general_needs_fixed_tenancy_length_intermediate_rent(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+
+
# File 'tenancy_validations.rb', line 33
+
+def validate_general_needs_fixed_tenancy_length_intermediate_rent(record)
+  return unless record.tenancy_type_fixed_term? && !record.affordable_or_social_rent? && record.is_general_needs?
+  return if record.tenancylength.blank?
+
+  min_tenancy_length = 1
+  return if record.tenancylength.to_i.between?(min_tenancy_length, 99)
+
+  message = I18n.t("validations.tenancy.length.invalid_fixed", min_tenancy_length:)
+  record.errors.add :needstype, message
+  record.errors.add :rent_type, message
+  record.errors.add :tenancylength, :tenancylength_invalid, message: message
+  record.errors.add :tenancy, message
+end
+
+
+ +
+

+ + #validate_joint_tenancy(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+71
+72
+73
+74
+75
+76
+77
+78
+
+
# File 'tenancy_validations.rb', line 71
+
+def validate_joint_tenancy(record)
+  return unless record.collection_start_year && record.joint
+
+  if record.hhmemb == 1 && record.joint == 1 && record.collection_start_year >= 2022
+    record.errors.add :joint, :not_joint_tenancy, message: I18n.t("validations.tenancy.not_joint")
+    record.errors.add :hhmemb, I18n.t("validations.tenancy.joint_more_than_one_member")
+  end
+end
+
+
+ +
+

+ + #validate_other_tenancy_type(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+67
+68
+69
+
+
# File 'tenancy_validations.rb', line 67
+
+def validate_other_tenancy_type(record)
+  validate_other_field(record, 3, :tenancy, :tenancyother, "tenancy type", "other tenancy type")
+end
+
+
+ +
+

+ + #validate_periodic_tenancy_length(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+
# File 'tenancy_validations.rb', line 47
+
+def validate_periodic_tenancy_length(record)
+  return unless record.is_periodic_tenancy? && record.tenancylength.present?
+
+  min_tenancy_length = 1
+  return if record.tenancylength.to_i.between?(min_tenancy_length, 99)
+
+  message = I18n.t("validations.tenancy.length.invalid_periodic", min_tenancy_length:)
+  record.errors.add :tenancylength, :tenancylength_invalid, message: message
+  record.errors.add :tenancy, message
+end
+
+
+ +
+

+ + #validate_supported_housing_fixed_tenancy_length(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+
+
# File 'tenancy_validations.rb', line 6
+
+def validate_supported_housing_fixed_tenancy_length(record)
+  return unless record.tenancy_type_fixed_term? && record.is_supported_housing?
+  return if record.tenancylength.blank?
+
+  min_tenancy_length = 1
+  return if record.tenancylength.to_i.between?(min_tenancy_length, 99)
+
+  message = I18n.t("validations.tenancy.length.invalid_fixed", min_tenancy_length:)
+  record.errors.add :needstype, message
+  record.errors.add :tenancylength, :tenancylength_invalid, message: message
+  record.errors.add :tenancy, message
+end
+
+
+ +
+

+ + #validate_tenancy_length_blank_when_not_required(record) ⇒ Object + + + + + +

+ + + + +
+
+
+
+58
+59
+60
+61
+62
+63
+64
+65
+
+
# File 'tenancy_validations.rb', line 58
+
+def validate_tenancy_length_blank_when_not_required(record)
+  return if record.tenancylength.blank?
+  return if record.tenancy_type_fixed_term? || record.is_periodic_tenancy?
+
+  message = I18n.t("validations.tenancy.length.fixed_term_not_required")
+  record.errors.add :tenancylength, :tenancylength_invalid, message: message
+  record.errors.add :tenancy, message
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/_index.html b/app/models/validations/doc/_index.html new file mode 100644 index 000000000..6c5778ed4 --- /dev/null +++ b/app/models/validations/doc/_index.html @@ -0,0 +1,246 @@ + + + + + + + Documentation by YARD 0.9.36 + + + + + + + + + + + + + + + + + + + +
+ + +

Documentation by YARD 0.9.36

+
+

Alphabetic Index

+ +
+

Namespace Listing A-Z

+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/app/models/validations/doc/class_list.html b/app/models/validations/doc/class_list.html new file mode 100644 index 000000000..5f36869e7 --- /dev/null +++ b/app/models/validations/doc/class_list.html @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + Class List + + + +
+
+

Class List

+ + + +
+ + +
+ + diff --git a/app/models/validations/doc/css/common.css b/app/models/validations/doc/css/common.css new file mode 100644 index 000000000..cf25c4523 --- /dev/null +++ b/app/models/validations/doc/css/common.css @@ -0,0 +1 @@ +/* Override this file with custom rules */ \ No newline at end of file diff --git a/app/models/validations/doc/css/full_list.css b/app/models/validations/doc/css/full_list.css new file mode 100644 index 000000000..fa3598242 --- /dev/null +++ b/app/models/validations/doc/css/full_list.css @@ -0,0 +1,58 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; + background: #fafafa; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +.fixed_header { position: fixed; background: #fff; width: 100%; padding-bottom: 10px; margin-top: 0; top: 0; z-index: 9999; height: 70px; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; margin-top: 80px; font-size: 1.1em; } +#full_list ul { padding: 0; } +#full_list li { padding: 0; margin: 0; list-style: none; } +#full_list li .item { padding: 5px 5px 5px 12px; } +#noresults { padding: 7px 12px; background: #fff; } +#content.insearch #noresults { margin-left: 7px; } +li.collapsed ul { display: none; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { opacity: 0.5; cursor: default; background-position: top left; } +li { color: #888; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.odd { background: #f0f0f0; } +li.even { background: #fafafa; } +.item:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a, a:visited { text-decoration: none; color: #05a; } +li.clicked > .item { background: #05a; color: #ccc; } +li.clicked > .item a, li.clicked > .item a:visited { color: #eee; } +li.clicked > .item a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#search input { border: 1px solid #bbb; border-radius: 3px; } +#full_list_nav { margin-left: 10px; font-size: 0.9em; display: block; color: #aaa; } +#full_list_nav a, #nav a:visited { color: #358; } +#full_list_nav a:hover { background: transparent; color: #5af; } +#full_list_nav span:after { content: ' | '; } +#full_list_nav span:last-child:after { content: ''; } + +#content h1 { margin-top: 0; } +li { white-space: nowrap; cursor: normal; } +li small { display: block; font-size: 0.8em; } +li small:before { content: ""; } +li small:after { content: ""; } +li small.search_info { display: none; } +#search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #888; padding-left: 0; padding-right: 24px; } +#content.insearch #search { background-position: center right; } +#search input { width: 110px; } + +#full_list.insearch ul { display: block; } +#full_list.insearch .item { display: none; } +#full_list.insearch .found { display: block; padding-left: 11px !important; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/app/models/validations/doc/css/style.css b/app/models/validations/doc/css/style.css new file mode 100644 index 000000000..eb0dbc86f --- /dev/null +++ b/app/models/validations/doc/css/style.css @@ -0,0 +1,497 @@ +html { + width: 100%; + height: 100%; +} +body { + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + width: 100%; + margin: 0; + padding: 0; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; +} + +#nav { + position: relative; + width: 100%; + height: 100%; + border: 0; + border-right: 1px dotted #eee; + overflow: auto; +} +.nav_wrap { + margin: 0; + padding: 0; + width: 20%; + height: 100%; + position: relative; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; + flex-shrink: 0; + -webkit-flex-shrink: 0; + -ms-flex: 1 0; +} +#resizer { + position: absolute; + right: -5px; + top: 0; + width: 10px; + height: 100%; + cursor: col-resize; + z-index: 9999; +} +#main { + flex: 5 1; + -webkit-flex: 5 1; + -ms-flex: 5 1; + outline: none; + position: relative; + background: #fff; + padding: 1.2em; + padding-top: 0.2em; + box-sizing: border-box; +} + +@media (max-width: 920px) { + .nav_wrap { width: 100%; top: 0; right: 0; overflow: visible; position: absolute; } + #resizer { display: none; } + #nav { + z-index: 9999; + background: #fff; + display: none; + position: absolute; + top: 40px; + right: 12px; + width: 500px; + max-width: 80%; + height: 80%; + overflow-y: scroll; + border: 1px solid #999; + border-collapse: collapse; + box-shadow: -7px 5px 25px #aaa; + border-radius: 2px; + } +} + +@media (min-width: 920px) { + body { height: 100%; overflow: hidden; } + #main { height: 100%; overflow: auto; } + #search { display: none; } +} + +#main img { max-width: 100%; } +h1 { font-size: 25px; margin: 1em 0 0.5em; padding-top: 4px; border-top: 1px dotted #d5d5d5; } +h1.noborder { border-top: 0px; margin-top: 0; padding-top: 4px; } +h1.title { margin-bottom: 10px; } +h1.alphaindex { margin-top: 0; font-size: 22px; } +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; + position: relative; +} +h2 small { font-weight: normal; font-size: 0.7em; display: inline; position: absolute; right: 0; } +h2 small a { + display: block; + height: 20px; + border: 1px solid #aaa; + border-bottom: 0; + border-top-left-radius: 5px; + background: #f8f8f8; + position: relative; + padding: 2px 7px; +} +.clear { clear: both; } +.inline { display: inline; } +.inline p:first-child { display: inline; } +.docstring, .tags, #filecontents { font-size: 15px; line-height: 1.5145em; } +.docstring p > code, .docstring p > tt, .tags p > code, .tags p > tt { + color: #c7254e; background: #f9f2f4; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 1px dotted #bbb; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; border-bottom: 0; padding-top: 10px; } +.summary_desc .object_link a, .docstring .object_link a { + font-family: monospace; font-size: 1.05em; + color: #05a; background: #EDF4FA; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.rdoc-term { padding-right: 25px; font-weight: bold; } +.rdoc-list p { margin: 0; padding: 0; margin-bottom: 4px; } +.summary_desc pre.code .object_link a, .docstring pre.code .object_link a { + padding: 0px; background: inherit; color: inherit; border-radius: inherit; +} + +/* style for */ +#filecontents table, .docstring table { border-collapse: collapse; } +#filecontents table th, #filecontents table td, +.docstring table th, .docstring table td { border: 1px solid #ccc; padding: 8px; padding-right: 17px; } +#filecontents table tr:nth-child(odd), +.docstring table tr:nth-child(odd) { background: #eee; } +#filecontents table tr:nth-child(even), +.docstring table tr:nth-child(even) { background: #fff; } +#filecontents table th, .docstring table th { background: #fff; } + +/* style for
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + \ No newline at end of file diff --git a/app/models/validations/doc/js/app.js b/app/models/validations/doc/js/app.js new file mode 100644 index 000000000..8d067fe30 --- /dev/null +++ b/app/models/validations/doc/js/app.js @@ -0,0 +1,314 @@ +(function() { + +var localStorage = {}, sessionStorage = {}; +try { localStorage = window.localStorage; } catch (e) { } +try { sessionStorage = window.sessionStorage; } catch (e) { } + +function createSourceLinks() { + $('.method_details_list .source_code'). + before("[View source]"); + $('.toggleSource').toggle(function() { + $(this).parent().nextAll('.source_code').slideDown(100); + $(this).text("Hide source"); + }, + function() { + $(this).parent().nextAll('.source_code').slideUp(100); + $(this).text("View source"); + }); +} + +function createDefineLinks() { + var tHeight = 0; + $('.defines').after(" more..."); + $('.toggleDefines').toggle(function() { + tHeight = $(this).parent().prev().height(); + $(this).prev().css('display', 'inline'); + $(this).parent().prev().height($(this).parent().height()); + $(this).text("(less)"); + }, + function() { + $(this).prev().hide(); + $(this).parent().prev().height(tHeight); + $(this).text("more..."); + }); +} + +function createFullTreeLinks() { + var tHeight = 0; + $('.inheritanceTree').toggle(function() { + tHeight = $(this).parent().prev().height(); + $(this).parent().toggleClass('showAll'); + $(this).text("(hide)"); + $(this).parent().prev().height($(this).parent().height()); + }, + function() { + $(this).parent().toggleClass('showAll'); + $(this).parent().prev().height(tHeight); + $(this).text("show all"); + }); +} + +function searchFrameButtons() { + $('.full_list_link').click(function() { + toggleSearchFrame(this, $(this).attr('href')); + return false; + }); + window.addEventListener('message', function(e) { + if (e.data === 'navEscape') { + $('#nav').slideUp(100); + $('#search a').removeClass('active inactive'); + $(window).focus(); + } + }); + + $(window).resize(function() { + if ($('#search:visible').length === 0) { + $('#nav').removeAttr('style'); + $('#search a').removeClass('active inactive'); + $(window).focus(); + } + }); +} + +function toggleSearchFrame(id, link) { + var frame = $('#nav'); + $('#search a').removeClass('active').addClass('inactive'); + if (frame.attr('src') === link && frame.css('display') !== "none") { + frame.slideUp(100); + $('#search a').removeClass('active inactive'); + } + else { + $(id).addClass('active').removeClass('inactive'); + if (frame.attr('src') !== link) frame.attr('src', link); + frame.slideDown(100); + } +} + +function linkSummaries() { + $('.summary_signature').click(function() { + document.location = $(this).find('a').attr('href'); + }); +} + +function summaryToggle() { + $('.summary_toggle').click(function(e) { + e.preventDefault(); + localStorage.summaryCollapsed = $(this).text(); + $('.summary_toggle').each(function() { + $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); + var next = $(this).parent().parent().nextAll('ul.summary').first(); + if (next.hasClass('compact')) { + next.toggle(); + next.nextAll('ul.summary').first().toggle(); + } + else if (next.hasClass('summary')) { + var list = $('