Class: LocatorRecord

Inherits:
ApplicationRecord show all
Extended by:
FriendlyId
Includes:
Models::Auditable, Models::LiquidMethods, Models::Taggable
Defined in:
app/models/locator_record.rb

Overview

== Schema Information

Table name: locator_records
Database name: primary

id :integer not null, primary key
confirmed_at :datetime
date_of_wy_visit :datetime
date_wyu_last_passed :datetime
has_countertop_display :boolean
has_had_wy_visit :boolean
has_in_floor_display :boolean
has_in_house_service_team :boolean
has_marketing_materials :boolean
has_passed_wyu :boolean
is_electrician :boolean
is_inactive :boolean default(FALSE), not null
is_installer :boolean
is_remodel_contractor :boolean
is_retailer :boolean
is_wy_certified :boolean
jobs_a_year :string
last_confirmed_at :datetime
maintains_wy_stock :boolean
preferred_dealer :boolean
profile_ids :text
slug :string
star_status_level :integer
state :string(255)
supports_comfort_products :boolean
supports_flooring :boolean
supports_roof_deicing :boolean
supports_snowmelting :boolean
created_at :datetime
updated_at :datetime
address_id :integer
customer_id :integer

Indexes

idx_state (state)
index_locator_records_confirmed_at (confirmed_at)
index_locator_records_customer_id (customer_id)
index_locator_records_on_address_id (address_id)
index_locator_records_on_slug (slug)
index_locator_records_on_supports_roof_deicing (supports_roof_deicing)

Constant Summary collapse

STAR_STATUS_LEVELS =

Star status levels.

%w[0 1 2 3 4 5].freeze
JOBS_A_YEAR =

Jobs a year.

%w[1-5 5-10 10-50 50+].freeze

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Constants included from Schedulable

Schedulable::SIMPLE_FORM_OPTIONS

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

Has many collapse

Methods included from Models::Taggable

#tag_records, #taggings

Delegated Instance Attributes collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Models::Taggable

#add_tag, all_tags, #has_tag?, normalize_tag_names, not_tagged_with, #remove_tag, #tag_list, #tag_list=, #taggable_type_for_tagging, tagged_with, #tags, #tags=, tags_cloud, tags_exclude, tags_include, with_all_tags, with_any_tags, without_all_tags, without_any_tags

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Schedulable

config

Methods included from Models::AfterCommittable

#after_commit

Methods included from Models::EventPublishable

#publish_event

Class Method Details

.activeActiveRecord::Relation<LocatorRecord>

A relation of LocatorRecords that are active. Active Record Scope

Returns:

See Also:



72
# File 'app/models/locator_record.rb', line 72

scope :active, -> { where(is_inactive: false) }

.are_confirmedActiveRecord::Relation<LocatorRecord>

A relation of LocatorRecords that are are confirmed. Active Record Scope

Returns:

See Also:



73
# File 'app/models/locator_record.rb', line 73

scope :are_confirmed, -> { where(state: 'confirmed') }

.filter_optionsObject



119
120
121
122
123
124
125
126
127
128
129
130
# File 'app/models/locator_record.rb', line 119

def self.filter_options
  { 'Supports Comfort Products' => 'supports_comfort_products' }
  # { "Retailer" => "is_retailer",
  #   "Installer" => "is_installer",
  #   "Electrician" => "is_electrician",
  #   "Remodeling Contractor" => "is_remodel_contractor",
  #   "Supports Floor Heating" => "supports_flooring",
  #   "Supports Snow Melting" => "supports_snowmelting",
  #   "Supports Roof & Gutter Deicing" => "supports_roof_deicing",
  #   "Supports Comfort Products" => "supports_comfort_products",
  #   "Preferred Stocking Kit Dealer" => "preferred_dealer" }
end

.near_coordinatesActiveRecord::Relation<LocatorRecord>

A relation of LocatorRecords that are near coordinates. Active Record Scope

Returns:

See Also:



74
75
76
77
78
79
80
# File 'app/models/locator_record.rb', line 74

scope :near_coordinates, ->(coordinates, distance) {
  are_confirmed
    .active
    .joins(:address, :customer)
    .merge(Address.near(coordinates, distance))
    .select('locator_records.*')
}

