Class: Customer::NewCustomer
- Inherits:
-
Object
- Object
- Customer::NewCustomer
- Includes:
- ActiveModel::API, ActiveModel::Attributes, ActiveModel::Validations, ActiveModel::Validations::Callbacks, Heatwave::AttributeNormalizing, StripAttributes
- Defined in:
- app/services/customer/new_customer.rb
Overview
Service object: new customer.
Constant Summary collapse
- REP_ASSIGN_METHODS =
Rep assign methods.
{ aa: 'Auto Assign', sa: 'Self Assign', ma: 'Manually Assign', dna: 'Do Not Assign' }.with_indifferent_access
Instance Attribute Summary collapse
- #cell ⇒ Object readonly
-
#email ⇒ Object
readonly
We always validate these fields no matter what step we're in.
-
#email2 ⇒ Object
readonly
We always validate these fields no matter what step we're in.
- #fax ⇒ Object readonly
- #phone ⇒ Object readonly
- #phone2 ⇒ Object readonly
- #website ⇒ Object readonly
Delegated Instance Attributes collapse
-
#company_id ⇒ Object
Alias for Catalog#company_id.
Instance Method Summary collapse
-
#address_complete? ⇒ Boolean
Bare mininum information we need for a valid address.
-
#allow_disablement_of_address_validation? ⇒ Boolean
Accessor method to determine if we can allow disabling the address validation.
- #assignment_step? ⇒ Boolean
-
#build_address(address) ⇒ Object
Copy over address attributes.
-
#build_and_save_customer(check_for_spam: false) ⇒ Object
Builds, qualify, create lead and save customer.
-
#build_contact_points(party) ⇒ Object
Build the contact points into the party.
-
#build_customer ⇒ Object
Instantiate a new customer translating all attributes from newcustomer.
-
#buying_group ⇒ Object
Accessor method to retrieve buying group.
-
#buying_group_options_for_select ⇒ Object
Retrieves a list of buying available for the customer company.
-
#catalog ⇒ Object
Catalog is based on country in this model.
- #catalog_id ⇒ Object
- #catalog_name ⇒ Object
-
#company_name_parts ⇒ Object
Split company name in parts for highlighting on screen.
- #contact_point_details ⇒ Object
- #default_pricing_program ⇒ Object
- #default_profile ⇒ Object
- #find_duplicates ⇒ Object
- #full_address ⇒ Object
- #has_address? ⇒ Boolean
- #identify_step? ⇒ Boolean
- #is_individual? ⇒ Boolean
- #is_organization? ⇒ Boolean
- #is_spam? ⇒ Boolean
-
#name_presence ⇒ Object
Check for name presence and normalize the person name using our name parser e.g Smith, John III will be John Smith III.
- #person_first_name ⇒ Object
- #person_last_name ⇒ Object
-
#person_name_parts ⇒ Object
Split person name in parts for highlighting on screen.
-
#pricing_program_options_for_select ⇒ Object
Used in the final step to determine the pricing offered.
-
#profile ⇒ Object
Accessor method to retrieve profile.
-
#profile_collection_for_select ⇒ Object
List of profiles for selection, we assume an individual is always a homeowner only, otherwise we pull up every trade.
- #rep_assignment_method_name ⇒ Object
- #set_default_email_preferences ⇒ Object
-
#set_email_preferences ⇒ Object
Creates or updates email preferences if an email address was provided.
- #setup_or_assignment_step? ⇒ Boolean
- #setup_step? ⇒ Boolean
-
#split_person_name ⇒ Object
Calls the person name parser to split a name, returns a hash with :first_name, :last_name, :middle_name, :suffix, :prefix.
- #start_in_lead_qualify? ⇒ Boolean
- #website_url_to_base_url ⇒ Object
Methods included from Heatwave::AttributeNormalizing
Instance Attribute Details
#cell ⇒ Object (readonly)
70 |
# File 'app/services/customer/new_customer.rb', line 70 validates :phone, :phone2, :cell, :fax, phone_format: true |
#email ⇒ Object (readonly)
We always validate these fields no matter what step we're in
Validations:
- Email_format
69 |
# File 'app/services/customer/new_customer.rb', line 69 validates :email, :email2, email_format: true |
#email2 ⇒ Object (readonly)
We always validate these fields no matter what step we're in
Validations:
- Email_format
69 |
# File 'app/services/customer/new_customer.rb', line 69 validates :email, :email2, email_format: true |
#fax ⇒ Object (readonly)
70 |
# File 'app/services/customer/new_customer.rb', line 70 validates :phone, :phone2, :cell, :fax, phone_format: true |
#phone ⇒ Object (readonly)
70 |
# File 'app/services/customer/new_customer.rb', line 70 validates :phone, :phone2, :cell, :fax, phone_format: true |
#phone2 ⇒ Object (readonly)
70 |
# File 'app/services/customer/new_customer.rb', line 70 validates :phone, :phone2, :cell, :fax, phone_format: true |
#website ⇒ Object (readonly)
71 |
# File 'app/services/customer/new_customer.rb', line 71 validates :website, url: { allow_nil: true, allow_blank: true } |
Instance Method Details
#address_complete? ⇒ Boolean
Bare mininum information we need for a valid address
327 328 329 |
# File 'app/services/customer/new_customer.rb', line 327 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
380 381 382 |
# File 'app/services/customer/new_customer.rb', line 380 def allow_disablement_of_address_validation? @address_carrier_error end |
#assignment_step? ⇒ Boolean
105 106 107 |
# File 'app/services/customer/new_customer.rb', line 105 def assignment_step? step == :assignment end |
#build_address(address) ⇒ Object
Copy over address attributes
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'app/services/customer/new_customer.rb', line 295 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
336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 |
# File 'app/services/customer/new_customer.rb', line 336 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.(buying_group_id_added: customer.) # 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
316 317 318 319 320 321 322 323 324 |
# File 'app/services/customer/new_customer.rb', line 316 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_customer ⇒ Object
Instantiate a new customer translating all attributes from newcustomer
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 290 291 292 |
# File 'app/services/customer/new_customer.rb', line 254 def build_customer cu = Customer.new cu.profile_id = profile_id cu. = 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_group ⇒ Object
Accessor method to retrieve buying group
218 219 220 |
# File 'app/services/customer/new_customer.rb', line 218 def BuyingGroup.find(.presence) if .presence end |
#buying_group_options_for_select ⇒ Object
Retrieves a list of buying available for the customer company
223 224 225 |
# File 'app/services/customer/new_customer.rb', line 223 def BuyingGroup.(company_id: company_id) end |
#catalog ⇒ Object
Catalog is based on country in this model
228 229 230 231 |
# File 'app/services/customer/new_customer.rb', line 228 def catalog # Always return a catalog; default to US when country is not provided Catalog.default_for_country(country_iso) end |
#catalog_id ⇒ Object
233 234 235 |
# File 'app/services/customer/new_customer.rb', line 233 def catalog_id catalog.try(:id) end |
#catalog_name ⇒ Object
237 238 239 |
# File 'app/services/customer/new_customer.rb', line 237 def catalog_name catalog.try(:name) end |
#company_id ⇒ Object
Alias for Catalog#company_id
241 |
# File 'app/services/customer/new_customer.rb', line 241 delegate :company_id, to: :catalog |
#company_name_parts ⇒ Object
Split company name in parts for highlighting on screen
168 169 170 |
# File 'app/services/customer/new_customer.rb', line 168 def company_name_parts company_name.to_s.split(/[ ,.]/).filter_map(&:presence) end |
#contact_point_details ⇒ Object
158 159 160 |
# File 'app/services/customer/new_customer.rb', line 158 def contact_point_details [email, phone, fax].compact.uniq end |
#default_pricing_program ⇒ Object
180 181 182 183 184 185 186 |
# File 'app/services/customer/new_customer.rb', line 180 def default_pricing_program if is_individual? Coupon::Tier2ProgramPricing.msrp_tier2_pricing_coupon else Coupon::Tier2ProgramPricing.customer_default_trade end end |
#default_profile ⇒ Object
188 189 190 191 192 193 194 |
# File 'app/services/customer/new_customer.rb', line 188 def default_profile if is_individual? Profile.homeowner_profile else Profile.unknown_trade end end |
#find_duplicates ⇒ Object
145 146 147 148 |
# File 'app/services/customer/new_customer.rb', line 145 def find_duplicates cf = Query::CustomerFinder.new(attributes) cf.find_duplicates end |
#full_address ⇒ Object
331 332 333 |
# File 'app/services/customer/new_customer.rb', line 331 def full_address %i[street1 city postal_code country_iso].map { |f| send(f).presence }.join(' ') end |
#has_address? ⇒ Boolean
115 116 117 |
# File 'app/services/customer/new_customer.rb', line 115 def has_address? street1.present? end |
#identify_step? ⇒ Boolean
97 98 99 |
# File 'app/services/customer/new_customer.rb', line 97 def identify_step? step == :identify end |
#is_individual? ⇒ Boolean
172 173 174 |
# File 'app/services/customer/new_customer.rb', line 172 def is_individual? company_name.blank? end |
#is_organization? ⇒ Boolean
176 177 178 |
# File 'app/services/customer/new_customer.rb', line 176 def is_organization? company_name.present? end |
#is_spam? ⇒ Boolean
384 385 386 387 388 389 |
# File 'app/services/customer/new_customer.rb', line 384 def is_spam? SpamCheck.new.process( author_email: email.presence, phone_number: phone.presence || phone2.presence || cell.presence || fax.presence ) end |
#name_presence ⇒ Object
Check for name presence and normalize the person name using our name parser
e.g Smith, John III will be John Smith III
121 122 123 124 125 126 127 128 129 130 |
# File 'app/services/customer/new_customer.rb', line 121 def name_presence if person_name.present? pnp = split_person_name self.person_name = pnp.full_name end return if company_name.present? || 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_name ⇒ Object
150 151 152 |
# File 'app/services/customer/new_customer.rb', line 150 def person_first_name pnp.first end |
#person_last_name ⇒ Object
154 155 156 |
# File 'app/services/customer/new_customer.rb', line 154 def person_last_name pnp.last end |
#person_name_parts ⇒ Object
Split person name in parts for highlighting on screen
163 164 165 |
# File 'app/services/customer/new_customer.rb', line 163 def person_name_parts person_name.to_s.scan(/(\w+)/).flatten end |
#pricing_program_options_for_select ⇒ Object
Used in the final step to determine the pricing offered
197 198 199 |
# File 'app/services/customer/new_customer.rb', line 197 def Coupon::Tier2ProgramPricing.(build_customer) end |
#profile ⇒ Object
Accessor method to retrieve profile
202 203 204 |
# File 'app/services/customer/new_customer.rb', line 202 def profile Profile.find(profile_id) if profile_id.present? end |
#profile_collection_for_select ⇒ Object
List of profiles for selection, we assume an individual is always a homeowner
only, otherwise we pull up every trade
208 209 210 211 212 213 214 215 |
# File 'app/services/customer/new_customer.rb', line 208 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_name ⇒ Object
93 94 95 |
# File 'app/services/customer/new_customer.rb', line 93 def rep_assignment_method_name REP_ASSIGN_METHODS[rep_assignment_method] end |
#set_default_email_preferences ⇒ Object
243 244 245 246 247 248 249 250 251 |
# File 'app/services/customer/new_customer.rb', line 243 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_preferences ⇒ Object
Creates or updates email preferences if an email address was provided
362 363 364 365 366 367 368 369 370 371 372 |
# File 'app/services/customer/new_customer.rb', line 362 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. = != true ep.disable_promotions = subscribe_to_promotions != true ep.disable_webinars = subscribe_to_webinars != true ep.save end |
#setup_or_assignment_step? ⇒ Boolean
109 110 111 |
# File 'app/services/customer/new_customer.rb', line 109 def setup_or_assignment_step? (setup_step? or assignment_step?) end |
#setup_step? ⇒ Boolean
101 102 103 |
# File 'app/services/customer/new_customer.rb', line 101 def setup_step? step == :setup end |
#split_person_name ⇒ Object
Calls the person name parser to split a name, returns a hash with :first_name, :last_name, :middle_name, :suffix, :prefix
375 376 377 |
# File 'app/services/customer/new_customer.rb', line 375 def split_person_name PersonNameParser.new(person_name) end |
#start_in_lead_qualify? ⇒ Boolean
113 |
# File 'app/services/customer/new_customer.rb', line 113 def start_in_lead_qualify? = start_in_lead_qualify |
#website_url_to_base_url ⇒ Object
132 133 134 135 136 137 138 139 140 141 142 143 |
# File 'app/services/customer/new_customer.rb', line 132 def website_url_to_base_url return if website.blank? pv = begin Addressable::URI.parse(website) rescue StandardError nil end return unless pv self.website = "#{pv.scheme || 'https'}://#{pv.host}" end |