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