Class: CustomerSearch
Overview
== Schema Information
Table name: searches
Database name: primary
id :integer not null, primary key
name :string(255)
persist :boolean default(FALSE)
pinned :boolean default(FALSE), not null
query_params :jsonb
result_set_size :integer default(0)
selected_columns :string is an Array
set_limit :integer default(25)
sort_column :string(255)
sort_columns :string default([]), not null, is an Array
sort_direction :string(255) default("ASC")
type :string(255) not null
created_at :datetime
updated_at :datetime
employee_id :integer
Indexes
employee_id_pinned (employee_id,pinned)
employee_id_type (employee_id,type)
Constant Summary
collapse
- CUSTOM_CRITERIA_KEYS =
Keys consumed by apply_custom_criteria — excluded from the Ransack strict probe
so we don't get false-positive InvalidSearchError reports in AppSignal.
%w[
has_ordered_item_id has_ordered_product_category_id has_ordered_product_line_id
has_ordered_days has_ordered_days_time_range_gteq has_ordered_days_time_range_lteq
minimum_number_of_orders has_ordered_type
campaign_id_in campaign_id_not_in has_campaign_activity_status
custom_drop_reason_codes custom_drop_rep_ids
profile_in profile_not_in is_certified_installer
].freeze
Constants inherited
from Search
Search::DISTANCE_SEARCH_KEYS
Instance Attribute Summary
Attributes inherited from Search
#composite_columns, #pagy_count, #pagy_limit, #pagy_page, #sort_column1, #sort_column2, #sort_column3, #sql_select_columns
Class Method Summary
collapse
Instance Method Summary
collapse
-
#address_id_fields ⇒ Object
-
#apply_custom_criteria(results) ⇒ Object
-
#drop_action_reps_for_select ⇒ Object
-
#mass_assign_reps(params, cur_user = nil) ⇒ Object
-
#mass_assign_source(params, cur_user = nil) ⇒ Object
-
#mass_assign_to_campaign(params, cur_user = nil) ⇒ Object
-
#mass_assign_to_subscriber_list(params, cur_user = nil) ⇒ Object
-
#mass_auto_assign_sales_rep(params, cur_user = nil) ⇒ Object
-
#mass_create_subscriber_list(params, cur_user = nil) ⇒ Object
-
#mass_delete_on_lead_qualify_and_guest_state(_params, cur_user = nil) ⇒ Object
-
#mass_drop_sales_rep(params, cur_user) ⇒ Object
-
#mass_locator_blacklist(params, cur_user) ⇒ Object
-
#mass_locator_unblacklist(params, cur_user) ⇒ Object
-
#mass_locator_unwhitelist(_params, cur_user) ⇒ Object
-
#mass_locator_whitelist(params, cur_user) ⇒ Object
-
#mass_online_account_invite(_params, cur_user = nil) ⇒ Object
-
#mass_schedule_activity(params, cur_user = nil) ⇒ Object
-
#mass_switch_rep_roles(_params, cur_user = nil) ⇒ Object
-
#set_defaults ⇒ Object
Default new customer searches to exclude guest accounts.
#mass_googlemap
Methods inherited from Search
#all_composite_columns, allowed_role_ids, #append_custom_column, #append_ouput_column, #append_to_sql_select_columns, #applicable_sort_terms, #apply_array_match, #apply_criteria, #apply_customer_cross_reference, #apply_distance_search, #apply_select, #apply_sort, #available_events, available_output_columns, #available_output_columns, base_search_class_name, #cleanup_search_results, composite_column, #composite_column, database_columns, default_columns, default_sort, #discard_excess, #effective_name, #effective_short_name, #employee, #enqueue_navbar_pinned_refresh, #fast_count, favorites, friendly_column_name, #get_pinned_results, #get_sort_term, global_favorite, has_role_for_search?, #human_query_params, instantiate_query_template, #instantiate_resource_updater, #limit_options, main_resource_class, main_resource_table, mass_actions_for_select, #mass_export, maximum_unpersisted_queries, #normalize_for_mass_update, options, options_classes, #output_columns_for_select, #pagy_from_search, #perform, #perform_selected, #pinned_query, #prepend_custom_column, #prepend_output_column, query_favorites_templates, #ransack_probe_params, recent_searches_for_employee_id, #record_list, #refresh_pinned_results, #remove_other_pins, search_name, #search_name, #search_results, search_type, search_type_humanized, select_sort_columns, #select_sort_columns, #select_statement, #set_sort_term, #sort_columns_for_select, #sort_columns_to_hash, #target_geocoding, unpersisted_queries_quote_reached?, #unrecord_list, #validated_selected_columns, view_resource_class, view_resource_klass, #view_resource_klass, view_resource_table, visible?, with_search_results
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
#publish_event
Class Method Details
.custom_criteria_keys ⇒ Object
93
94
95
|
# File 'app/models/customer_search.rb', line 93
def self.custom_criteria_keys
CUSTOM_CRITERIA_KEYS
end
|
.scope_options_for_mass_schedule_activity ⇒ Object
325
326
327
|
# File 'app/models/customer_search.rb', line 325
def self.scope_options_for_mass_schedule_activity
[['Customer Only', 'customer_only'], ['Primary Contact', 'primary_contact'], ['All Active Contacts', 'all_active_contacts']]
end
|
.select_options_for_profile ⇒ Object
394
395
396
|
# File 'app/models/customer_search.rb', line 394
def self.select_options_for_profile
[['Any Organization', 'ORG']] + Profile.options_for_select(false)
end
|
Instance Method Details
#address_id_fields ⇒ Object
390
391
392
|
# File 'app/models/customer_search.rb', line 390
def address_id_fields
[%w[Shipping shipping_address_id], %w[Billing billing_address_id], %w[Mailing mailing_address_id]]
end
|
#apply_custom_criteria(results) ⇒ Object
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
# File 'app/models/customer_search.rb', line 108
def apply_custom_criteria(results)
results = apply_distance_search(results, custom_table_join: 'INNER JOIN addresses on addresses.party_id = view_customers.id', custom_table_alias: 'addresses')
has_ordered_query = []
has_quoted_query = []
unless query_params[:has_ordered_item_id].blank?
cond = "line_items.item_id in (#{query_params[:has_ordered_item_id].join(',')})"
has_ordered_query << cond
has_quoted_query << cond
end
unless query_params[:has_ordered_product_category_id].blank?
pc_ids = [query_params[:has_ordered_product_category_id]].flatten.compact.map(&:to_i)
cond = "items.pc_path_ids <@ ANY(SELECT ltree_path_ids FROM product_categories WHERE id = ANY(ARRAY[#{pc_ids.join(',')}]::integer[]))"
has_ordered_query << cond
has_quoted_query << cond
end
unless query_params[:has_ordered_product_line_id].blank?
pl_ids = [query_params[:has_ordered_product_line_id]].flatten.compact.map(&:to_i)
cond = "items.primary_pl_path_ids <@ ANY(SELECT ltree_path_ids FROM product_lines WHERE id = ANY(ARRAY[#{pl_ids.join(',')}]::integer[]))"
has_ordered_query << cond
has_quoted_query << cond
end
unless query_params[:has_ordered_days].blank?
has_ordered_query << "orders.shipped_date >= '#{Date.current.days_ago(query_params[:has_ordered_days].to_i)}'"
has_quoted_query << "quotes.complete_datetime >= '#{Date.current.days_ago(query_params[:has_ordered_days].to_i)}'"
end
unless query_params[:has_ordered_days_time_range_gteq].blank?
if query_params[:has_ordered_days_time_range_gteq].present? && query_params[:has_ordered_days_time_range_lteq].present?
has_ordered_query << "orders.shipped_date between '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_lteq].to_i)}' and '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_gteq].to_i)}'"
has_quoted_query << "quotes.complete_datetime between '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_lteq].to_i)}' and '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_gteq].to_i)}'"
else
has_ordered_query << "orders.shipped_date >= '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_gteq].to_i)}'"
has_quoted_query << "quotes.complete_datetime >= '#{Date.current.days_ago(query_params[:has_ordered_days_time_range_gteq].to_i)}'"
end
end
if has_ordered_query.any?
oq = "from line_items inner join orders on orders.id = line_items.resource_id and line_items.resource_type = 'Order' inner join items on items.id = line_items.item_id inner join item_product_lines on item_product_lines.item_id = items.id where orders.customer_id = view_customers.id and orders.state = 'invoiced' and #{has_ordered_query.join(' and ')}"
qq = "from line_items inner join quotes on quotes.id = line_items.resource_id and line_items.resource_type = 'Quote' inner join opportunities on opportunities.id = quotes.opportunity_id inner join items on items.id = line_items.item_id inner join item_product_lines on item_product_lines.item_id = items.id where opportunities.customer_id = view_customers.id and quotes.state = 'complete' and #{has_quoted_query.join(' and ')}"
order_query = "EXISTS(select 1 #{oq})"
quote_query = "EXISTS(select 1 #{qq})"
unless query_params[:minimum_number_of_orders].blank?
order_query += " and (select COUNT(distinct resource_id) #{oq}) >= #{query_params[:minimum_number_of_orders]}"
quote_query += " and (select COUNT(distinct resource_id) #{qq}) >= #{query_params[:minimum_number_of_orders]}"
end
results = case query_params[:has_ordered_type]
when 'both'
results.where("(#{order_query} or #{quote_query})")
when 'quotes'
results.where(quote_query)
else
results.where(order_query)
end
end
unless query_params[:campaign_id_in].blank?
results = results.where("view_customers.id in (select distinct subscribers.customer_id from campaigns
LEFT OUTER JOIN campaigns_subscriber_lists ON campaigns_subscriber_lists.campaign_id = campaigns.id
LEFT OUTER JOIN subscriber_lists ON subscriber_lists.id = campaigns_subscriber_lists.subscriber_list_id
LEFT OUTER JOIN subscribers ON subscribers.subscriber_list_id = subscriber_lists.id
where campaigns.campaign_type = 'outside_sales' and campaigns.id in (#{query_params[:campaign_id_in].join(',')}))")
case query_params[:has_campaign_activity_status]
when 'open'
results = results.where("EXISTS(select 1 from activities where activities.party_id = view_customers.id and campaign_id in (#{query_params[:campaign_id_in].join(',')}) and activity_type_id is not null and activity_result_type_id is null)")
when 'any'
results = results.where("EXISTS(select 1 from activities where activities.party_id = view_customers.id and campaign_id in (#{query_params[:campaign_id_in].join(',')}) and activity_type_id is not null)")
when 'none'
results = results.where("NOT EXISTS(select 1 from activities where activities.party_id = view_customers.id and campaign_id in (#{query_params[:campaign_id_in].join(',')}) and activity_type_id is not null)")
end
end
unless query_params[:campaign_id_not_in].blank?
results = results.where("NOT EXISTS(select 1 from campaigns LEFT OUTER JOIN campaigns_subscriber_lists ON campaigns_subscriber_lists.campaign_id = campaigns.id LEFT OUTER JOIN subscriber_lists ON subscriber_lists.id = campaigns_subscriber_lists.subscriber_list_id LEFT OUTER JOIN subscribers ON subscribers.subscriber_list_id = subscriber_lists.id LEFT OUTER JOIN contact_points ON contact_points.detail = subscribers.email_address LEFT OUTER JOIN parties ON parties.id = contact_points.party_id where (subscribers.customer_id = view_customers.id or parties.id = view_customers.id) and campaigns.id in (#{query_params[:campaign_id_not_in].join(',')}))")
end
drop_reason_codes = [query_params[:custom_drop_reason_codes]].flatten.map(&:presence).compact
if drop_reason_codes.present?
results = results.joins(:customer_drop_events).where(customer_drop_events: { reason_code: drop_reason_codes })
end
drop_rep_ids = [query_params[:custom_drop_rep_ids]].flatten.map(&:presence).compact
if drop_rep_ids.present?
results = results.joins(:customer_drop_events).where(customer_drop_events: { sales_rep_id: drop_rep_ids })
end
profile_ids = [query_params[:profile_in]].flatten.map(&:presence).compact
if profile_ids.present?
if profile_ids.delete('ORG')
results = results.where.not(profile_id: [ProfileConstants::HOMEOWNER])
end
results = results.where(profile_id: profile_ids) if profile_ids.present?
end
not_profile_ids = [query_params[:profile_not_in]].flatten.map(&:presence).compact
if not_profile_ids.present?
results = results.where(profile_id: ProfileConstants::HOMEOWNER) if not_profile_ids.delete('ORG')
results = results.where.not(profile_id: not_profile_ids) if not_profile_ids.present?
end
if query_params[:is_certified_installer].present? && query_params[:is_certified_installer].to_b
results = results.joins(:certifications)
end
results
end
|
#drop_action_reps_for_select ⇒ Object
217
218
219
220
|
# File 'app/models/customer_search.rb', line 217
def drop_action_reps_for_select
selected_customer_ids = search_results.pluck(:resource_id)
Employee.assigned_sales_rep_options_for_select(customer_ids: selected_customer_ids)
end
|
#mass_assign_reps(params, cur_user = nil) ⇒ Object
222
223
224
225
226
227
228
229
230
|
# File 'app/models/customer_search.rb', line 222
def mass_assign_reps(params, cur_user = nil)
jid = MassSearch::CustomerAssignRepsWorker.perform_async(
'search_id' => id,
'action_params' => { 'resource_params' => (params[:resource] || {}).to_h, 'activity' => (params[:activity] || {}).to_h },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_assign_source(params, cur_user = nil) ⇒ Object
246
247
248
249
250
251
252
253
254
|
# File 'app/models/customer_search.rb', line 246
def mass_assign_source(params, cur_user = nil)
jid = ::SearchResourceUpdateWorker.perform_async(
'search_id' => id,
'action_params' => { 'resource_params' => { 'source_id' => params[:source_id] } },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_assign_to_campaign(params, cur_user = nil) ⇒ Object
276
277
278
279
280
281
282
283
284
285
286
287
288
289
|
# File 'app/models/customer_search.rb', line 276
def mass_assign_to_campaign(params, cur_user = nil)
campaign_params = params[:campaign] || {}
if campaign_params[:campaign_id].blank? && campaign_params[:new_campaign_name].blank?
return { status: :error, message: 'You must specify an existing campaign or enter a name for a new campaign' }
end
jid = MassSearch::CustomerAssignToCampaignWorker.perform_async(
'search_id' => id,
'action_params' => { 'campaign' => campaign_params.to_h },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_assign_to_subscriber_list(params, cur_user = nil) ⇒ Object
266
267
268
269
270
271
272
273
274
|
# File 'app/models/customer_search.rb', line 266
def mass_assign_to_subscriber_list(params, cur_user = nil)
jid = MassSearch::CustomerAssignToSubscriberListWorker.perform_async(
'search_id' => id,
'action_params' => { 'subscriber_list_id' => params[:subscriber_list_id] },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_auto_assign_sales_rep(params, cur_user = nil) ⇒ Object
232
233
234
235
236
237
238
239
240
241
242
243
244
|
# File 'app/models/customer_search.rb', line 232
def mass_auto_assign_sales_rep(params, cur_user = nil)
jid = MassSearch::CustomerAutoAssignSalesRepWorker.perform_async(
'search_id' => id,
'action_params' => {
'remove_existing_reps' => params[:remove_existing_reps],
'skip_lead_assignment' => params[:skip_lead_assignment],
'activity' => (params[:activity] || {}).to_h
},
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_create_subscriber_list(params, cur_user = nil) ⇒ Object
256
257
258
259
260
261
262
263
264
|
# File 'app/models/customer_search.rb', line 256
def mass_create_subscriber_list(params, cur_user = nil)
jid = MassSearch::CustomerCreateSubscriberListWorker.perform_async(
'search_id' => id,
'action_params' => { 'subscriber_list' => (params[:subscriber_list] || {}).to_h },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_delete_on_lead_qualify_and_guest_state(_params, cur_user = nil) ⇒ Object
301
302
303
304
305
306
307
308
309
|
# File 'app/models/customer_search.rb', line 301
def mass_delete_on_lead_qualify_and_guest_state(_params, cur_user = nil)
jid = MassSearch::CustomerDeleteLeadsWorker.perform_async(
'search_id' => id,
'action_params' => {},
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_drop_sales_rep(params, cur_user) ⇒ Object
329
330
331
332
333
334
335
336
337
|
# File 'app/models/customer_search.rb', line 329
def mass_drop_sales_rep(params, cur_user)
jid = MassSearch::CustomerDropSalesRepWorker.perform_async(
'search_id' => id,
'action_params' => { 'sales_rep_id' => params[:sales_rep_id], 'reason_code' => params[:reason_code], 'comment' => params[:comment] },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_locator_blacklist(params, cur_user) ⇒ Object
349
350
351
352
353
354
355
356
357
|
# File 'app/models/customer_search.rb', line 349
def mass_locator_blacklist(params, cur_user)
jid = MassSearch::CustomerLocatorBlacklistWorker.perform_async(
'search_id' => id,
'action_params' => { 'reason' => params[:reason] },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_locator_unblacklist(params, cur_user) ⇒ Object
369
370
371
372
373
374
375
376
377
|
# File 'app/models/customer_search.rb', line 369
def mass_locator_unblacklist(params, cur_user)
jid = MassSearch::CustomerLocatorUnblacklistWorker.perform_async(
'search_id' => id,
'action_params' => { 'inform_customer' => params[:inform_customer] },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_locator_unwhitelist(_params, cur_user) ⇒ Object
359
360
361
362
363
364
365
366
367
|
# File 'app/models/customer_search.rb', line 359
def mass_locator_unwhitelist(_params, cur_user)
jid = MassSearch::CustomerLocatorUnwhitelistWorker.perform_async(
'search_id' => id,
'action_params' => {},
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_locator_whitelist(params, cur_user) ⇒ Object
339
340
341
342
343
344
345
346
347
|
# File 'app/models/customer_search.rb', line 339
def mass_locator_whitelist(params, cur_user)
jid = MassSearch::CustomerLocatorWhitelistWorker.perform_async(
'search_id' => id,
'action_params' => { 'reason' => params[:reason] },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_online_account_invite(_params, cur_user = nil) ⇒ Object
379
380
381
382
383
384
385
386
387
|
# File 'app/models/customer_search.rb', line 379
def mass_online_account_invite(_params, cur_user = nil)
jid = MassSearch::CustomerOnlineAccountInviteWorker.perform_async(
'search_id' => id,
'action_params' => {},
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_schedule_activity(params, cur_user = nil) ⇒ Object
311
312
313
314
315
316
317
318
319
320
321
322
323
|
# File 'app/models/customer_search.rb', line 311
def mass_schedule_activity(params, cur_user = nil)
activity_params = (params[:activity] || {}).to_h
apply_scope = activity_params.delete('apply_scope')
campaign_id = activity_params.delete('campaign_id')
jid = MassSearch::CustomerScheduleActivityWorker.perform_async(
'search_id' => id,
'action_params' => { 'activity' => activity_params, 'apply_scope' => apply_scope, 'campaign_id' => campaign_id },
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#mass_switch_rep_roles(_params, cur_user = nil) ⇒ Object
291
292
293
294
295
296
297
298
299
|
# File 'app/models/customer_search.rb', line 291
def mass_switch_rep_roles(_params, cur_user = nil)
jid = MassSearch::CustomerSwitchRepRolesWorker.perform_async(
'search_id' => id,
'action_params' => {},
'user_id' => cur_user&.id,
'locale' => I18n.locale.to_s
)
{ status: :ok, job_id: jid }
end
|
#set_defaults ⇒ Object
Default new customer searches to exclude guest accounts
98
99
100
101
102
103
104
105
106
|
# File 'app/models/customer_search.rb', line 98
def set_defaults
super
return unless new_record?
qp = (query_params || {}).with_indifferent_access
if qp[:state_in].blank? && qp[:state_not_in].blank?
self.query_params = (query_params || {}).merge('state_not_in' => ['guest'])
end
end
|