call_attempt_repo.rb

 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