cdr.rb

 1# frozen_string_literal: true
 2
 3require "value_semantics/monkey_patched"
 4
 5class CDR
 6	module Disposition
 7		def self.===(other)
 8			["NO ANSWER", "ANSWERED", "BUSY", "FAILED", "VOICEMAIL"].include?(other)
 9		end
10
11		CAUSES = {
12			timeout: "NO ANSWER",
13			rejected: "NO ANSWER",
14			cancel: "NO ANSWER",
15			hangup: "ANSWERED",
16			busy: "BUSY"
17		}.freeze
18
19		def self.for(cause, tag)
20			return tag if tag == "VOICEMAIL"
21
22			CAUSES.fetch(cause.to_sym, "FAILED")
23		end
24	end
25
26	value_semantics do
27		cdr_id String
28		customer_id String
29		start Time
30		billsec Integer
31		disposition Disposition
32		tel(/\A\+\d+\Z/)
33		direction Either(:inbound, :outbound)
34	end
35
36	def self.for(event, **kwargs)
37		start = Time.parse(event["startTime"])
38
39		new({
40			cdr_id: "sgx-jmp/#{event['callId']}",
41			start: start,
42			billsec: (Time.parse(event["endTime"]) - start).ceil,
43			disposition: Disposition.for(event["cause"], event["tag"])
44		}.merge(kwargs))
45	end
46
47	def self.for_inbound(customer_id, event)
48		self.for(
49			event,
50			customer_id: customer_id,
51			tel: event["from"],
52			direction: :inbound
53		)
54	end
55
56	def self.for_outbound(event)
57		self.for(
58			event,
59			customer_id: event["from"].sub(/^\+/, ""),
60			tel: event["to"],
61			direction: :outbound
62		)
63	end
64
65	def save
66		columns, values = to_h.to_a.transpose
67		DB.query_defer(<<~SQL, values)
68			INSERT INTO cdr (#{columns.join(',')})
69			VALUES ($1, $2, $3, $4, $5, $6, $7)
70		SQL
71	end
72end