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