Class: Customer::NewCustomer

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::API, ActiveModel::Attributes, ActiveModel::Validations, ActiveModel::Validations::Callbacks, Normalizr::Concern, StripAttributes
Defined in:
app/services/customer/new_customer.rb

Constant Summary collapse

REP_ASSIGN_METHODS =
{ aa: 'Auto Assign', sa: 'Self Assign', ma: 'Manually Assign', dna: 'Do Not Assign' }.with_indifferent_access

Instance Attribute Summary collapse

Delegated Instance Attributes collapse

Instance Method Summary collapse

Instance Attribute Details

#cellObject (readonly)



67
# File 'app/services/customer/new_customer.rb', line 67

validates :phone, :phone2, :cell, :fax, phone_format: true

#emailObject (readonly)

We always validate these fields no matter what step we're in

Validations:

  • Email_format


66
# File 'app/services/customer/new_customer.rb', line 66

validates :email, :email2, email_format: true

#email2Object (readonly)

We always validate these fields no matter what step we're in

Validations:

  • Email_format


66
# File 'app/services/customer/new_customer.rb', line 66

validates :email, :email2, email_format: true

#faxObject (readonly)



67
# File 'app/services/customer/new_customer.rb', line 67

validates :phone, :phone2, :cell, :fax, phone_format: true

#phoneObject (readonly)



67
# File 'app/services/customer/new_customer.rb', line 67

validates :phone, :phone2, :cell, :fax, phone_format: true

#phone2Object (readonly)



67
# File 'app/services/customer/new_customer.rb', line 67

validates :phone, :phone2, :cell, :fax, phone_format: true

#websiteObject (readonly)



68
# File 'app/services/customer/new_customer.rb', line 68

validates :website, url: { allow_nil: true, allow_blank: true }

Instance Method Details

#address_complete?Boolean

Bare mininum information we need for a valid address

Returns:

  • (Boolean)


324
325
326
# File 'app/services/customer/new_customer.rb', line 324

def address_complete?
  %i[street1 city postal_code country_iso].all? { |f| send(f).presence }
end

#allow_disablement_of_address_validation?Boolean

Accessor method to determine if we can allow disabling the address validation

Returns:

  • (Boolean)


377
378
379
# File 'app/services/customer/new_customer.rb', line 377

def allow_disablement_of_address_validation?
  @address_carrier_error
end

#assignment_step?Boolean

Returns:

  • (Boolean)


102
103
104
# File 'app/services/customer/new_customer.rb', line 102

def assignment_step?
  step == :assignment
end

#build_address(address) ⇒ Object

Copy over address attributes



292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'app/services/customer/new_customer.rb', line 292

def build_address(address)
  address.street1 = street1
  address.street2 = street2
  address.city = city
  address.state_code = state_code
  address.zip = postal_code
  address.country_iso3 = Country.find_by(iso: country_iso).iso3
  address.is_residential = residential_address.nil? ? false : residential_address
  address.lat = lat
  address.lng = lng
  address.has_loading_dock = has_loading_dock
  address.is_construction_site = is_construction_site
  address.requires_inside_delivery = requires_inside_delivery
  address.requires_liftgate = requires_liftgate
  address.limited_access = limited_access
  address.requires_appointment = requires_appointment
  address.disable_address_correction = disable_address_correction.nil? ? false : disable_address_correction
  address
end

#build_and_save_customer(check_for_spam: false) ⇒ Object

Builds, qualify, create lead and save customer



333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
# File 'app/services/customer/new_customer.rb', line 333

def build_and_save_customer(check_for_spam: false)
  customer = build_customer
  if check_for_spam && is_spam?
    customer.errors.add(:base, 'Spam customer detected')
  else
    customer.state = 'lead_qualify'
    customer.state_event = :complete_qualification unless start_in_lead_qualify?

    if customer.save
      # Update the return path
      self.return_path = return_path && customer.id && return_path.gsub('new_party_id', customer.id.to_s)
      NewLead::LeadActivityAssigner.new.process(customer, notes: notes) # unless customer.primary_sales_rep_id.nil?
      # record email preferences
      set_email_preferences
      # Broadcast product interest if any
      customer.broadcast_product_interest_changed(product_line_ids_added: customer.product_line_ids)
      # Broadcast buying groups if any
      customer.broadcast_buying_group_changed(buying_group_id_added: customer.buying_group_id)
      # Queue profile image lookup (logo from Clearbit)
      PartyProfileImageWorker.perform_async(customer.id)
    end
  end
  customer
end

#build_contact_points(party) ⇒ Object

Build the contact points into the party



313
314
315
316
317
318
319
320
321
# File 'app/services/customer/new_customer.rb', line 313

