Class: Telephony::Conversation

Inherits:
Base
  • Object
show all
Extended by:
NumberHelper
Includes:
ConversationStateMachine
Defined in:
app/models/telephony/conversation.rb

Defined Under Namespace

Modules: CONVERSATION_TYPES

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NumberHelper

extract_area_code, normalize_number

Class Method Details

.begin!(args) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/models/telephony/conversation.rb', line 23

def self.begin!(args)
  agent = Agent.find_by_csr_id args[:from_id]

  if agent.generate_caller_id?
    caller_id = Telephony.provider.caller_id_for extract_area_code(args[:to])
  else
    caller_id = Telephony.provider.outbound_caller_id
  end

  conversation = transaction do
    conversation = create loan_id:      args[:loan_id],
                          initiator_id: args[:from_id],
                          caller_id:    caller_id

    conversation.calls.create! number:           agent.number,
                               participant_id:   args[:from_id],
                               participant_type: args[:from_type],
                               agent:            agent

    conversation.calls.create! number: args[:to],
                               participant_id:   args[:to_id],
                               participant_type: args[:to_type]
    conversation
  end
  conversation.connect!
  conversation.initiating_call.connect!
  conversation.initiating_call.make!
  conversation
end

.create_inbound!(args) ⇒ Object



71
72
73
# File 'app/models/telephony/conversation.rb', line 71

def self.create_inbound!(args)
  create! args.merge(conversation_type: 'inbound')
end

.find_inbound_calls_with_lock(id) ⇒ Object



65
66
67
68
69
# File 'app/models/telephony/conversation.rb', line 65

def self.find_inbound_calls_with_lock(id)
  transaction do
    yield find(id, joins: :calls, lock: true)
  end
end

.find_inbound_with_lock(id) ⇒ Object



59
60
61
62
63
# File 'app/models/telephony/conversation.rb', line 59

def self.find_inbound_with_lock(id)
  transaction do
    yield find(id, lock: true)
  end
end

.find_with_lock(id) ⇒ Object



53
54
55
56
57
# File 'app/models/telephony/conversation.rb', line 53

def self.find_with_lock(id)
  transaction do
    yield find(id, joins: {calls: :agent}, lock: true, readonly: false)
  end
end

.queue_sizeObject



75
76
77
# File 'app/models/telephony/conversation.rb', line 75

def self.queue_size
  where(state: 'enqueued').count
end

Instance Method Details

#active_agent_legObject



198
199
200
# File 'app/models/telephony/conversation.rb', line 198

def active_agent_leg
  active_agent_legs.first
end

#active_agent_legsObject



192
193
194
195
196
# File 'app/models/telephony/conversation.rb', line 192

def active_agent_legs
  active_on_call.select do |call|
    call.agent.present?
  end
end

#active_on_callObject



83
84
85
# File 'app/models/telephony/conversation.rb', line 83

def active_on_call
  calls.reject(&:terminated?)
end

#as_json(options = {}) ⇒ Object



180
181
182
# File 'app/models/telephony/conversation.rb', line 180

def as_json(options={})
  super({ include: { calls: { include: :recordings } } }.deep_merge(options))
end

#check_for_successful_holdObject



92
93
94
# File 'app/models/telephony/conversation.rb', line 92

def check_for_successful_hold
  complete_hold if all_agents_in_conference? && customer.in_progress_hold?
end

#check_for_successful_resumeObject



96
97
98
# File 'app/models/telephony/conversation.rb', line 96

def check_for_successful_resume
  complete_resume if all_agents_in_conference? && customer.in_conference?
end

#check_for_successful_transferObject



87
88
89
90
# File 'app/models/telephony/conversation.rb', line 87

def check_for_successful_transfer
  complete_two_step_transfer if all_agents_in_conference? &&
                                (customer.in_conference? || customer.in_progress_hold?)
end

#check_for_terminateObject



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'app/models/telephony/conversation.rb', line 109

