customer_info.rb

  1# frozen_string_literal: true
  2
  3require "bigdecimal"
  4require "forwardable"
  5require "relative_time"
  6require "value_semantics/monkey_patched"
  7require_relative "proxied_jid"
  8require_relative "customer_plan"
  9require_relative "form_template"
 10require_relative "promise_hash"
 11
 12class PlanInfo
 13	extend Forwardable
 14
 15	def_delegators :plan, :expires_at, :auto_top_up_amount
 16
 17	def self.for(plan)
 18		return EMPromise.resolve(NoPlan.new) unless plan&.plan_name
 19
 20		plan.activation_date.then do |adate|
 21			new(plan: plan, start_date: adate)
 22		end
 23	end
 24
 25	class NoPlan
 26		def template
 27			FormTemplate.new("")
 28		end
 29
 30		def admin_template
 31			FormTemplate.new("")
 32		end
 33
 34		def status
 35			"Transitional"
 36		end
 37	end
 38
 39	value_semantics do
 40		plan CustomerPlan
 41		start_date Time
 42	end
 43
 44	def template
 45		FormTemplate.for("plan_info", plan_info: self)
 46	end
 47
 48	def admin_template
 49		FormTemplate.for("admin_plan_info", plan_info: self)
 50	end
 51
 52	def monthly_price
 53		"$%.4f / month" % plan.monthly_price
 54	end
 55
 56	def relative_start_date
 57		RelativeTime.in_words(start_date)
 58	end
 59
 60	def formatted_start_date
 61		start_date.strftime("%Y-%m-%d %H:%M:%S")
 62	end
 63
 64	def currency
 65		(plan.currency || "No Currency").to_s
 66	end
 67
 68	def status
 69		plan.active? ? "Active" : "Expired"
 70	end
 71end
 72
 73class CustomerInfo
 74	value_semantics do
 75		plan_info Either(PlanInfo, PlanInfo::NoPlan)
 76		tel Either(String, nil)
 77		balance BigDecimal
 78		cnam Either(String, nil)
 79	end
 80
 81	def self.for(customer, plan)
 82		PromiseHash.all(
 83			plan_info: PlanInfo.for(plan),
 84			tel: customer.registered? ? customer.registered?.phone : nil,
 85			balance: customer.balance,
 86			cnam: customer.tndetails.dig(:features, :lidb, :subscriber_information)
 87		).then(&method(:new))
 88	end
 89
 90	def form
 91		FormTemplate.render("customer_info", info: self)
 92	end
 93end
 94
 95class AdminInfo
 96	value_semantics do
 97		jid ProxiedJID, coerce: ProxiedJID.method(:new)
 98		customer_id String
 99		fwd Either(CustomerFwd, nil)
100		info CustomerInfo
101		api API
102		call_info String
103	end
104
105	def self.for(customer, plan)
106		PromiseHash.all(
107			jid: customer.jid,
108			customer_id: customer.customer_id,
109			fwd: customer.fwd,
110			info: CustomerInfo.for(customer, plan),
111			api: customer.api,
112			call_info: call_info(customer)
113		).then(&method(:new))
114	end
115
116	class FakeLowBalance
117		def self.for(_)
118			self
119		end
120
121		def self.notify!
122			EMPromise.resolve(0)
123		end
124	end
125
126	def self.call_info(customer)
127		if customer.registered?
128			CallAttemptRepo.new
129				.find_outbound(customer, "+1", call_id: "", low_balance: FakeLowBalance)
130				.then(&:to_s)
131		else
132			EMPromise.resolve("No calling")
133		end
134	end
135
136	def form
137		FormTemplate.render("admin_info", admin_info: self)
138	end
139
140	def tel_link
141		[
142			"https://dashboard.bandwidth.com/portal/r/a",
143			CONFIG[:creds][:account],
144			"numbers/details",
145			info.tel.gsub(/\A\+1/, "")
146		].join("/")
147	end
148end