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), coerce: :to_sym.to_proc
34 rate Either(nil, BigDecimal), default: nil
35 charge Either(nil, BigDecimal), default: nil
36 end
37
38 def formatted_rate
39 "$%.4f" % rate
40 end
41
42 def formatted_charge
43 "$%.4f" % charge
44 end
45
46 def duration
47 "%02d:%02d:%02d" % [
48 billsec / (60 * 60),
49 billsec % (60 * 60) / 60,
50 billsec % 60
51 ]
52 end
53
54 def self.for(event, **kwargs)
55 start = Time.parse(event["startTime"])
56
57 new({
58 cdr_id: "sgx-jmp/#{event['callId']}",
59 start: start,
60 billsec: (Time.parse(event["endTime"]) - start).ceil,
61 disposition: Disposition.for(event["cause"], event["tag"])
62 }.merge(kwargs))
63 end
64
65 def self.for_inbound(customer_id, event)
66 self.for(
67 event,
68 customer_id: customer_id,
69 tel: event["from"],
70 direction: :inbound
71 )
72 end
73
74 def self.for_outbound(customer_id, event)
75 self.for(
76 event,
77 customer_id: customer_id,
78 tel: event["to"],
79 direction: :outbound
80 )
81 end
82end