.notify_non_qualifying_dealersObject



382
383
384
385
386
387
388
389
390
391
392
# File 'app/models/locator_record.rb', line 382

def self.notify_non_qualifying_dealers
  customers_to_delete = Customer.locator_expired.joins(locator_record: :contact_points)
                                .where(LocatorRecord[:state].eq('confirmed'))
                                .where(ContactPoint[:category].eq('email'))
  customers_to_delete.find_each(batch_size: 100) do |c|
    c.locator_record.send_dealer_deletion_notice
  end
  return if customers_to_delete.empty?

  InternalReportsMailer.dealer_locator_communication_report(customers_to_delete.map(&:locator_record), 'Dealers Set to Delete - First notice').deliver
end

.process_task(task_name, task_condition, task_include_associations, task_method, trial_run = false, logger = nil, _stop_hours = 3, batch = 100) ⇒ Object



557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
# File 'app/models/locator_record.rb', line 557

def self.process_task(task_name, task_condition, task_include_associations, task_method, trial_run = false, logger = nil, _stop_hours = 3, batch = 100)
  # Process a task on all locator records that meet the conditions, work for stop_hours, it will resume the next time the task is run
  logger ||= Rails.logger
  logger.info "* #{task_name} started #{Time.current}"
  logger.info '* TRIAL RUN MODE ' if trial_run
  logger.info "** Dealer Locator Records, finding all locator_records that meet criteria: #{task_condition}"
  locator_record_counter = 0
  locator_record_processed_counter = 0
  Time.current
  locator_record_ids_with_errors = []
  locator_records = LocatorRecord.where(task_condition).includes(task_include_associations).references(task_include_associations)
  locator_records.find_each(batch_size: batch) do |l|
    locator_record_counter += 1
    processed = l.send(task_method, trial_run)
    if processed[:status_code] == :ok
      locator_record_processed_counter += 1
      logger.info  "*** Locator record #{l.customer.name} #{l.id} completed, status message #{processed[:status_message]}"
    else
      logger.error "!!! Locator record #{l.customer.name} #{l.id} failed to process  with #{task_method}, status message was #{processed[:status_message]}"
      locator_record_ids_with_errors << [l.id, l.customer.try(:name), processed[:status_code], processed[:status_message]]
    end
  end
  # Send email to Elodie
  InternalReportsMailer.dealer_locator_communication_report(locator_records, task_name).deliver_later unless locator_records.empty?
  if @locator_record_ids_with_errors.present?
    ErrorReporting.error("*** #{task_name} Processed #{locator_record_processed_counter} and failed to process #{locator_record_ids_with_errors.size} records,  #{Time.current}. These are the locator record ids: #{locator_record_ids_with_errors}")
  end
  logger.info "*** #{task_name} Processed #{locator_record_processed_counter} and failed to process #{locator_record_ids_with_errors.size} records,  #{Time.current}"
  locator_record_ids_with_errors.each do |e|
    logger.error "**** Locator record error #{e.join(' ')}"
  end
end

.purge_invalid_locator_recordsObject



375
376
377
378
379
380
# File 'app/models/locator_record.rb', line 375

def self.purge_invalid_locator_records
  # LocatorRecord.joins(:customer => :profile).where(Profile[:locator_eligible].eq(false)).find_each do |lr|
  LocatorRecord.joins(:customer).where(Customer[:profile_id].eq(ProfileConstants::HOMEOWNER)).find_each do |lr|
    lr.remove_dealer_from_locator(false)
  end
end

.star_level_options_for_select(nil_option = true) ⇒ Object



147
148
149
150
151
# File 'app/models/locator_record.rb', line 147

def self.star_level_options_for_select(nil_option = true)
  base_options = []
  base_options = [[' ', nil]] if nil_option
  base_options.concat(STAR_STATUS_LEVELS.map { |rl| [rl.to_s, rl.to_i] })
end

.states_for_selectObject



143
144
145
# File 'app/models/locator_record.rb', line 143

def self.states_for_select
  state_machines[:state].states.map { |s| [s.human_name, s.value] }
end

Instance Method Details

#addressAddress

Returns:

See Also:

Validations:



59
# File 'app/models/locator_record.rb', line 59

belongs_to :address, inverse_of: :locator_record, optional: true

