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 trust_level String
104 end
105
106 def self.for(
107 customer, plan,
108 trust_level_repo: TrustLevelRepo.new,
109 call_attempt_repo: CallAttemptRepo.new
110 )
111 PromiseHash.all(
112 jid: customer.jid,
113 customer_id: customer.customer_id,
114 fwd: customer.fwd,
115 info: CustomerInfo.for(customer, plan),
116 api: customer.api,
117 call_info: call_info(customer, call_attempt_repo),
118 trust_level: trust_level_repo.find(customer).then(&:to_s)
119 ).then(&method(:new))
120 end
121
122 class FakeLowBalance
123 def self.for(_)
124 self
125 end
126
127 def self.notify!
128 EMPromise.resolve(0)
129 end
130 end
131
132 def self.call_info(customer, call_attempt_repo)
133 if customer.registered?
134 call_attempt_repo
135 .find_outbound(customer, "+1", call_id: "dry_run")
136 .then(&:to_s)
137 else
138 EMPromise.resolve("No calling")
139 end
140 end
141
142 def form
143 FormTemplate.render("admin_info", admin_info: self)
144 end
145
146 def tel_link
147 [
148 "https://dashboard.bandwidth.com/portal/r/a",
149 CONFIG[:creds][:account],
150 "numbers/details",
151 info.tel.gsub(/\A\+1/, "")
152 ].join("/")
153 end
154end