def build_contact_points(party)
  party.contact_points.build(detail: phone, category: ContactPoint::PHONE) if phone.present?
  party.contact_points.build(detail: phone2, category: ContactPoint::PHONE) if phone2.present?
  party.contact_points.build(detail: cell, category: ContactPoint::CELL) if cell.present?
  party.contact_points.build(detail: fax, category: ContactPoint::FAX) if fax.present?
  party.contact_points.build(detail: email, category: ContactPoint::EMAIL) if email.present?
  party.contact_points.build(detail: email2, category: ContactPoint::EMAIL) if email2.present?
  party.contact_points.build(detail: website, category: ContactPoint::WEBSITE) if website.present?
end

#build_customerObject

Instantiate a new customer translating all attributes from newcustomer



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'app/services/customer/new_customer.rb', line 251

def build_customer
  cu = Customer.new
  cu.profile_id = profile_id
  cu.buying_group_id = buying_group_id
  cu.source_id = source_id
  cu.source_info = source_info.presence
  cu.preferred_language = preferred_language
  cu.catalog_id = catalog_id
  cu.tier2_program_pricing_id = tier2_program_pricing_id
  cu.gclid = gclid.presence
  # Split the person name, we'll reuse that later
  pnp = split_person_name
  if company_name.blank?
    pnp.to_party(cu)
  else # If not company, build a person
    cu.full_name = company_name
    if pnp.valid? # A contact is present
      cnt = cu.contacts.build
      pnp.to_party(cnt)
      cnt.job_title = job_title
    end
  end
  # Build the contact points into the contact if present otherwise customer
  build_contact_points(cnt || cu)
  cu.primary_sales_rep_id = primary_sales_rep_id
  cu.secondary_sales_rep_id = secondary_sales_rep_id
  cu.local_sales_rep_id = local_sales_rep_id
  cu.service_rep_id = service_rep_id
  cu.do_not_auto_assign = (rep_assignment_method.to_s.to_sym == :dna)
  cu.creation_method = creation_method

  # Build the address if we have all the elements
  if address_complete?
    a = build_address(cu.addresses.new)
    cu.shipping_address = cu.billing_address = cu.mailing_address = a
  end
  cu.product_line_ids = (product_line_ids || []).compact.uniq
  cu
end

#buying_groupObject

Accessor method to retrieve buying group



215
216
217
# File 'app/services/customer/new_customer.rb', line 215

def buying_group
  BuyingGroup.find(buying_group_id.presence) if buying_group_id.presence
end

#buying_group_options_for_selectObject

Retrieves a list of buying available for the customer company



220
221
222
# File 'app/services/customer/new_customer.rb', line 220

def buying_group_options_for_select
  BuyingGroup.options_for_select(company_id: company_id)
end

#catalogObject

Catalog is based on country in this model



225
226
227
228
# File 'app/services/customer/new_customer.rb', line 225

def catalog
  # Always return a catalog; default to US when country is not provided
  Catalog.default_for_country(country_iso)
end

#catalog_idObject



230
231
232
# File 'app/services/customer/new_customer.rb', line 230

def catalog_id
  catalog.try(:id)
end

#catalog_nameObject



234
235
236
# File 'app/services/customer/new_customer.rb', line 234

def catalog_name
  catalog.try(:name)
end

#company_idObject

Alias for Catalog#company_id

Returns:

  • (Object)

    Catalog#company_id

See Also:



238
# File 'app/services/customer/new_customer.rb', line 238

delegate :company_id, to: :catalog

#company_name_partsObject

Split company name in parts for highlighting on screen



165
166
167
# File 'app/services/customer/new_customer.rb', line 165

def company_name_parts
  company_name.to_s.split(/[ ,\.]/).map(&:presence).compact
end

#contact_point_detailsObject



155
156
157
# File 'app/services/customer/new_customer.rb', line 155

def contact_point_details
  [email, phone, fax].compact.uniq
end

#default_pricing_programObject



177
178
179
180
181
182
183
# File 'app/services/customer/new_customer.rb', line 177

def default_pricing_program
  if is_individual?
    Coupon::Tier2ProgramPricing.msrp_tier2_pricing_coupon
  else
    Coupon::Tier2ProgramPricing.customer_default_trade
  end
end

#default_profileObject



185
186
187
188
189
190
191
# File 'app/services/customer/new_customer.rb', line 185

def default_profile
  if is_individual?
    Profile.homeowner_profile
  else
    Profile.unknown_trade
  end
end

#find_duplicatesObject



142
143
144
145
# File 'app/services/customer/new_customer.rb', line 142

def find_duplicates
  cf = Query::CustomerFinder.new(attributes)
  cf.find_duplicates
end

#full_addressObject



328
329
330
# File 'app/services/customer/new_customer.rb', line 328

def full_address
  %i[street1 city postal_code country_iso].map { |f| send(f).presence }.join(' ')
end

#has_address?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'app/services/customer/new_customer.rb', line 112

def has_address?
  street1.present?
end

#identify_step?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'app/services/customer/new_customer.rb', line 94

def identify_step?
  step == :identify
end

#is_individual?Boolean

Returns:

  • (Boolean)


169
170
171
# File 'app/services/customer/new_customer.rb', line 169

def is_individual?
  company_name.blank?
end

#is_organization?Boolean