def check_for_terminate
  if active_on_call.size == 0
    terminate! unless terminated?
  elsif one_step_transferring? && active_on_call.size == 1
    fail_one_step_transfer!
  elsif leaving_voicemail? && active_on_call.size == 1
    # noop
  elsif inbound? && connecting? && active_on_call.first == customer
    rona!
  elsif active_on_call.size == 1
    lone_call = active_on_call.first
    if lone_call.in_conference? || lone_call.in_progress_hold?
      Telephony.provider.hangup lone_call.sid if lone_call.sid
    end
    lone_call.terminate!
  elsif (two_step_transferring? || two_step_transferring_hold?) && active_on_call.size == 2
    fail_two_step_transfer!
  elsif (in_progress_two_step_transfer? || in_progress_two_step_transfer_hold?) && active_on_call.size == 2 && customer.terminated?
    customer_left_two_step_transfer!
  elsif (in_progress_two_step_transfer? || in_progress_two_step_transfer_hold?) && active_on_call.size == 2
    leave_two_step_transfer!
  end
end

#child_call(sid = nil) ⇒ Object



133
134
135
# File 'app/models/telephony/conversation.rb', line 133

def child_call(sid=nil)
  (sid && calls.detect { |c| c.sid == sid }) || active_on_call[1]
end

#customerObject



137
138
139
# File 'app/models/telephony/conversation.rb', line 137

def customer
  calls.detect { |call| !call.agent? }
end

#first_active_agentObject



202
203
204
205
# File 'app/models/telephony/conversation.rb', line 202

def first_active_agent
  leg = active_agent_legs[0]
  leg.agent if leg
end

#first_inactive_agentObject



207
208
209
210
211
212
# File 'app/models/telephony/conversation.rb', line 207

def first_inactive_agent
  leg = calls.detect do |call|
    call.agent? && call.terminated?
  end
  leg.agent if leg
end

#hold!Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'app/models/telephony/conversation.rb', line 145

def hold!
  initiate_hold!

  if customer.in_conference?
    customer.redirect_to_hold
    if active_agent_legs.size == 1
      # If there's only one agent on, redirect them so they
      # get the conference music
      active_agent_leg.redirect_to_conference
    end
  elsif customer == child_call
    customer.redirect_to_hold
  else
    child_call.redirect_to_conference
  end
end

#inbound?Boolean

Returns:

  • (Boolean)


188
189
190
# File 'app/models/telephony/conversation.rb', line 188

def inbound?
  conversation_type == CONVERSATION_TYPES::INBOUND
end

#initiating_callObject



141
142
143
# File 'app/models/telephony/conversation.rb', line 141

def initiating_call
  calls.first
end

#not_initiated_callObject



79
80
81
# File 'app/models/telephony/conversation.rb', line 79

def not_initiated_call
  calls.detect(&:not_initiated?)
end

#outbound?Boolean

Returns:

  • (Boolean)


184
185
186
# File 'app/models/telephony/conversation.rb', line 184

def outbound?
  conversation_type == CONVERSATION_TYPES::OUTBOUND
end

#resume!Object



162
163
164
165
# File 'app/models/telephony/conversation.rb', line 162

def resume!
   initiate_resume!
   customer.redirect_to_conference
end

#second_active_agentObject



214
215
216
217
# File 'app/models/telephony/conversation.rb', line 214

def second_active_agent
  leg = active_agent_legs[1]
  leg.agent if leg
end

#terminate_conferenced_calls(except_call_id) ⇒ Object



100
101
102
103
104
105
106
107
# File 'app/models/telephony/conversation.rb', line 100

def terminate_conferenced_calls(except_call_id)
  calls.select(&:in_conference?).each do |call|
    if call.id != except_call_id
      Telephony.provider.hangup call.sid
      call.terminate!
    end
  end
end

#transfer!(csr_id, one_step) ⇒ Object



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

def transfer!(csr_id, one_step)
  unless in_progress? || in_progress_hold?
    errors[:base] << "Conversation already #{state}"
    return false
  end

  agent = Agent.find_by_csr_id csr_id

  agent.with_lock do
    one_step ? one_step_transfer!(agent) : two_step_transfer!(agent)
  end
end