Submit social housing lettings and sales data (CORE)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

293 lines
8.3 KiB

class Log < ApplicationRecord
include CollectionTimeHelper
self.abstract_class = true
belongs_to :owning_organisation, class_name: "Organisation", optional: true
belongs_to :created_by, class_name: "User", optional: true
belongs_to :updated_by, class_name: "User", optional: true
belongs_to :bulk_upload, optional: true
before_save :update_status!
STATUS = {
"not_started" => 0,
"in_progress" => 1,
"completed" => 2,
"pending" => 3,
"deleted" => 4,
}.freeze
enum status: STATUS
enum status_cache: STATUS, _prefix: true
CREATION_METHOD = {
"single log" => 1,
"bulk upload" => 2,
}.freeze
enum creation_method: CREATION_METHOD
scope :visible, -> { where(status: %w[not_started in_progress completed]) }
scope :exportable, -> { where(status: %w[not_started in_progress completed deleted]) }
scope :filter_by_status, ->(status, _user = nil) { where status: }
scope :filter_by_years, lambda { |years, _user = nil|
first_year = years.shift
query = filter_by_year(first_year)
years.each { |year| query = query.or(filter_by_year(year)) }
query.all
}
scope :filter_by_postcode, ->(postcode_full) { where("REPLACE(postcode_full, ' ', '') ILIKE ?", "%#{postcode_full.delete(' ')}%") }
scope :filter_by_id, ->(id) { where(id:) }
scope :filter_by_user, lambda { |selected_user, user|
if !selected_user.include?("all") && user.present?
where(created_by: user)
end
}
scope :filter_by_bulk_upload_id, lambda { |bulk_upload_id, user|
joins(:bulk_upload)
.where(bulk_upload: { id: bulk_upload_id, user: })
}
scope :created_by, ->(user) { where(created_by: user) }
attr_accessor :skip_update_status, :skip_update_uprn_confirmed
def process_uprn_change!
if uprn.present?
service = UprnClient.new(uprn)
service.call
return errors.add(:uprn, :uprn_error, message: service.error) if service.error.present?
presenter = UprnDataPresenter.new(service.result)
self.uprn_known = 1
self.uprn_confirmed = nil unless skip_update_uprn_confirmed
self.address_line1 = presenter.address_line1
self.address_line2 = presenter.address_line2
self.town_or_city = presenter.town_or_city
self.postcode_full = presenter.postcode
self.county = nil
process_postcode_changes!
end
end
def collection_start_year
return @start_year if @start_year
return unless startdate
window_end_date = Time.zone.local(startdate.year, 4, 1)
@start_year = startdate < window_end_date ? startdate.year - 1 : startdate.year
end
def recalculate_start_year!
@start_year = nil
collection_start_year
end
def lettings?
false
end
def sales?
false
end
def ethnic_refused?
ethnic_group == 17
end
def collection_period_open?
return false if older_than_previous_collection_year?
form.new_logs_end_date > Time.zone.today
end
def collection_period_open_for_editing?
return false if older_than_previous_collection_year?
form.edit_end_date > Time.zone.today
end
def blank_invalid_non_setup_fields!
setup_ids = form.setup_sections.flat_map(&:subsections).flat_map(&:questions).map(&:id)
2.times do
next if valid?
errors.each do |error|
next if setup_ids.include?(error.attribute.to_s)
question = form.questions.find { |q| q.id == error.attribute.to_s }
if question&.type == "checkbox"
question.answer_keys_without_dividers.each { |attribute| public_send("#{attribute}=", nil) }
else
public_send("#{error.attribute}=", nil)
end
end
blank_compound_invalid_non_setup_fields!
errors.clear
end
end
(1..8).each do |person_num|
define_method("retirement_age_for_person_#{person_num}") do
retirement_age_for_person(person_num)
end
define_method("plural_gender_for_person_#{person_num}") do
plural_gender_for_person(person_num)
end
end
(2..8).each do |person_num|
define_method("person_#{person_num}_child_relation?") do
send("relat#{person_num}") == "C"
end
end
def discard!
update!(status: "deleted", discarded_at: Time.zone.now)
end
def calculate_status
return "deleted" if discarded_at.present?
if all_subsections_completed? && errors.empty?
"completed"
elsif all_subsections_unstarted?
"not_started"
else
"in_progress"
end
end
def field_formatted_as_currency(field_name)
field_value = public_send(field_name)
format_as_currency(field_value)
end
def blank_compound_invalid_non_setup_fields!
self.ppcodenk = nil if errors.attribute_names.include? :ppostcode_full
if errors.of_kind?(:uprn, :uprn_error)
self.uprn_known = nil
self.uprn_confirmed = nil
self.address_line1 = nil
self.address_line2 = nil
self.town_or_city = nil
self.postcode_full = nil
self.county = nil
process_postcode_changes!
end
end
def bulk_uploaded?
bulk_upload_id.present?
end
def collection_closed_for_editing?
form.edit_end_date < Time.zone.now || older_than_previous_collection_year?
end
private
# Handle logs that are older than previous collection start date
def older_than_previous_collection_year?
return false unless startdate
startdate < previous_collection_start_date
end
def plural_gender_for_person(person_num)
gender = public_send("sex#{person_num}".to_sym)
return unless gender
if %w[M X].include?(gender)
"male and non-binary people"
elsif gender == "F"
"females"
end
end
def update_status!
return if skip_update_status
self.status = calculate_status
end
def all_subsections_completed?
form.subsections.all? { |subsection| subsection.complete?(self) || subsection.not_displayed_in_tasklist?(self) }
end
def all_subsections_unstarted?
not_started_statuses = %i[not_started cannot_start_yet]
form.subsections.all? { |subsection| not_started_statuses.include? subsection.status(self) }
end
def reset_invalidated_dependent_fields!
return unless form
form.reset_not_routed_questions_and_invalid_answers(self)
reset_created_by!
end
PIO = PostcodeService.new
def process_previous_postcode_changes!
self.ppostcode_full = upcase_and_remove_whitespace(ppostcode_full)
process_postcode(ppostcode_full, "ppcodenk", "is_previous_la_inferred", "prevloc")
end
LA_CHANGES = {
"E07000027" => "E06000064", # Barrow-in-Furness => Westmorland and Furness
"E07000030" => "E06000064", # Eden => Westmorland and Furness
"E07000031" => "E06000064", # South Lakeland => Westmorland and Furness
"E07000026" => "E06000063", # Allerdale => Cumberland
"E07000028" => "E06000063", # Carlisle => Cumberland
"E07000029" => "E06000063", # Copeland => Cumberland
"E07000163" => "E06000065", # Craven => North Yorkshire
"E07000164" => "E06000065", # Hambleton => North Yorkshire
"E07000165" => "E06000065", # Harrogate => North Yorkshire
"E07000166" => "E06000065", # Richmondshire => North Yorkshire
"E07000167" => "E06000065", # Ryedale => North Yorkshire
"E07000168" => "E06000065", # Scarborough => North Yorkshire
"E07000169" => "E06000065", # Selby => North Yorkshire
"E07000187" => "E06000066", # Mendip => Somerset
"E07000188" => "E06000066", # Sedgemoor => Somerset
"E07000246" => "E06000066", # Somerset West and Taunton => Somerset
"E07000189" => "E06000066", # South Somerset => Somerset
}.freeze
def get_inferred_la(postcode)
result = PIO.lookup(postcode)
location_code = result[:location_code] if result
if LA_CHANGES.key?(location_code) && form.start_date.year >= 2023
LA_CHANGES[location_code]
elsif !(LA_CHANGES.value?(location_code) && form.start_date.year < 2023)
location_code
end
end
def upcase_and_remove_whitespace(string)
string.present? ? string.upcase.gsub(/\s+/, "") : string
end
def reset_location_fields!
reset_location(is_la_inferred, "la", "is_la_inferred", "postcode_full", 1)
end
def reset_previous_location_fields!
reset_location(is_previous_la_inferred, "prevloc", "is_previous_la_inferred", "ppostcode_full", previous_la_known)
end
def reset_location(is_inferred, la_key, is_inferred_key, postcode_key, is_la_known)
if is_inferred || is_la_known != 1
self[la_key] = nil
end
self[is_inferred_key] = false
self[postcode_key] = nil
end
end