#blacklistObject



258
259
260
# File 'app/models/locator_record.rb', line 258

def blacklist
  update(is_inactive: true)
end

#capabilitiesObject



134
135
136
137
138
139
140
141
# File 'app/models/locator_record.rb', line 134

def capabilities
  res = []
  res << 'Supports Floor Heating' if supports_flooring?
  res << 'Supports Snow Melting' if supports_snowmelting?
  res << 'Supports Roof & Gutter Deicing' if supports_roof_deicing?
  res << 'Supports Comfort Products' if supports_comfort_products?
  res
end

#communicationsActiveRecord::Relation<Communication>

Returns:

See Also:



61
# File 'app/models/locator_record.rb', line 61

has_many :communications, -> { order(:id).reverse_order }, as: :resource, dependent: :nullify

#contact_pointsActiveRecord::Relation<ContactPoint>

Returns:

See Also:



60
# File 'app/models/locator_record.rb', line 60

has_many :contact_points, inverse_of: :locator_record


252
253
254
# File 'app/models/locator_record.rb', line 252

def crm_link
  UrlHelper.instance.customer_path(customer)
end

#customerCustomer

Returns:

See Also:



58
# File 'app/models/locator_record.rb', line 58

belongs_to :customer, inverse_of: :locator_record, optional: true

#dealer_confirmObject



270
271
272
273
274
275
276
277
278
279
280
281
# File 'app/models/locator_record.rb', line 270

def dealer_confirm
  self.last_confirmed_at = Time.current
  if confirmed_at
    save
    dealer_confirmed! unless state == 'confirmed'
  else
    # ensure that the confirmation date and state change to confirmed is set only once on the *initial* confirmation
    self.confirmed_at = Time.current
    save
    dealer_confirmed!
  end
end

#emailObject



184
185
186
187
188
# File 'app/models/locator_record.rb', line 184

def email
  contact_points.find { |cp| cp.category == 'email' }.detail
rescue StandardError
  nil
end

#email_idObject



178
179
180
181
182
# File 'app/models/locator_record.rb', line 178

def email_id
  contact_points.find { |cp| cp.category == 'email' }.id
rescue StandardError
  nil
end

#email_id=(cp_id) ⇒ Object



167
168
169
170
171
172
173
174
175
176
# File 'app/models/locator_record.rb', line 167

def email_id=(cp_id)
  current_cp = contact_points.find { |cp| cp.category == 'email' }
  contact_points.delete(current_cp) if current_cp
  return if cp_id.blank?

  cp = ContactPoint.find(cp_id)
  contact_points << cp
  # don't want duplicates say validation issue to block save
  # cp.save(:validate => false)
end

#faxObject



208
209
210
211
212
# File 'app/models/locator_record.rb', line 208

def fax
  contact_points.find { |cp| cp.category == 'fax' }.detail
rescue StandardError
  nil
end

#fax_idObject



202
203
204
205
206
# File 'app/models/locator_record.rb', line 202

def fax_id
  contact_points.find { |cp| cp.category == 'fax' }.id
rescue StandardError
  nil
end

#fax_id=(cp_id) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
# File 'app/models/locator_record.rb', line 190

def fax_id=(cp_id)
  current_cp = contact_points.find { |cp| cp.category == 'fax' }
  contact_points.delete(current_cp) if current_cp
  contact_points << ContactPoint.find(cp_id) if cp_id.present?
  return if cp_id.blank?

  cp = ContactPoint.find(cp_id)
  contact_points << cp
  # don't want duplicates (say) validation issue to block save
  # cp.save(:validate => false)
end

#first_nameObject

Alias for Customer#first_name

Returns:

  • (Object)

    Customer#first_name

See Also:



132
# File 'app/models/locator_record.rb', line 132

delegate :first_name, to: :customer

#generate_confirmation_form_urlObject

On Aprl 25th 2022 we decided to stop sending email notifications for dealers
def self.send_ongoing_dealer_locator_communications(trial_run = false, logger = nil, stop_hours = 3, batch = 100)

First purge invalids

purge_invalid_locator_records

Potential dealers that do qualify, inviting them to update/confirm their information so that they can be part of the new dealer database.

