Class: Crm::SmsMessagesController

Inherits:
CrmController show all
Includes:
Controllers::Attachable
Defined in:
app/controllers/crm/sms_messages_controller.rb

Constant Summary

Constants included from Controllers::Attachable

Controllers::Attachable::PUBLICATIONS_PER_PAGE

Constants included from Controllers::ReferenceFindable

Controllers::ReferenceFindable::ID_EMBEDDED_PATTERNS

Constants included from Controllers::AnalyticsEvents

Controllers::AnalyticsEvents::MAX_QUEUED_EVENTS, Controllers::AnalyticsEvents::SESSION_KEY

Constants included from Controllers::ErrorRendering

Controllers::ErrorRendering::NON_CONTENT_PATH_PREFIXES

Constants included from Www::SeoHelper

Www::SeoHelper::AWARDS, Www::SeoHelper::CA_ADDRESS, Www::SeoHelper::CA_BUSINESS_HOURS, Www::SeoHelper::CA_CONTACT_POINT, Www::SeoHelper::CA_CURRENCIES, Www::SeoHelper::CA_DESCRIPTION, Www::SeoHelper::CA_FOUNDING_DATE, Www::SeoHelper::CA_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::CA_LEGAL_NAME, Www::SeoHelper::CA_LOCAL_BUSINESS, Www::SeoHelper::CA_ONLINE_STORE, Www::SeoHelper::CA_RETURN_POLICY, Www::SeoHelper::CA_SALES_DEPARTMENT, Www::SeoHelper::CA_SERVICE_AREA, Www::SeoHelper::CA_URL, Www::SeoHelper::CA_VAT_ID, Www::SeoHelper::CA_WAREHOUSE_DEPARTMENT, Www::SeoHelper::CA_WAREHOUSE_HOURS, Www::SeoHelper::COMPANY_EMAIL, Www::SeoHelper::COMPANY_LOGO, Www::SeoHelper::COMPANY_NAME, Www::SeoHelper::COMPANY_SLOGAN, Www::SeoHelper::EXPERTISE, Www::SeoHelper::FAX_NUMBER, Www::SeoHelper::GS1_COMPANY_PREFIX, Www::SeoHelper::ISO6523_CODE, Www::SeoHelper::PAYMENT_METHODS, Www::SeoHelper::PHONE_NUMBER, Www::SeoHelper::PRIMARY_NAICS, Www::SeoHelper::REFUND_TYPE, Www::SeoHelper::RETURN_FEES, Www::SeoHelper::RETURN_METHOD, Www::SeoHelper::RETURN_POLICY_CATEGORY, Www::SeoHelper::SECONDARY_NAICS, Www::SeoHelper::SOCIAL_PROFILES, Www::SeoHelper::US_ADDRESS, Www::SeoHelper::US_BUSINESS_HOURS, Www::SeoHelper::US_CONTACT_POINT, Www::SeoHelper::US_CURRENCIES, Www::SeoHelper::US_DESCRIPTION, Www::SeoHelper::US_FOUNDING_DATE, Www::SeoHelper::US_GLOBAL_LOCATION_NUMBER, Www::SeoHelper::US_IMAGE, Www::SeoHelper::US_LEGAL_NAME, Www::SeoHelper::US_LOCAL_BUSINESS, Www::SeoHelper::US_ONLINE_STORE, Www::SeoHelper::US_RETURN_POLICY, Www::SeoHelper::US_SALES_DEPARTMENT, Www::SeoHelper::US_SERVICE_AREA, Www::SeoHelper::US_TAX_ID, Www::SeoHelper::US_URL, Www::SeoHelper::US_WAREHOUSE_DEPARTMENT, Www::SeoHelper::US_WAREHOUSE_HOURS

Constants included from IconHelper

IconHelper::CUSTOM_ICON_MAP, IconHelper::CUSTOM_SVG_DIR, IconHelper::DEFAULT_FAMILY

Instance Method Summary collapse

Methods included from Controllers::Attachable

#attach, #publication_modal, #remove_attachment, #search_library

Methods inherited from CrmController

