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