1# frozen_string_literal: true
2
3require "value_semantics/monkey_patched"
4require "lazy_object"
5
6require_relative "call_attempt"
7
8class CallAttemptRepo
9 value_semantics do
10 db Anything(), default: LazyObject.new { DB }
11 end
12
13 def find_outbound(customer, to, **kwargs)
14 find(
15 customer,
16 to,
17 direction: :outbound,
18 from: customer.registered?.phone,
19 to: to,
20 **kwargs
21 )
22 end
23
24 def find_inbound(customer, from, **kwargs)
25 find(
26 customer,
27 from,
28 direction: :inbound,
29 from: from,
30 to: customer.registered?.phone,
31 **kwargs
32 )
33 end
34
35protected
36
37 def find(customer, other_tel, direction:, **kwargs)
38 EMPromise.all([
39 find_rate(customer.plan_name, other_tel, direction),
40 find_usage(customer.customer_id)
41 ]).then do |(rate, usage)|
42 CallAttempt.for(
43 customer, rate, usage, direction: direction, **kwargs
44 )
45 end
46 end
47
48 def find_usage(customer_id)
49 promise = db.query_defer(<<~SQL, [customer_id])
50 SELECT COALESCE(SUM(charge), 0) AS a FROM cdr_with_charge
51 WHERE
52 customer_id=$1 AND
53 start > DATE_TRUNC('month', LOCALTIMESTAMP)
54 SQL
55 promise.then { |rows| rows.first&.dig("a") || 0 }
56 end
57
58 def find_rate(plan_name, other_tel, direction)
59 promise = db.query_defer(<<~SQL, [plan_name, other_tel, direction])
60 SELECT rate FROM call_rates
61 WHERE
62 plan_name=$1 AND
63 $2 LIKE prefix || '%' AND
64 direction=$3
65 ORDER BY prefix DESC
66 LIMIT 1;
67 SQL
68 promise.then { |rows| rows.first&.dig("rate") }
69 end
70end