#access_denied, #context_id, #context_object, #crm_home_path, #current_ability, #default_url_options, #download_temp, #get_tempfile_path_for_download, #initialize_crm_lazy_chunks, #record_not_found, #redirect_to_job_or_fallback, #render_edit_action, #set_context, #set_download_path, #stash_file_for_temp_download

Methods inherited from ApplicationController

#account_impersonated?, #add_to_flash, #append_token, #bypass_forgery_protection?, #chat_enabled?, #cloudflare_cleared?, #default_catalog, #default_url_options, #enable_turbo_frames, #find_publication, #fix_invalid_accept_header, #init_js_utils, #is_globals_call?, #layout_by_resource, #locale_store, #redirect_to, #require_employee_for_crm, #set_base_host, #set_real_ip, #set_report_errors_for, #should_render_layout?, #stamp_impersonation_context, #warmlyyours_canada_ip?, #warmlyyours_ip?, #y

Methods included from Controllers::ReturnPathHandling

#check_for_return_path, #redirect_to_return_path_or_default

Methods included from Controllers::AnalyticsEvents

#consume_queued_analytics_events, #track_event

Methods included from Controllers::DeviceDetection

#device_detector, #is_ie?

Methods included from Controllers::SubdomainDetection

#is_crm_request?, #is_www_request?, #json_request?

Methods included from Controllers::TrackingDetection

#bot_request?, #gdpr_country?, #gdpr_country_data, #prevent_bots, #set_tracking_cookie, #track_visitor?

Methods included from Controllers::AcceleratedFileSending

#send_file_accelerated, #send_upload_accelerated

Methods included from Controllers::ErrorRendering

#excp_string, #mail_to_for_error_reporting, #render_400, #render_404, #render_406, #render_410, #render_500, #render_invalid_authenticity_token, #render_ip_spoof_error, #safe_referer_or_fallback

Methods included from Controllers::TurnstileVerification

#load_turnstile_script_tag, #turnstile_lazy_widget, #turnstile_script_tag, #turnstile_widget, #validate_turnstile!

Methods included from Controllers::CloudflareCaching

edge_cached, #edge_cached_action?, #reset_cloudflare_cache, #set_cloudflare_cache, #skip_session

Methods included from Controllers::Webpackable

#preload_webpack_fonts, #webpack_css_include, #webpack_css_url, #webpack_js_include, #wpd_is_running?

Methods included from Controllers::Localizable

#cloudflare_country_locale, #determine_request_locale, #geocoder_locale, #guest_user_locale_check, #locale_optional_www_auth_path?, #param_locale, #set_locale, #set_request_locale, #skip_localization?, #warmlyyours_ip_locale

Methods included from Controllers::Authenticable

#access_denied, #authenticate_account, #authenticate_account!, #authenticate_account_from_login_token!, #authenticate_account_from_token!, #check_is_a_manager, #check_is_a_sales_manager, #check_is_an_admin, #check_is_an_employee, #check_party, #clear_mismatched_guest_user, #create_guest_user, #credentials?, #current_or_guest_user, #current_or_guest_user_id_read_only, #current_user, #devise_mapping, #fully_logged_in?, #generate_bot_id, #guest_user, #identifiable?, #init_current_user, #initialize_guest, #load_context_user, #logging_in, #resource, #resource_name, #restrict_access_for_non_employees, #scrubbed_request_path, #user_object, #warn_on_session_guest_id_leak

Methods included from ApplicationHelper

#better_number_to_currency, #check_force_logout, #check_or_cross, #check_or_times, #error_messages, #general_disclaimer_on_product_installation_and_local_codes, #gridjs_from_html_table, #gridjs_table, #is_wy_ip, #line_break, #parent_layout, #pass_or_fail, #render_error_messages_list, #render_video_card, #resolved_auth_form_turbo_frame, #return_path_or, #safe_css_color, #set_return_path_if_present, #set_section_if_present, #tab_frame_id, #to_underscore, #track_page?, #turbo_section_wrapper, #turbo_tabs_request?, #url_on_same_domain_as_request, #widget_index_daily_focus_index_path, #working_hours?, #yes_or_no, #yes_or_no_highlighted, #yes_or_no_with_check_or_cross, #youtube_video

