module Imports
class LettingsLogsImportService < LogsImportService
def initialize ( storage_service , logger = Rails . logger , allow_updates : false )
@logs_with_discrepancies = Set . new
@logs_overridden = Set . new
super
end
def create_logs ( folder )
import_from ( folder , :create_log )
end
private
FORM_NAME_INDEX = {
start_year : 0 ,
rent_type : 2 ,
needs_type : 3 ,
} . freeze
GN_SH = {
general_needs : 1 ,
supported_housing : 2 ,
} . freeze
SR_AR_IR = {
social_rent : 1 ,
affordable_rent : 2 ,
intermediate_rent : 3 ,
} . freeze
# For providertype, values are reversed!!!
PRP_LA = {
private_registered_provider : 1 ,
local_authority : 2 ,
} . freeze
IRPRODUCT = {
rent_to_buy : 1 ,
london_living_rent : 2 ,
other_intermediate_rent_product : 3 ,
} . freeze
# These must match our form
RENT_TYPE = {
social_rent : 0 ,
affordable_rent : 1 ,
london_affordable_rent : 2 ,
rent_to_buy : 3 ,
london_living_rent : 4 ,
other_intermediate_rent_product : 5 ,
} . freeze
def create_log ( xml_doc )
return if meta_field_value ( xml_doc , " form-name " ) . include? ( " Sales " )
attributes = { }
previous_status = meta_field_value ( xml_doc , " status " )
# Required fields for status complete or logic to work
# Note: order matters when we derive from previous values (attributes parameter)
attributes [ " startdate " ] = compose_date ( xml_doc , " DAY " , " MONTH " , " YEAR " )
attributes [ " owning_organisation_id " ] = find_organisation_id ( xml_doc , " owner-institution-id " )
attributes [ " managing_organisation_id " ] = find_organisation_id ( xml_doc , " managing-institution-id " )
attributes [ " creation_method " ] = creation_method ( xml_doc )
attributes [ " joint " ] = unsafe_string_as_integer ( xml_doc , " joint " )
attributes [ " startertenancy " ] = unsafe_string_as_integer ( xml_doc , " _2a " )
attributes [ " tenancy " ] = unsafe_string_as_integer ( xml_doc , " Q2b " )
attributes [ " tenancycode " ] = string_or_nil ( xml_doc , " _2bTenCode " )
attributes [ " tenancyother " ] = string_or_nil ( xml_doc , " Q2ba " )
attributes [ " tenancylength " ] = safe_string_as_integer ( xml_doc , " _2cYears " )
attributes [ " needstype " ] = needs_type ( xml_doc )
attributes [ " lar " ] = london_affordable_rent ( xml_doc )
attributes [ " irproduct " ] = unsafe_string_as_integer ( xml_doc , " IRProduct " )
attributes [ " irproduct_other " ] = string_or_nil ( xml_doc , " IRProductOther " )
attributes [ " rent_type " ] = rent_type ( xml_doc , attributes [ " lar " ] , attributes [ " irproduct " ] )
attributes [ " hhmemb " ] = household_members ( xml_doc , previous_status )
people_indexes = people_with_details_ids ( xml_doc )
available_people_indexes = people_indexes + ( people_indexes . max + 1 .. 8 ) . to_a
( 1 .. 8 ) . each do | index |
person_index = available_people_indexes [ index - 1 ]
attributes [ " age #{ index } " ] = safe_string_as_integer ( xml_doc , " P #{ person_index } Age " )
attributes [ " age #{ index } _known " ] = age_known ( xml_doc , index , person_index , attributes [ " hhmemb " ] )
attributes [ " sex #{ index } " ] = sex ( xml_doc , person_index )
attributes [ " ecstat #{ index } " ] = unsafe_string_as_integer ( xml_doc , " P #{ person_index } Eco " )
end
( 2 .. 8 ) . each do | index |
person_index = available_people_indexes [ index - 1 ]
attributes [ " relat #{ index } " ] = relat ( xml_doc , person_index )
attributes [ " details_known_ #{ index } " ] = details_known ( index , attributes )
# Trips validation
if attributes [ " age #{ index } " ] . present? && attributes [ " age #{ index } " ] < 16 && attributes [ " relat #{ index } " ] . present? && attributes [ " relat #{ index } " ] != " C " && attributes [ " relat #{ index } " ] != " R "
attributes [ " age #{ index } " ] = nil
attributes [ " relat #{ index } " ] = nil
end
end
attributes [ " ethnic " ] = unsafe_string_as_integer ( xml_doc , " P1Eth " )
attributes [ " ethnic_group " ] = ethnic_group ( attributes [ " ethnic " ] )
attributes [ " national " ] = unsafe_string_as_integer ( xml_doc , " P1Nat " )
attributes [ " preg_occ " ] = unsafe_string_as_integer ( xml_doc , " Preg " )
attributes [ " armedforces " ] = unsafe_string_as_integer ( xml_doc , " ArmedF " )
attributes [ " leftreg " ] = unsafe_string_as_integer ( xml_doc , " LeftAF " )
attributes [ " reservist " ] = unsafe_string_as_integer ( xml_doc , " Inj " )
attributes [ " hb " ] = unsafe_string_as_integer ( xml_doc , " Q6Ben " )
attributes [ " benefits " ] = unsafe_string_as_integer ( xml_doc , " Q7Ben " )
attributes [ " earnings " ] = safe_string_as_decimal ( xml_doc , " Q8Money " ) & . round
attributes [ " net_income_known " ] = net_income_known ( xml_doc , attributes [ " earnings " ] )
attributes [ " incfreq " ] = unsafe_string_as_integer ( xml_doc , " Q8a " )
attributes [ " reason " ] = unsafe_string_as_integer ( xml_doc , " Q9a " )
attributes [ " reasonother " ] = string_or_nil ( xml_doc , " Q9aa " )
attributes [ " underoccupation_benefitcap " ] = unsafe_string_as_integer ( xml_doc , " _9b " )
%w[ a b c f g h ] . each do | letter |
attributes [ " housingneeds_ #{ letter } " ] = housing_needs ( xml_doc , letter )
end
attributes [ " housingneeds " ] = 1 if [ attributes [ " housingneeds_a " ] , attributes [ " housingneeds_b " ] , attributes [ " housingneeds_c " ] , attributes [ " housingneeds_f " ] ] . any? { | housingneed | housingneed == 1 }
attributes [ " housingneeds " ] = 2 if attributes [ " housingneeds_g " ] == 1
attributes [ " housingneeds " ] = 3 if attributes [ " housingneeds_h " ] == 1
attributes [ " housingneeds_type " ] = 0 if attributes [ " housingneeds_a " ] == 1
attributes [ " housingneeds_type " ] = 1 if attributes [ " housingneeds_b " ] == 1
attributes [ " housingneeds_type " ] = 2 if attributes [ " housingneeds_c " ] == 1
attributes [ " housingneeds_type " ] = 3 if attributes [ " housingneeds_f " ] == 1 && [ attributes [ " housingneeds_a " ] , attributes [ " housingneeds_b " ] , attributes [ " housingneeds_c " ] ] . all? { | housingneed | housingneed != 1 }
attributes [ " housingneeds_other " ] = attributes [ " housingneeds_f " ] == 1 ? 1 : 0
attributes [ " illness " ] = unsafe_string_as_integer ( xml_doc , " Q10ia " )
( 1 .. 10 ) . each do | index |
attributes [ " illness_type_ #{ index } " ] = illness_type ( xml_doc , index , attributes [ " illness " ] )
end
attributes [ " prevten " ] = unsafe_string_as_integer ( xml_doc , " Q11 " )
attributes [ " prevloc " ] = string_or_nil ( xml_doc , " Q12aONS " )
attributes [ " ppostcode_full " ] = compose_postcode ( xml_doc , " PPOSTC1 " , " PPOSTC2 " )
attributes [ " ppcodenk " ] = previous_postcode_known ( xml_doc , attributes [ " ppostcode_full " ] , attributes [ " prevloc " ] )
attributes [ " layear " ] = unsafe_string_as_integer ( xml_doc , " Q12c " )
attributes [ " waityear " ] = unsafe_string_as_integer ( xml_doc , " Q12d " )
attributes [ " homeless " ] = unsafe_string_as_integer ( xml_doc , " Q13 " )
attributes [ " reasonpref " ] = unsafe_string_as_integer ( xml_doc , " Q14a " )
attributes [ " rp_homeless " ] = unsafe_string_as_integer ( xml_doc , " Q14b1 " ) . present? ? 1 : nil
attributes [ " rp_insan_unsat " ] = unsafe_string_as_integer ( xml_doc , " Q14b2 " ) . present? ? 1 : nil
attributes [ " rp_medwel " ] = unsafe_string_as_integer ( xml_doc , " Q14b3 " ) . present? ? 1 : nil
attributes [ " rp_hardship " ] = unsafe_string_as_integer ( xml_doc , " Q14b4 " ) . present? ? 1 : nil
attributes [ " rp_dontknow " ] = unsafe_string_as_integer ( xml_doc , " Q14b5 " ) . present? ? 1 : nil
attributes [ " cbl " ] = allocation_system ( unsafe_string_as_integer ( xml_doc , " Q15CBL " ) )
attributes [ " chr " ] = allocation_system ( unsafe_string_as_integer ( xml_doc , " Q15CHR " ) )
attributes [ " cap " ] = allocation_system ( unsafe_string_as_integer ( xml_doc , " Q15CAP " ) )
attributes [ " letting_allocation_unknown " ] = allocation_system_unknown ( attributes [ " cbl " ] , attributes [ " chr " ] , attributes [ " cap " ] )
attributes [ " referral " ] = unsafe_string_as_integer ( xml_doc , " Q16 " )
attributes [ " period " ] = unsafe_string_as_integer ( xml_doc , " Q17 " )
attributes [ " brent " ] = safe_string_as_decimal ( xml_doc , " Q18ai " )
attributes [ " scharge " ] = safe_string_as_decimal ( xml_doc , " Q18aii " )
attributes [ " pscharge " ] = safe_string_as_decimal ( xml_doc , " Q18aiii " )
attributes [ " supcharg " ] = safe_string_as_decimal ( xml_doc , " Q18aiv " )
attributes [ " tcharge " ] = safe_string_as_decimal ( xml_doc , " Q18av " )
attributes [ " hbrentshortfall " ] = unsafe_string_as_integer ( xml_doc , " Q18d " )
attributes [ " tshortfall " ] = safe_string_as_decimal ( xml_doc , " Q18dyes " )
attributes [ " tshortfall_known " ] = tshortfall_known? ( xml_doc , attributes )
attributes [ " voiddate " ] = compose_date ( xml_doc , " VDAY " , " VMONTH " , " VYEAR " )
attributes [ " mrcdate " ] = compose_date ( xml_doc , " MRCDAY " , " MRCMONTH " , " MRCYEAR " )
attributes [ " majorrepairs " ] = if attributes [ " mrcdate " ] . present? && previous_status . include? ( " submitted " )
1
elsif previous_status . include? ( " submitted " )
0
end
attributes [ " offered " ] = safe_string_as_decimal ( xml_doc , " Q20 " )
attributes [ " propcode " ] = string_or_nil ( xml_doc , " Q21a " )
attributes [ " beds " ] = safe_string_as_integer ( xml_doc , " Q22 " )
attributes [ " unittype_gn " ] = unsafe_string_as_integer ( xml_doc , " Q23 " )
attributes [ " builtype " ] = unsafe_string_as_integer ( xml_doc , " Q24 " )
attributes [ " wchair " ] = unsafe_string_as_integer ( xml_doc , " Q25 " )
attributes [ " unitletas " ] = unsafe_string_as_integer ( xml_doc , " Q26 " )
attributes [ " rsnvac " ] = unsafe_string_as_integer ( xml_doc , " Q27 " )
attributes [ " renewal " ] = renewal ( attributes [ " rsnvac " ] )
attributes [ " la " ] = string_or_nil ( xml_doc , " Q28ONS " )
attributes [ " postcode_full " ] = compose_postcode ( xml_doc , " POSTCODE " , " POSTCOD2 " )
attributes [ " postcode_known " ] = postcode_known ( attributes )
# Not specific to our form but required for consistency (present in import)
attributes [ " old_form_id " ] = safe_string_as_integer ( xml_doc , " FORM " )
attributes [ " created_at " ] = Time . zone . parse ( meta_field_value ( xml_doc , " created-date " ) )
attributes [ " updated_at " ] = Time . zone . parse ( meta_field_value ( xml_doc , " modified-date " ) )
attributes [ " old_id " ] = meta_field_value ( xml_doc , " document-id " )
# Required for our form invalidated questions (not present in import)
attributes [ " previous_la_known " ] = attributes [ " prevloc " ] . nil? ? 0 : 1
attributes [ " is_la_inferred " ] = attributes [ " postcode_full " ] . present?
attributes [ " first_time_property_let_as_social_housing " ] = first_time_let ( attributes [ " rsnvac " ] )
attributes [ " declaration " ] = declaration ( xml_doc )
attributes [ " address_line1 " ] = string_or_nil ( xml_doc , " AddressLine1 " )
attributes [ " address_line2 " ] = string_or_nil ( xml_doc , " AddressLine2 " )
attributes [ " town_or_city " ] = string_or_nil ( xml_doc , " TownCity " )
attributes [ " county " ] = string_or_nil ( xml_doc , " County " )
attributes [ " uprn " ] = address_given? ( attributes ) ? nil : string_or_nil ( xml_doc , " UPRN " )
attributes [ " uprn_known " ] = attributes [ " uprn " ] . present? ? 1 : 0
attributes [ " uprn_confirmed " ] = attributes [ " uprn " ] . present? ? 1 : 0
set_partial_charges_to_zero ( attributes )
# Supported Housing fields
if attributes [ " needstype " ] == GN_SH [ :supported_housing ]
location_old_visible_id = string_or_nil ( xml_doc , " _1cschemecode " )
scheme_old_visible_id = string_or_nil ( xml_doc , " _1cmangroupcode " )
schemes = Scheme . where ( old_visible_id : scheme_old_visible_id , owning_organisation_id : attributes [ " owning_organisation_id " ] )
location = Location . find_by ( old_visible_id : location_old_visible_id , scheme : schemes )
if location . present?
# Set the scheme via location, because the scheme old visible ID can be duplicated at import
attributes [ " location_id " ] = location . id
attributes [ " scheme_id " ] = location . scheme . id
attributes [ " sheltered " ] = unsafe_string_as_integer ( xml_doc , " Q1e " )
attributes [ " chcharge " ] = safe_string_as_decimal ( xml_doc , " Q18b " )
attributes [ " household_charge " ] = household_charge ( xml_doc )
attributes [ " is_carehome " ] = is_carehome ( location . scheme )
end
end
# Handles confidential schemes
if attributes [ " postcode_full " ] == " ****** "
attributes [ " postcode_known " ] = 0
attributes [ " postcode_full " ] = nil
end
# Soft validations can become required answers, set them to yes by default
attributes [ " pregnancy_value_check " ] = 0
attributes [ " major_repairs_date_value_check " ] = 0
attributes [ " void_date_value_check " ] = 0
attributes [ " retirement_value_check " ] = 0
attributes [ " rent_value_check " ] = 0
attributes [ " net_income_value_check " ] = 0
attributes [ " carehome_charges_value_check " ] = 0
attributes [ " referral_value_check " ] = 0
attributes [ " scharge_value_check " ] = 0
attributes [ " pscharge_value_check " ] = 0
attributes [ " supcharg_value_check " ] = 0
# Sets the log creator
owner_id = meta_field_value ( xml_doc , " owner-user-id " ) . strip
if owner_id . present?
user = LegacyUser . find_by ( old_user_id : owner_id ) & . user
if user . blank? || ( user . organisation_id != attributes [ " managing_organisation_id " ] && user . organisation_id != attributes [ " owning_organisation_id " ] )
if user . blank?
@logger . error ( " Lettings log ' #{ attributes [ 'old_id' ] } ' belongs to legacy user with owner-user-id: ' #{ owner_id } ' which cannot be found. Assigning log to 'Unassigned' user. " )
else
@logger . error ( " Lettings log ' #{ attributes [ 'old_id' ] } ' belongs to legacy user with owner-user-id: ' #{ owner_id } ' which belongs to a different organisation. Assigning log to 'Unassigned' user. " )
end
if User . find_by ( name : " Unassigned " , organisation_id : attributes [ " managing_organisation_id " ] )
user = User . find_by ( name : " Unassigned " , organisation_id : attributes [ " managing_organisation_id " ] )
else
user = User . new (
name : " Unassigned " ,
organisation_id : attributes [ " managing_organisation_id " ] ,
is_dpo : false ,
encrypted_password : SecureRandom . hex ( 10 ) ,
email : SecureRandom . uuid ,
confirmed_at : Time . zone . now ,
active : false ,
)
user . save! ( validate : false )
end
end
attributes [ " created_by " ] = user
end
attributes [ " values_updated_at " ] = Time . zone . now
apply_date_consistency! ( attributes )
apply_household_consistency! ( attributes )
create_organisation_relationship! ( attributes )
lettings_log = save_lettings_log ( attributes , previous_status )
compute_differences ( lettings_log , attributes )
check_status_completed ( lettings_log , previous_status ) unless @logs_overridden . include? ( lettings_log . old_id )
end
def save_lettings_log ( attributes , previous_status )
lettings_log = LettingsLog . new ( attributes )
begin
lettings_log . save!
lettings_log
rescue ActiveRecord :: RecordNotUnique
legacy_id = attributes [ " old_id " ]
record = LettingsLog . find_by ( old_id : legacy_id )
if allow_updates
attributes [ " updated_at " ] = Time . zone . now
record . update! ( attributes )
end
record
rescue ActiveRecord :: RecordInvalid = > e
rescue_validation_or_raise ( lettings_log , attributes , previous_status , e )
end
end
def rescue_validation_or_raise ( lettings_log , attributes , previous_status , exception )
charges_attributes = %w[ brent scharge pscharge supcharg tcharge ]
# Blank out all invalid fields for in-progress logs
if %w[ saved submitted-invalid ] . include? ( previous_status )
lettings_log . errors . each do | error |
attributes . delete ( error . attribute . to_s )
charges_attributes . each { | attribute | attributes . delete ( attribute ) } if error . attribute == :tcharge
end
@logs_overridden << lettings_log . old_id
return save_lettings_log ( attributes , previous_status )
end
errors = {
% i [ chcharge out_of_range ] = > %w[ chcharge ] ,
% i [ referral internal_transfer_non_social_housing ] = > %w[ referral ] ,
% i [ referral internal_transfer_fixed_or_lifetime ] = > %w[ referral ] ,
% i [ tenancylength tenancylength_invalid ] = > %w[ tenancylength ] ,
% i [ prevten over_25_foster_care ] = > %w[ prevten age1 ] ,
% i [ prevten non_temp_accommodation ] = > %w[ prevten rsnvac ] ,
% i [ joint not_joint_tenancy ] = > %w[ joint ] ,
% i [ offered outside_the_range ] = > %w[ offered ] ,
% i [ offered not_integer ] = > %w[ offered ] ,
% i [ earnings over_hard_max ] = > %w[ ecstat1 ] ,
% i [ tshortfall no_outstanding_charges ] = > %w[ tshortfall hbrentshortfall ] ,
% i [ beds outside_the_range ] = > %w[ beds ] ,
% i [ tcharge complete_1_of_3 ] = > charges_attributes ,
% i [ scharge under_min ] = > charges_attributes ,
% i [ tshortfall must_be_positive ] = > %w[ tshortfall tshortfall_known ] ,
% i [ referral referral_invalid ] = > %w[ referral ] ,
% i [ pscharge outside_the_range ] = > charges_attributes ,
% i [ supcharg outside_the_range ] = > charges_attributes ,
% i [ scharge outside_the_range ] = > charges_attributes ,
% i [ location_id not_active ] = > %w[ location_id scheme_id ] ,
% i [ tcharge under_10 ] = > charges_attributes ,
% i [ brent over_hard_max ] = > charges_attributes ,
% i [ brent below_hard_min ] = > charges_attributes ,
% i [ period wrong_rent_period ] = > %w[ period ] ,
% i [ layear renewal_just_moved ] = > %w[ layear ] ,
% i [ voiddate after_mrcdate ] = > %w[ voiddate mrcdate majorrepairs ] ,
% i [ tshortfall more_than_rent ] = > %w[ tshortfall tshortfall_known ] ,
% i [ scheme_id no_completed_locations ] = > %w[ scheme_id location_id ] ,
% i [ location_id incomplete ] = > %w[ scheme_id location_id ] ,
% i [ beds one_three_bedroom_single_tenant_shared ] = > %w[ beds ] ,
}
( 2 .. 8 ) . each do | person |
errors [ [ :" age #{ person } " , :outside_the_range ] ] = [ " age #{ person } " , " age #{ person } _known " ]
end
errors . each do | ( error , fields ) |
next unless lettings_log . errors . of_kind? ( * error )
fields . each do | field |
attributes . delete ( field )
end
@logs_overridden << lettings_log . old_id
return save_lettings_log ( attributes , previous_status )
end
if lettings_log . errors . of_kind? ( :earnings , :under_hard_min )
@logs_overridden << lettings_log . old_id
attributes . delete ( " earnings " )
attributes . delete ( " incfreq " )
attributes [ " incref " ] = 1
attributes [ " net_income_known " ] = 2
return save_lettings_log ( attributes , previous_status )
end
if lettings_log . errors . of_kind? ( :uprn , :uprn_error )
@logs_overridden << lettings_log . old_id
attributes [ " uprn_known " ] = 0
return save_lettings_log ( attributes , previous_status )
end
@logger . error ( " Log #{ lettings_log . old_id } : Failed to import " )
lettings_log . errors . each do | error |
@logger . error ( " Validation error: Field #{ error . attribute } : " )
@logger . error ( " \t Owning Organisation: #{ lettings_log . owning_organisation & . name } " )
@logger . error ( " \t Managing Organisation: #{ lettings_log . managing_organisation & . name } " )
@logger . error ( " \t Old CORE ID: #{ lettings_log . old_id } " )
@logger . error ( " \t Old CORE: #{ attributes [ error . attribute . to_s ] & . inspect } " )
@logger . error ( " \t New CORE: #{ lettings_log . read_attribute ( error . attribute ) & . inspect } " )
@logger . error ( " \t Error message: #{ error . type } " )
end
raise exception
end
def compute_differences ( lettings_log , attributes )
differences = [ ]
attributes . each do | key , value |
lettings_log_value = lettings_log . send ( key . to_sym )
next if fields_not_present_in_softwire_data . include? ( key )
if value != lettings_log_value
differences . push ( " #{ key } #{ value . inspect } #{ lettings_log_value . inspect } " )
end
end
end
def fields_not_present_in_softwire_data
%w[ majorrepairs illness_type_0 tshortfall_known pregnancy_value_check retirement_value_check rent_value_check net_income_value_check major_repairs_date_value_check void_date_value_check carehome_charges_value_check referral_value_check scharge_value_check pscharge_value_check supcharg_value_check housingneeds_type housingneeds_other created_by uprn_known uprn_confirmed ]
end
def check_status_completed ( lettings_log , previous_status )
if previous_status . include? ( " submitted " ) && lettings_log . status != " completed "
@logs_with_discrepancies << lettings_log . old_id
end
end
def get_form_name_component ( xml_doc , index )
form_name = meta_field_value ( xml_doc , " form-name " )
form_type_components = form_name . split ( " - " )
form_type_components [ index ]
end
def needs_type ( xml_doc )
gn_sh = get_form_name_component ( xml_doc , FORM_NAME_INDEX [ :needs_type ] )
case gn_sh
when " GN "
GN_SH [ :general_needs ]
when " SH "
GN_SH [ :supported_housing ]
else
raise " Unknown needstype value: #{ gn_sh } "
end
end
# This does not match renttype (CDS) which is derived by lettings log logic
def rent_type ( xml_doc , lar , irproduct )
sr_ar_ir = get_form_name_component ( xml_doc , FORM_NAME_INDEX [ :rent_type ] )
case sr_ar_ir
when " SR "
RENT_TYPE [ :social_rent ]
when " AR "
if lar == 1
RENT_TYPE [ :london_affordable_rent ]
else
RENT_TYPE [ :affordable_rent ]
end
when " IR "
if irproduct == IRPRODUCT [ :rent_to_buy ]
RENT_TYPE [ :rent_to_buy ]
elsif irproduct == IRPRODUCT [ :london_living_rent ]
RENT_TYPE [ :london_living_rent ]
elsif irproduct == IRPRODUCT [ :other_intermediate_rent_product ]
RENT_TYPE [ :other_intermediate_rent_product ]
end
else
raise " Could not infer rent type with ' #{ sr_ar_ir } ' "
end
end
def age_known ( xml_doc , index , person_index , hhmemb )
return nil if hhmemb . present? && index > hhmemb
age_refused = string_or_nil ( xml_doc , " P #{ person_index } AR " )
if age_refused . present?
if age_refused . casecmp? ( " AGE_REFUSED " ) || age_refused . casecmp? ( " No " )
return 1 # No
else
return 0 # Yes
end
end
0
end
def details_known ( index , attributes )
return nil if attributes [ " hhmemb " ] . nil? || index > attributes [ " hhmemb " ]
if attributes [ " age #{ index } _known " ] == 1 &&
attributes [ " sex #{ index } " ] == " R " &&
attributes [ " relat #{ index } " ] == " R " &&
attributes [ " ecstat #{ index } " ] == 10
1 # No
else
0 # Yes
end
end
def previous_postcode_known ( xml_doc , previous_postcode , prevloc )
previous_postcode_known = string_or_nil ( xml_doc , " Q12bnot " )
if previous_postcode_known == " Temporary_or_Unknown " || ( previous_postcode . nil? && prevloc . present? )
1 # not known
elsif previous_postcode . nil?
nil
else
0 # known
end
end
def london_affordable_rent ( xml_doc )
lar = unsafe_string_as_integer ( xml_doc , " LAR " )
if lar == 1
1
else
# We default to No for any other values (nil, not known)
2
end
end
def renewal ( rsnvac )
# Relet – renewal of fixed-term tenancy
if rsnvac == 14
1
else
0
end
end
# Letters should be lowercase to match case
def housing_needs ( xml_doc , letter )
housing_need = string_or_nil ( xml_doc , " Q10- #{ letter } " )
if housing_need == " Yes "
1
else
0
end
end
def net_income_known ( xml_doc , earnings )
incref = string_or_nil ( xml_doc , " Q8Refused " )
if incref == " Refused "
# Tenant prefers not to say
2
elsif earnings . nil?
# No
1
else
# Yes
0
end
end
def illness_type ( xml_doc , index , illness )
illness_type = string_or_nil ( xml_doc , " Q10ib- #{ index } " )
if illness_type == " Yes " && illness == 1
1
elsif illness == 1
0
end
end
def first_time_let ( rsnvac )
if [ 15 , 16 , 17 ] . include? ( rsnvac )
1
else
0
end
end
def declaration ( xml_doc )
declaration = string_or_nil ( xml_doc , " Qdp " )
if declaration == " Yes "
1
end
end
def postcode_known ( attributes )
if attributes [ " postcode_full " ] . nil? && attributes [ " la " ] . nil?
nil
elsif attributes [ " postcode_full " ] . nil?
0 # Assumes we selected No in the form since the LA is present
else
1
end
end
def household_members ( xml_doc , previous_status )
hhmemb = safe_string_as_integer ( xml_doc , " HHMEMB " )
if previous_status . include? ( " submitted " ) && hhmemb . nil?
hhmemb = people_with_details ( xml_doc ) . count
return nil if hhmemb . zero?
end
hhmemb
end
def people_with_details ( xml_doc )
( ( 2 .. 8 ) . map { | x | string_or_nil ( xml_doc , " P #{ x } Rel " ) } + [ string_or_nil ( xml_doc , " P1Sex " ) ] ) . compact
end
def people_with_details_ids ( xml_doc )
[ 1 ] + ( 2 .. 8 ) . select do | x |
string_or_nil ( xml_doc , " P #{ x } Rel " ) . present? ||
string_or_nil ( xml_doc , " P #{ x } Sex " ) . present? ||
string_or_nil ( xml_doc , " P #{ x } Age " ) . present? ||
string_or_nil ( xml_doc , " P #{ x } Eco " ) . present?
end
end
def tshortfall_known? ( xml_doc , attributes )
if attributes [ " tshortfall " ] . blank? && attributes [ " hbrentshortfall " ] == 1 && overridden? ( xml_doc , " xmlns " , " Q18dyes " )
1
else
0
end
end
def allocation_system ( value )
case value
when 1
1
when 2
0
end
end
def allocation_system_unknown ( cbl , chr , cap )
allocation_values = [ cbl , chr , cap ]
if allocation_values . all? ( & :nil? )
nil
elsif allocation_values . all? { | att | att & . zero? }
1
else
0
end
end
def apply_date_consistency! ( attributes )
return if attributes [ " voiddate " ] . nil? || attributes [ " startdate " ] . nil?
if attributes [ " voiddate " ] > attributes [ " startdate " ]
attributes . delete ( " voiddate " )
end
end
def apply_household_consistency! ( attributes )
( 2 .. 8 ) . each do | index |
next if attributes [ " age #{ index } " ] . nil?
if attributes [ " age #{ index } " ] < 16 && attributes [ " relat #{ index } " ] == " R "
attributes [ " relat #{ index } " ] = " C "
end
end
end
def household_charge ( xml_doc )
value = string_or_nil ( xml_doc , " Q18c " )
start_year = Integer ( get_form_name_component ( xml_doc , FORM_NAME_INDEX [ :start_year ] ) )
if start_year < = 2021
# Yes means that there are no charges (2021 or earlier)
value && value . include? ( " Yes " ) ? 1 : 0
else
# Yes means that there are charges (2022 onwards)
value && value . include? ( " Yes " ) ? 0 : 1
end
end
def set_partial_charges_to_zero ( attributes )
unless attributes [ " brent " ] . nil? &&
attributes [ " scharge " ] . nil? &&
attributes [ " pscharge " ] . nil? &&
attributes [ " supcharg " ] . nil?
attributes [ " brent " ] || = BigDecimal ( " 0.0 " )
attributes [ " scharge " ] || = BigDecimal ( " 0.0 " )
attributes [ " pscharge " ] || = BigDecimal ( " 0.0 " )
attributes [ " supcharg " ] || = BigDecimal ( " 0.0 " )
end
end
def is_carehome ( scheme )
return nil unless scheme
if [ 2 , 3 , 4 ] . include? ( scheme . registered_under_care_act_before_type_cast )
1
else
0
end
end
def create_organisation_relationship! ( attributes )
parent_organisation_id = attributes [ " owning_organisation_id " ]
child_organisation_id = attributes [ " managing_organisation_id " ]
return if parent_organisation_id == child_organisation_id
OrganisationRelationship . find_or_create_by! ( parent_organisation_id : , child_organisation_id : )
end
def address_given? ( attributes )
attributes [ " address_line1 " ] . present? && attributes [ " town_or_city " ] . present?
end
end
end