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
37protected
38
39 def find(customer, other_tel, direction:, **kwargs)
40 EMPromise.all([
41 find_rate(customer.plan_name, other_tel, direction),
42 find_usage(customer.customer_id),
43 TrustLevelRepo.new(db: db, redis: redis).find(customer)
44 ]).then do |(rate, usage, trust_level)|
45 CallAttempt.for(
46 customer, rate, usage, trust_level, direction: direction, **kwargs
47 )
48 end
49 end
50
51 def find_usage(customer_id)
52 promise = db.query_defer(<<~SQL, [customer_id])
53 SELECT COALESCE(SUM(charge), 0) AS a FROM cdr_with_charge
54 WHERE
55 customer_id=$1 AND
56 start > DATE_TRUNC('month', LOCALTIMESTAMP)
57 SQL
58 promise.then { |rows| rows.first&.dig("a") || 0 }
59 end
60
61 def find_rate(plan_name, other_tel, direction)
62 promise = db.query_defer(<<~SQL, [plan_name, other_tel, direction])
63 SELECT rate FROM call_rates
64 WHERE
65 plan_name=$1 AND
66 $2 LIKE prefix || '%' AND
67 direction=$3
68 ORDER BY prefix DESC
69 LIMIT 1;
70 SQL
71 promise.then { |rows| rows.first&.dig("rate") }
72 end
73end