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.
289 lines
8.2 KiB
289 lines
8.2 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 |
|
|
|
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
|
|
|