Class: Phone::CallLogEventToRecordMatcher

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

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Instance Method Details

#find_call_record(cle) ⇒ Object



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
# File 'app/services/phone/call_log_event_to_record_matcher.rb', line 27

def find_call_record(cle)
  begin
    # Extract parts of the call log event
    caller_id,duration_raw = parse_display_string(cle.display)
    # Caller ID parse
    caller_id = CallRecord.parse_phone_number(caller_id) || caller_id
    require 'chronic_duration'
    duration_in_seconds = (ChronicDuration.parse(duration_raw) rescue nil) || 0
    # If duration is not parseable it is probably zero
    if caller_id.blank? || duration_in_seconds.nil? || duration_in_seconds == 0
      logger.warn "Call Log Event #{cle} has no duration or caller id, aborting"
      return nil
    end
    # Now try to match
    start_time = cle.call_log.start_time
    end_time = start_time + (cle.call_log.total_duration || 60)
    talk_time_min = (duration_in_seconds * 0.95).round
    logger.info "Looking for a call record between #{start_time} and #{end_time} talking to #{caller_id} for #{duration_raw}"
    call_records = CallRecord.where( "origin_number = :caller_id OR destination_number = :caller_id", caller_id: caller_id).
                              where( created_at: start_time..end_time ).
                              where( "duration_secs IS NULL OR duration_secs >= ?", talk_time_min).
                              where.not("exists(select 1 from call_log_events where call_log_events.call_record_id = call_records.id)").
                              order(Arel.sql("@ extract(epoch from('#{start_time.to_fs(:db)}'::timestamp - call_records.created_at)), @ #{duration_in_seconds} - COALESCE(duration_secs,0)"))
    call_record = call_records.first
    logger.info call_record ? "Found #{call_record}" : "Did not find a call record for #{cle}"
  rescue StandardError => exc
    logger.error "Exception while processing call log event #{cle}, #{exc.to_s}"
    return nil
  end
  call_record
end

#load_call_log_events(options) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'app/services/phone/call_log_event_to_record_matcher.rb', line 59

def load_call_log_events(options)
  if options[:call_log_events].present?
    call_log_events = options[:call_log_events]
  elsif options[:call_log_event_ids].present?
    call_log_events = CallLogEvent.where(id: options[:call_log_event_ids])
  elsif options[:call_log_ids].present?
    call_log_events = CallLogEvent.where(call_log_id: options[:call_log_ids])
  else
    call_log_events = CallLogEvent.where(call_record_id: nil)
  end
  # Filter only leg type TALKING
  call_log_events = call_log_events.where(leg_type: 'TALKING').order(:start_time).reverse_order
  # Include call_logs
  call_log_events = call_log_events.includes(:call_log)
  # Filter by start time
  call_log_events = call_log_events.where(CallLogEvent[:start_time].gteq(options[:start_time])) if options[:start_time]
  # Filter by limit
  call_log_events = call_log_events.limit(options[:limit]) if options[:limit].present?
  logger.info "Loaded #{call_log_events.size} call log event(s) to process"

  call_log_events
end

#parse_display_string(display) ⇒ Object



86
87
88
# File 'app/services/phone/call_log_event_to_record_matcher.rb', line 86

def parse_display_string(display)
  display.scan(/\ATalked\sto.*\<(\d{3,})\>\sfor\s(.*)\z/).flatten
end

#process(options = {}) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'app/services/phone/call_log_event_to_record_matcher.rb', line 7

def process(options={})
  # Get all call logs
  call_log_events = load_call_log_events(options)
  records_processed,records_matched,records_unmatched = 0,0,0
  total_events = call_log_events.size
  call_log_events.find_each do |cle|
    records_processed += 1
    logger.info "CallLogEventToRecordMatcher #{(records_processed*100/total_events).round}% [#{records_processed}/#{total_events}] - Processing #{cle}"
    if cr = find_call_record(cle)
      records_matched += 1
      cle.update_column(:call_record_id, cr.id)
    else
      records_unmatched += 1
    end
  end
  return Result.new(records_processed: records_processed,
                    records_matched: records_matched,
                    records_unmatched: records_unmatched)
end


82
83
84
# File 'app/services/phone/call_log_event_to_record_matcher.rb', line 82

def reset_call_record_link(call_log_events=nil)
  (call_log_events || CallRecord.all).update_all(call_record_id: nil)
end