process_task('New Dealer Locator Invitations', "locator_records.state = 'not_invited' and locator_records.is_inactive IS NOT TRUE and contact_points.category = 'email'", [:contact_points], 'send_dealer_invite', trial_run, logger, stop_hours, batch)

Contact potential dealers who have been invited but have not confirmed after 30 days.

process_task('Invited Dealers 30 Day Reminder', "locator_records.state = 'invited' and locator_records.created_at < '#30.days.ago.to_fs(:db)' and locator_records.is_inactive IS NOT TRUE and contact_points.category = 'email'", [:contact_points], 'send_invited_dealers_30_day_reminder', trial_run, logger, stop_hours, batch)

Dealers that don't qualify anymore, sending them a notice so they can manually decide to remain in the delaer list

notify_non_qualifying_dealers

Dealers that were noticed for deletion and didn't confirm their stay, sending them a final notice so they can manually decide to remain in the delaer list

process_task('Deletion in 7 day Reminder', "locator_records.state = 'set_to_delete' and locator_records.updated_at < '#7.days.ago.to_fs(:db)' and contact_points.category = 'email'", [:contact_points], 'send_dealer_deletion_notice_7_day_reminder', trial_run, logger, stop_hours, batch)

Dealers that were noticed for deletion and didn't confirm their stay, deleting

process_task('Dealers Deleted', "locator_records.state = 'set_to_delete_remainded' and locator_records.updated_at < '#7.days.ago.to_fs(:db)' and contact_points.category = 'email'", [:contact_points], 'remove_dealer', trial_run, logger, stop_hours, batch)
end



410
411
412
# File 'app/models/locator_record.rb', line 410

def generate_confirmation_form_url
  LOCATOR_RECORD_FORM_BASE_URL + "?locator_record_id=#{CGI.escape(Encryption.encrypt_string(id.to_s))}"
end

#get_callable_cpObject



155
156
157
158
159
# File 'app/models/locator_record.rb', line 155

def get_callable_cp
  contact_points.voice_callable.first
rescue StandardError
  nil
end

#get_cp_by_category(cat) ⇒ Object



161
162
163
164
165
# File 'app/models/locator_record.rb', line 161

def get_cp_by_category(cat)
  contact_points.find { |cp| cp.category == cat }.detail
rescue StandardError
  nil
end


535
536
537
# File 'app/models/locator_record.rb', line 535

def map_link(label)
  "<a target = '_new' href='http://maps.google.com/maps?f=q&amp;source=embed&amp;hl=en&amp;geocode=&amp;q=#{address.street1}+#{address.street2}+#{address.street3}+#{address.city}+#{address.state_code}+#{address.zip}+#{address.country_iso3}&amp;sll=#{address.lat},#{address.lng}&amp;sspn=0.008969,0.021522&amp;ie=UTF8&amp;hq=&amp;hnear=#{address.street1}+#{address.street2}+#{address.street3}+#{address.city}+#{address.state_code}+#{address.zip}+#{address.country_iso3}&amp;z=16&amp;ll=#{address.lat},#{address.lng}'>#{label || 'View On Map'}</a>"
end

#must_be_an_organizationObject (protected)



547
548
549
550
551
# File 'app/models/locator_record.rb', line 547

def must_be_an_organization
  return unless customer&.is_homeowner?

  errors.add :base, "Homeowner can't be in dealer locator dealer must be an organization"
end

#nameObject

Alias for Customer#name

Returns:

  • (Object)

    Customer#name

See Also:



153
# File 'app/models/locator_record.rb', line 153

delegate :name, to: :customer

#not_blacklistedObject (protected)



541
542
543
544
545
# File 'app/models/locator_record.rb', line 541

def not_blacklisted
  return unless customer&.locator_black_listing && new_record?

  errors.add :base, "Dealer can't be in locator dealer is blacklisted"
end

#phoneObject



231
232
233
# File 'app/models/locator_record.rb', line 231

def phone
  contact_points.find { |cp| ContactPoint::CAN_VOICE.include? cp.category }&.detail
end

#phone_idObject



225
226
227
228
229
# File 'app/models/locator_record.rb', line 225

def phone_id
  contact_points.voice_callable.first.id
rescue StandardError
  nil
end

#phone_id=(cp_id) ⇒ Object



214
215
216
217
218
219
220
221
222
223
# File 'app/models/locator_record.rb', line 214