Methods included from UppyUploaderHelper

#file_uploader, #image_uploader, #large_file_uploader_s3, #lead_sketch_uploader, #rma_image_uploader, #rma_image_uploader_s3, #uppy_uploader, #video_uploader

Methods included from Www::ImagesHelper

#image_asset_tag, #image_asset_url

Methods included from Www::SeoHelper

#add_page_schema, #canada?, #company_social_links, #ensure_context_json, #json_ld_script_tag, #local_business_schema, #online_store_id, #online_store_schema, #page_main_entity, #page_main_entity_json, #render_auto_collection_page_schema, #render_collection_page_schema, #render_local_business_schema, #render_online_store_schema, #render_page_schemas, #render_page_video_schemas, #render_webpage_schema, #render_webpage_schema_with_collections, #usa?

Methods included from UrlsHelper

#catalog_breadcrumb_links, #catalog_link, #catalog_link_for_product_line, #catalog_link_for_sku, #cms_link, #delocalized_path, #path_to_sales_product_sku, #path_to_sales_product_sku_for_product_line, #path_to_sales_product_sku_for_product_line_slug, #product_line_from_catalog_link, #protocol_neutral_url, #sanitize_external_url, #valid_external_url?

Methods included from IconHelper

#account_nav_icon, #fa_icon, #star_rating_html

Instance Method Details

#attach_to_partyObject



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'app/controllers/crm/sms_messages_controller.rb', line 181

def attach_to_party
  @sms_message = SmsMessage.find(params[:id])
  if @sms_message.inbound? && @sms_message.sender_party.nil? && new_party_id = params.dig(:attach, :party_id).presence
    @sms_message.sender_party_id = new_party_id
    @sms_message.save
    @sms_message.reload
    # Add this number to the party
    @sms_message.sender_party.contact_points.create!(category: ContactPoint::CELL, detail: @sms_message.sender)
    SmsMessage.match_unknown(numbers: [@sms_message.sender], party: @sms_message.sender_party)
    flash[:info] = "#{@sms_message.sender_party.full_name} attached to message"
  else
    flash[:error] = 'Message is not inbound or already has a party'
  end
  redirect_to_return_path_or_default sms_message_path(@sms_message)
end

#block_senderObject



197
198
199
200
201
202
203
204
205
# File 'app/controllers/crm/sms_messages_controller.rb', line 197

def block_sender
  @sms_message = SmsMessage.find(params[:id])
  if @sms_message.inbound?
    @sms_message.block_sender
  else
    flash[:error] = 'Can only block inbounds'
  end
  redirect_to_return_path_or_default sms_message_path(@sms_message)
end

#createObject



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/controllers/crm/sms_messages_controller.rb', line 74

def create
  # Extract our upload ids
  @sms_message = SmsMessage.new(params[:sms_message])
  authorize!(:create, @sms_message)
  @sms_message.direction = :outbound
  if @sms_message.valid? && @sms_message.send_message
    redirect_to_return_path_or_default redirect_url(@sms_message)
  else
    flash.now[:error] = "Unable to create outbound sms message. #{@sms_message.errors_to_s}"
    load_destination_numbers
    render :new, status: :unprocessable_entity
  end
end

#create_customerObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'app/controllers/crm/sms_messages_controller.rb', line 141

def create_customer
  @sms_message = SmsMessage.find(params[:id])
  if @sms_message.inbound? && @sms_message.sender_party.nil?
    # Try first a match just in case
    @sms_message.match_inbound_sender
    if @sms_message.sender_party
      flash[:info] = "An existing matching party was discovered: #{@sms_message.sender_party.full_name}"
      @sms_message.save!
      redirect_to_return_path_or_default sms_message_path(@sms_message)
    else
      new_customer = {
        person_name: params.dig(:new_customer, :person_name),
        cell: @sms_message.sender,
        source_id: Source.find_by(referral_code: 'SMS'),
        country_iso: @sms_message.from_country_iso
      }
      redirect_to new_customer_identify_path(new_customer: new_customer)
    end
  else
    flash[:error] = 'Cannot create customer from message, message must be inbound and not already have a party'
    redirect_to_return_path_or_default sms_message_path(@sms_message)
  end
