1# frozen_string_literal: true
2
3require "value_semantics/monkey_patched"
4require "lazy_object"
5
6require_relative "call_attempt"
7require_relative "trust_level_repo"
8
9class CallAttemptRepo
10 value_semantics do
11 db Anything(), default: LazyObject.new { DB }
12 redis Anything(), default: LazyObject.new { REDIS }
13 end
14
15 def find_outbound(customer, to, **kwargs)
16 find(
17 customer,
18 to,
19 direction: :outbound,
20 from: customer.registered?.phone,
21 to: to,
22 **kwargs
23 )
24 end
25
26 def find_inbound(customer, from, **kwargs)
27 find(
28 customer,
29 from,
30 direction: :inbound,
31 from: from,
32 to: customer.registered?.phone,
33 **kwargs
34 )
35 end
36
37 def starting_call(customer, call_id)
38 redis.sadd(
39 "jmp_customer_ongoing_calls-#{customer.customer_id}",
40 call_id
41 ).then do
42 redis.expire(
43 "jmp_customer_ongoing_calls-#{customer.customer_id}",
44 60 * 60
45 )
46 end
47 end
48
49 def ending_call(customer_id, call_id)
50 redis.srem(
51 "jmp_customer_ongoing_calls-#{customer_id}",
52 call_id
53 ).then do |result|
54 log.info "ending_call #{customer_id} #{call_id}", result
55 end
56 end
57
58protected
59
60 def find(customer, other_tel, direction:, **kwargs)
61 find_all(customer, other_tel, direction).then do |(rate, usage, tl, c)|
62 CallAttempt.for(
63 customer: customer, rate: rate, usage: usage,
64 supported:
65 rate &&
66 tl.support_call?(rate, c || 0) &&
67 other_tel !~ /\A\+?1?[94]11\Z/,
68 direction: direction, **kwargs
69 )
70 end
71 end
72
73 def find_all(customer, other_tel, direction)
74 EMPromise.all([
75 find_rate(customer.plan_name, other_tel, direction),
76 find_usage(customer.customer_id),
77 TrustLevelRepo.new(db: db, redis: redis).find(customer),
78 redis.scard("jmp_customer_ongoing_calls-#{customer.customer_id}")
79 ])
80 end
81
82 def find_usage(customer_id)
83 db.query_one(<<~SQL, customer_id, default: { a: 0 }).then { |r| r[:a] }
84 SELECT COALESCE(SUM(charge), 0) AS a FROM cdr_with_charge
85 WHERE
86 customer_id=$1 AND
87 start > DATE_TRUNC('month', LOCALTIMESTAMP)
88 SQL
89 end
90
91 def find_rate(plan_name, other_tel, direction)
92 # || CAD temporary for transitional accounts
93 promise = db.query_one(<<~SQL, plan_name || "CAD", other_tel, direction)
94 SELECT rate FROM call_rates
95 WHERE
96 plan_name=$1 AND
97 $2 LIKE prefix || '%' AND
98 direction=$3
99 ORDER BY prefix DESC
100 LIMIT 1
101 SQL
102 promise.then { |row| row&.dig(:rate) }
103 end
104end