call_attempt_repo.rb

 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