end

#destroyObject



122
123
124
125
126
127
128
129
130
131
132
# File 'app/controllers/crm/sms_messages_controller.rb', line 122

def destroy
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:destroy, @sms_message)
  if @sms_message.destroy
    flash[:info] = "SMS Message #{@sms_message.id} deleted"
    redirect_to_return_path_or_default redirect_url(@sms_message)
  else
    flash[:error] = "SMS Message could not be deleted. #{@sms_message.full_messages.join(', ')}"
    redirect_to_return_path_or_default sms_message_path(@sms_message)
  end
end

#destroy_and_block_senderObject



134
135
136
137
138
139
# File 'app/controllers/crm/sms_messages_controller.rb', line 134

def destroy_and_block_sender
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:destroy, @sms_message)
  @sms_message.block_sender
  destroy
end

#do_forwardObject



221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'app/controllers/crm/sms_messages_controller.rb', line 221

def do_forward
  target_employee = Employee.active_employees.find_by(id: params[:target_employee_id])
  unless target_employee
    flash[:error] = 'Employee not found'
    return redirect_to_return_path_or_default sms_message_path(@sms_message)
  end

  target_number = target_employee.sms_enabled_numbers.first
  unless target_number
    flash[:error] = "#{target_employee.full_name} does not have an SMS-enabled number"
    return redirect_to_return_path_or_default sms_message_path(@sms_message)
  end

  if target_employee.id == @sms_message.recipient_party_id
    flash[:warning] = 'Message is already assigned to this employee'
    return redirect_to_return_path_or_default sms_message_path(@sms_message)
  end

  @sms_message.raw_data ||= {}
  @sms_message.raw_data['forwarded_from'] = {
    'original_recipient' => @sms_message.recipient,
    'original_recipient_party_id' => @sms_message.recipient_party_id,
    'forwarded_by' => current_user.id,
    'forwarded_at' => Time.current.iso8601
  }
  @sms_message.recipient = target_number
  @sms_message.recipient_party = target_employee
  @sms_message.unread = true
  # Skip validations: state-machine callbacks (e.g. trigger_send) must not fire
  # on a received message; only recipient, recipient_party_id, unread, and raw_data change.
  @sms_message.save!(validate: false)

  flash[:info] = "Message forwarded to #{target_employee.full_name}"
  redirect_to_return_path_or_default sms_message_path(@sms_message)
end

#editObject



62
63
64
65
66
67
68
69
70
71
72
# File 'app/controllers/crm/sms_messages_controller.rb', line 62

def edit
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:update, @sms_message)
  if @sms_message.new?
    load_destination_numbers
    render :edit
  else
    flash[:error] = 'Only messages in new state can be edited'
    redirect_to_return_path_or_default redirect_url(@sms_message)
  end
end

#forwardObject



217
218
219
# File 'app/controllers/crm/sms_messages_controller.rb', line 217

def forward
  @sms_enabled_employee_options = Employee.sms_enabled_for_select
end

#indexObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'app/controllers/crm/sms_messages_controller.rb', line 5

def index
  authorize!(:show, SmsMessage)
  if (@context_object = context_object)
    @q = @context_object.sms_messages.ransack(params[:q])
    @return_path = polymorphic_path(@context_object, tab: "sms")
    @context_sms_contact_points = sms_enabled_contact_points_for(@context_object)
  else
    @q = SmsMessage.ransack(params[:q])
    @return_path = sms_messages_path(q: params[:q])
    @context_sms_contact_points = ContactPoint.none
  end
  @q.sorts = 'created_at desc' if @q.sorts.blank?
  @pagy, @sms_messages = pagy(@q.result.includes(:recipient_party, :sender_party), limit: params[:per])
  respond_to do |format|
    format.html { render layout: should_render_layout? }
  end