def phone_id=(cp_id)
  current_cp = contact_points.find { |cp| %w[phone cell].include?(cp.category) }
  contact_points.delete(current_cp) if current_cp
  return if cp_id.blank?

  cp = ContactPoint.find(cp_id)
  contact_points << cp
  # don't want duplicates (say) validation issue to block save
  # cp.save(:validate => false)
end

#profilesObject



266
267
268
# File 'app/models/locator_record.rb', line 266

def profiles
  Profile.where(id: profile_ids)
end

#remove_dealer(trial_run = false) ⇒ Object



324
325
326
327
328
329
330
331
332
333
334
# File 'app/models/locator_record.rb', line 324

def remove_dealer(trial_run = false)
  stat = { status_code: :ok, status_message: "Dealer deleted, locator record id #{id}" }
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_DELETED').create
  if co.errors.any?
    stat[:status_code] = :error
    stat[:status_message] = "There were problem deleting a dealer to locator record #{id} : #{co.errors.full_messages}"
  else
    destroy unless trial_run
  end
  stat
end

#remove_dealer_from_locator(trial_run = false) ⇒ Object



367
368
369
370
371
372
373
# File 'app/models/locator_record.rb', line 367

def remove_dealer_from_locator(trial_run = false)
  stat = { status_code: :ok, status_message: 'Dealer is white listed, removal ignored' }
  unless customer.locator_white_listing
    destroy unless trial_run
  end
  stat
end

#schedule_dealer_locator_activity(task_type) ⇒ Object



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
# File 'app/models/locator_record.rb', line 283

def schedule_dealer_locator_activity(task_type)
  activity_type_id = begin
    ActivityType.find_by(task_type: task_type).id
  rescue StandardError
    8
  end
  activity = Activity.new
  activity.activity_type_id = activity_type_id
  activity.description = activity.activity_type.description + ", DL invite sent ~ #{created_at.to_fs(:crm_date_only)}"
  activity.new_note = "This #{task_type} activity was auto-generated by the customer confirming their dealer/installer record on #{Time.current.to_fs(:crm_date_only)}, and requesting marketing materials or displays."
  activity.party = customer
  activity.target_datetime = 1.day.from_now
  activity.assigned_resource = customer.primary_sales_rep
  activity.save(validate: false)
end

#send_confirmation_emailObject



360
361
362
363
364
365
# File 'app/models/locator_record.rb', line 360

def send_confirmation_email
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_CONFIRMED').create
  return unless co.errors.any?

  ErrorReporting.error("There were problem sending confirmation email to locator record #{id} : #{co.errors.full_messages}")
end

#send_dealer_deletion_notice(trial_run = false) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
310
# File 'app/models/locator_record.rb', line 299

def send_dealer_deletion_notice(trial_run = false)
  stat = { status_code: :ok, status_message: "Sent notice to dealer for deletion, locator record id #{id}" }
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_SET_TO_DELETE').create
  if co.errors.any?
    stat[:status_code] = :error
    stat[:status_message] = "There were problem sending notice to dealer for deletion to locator record #{id} : #{co.errors.full_messages}"
    ErrorReporting.error("There were problem sending notice to dealer for deletion to locator record #{id} : #{co.errors.full_messages}")
  elsif !trial_run && state == 'confirmed'
    dealer_deletion_noticed!
  end
  stat
end

#send_dealer_deletion_notice_7_day_reminder(trial_run = false) ⇒ Object



312
313
314
315
316
317
318
319
320
321
322
# File 'app/models/locator_record.rb', line 312

def send_dealer_deletion_notice_7_day_reminder(trial_run = false)
  stat = { status_code: :ok, status_message: "Sent remainder to dealer for deletion, locator record id #{id}" }
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_DELETE_IN7DAY').create
  if co.errors.any?
    stat[:status_code] = :error
    stat[:status_message] = "There were problem reminding a dealer locator record #{id} : #{co.errors.full_messages}"
  else
    dealer_deletion_remainded! unless trial_run
  end
  stat
end

#send_dealer_invite(trial_run = false) ⇒ Object



336
337
338
339
340
341
342
343
344
345
346
# File 'app/models/locator_record.rb', line 336

