Class: Phone::CallLogImporter

Inherits:
BaseService
  • Object
show all
Defined in:
app/services/phone/call_log_importer.rb

Overview

Service object: call log importer.

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Instance Method Details

#build_call_log_events_from_cdr(call_detail_record) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'app/services/phone/call_log_importer.rb', line 87

def build_call_log_events_from_cdr(call_detail_record)
  call_log_events = []
  call_log_event_count = 0
  # Pipe all events into the bulk insertion array
  call_detail_record.events.event.each do |call_detail_record_event|
    call_log_event_count += 1
    # only log talking legs after 20 events, it probably is a forever looping call
    # and the data is unusable anyway
    next unless call_log_event_count < 20 || call_detail_record_event[:type] == 'TALKING'

    call_log_event = CallLogEvent.new(
      cdr_call_id: call_detail_record.cdr_call_id,
      start_time:  call_detail_record_event[:start_time],
      leg_type: call_detail_record_event[:type],
      display: call_detail_record_event[:display]
    )
    call_log_events << call_log_event
  end
  call_log_events.uniq
end

#build_from_cdr(call_detail_record) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'app/services/phone/call_log_importer.rb', line 67

def build_from_cdr(call_detail_record)
  CallLog.new(
    origination: call_detail_record.origination,
    start_time: call_detail_record.start_time,
    from_account_id: call_detail_record.,
    from: call_detail_record.from,
    from_number: CallLog.parse_phone_number(call_detail_record.from_number),
    to_account_id: call_detail_record.,
    to: call_detail_record.to,
    to_number: CallLog.parse_phone_number(call_detail_record.to_number),
    # Schema declares total_duration/talk_duration NOT NULL DEFAULT 0; without
    # the .compact in insert_all (see process), an explicit nil here would
    # surface as a NOT NULL violation. Coerce to 0 to preserve the column
    # default semantics activerecord-import used to provide.
    total_duration: call_detail_record.total_duration || 0,
    talk_duration: call_detail_record.talk_duration || 0,
    cdr_call_id: call_detail_record.cdr_call_id
  )
end

#process(start_time_override: nil, end_time_override: nil) ⇒ Object



9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'app/services/phone/call_log_importer.rb', line 9

def process(start_time_override: nil, end_time_override: nil)
  # Find last import date
  start_time = start_time_override || (CallLog.maximum(:start_time) - 1.hour)
  end_time = [end_time_override || Date.current.end_of_day, start_time].max

  pbx = Phone::Pbx.instance
  params = {
    'start_date' => start_time,
    'end_date' => end_time
  }

  total_call_logs = 0
  total_call_log_events = 0

  pbx.call_log_search(params) do |calls|
    # Prep a massive insertion array
    call_log_events = []
    call_logs = []
    calls.each do |call_detail_record|
      call_logs << build_from_cdr(call_detail_record)
      # Extract our call log events
      call_log_events += build_call_log_events_from_cdr(call_detail_record)
    end
    total_call_logs += call_logs.size
    total_call_log_events += call_log_events.size
    # Bulk insert boom !
    # `.compact` produced heterogeneous key sets across rows (nil patterns
    # differ per CDR), which Rails 7.2 native `insert_all` rejects with
    # "All objects being inserted must have the same keys" (AppSignal #4952).
    # `activerecord-import` (replaced in the 7.2 PR) silently filled missing
    # keys with column defaults; we have to do that ourselves now. Drop only
    # the auto-incremented `id` so all rows expose the same union of columns.
    CallLog.insert_all(call_logs.map { |c| c.attributes.except('id') }) if call_logs.any?
    CallLogEvent.insert_all(call_log_events.map { |c| c.attributes.except('id') }) if call_log_events.any?
    Rails.logger.debug("Inserted call logs", count: call_logs.size)
    Rails.logger.debug("Inserted call log events", count: call_log_events.size)
  end

  if total_call_logs > 0
    # Match call log recently imported and see if we have a callrail data to enhance them (campaign, etc)
    Phone::ImportCallRailData.new.process(start_time)

    # Perform match on from party id, etc.  We go back 1 week in the call log
    # in case new data (such as customer phone number) are present since then
    match_results = Phone::CallLogPartyMatcher.new.process(start_time)
  end

  logger.debug("Call log import complete", total_logs: total_call_logs, total_events: total_call_log_events)

  Result.new(
      total_call_logs: total_call_logs,
      total_call_log_events: total_call_log_events,
      match_results: match_results,
      start_time: start_time,
      end_time: end_time
    )
end