Returns:

  • (Boolean)


173
174
175
# File 'app/services/customer/new_customer.rb', line 173

def is_organization?
  company_name.present?
end

#is_spam?Boolean

Returns:

  • (Boolean)


381
382
383
384
385
386
# File 'app/services/customer/new_customer.rb', line 381

def is_spam?
  SpamCheck.new.process(
     author_email: email.presence,
     phone_number: phone.presence || phone2.presence || cell.presence || fax.presence
   )
end

#name_presenceObject

Check for name presence and normalize the person name using our name parser
e.g Smith, John III will be John Smith III



118
119
120
121
122
123
124
125
126
127
# File 'app/services/customer/new_customer.rb', line 118

def name_presence
  if person_name.present?
    pnp = split_person_name
    self.person_name = pnp.full_name
  end
  return if company_name.present? or person_name.present?

  errors.add :company_name, 'must be specified if no person name present'
  errors.add :person_name, 'must be specified if no company name present'
end

#person_first_nameObject



147
148
149
# File 'app/services/customer/new_customer.rb', line 147

def person_first_name
  pnp.first
end

#person_last_nameObject



151
152
153
# File 'app/services/customer/new_customer.rb', line 151

def person_last_name
  pnp.last
end

#person_name_partsObject

Split person name in parts for highlighting on screen



160
161
162
# File 'app/services/customer/new_customer.rb', line 160

def person_name_parts
  person_name.to_s.scan(/(\w+)/).flatten
end

#pricing_program_options_for_selectObject

Used in the final step to determine the pricing offered



194
195
196
# File 'app/services/customer/new_customer.rb', line 194

def pricing_program_options_for_select
  Coupon::Tier2ProgramPricing.select_options_for_customer(build_customer)
end

#profileObject

Accessor method to retrieve profile



199
200
201
# File 'app/services/customer/new_customer.rb', line 199

def profile
  Profile.find(profile_id) if profile_id.present?
end

#profile_collection_for_selectObject

List of profiles for selection, we assume an individual is always a homeowner
only, otherwise we pull up every trade



205
206
207
208
209
210
211
212
# File 'app/services/customer/new_customer.rb', line 205

def profile_collection_for_select
  profiles = if is_individual?
               Profile.homeowner
             else
               Profile.trades
             end
  profiles.order(:name).pluck(:name, :id)
end

#rep_assignment_method_nameObject



90
91
92
# File 'app/services/customer/new_customer.rb', line 90

def rep_assignment_method_name
  REP_ASSIGN_METHODS[rep_assignment_method]
end

#set_default_email_preferencesObject



240
241
242
243
244
245
246
247
248
# File 'app/services/customer/new_customer.rb', line 240

def set_default_email_preferences
  # If it's for US, subscribe to everything by default
  # Canada will therefore be unsubscribed by default
  default_value = company_id == 1
  %i[subscribe_to_announcements subscribe_to_events subscribe_to_newsletters
     subscribe_to_product_review_requests subscribe_to_promotions subscribe_to_webinars].each do |field|
    public_send(:"#{field}=", default_value) if public_send(field).nil?
  end
end

#set_email_preferencesObject

Creates or updates email preferences if an email address was provided



359
360
361
362
363
364
365
366
367
368
369
# File 'app/services/customer/new_customer.rb', line 359

def set_email_preferences
  return true if email.blank?

  ep = EmailPreference.find_or_initialize_by(email: email&.downcase)
  ep.disable_announcements = subscribe_to_announcements != true
  ep.disable_events = subscribe_to_events != true
  ep.disable_newsletters = subscribe_to_newsletters != true
  ep.disable_promotions = subscribe_to_promotions != true
  ep.disable_webinars = subscribe_to_webinars != true
  ep.save
end

#setup_or_assignment_step?Boolean

Returns:

  • (Boolean)


106
107
108
# File 'app/services/customer/new_customer.rb', line 106

def setup_or_assignment_step?
  (setup_step? or assignment_step?)
end

#setup_step?Boolean

Returns:

  • (Boolean)


98
99
100
# File 'app/services/customer/new_customer.rb', line 98

def setup_step?
  step == :setup
end

#split_person_nameObject

Calls the person name parser to split a name, returns a hash with :first_name, :last_name, :middle_name, :suffix, :prefix



372
373
374
# File 'app/services/customer/new_customer.rb', line 372

def split_person_name
  PersonNameParser.new(person_name)
end

#start_in_lead_qualify?Boolean

Returns:

  • (Boolean)


110
# File 'app/services/customer/new_customer.rb', line 110

def start_in_lead_qualify? = start_in_lead_qualify

#website_url_to_base_urlObject



129
130
131
132
133
134
135
136
137
138
139
140
# File 'app/services/customer/new_customer.rb', line 129

def website_url_to_base_url
  return unless website.present?

  pv = begin
    Addressable::URI.parse(website)
  rescue StandardError
    nil
  end
  return unless pv

  self.website = "#{pv.scheme || 'https'}://#{pv.host}"
end