def send_dealer_invite(trial_run = false)
  stat = { status_code: :ok, status_message: "Dealer invited, locator record id #{id}" }
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_INVITE').create
  if co.errors.any?
    stat[:status_code] = :error
    stat[:status_message] = "There were problem sending dealer invite to locator record #{id} : #{co.errors.full_messages}"
  elsif not_invited? && !trial_run
    dealer_invited!
  end
  stat
end

#send_invited_dealers_30_day_reminder(trial_run = false) ⇒ Object



348
349
350
351
352
353
354
355
356
357
358
# File 'app/models/locator_record.rb', line 348

def send_invited_dealers_30_day_reminder(trial_run = false)
  stat = { status_code: :ok, status_message: "Dealer 30 day invitation reminder sent, locator record id #{id}" }
  co = CommunicationBuilder.new(resource: self, template_system_code: 'DEALER_REMINDER').create
  if co.errors.any?
    stat[:status_code] = :error
    stat[:status_message] = "There were problem sending dealer invite 30 days reminders to locator record #{id} : #{co.errors.full_messages}"
  else
    invite_reminded! unless trial_run
  end
  stat
end

#slug_candidatesObject (protected)



553
554
555
# File 'app/models/locator_record.rb', line 553

def slug_candidates
  customer.name
end

#unblacklistObject



262
263
264
# File 'app/models/locator_record.rb', line 262

def unblacklist
  update(is_inactive: false)
end

#update_from_user_params(params) ⇒ Object



414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
# File 'app/models/locator_record.rb', line 414