end

#match_inbound_senderObject



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'app/controllers/crm/sms_messages_controller.rb', line 165

def match_inbound_sender
  @sms_message = SmsMessage.find(params[:id])
  if @sms_message.inbound? && @sms_message.sender_party.nil?
    @sms_message.match_inbound_sender
    if @sms_message.sender_party
      flash[:info] = "Found matching party: #{@sms_message.sender_party.full_name}"
      @sms_message.save!
    else
      flash[:warning] = 'No matching party found'
    end
  else
    flash[:error] = 'Cannot create customer from message, message must be inbound and not already have a party'
  end
  redirect_to_return_path_or_default sms_message_path(@sms_message)
end

#newObject



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'app/controllers/crm/sms_messages_controller.rb', line 43

def new
  @sms_message = SmsMessage.new(params[:sms_message] || {})
  authorize!(:create, SmsMessage)
  @original_sms_message = nil
  if params[:mark_as_read_sms_message_id].present?
    @original_sms_message = SmsMessage.find_by(id: params[:mark_as_read_sms_message_id])
    @original_sms_message&.update_attribute(:unread, false)
  end
  # @sms_message.sender_party = current_user
  @sms_message.direction = :outbound
  if sender = current_user.sms_enabled_numbers.first
    @sms_message.sender ||= sender
    load_destination_numbers
  else
    flash[:error] = 'Current user not setup with a work SMS number'
    redirect_to_return_path_or_default redirect_url(@sms_message)
  end
end

#resendObject

If you resend a new message, you're just editing it
If you resend any other state of messages, it's a clone and new



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'app/controllers/crm/sms_messages_controller.rb', line 90

def resend
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:create, @sms_message)
  if @sms_message.outbound?
    load_destination_numbers
    if @sms_message.draft? # only new messages can be edited as is
      render :edit
    else # Clone and send to new
      @sms_message = @sms_message.deep_dup
      render :new
    end
  else
    flash[:error] = 'Can only resend outbound messages'
    redirect_to_return_path_or_default redirect_url(@sms_message)
  end
end

#showObject



30
31
32
33
34
35
36
37
38
39
40
41
# File 'app/controllers/crm/sms_messages_controller.rb', line 30

def show
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:show, @sms_message)
  return unless params[:mark_as_read].to_b || (@sms_message.unread && @sms_message.recipient_party_id == current_user.id)

  @sms_message.update_attribute(:unread, false)
  notice = <<-EOS
      Message was marked as read,
      #{view_context.link_to('undo and mark unread', toggle_unread_sms_message_path(@sms_message, return_path: @return_path), data: { turbo_method: :post })}
  EOS
  flash.now[:notice] = notice
end

#toggle_unreadObject



23
24
25
26
27
28
# File 'app/controllers/crm/sms_messages_controller.rb', line 23

def toggle_unread
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:update, SmsMessage)
  @sms_message.toggle!(:unread) if @sms_message.inbound?
  redirect_to_return_path_or_default redirect_url(@sms_message)
end

#unblock_senderObject



207
208
209
210
211
212
213
214
215
# File 'app/controllers/crm/sms_messages_controller.rb', line 207

def unblock_sender
  @sms_message = SmsMessage.find(params[:id])
  if @sms_message.unblock_sender
    flash[:info] = "Sender #{@sms_message.sender} was unblocked"
  else
    flash[:error] = "Could not unblock #{@sms_message.sender}. Could be already unblocked"
  end
  redirect_to_return_path_or_default sms_message_path(@sms_message)
end

#updateObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'app/controllers/crm/sms_messages_controller.rb', line 107

def update
  @sms_message = SmsMessage.find(params[:id])
  authorize!(:update, @sms_message)
  if @sms_message.update(params[:sms_message])
    if @sms_message.send_message
      flash[:info] = 'SMS message sent'
    else
      flash[:error] = 'Problem sending message'
    end
    redirect_to_return_path_or_default redirect_url(@sms_message)
  else
    render :edit, status: :unprocessable_entity
  end
end