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 log.info "starting_call started #{customer.customer_id} #{call_id}"
43 redis.expire(
44 "jmp_customer_ongoing_calls-#{customer.customer_id}",
45 60 * 60
46 )
47 end
48 end
49
50 def ending_call(customer_id, call_id)
51 redis.srem(
52 "jmp_customer_ongoing_calls-#{customer_id}",
53 call_id
54 ).then do |result|
55 log.info "ending_call #{customer_id} #{call_id}", result
56 end
57 end
58
59protected
60
61 def find(customer, other_tel, direction:, **kwargs)
62 find_all(customer, other_tel, direction).then do |(rate, usage, tl, c)|
63 CallAttempt.for(
64 customer: customer, rate: rate, usage: usage,
65 supported:
66 rate &&
67 tl.support_call?(rate, c || 0) &&
68 other_tel !~ /\A\+?1?[94]11\Z/,
69 direction: direction, **kwargs
70 )
71 end
72 end
73
74 def find_all(customer, other_tel, direction)
75 EMPromise.all([
76 find_rate(customer.plan_name, other_tel, direction),
77 find_usage(customer.customer_id),
78 TrustLevelRepo.new(db: db, redis: redis).find(customer),
79 redis.scard("jmp_customer_ongoing_calls-#{customer.customer_id}")
80 ])
81 end
82
83 def find_usage(customer_id)
84 db.query_one(<<~SQL, customer_id, default: { a: 0 }).then { |r| r[:a] }
85 SELECT COALESCE(SUM(charge), 0) AS a FROM cdr_with_charge
86 WHERE
87 customer_id=$1 AND
88 start > DATE_TRUNC('month', LOCALTIMESTAMP)
89 SQL
90 end
91
92 def find_rate(plan_name, other_tel, direction)
93 # || CAD temporary for transitional accounts
94 promise = db.query_one(<<~SQL, plan_name || "CAD", other_tel, direction)
95 SELECT rate FROM call_rates
96 WHERE
97 plan_name=$1 AND
98 $2 LIKE prefix || '%' AND
99 direction=$3
100 ORDER BY prefix DESC
101 LIMIT 1
102 SQL
103 promise.then { |row| row&.dig(:rate) }
104 end
105end