def update_from_user_params(params)
  customer = self.customer
  # do tasks like
  # - create DISPINF, DISPHCTD, DISPTW or BINDER
  # - update customer name if valid, and sane
  # - create new contact points in customer and link to locator record if necessary based on comparison to existing cp details, scanning all other customer and contacts contact points for detail and type matching
  # - create new address in customer and link to locator record if necessary based on comparison to existing addresses
  update(params[:locator_record]) if params[:locator_record]
  ###################################################################################
  # check to see if the dealer name should be updated
  new_dealer_name = params[:dealer_name].to_s.strip
  # only do if it's not blank and the customer name doesn't already contain it (strip both first)
  unless new_dealer_name.blank? || customer.name.strip.index(new_dealer_name)
    # ok, now see if it's at least 3 characters long and contains some alphabetical character
    if new_dealer_name.length >= 3 && new_dealer_name =~ /([A-Z]|[a-z])/
      customer.name = new_dealer_name
      customer.save
    end
  end
  ###################################################################################
  # check to see if the dealer contact points should be updated
  cp_types = %w[email phone fax website]
  new_dealer_cps = []
  cp_types.each do |cp_type|
    # get contact point detail from params (remove any 'http://' in the detail)
    new_dealer_cp_detail = params["dealer_#{cp_type}"].to_s.strip.gsub('http://', '').downcase
    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: Checking!!! #{cp_type}: #{new_dealer_cp_detail}"
    new_dealer_cp = ContactPoint.new(detail: new_dealer_cp_detail, category: cp_type)
    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: new_dealer_cp: #{new_dealer_cp.inspect}"
    # only add to the new contact point validation list if it's not blank
    new_dealer_cps << new_dealer_cp if new_dealer_cp_detail.present?
    # test if new cp is valid, allow blank since that will force blank out that contact point
    next unless new_dealer_cp.errors.empty? || new_dealer_cp_detail.blank?

    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: TRUE: new_dealer_cp.errors.empty? || new_dealer_cp_detail.blank?"
    # handle callable vs the other types
    lr_cp = if cp_type == 'phone'
              get_callable_cp
            else
              get_cp_by_category(cp_type)
            end
    # test if it has the same detail
    next if (begin
      lr_cp.detail
    rescue StandardError
      nil
    end).to_s.strip.downcase == new_dealer_cp_detail

    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: FALSE: ((lr_cp.detail rescue nil).to_s.strip.downcase == new_dealer_cp_detail)"
    # not the same, remove this one, if it's blank we assume it is a delete request
    contact_points.delete(lr_cp) if lr_cp.present?
    next if new_dealer_cp_detail.blank?

    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: FALSE: new_dealer_cp_detail.blank?"
    # if it's not blank and different, scan each of the customer/contacts' contact points of type cp_type to see if it's one of those
    # handle callable vs the other types
    new_cp = if cp_type == 'phone'
               customer.contacts_and_self_callable_contact_points.find { |cp| cp.detail.to_s.strip.downcase == new_dealer_cp_detail }
             else
               customer.contacts_and_self_contact_points_by_category(cp_type).find { |cp| cp.detail.to_s.strip.downcase == new_dealer_cp_detail }
             end
    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: new_cp: type: #{new_cp.category rescue nil}, detail: #{new_cp.detail rescue nil}"
    new_cp ||= customer.contact_points.create(detail: new_dealer_cp_detail, category: cp_type)
    # add the contact point to the locator record
    contact_points << new_cp
  end
  ###################################################################################
  # check that address needs to be updated
  # check that address is valid
  new_dealer_address = Address.new(params[:dealer_address])
  # puts "params[:dealer_address]: #{params[:dealer_address]}"
  new_dealer_address.party_id = customer.id
  valid_address = new_dealer_address.geocode_me
  if valid_address && new_dealer_address.valid?
    # puts "valid_address: #{valid_address}"
    #  and isn't the same as the existing
    unless address.same_as(new_dealer_address)
      # puts "not the same as the existing address"
      # see if it's in the customer already
      dealer_address = customer.all_related_addresses.find { |a| a.same_as(new_dealer_address) }
      unless dealer_address
        # puts "not the same as any existing address in customer"
        # nope so see if it's really close geocode wise to one of the existing, use 1000 ft since there's a big variation in these geocodings
        dealer_address = customer.all_related_addresses.find { |a| new_dealer_address.distance_to(a) < 0.189 }
        unless dealer_address
          # puts "not real close to any existing address in customer"
          # nope so create it in the customer
          new_dealer_address.save
          # puts "new_dealer_address.errors: #{new_dealer_address.errors_to_s}"
          # puts "saving new: new_dealer_address.id: #{new_dealer_address.id rescue 'nil'}"
          dealer_address = new_dealer_address
          customer.addresses << dealer_address
        end
      end
      # puts "new_dealer_address.id: #{new_dealer_address.id rescue 'nil'}"
      self.address = dealer_address
      save
    end
  end
  if errors.empty? && new_dealer_address.errors.empty? && new_dealer_cps.all? { |cp| cp.errors.empty? }
    dealer_confirm
    res = 'ok'
    ###################################################################################
    # check to see if the dealer ordered display materials
    schedule_dealer_locator_activity('DISPINF') if params[:order_infloor_display] == '1'
    schedule_dealer_locator_activity('DISPHCTD') if params[:order_countertop_display] == '1'
    schedule_dealer_locator_activity('BINDER') if params[:order_marketing_materials] == '1'
  else
    all_error_messages = []
    all_error_messages.concat(new_dealer_address.errors.full_messages.dup)
    new_dealer_cps.each do |cp|
      # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: cp errors: #{cp.errors.full_messages.dup}, detail: #{cp.category rescue 'nil'}, detail: #{cp.detail rescue 'nil'}" unless cp.errors.full_messages.empty?
      all_error_messages.concat(cp.errors.full_messages.dup)
    end
    all_error_messages.concat(errors.full_messages.dup)
    # logger.warn "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!confirm_by_email_link: lr errors: #{self.errors.full_messages.dup}" unless self.errors.full_messages.empty?
    res = all_error_messages.join(' and ').to_s
  end
  res
end

#websiteObject



248
249
250
# File 'app/models/locator_record.rb', line 248

def website
  contact_points.by_category('website').first&.detail
end

#website_idObject



244
245
246
# File 'app/models/locator_record.rb', line 244

def website_id
  contact_points.by_category('website').first&.id
end

#website_id=(cp_id) ⇒ Object



235
236
237
238
239
240
241
242
# File 'app/models/locator_record.rb', line 235

def website_id=(cp_id)
  current_cp = contact_points.find { |cp| cp.category == 'website' }
  contact_points.delete(current_cp) if current_cp
  return if cp_id.blank?

  cp = ContactPoint.find(cp_id)
  contact_points << cp
end

#whitelistObject



256
# File 'app/models/locator_record.rb', line 256

def whitelist; end