# frozen_string_literal: true
require "bigdecimal"
require "forwardable"
require "relative_time"
require "value_semantics/monkey_patched"
require_relative "api"
require_relative "call_attempt_repo"
require_relative "customer"
require_relative "customer_plan"
require_relative "form_template"
require_relative "promise_hash"
require_relative "proxied_jid"
class PlanInfo
extend Forwardable
def_delegators :customer, :expires_at, :auto_top_up_amount
def self.for(customer)
return EMPromise.resolve(NoPlan.new) unless customer&.plan_name
PromiseHash.all(
customer: customer,
start_date: customer.activation_date,
calling_charges_this_month: customer.calling_charges_this_month
).then(method(:new))
end
class NoPlan
def template
FormTemplate.new("")
end
def admin_template
FormTemplate.new("")
end
def status
"Transitional"
end
end
value_semantics do
method_missing :customer, Customer
start_date Time
calling_charges_this_month BigDecimal
end
def template
FormTemplate.for("plan_info", plan_info: self)
end
def admin_template
FormTemplate.for("admin_plan_info", plan_info: self)
end
def monthly_price
"$%.4f / month" % customer.monthly_price
end
def relative_start_date
RelativeTime.in_words(start_date)
end
def formatted_start_date
start_date.strftime("%Y-%m-%d %H:%M:%S")
end
def currency
(customer.currency || "No Currency").to_s
end
def status
customer.active? ? "Active" : "Expired"
end
def remaining_included_calling_credit
[customer.minute_limit.to_d - calling_charges_this_month, 0].max
end
end
class CustomerInfo
value_semantics do
plan_info Either(PlanInfo, PlanInfo::NoPlan)
tel Either(String, nil)
balance BigDecimal
cnam Either(String, nil)
end
def self.for(customer)
PromiseHash.all(
plan_info: PlanInfo.for(customer),
tel: customer.registered? ? customer.registered?.phone : nil,
balance: customer.balance,
cnam: customer.tndetails.dig(:features, :lidb, :subscriber_information)
).then(&method(:new))
end
def form
FormTemplate.render("customer_info", info: self)
end
end
class AdminInfo
value_semantics do
jid ProxiedJID, coerce: ProxiedJID.method(:new)
customer_id String
fwd Either(CustomerFwd, nil)
info CustomerInfo
api API
call_info String
trust_level String
end
def self.for(
customer,
trust_level_repo: TrustLevelRepo.new,
call_attempt_repo: CallAttemptRepo.new
)
PromiseHash.all(
jid: customer.jid,
customer_id: customer.customer_id,
fwd: customer.fwd,
info: CustomerInfo.for(customer),
api: API.for(customer),
call_info: call_info(customer, call_attempt_repo),
trust_level: trust_level_repo.find(customer).then(&:to_s)
).then(&method(:new))
end
class FakeLowBalance
def self.for(_)
self
end
def self.notify!
EMPromise.resolve(0)
end
end
def self.call_info(customer, call_attempt_repo)
if customer.registered?
call_attempt_repo
.find_outbound(customer, "+1", call_id: "dry_run")
.then(&:to_s)
else
EMPromise.resolve("No calling")
end
end
def form
FormTemplate.render("admin_info", admin_info: self)
end
def tel_link
[
"https://dashboard.bandwidth.com/portal/r/a",
CONFIG[:creds][:account],
"numbers/details",
info.tel.gsub(/\A\+1/, "")
].join("/")
end
end