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