1# frozen_string_literal: true
2
3require "delegate"
4
5module TrustLevel
6 def self.for(plan_name:, settled_amount: 0, manual: nil)
7 @levels.each do |level|
8 tl = level.call(
9 plan_name: plan_name,
10 settled_amount: settled_amount,
11 manual: manual
12 )
13 return manual ? Manual.new(tl) : tl if tl
14 end
15
16 raise "No TrustLevel matched"
17 end
18
19 def self.register(&maybe_mk)
20 @levels ||= []
21 @levels << maybe_mk
22 end
23
24 class Manual < SimpleDelegator
25 def to_s
26 "Manual(#{super})"
27 end
28 end
29
30 class Tomb
31 TrustLevel.register do |manual:, **|
32 new if manual == "Tomb"
33 end
34
35 def max_top_up_amount
36 0
37 end
38
39 def write_cdr?
40 false
41 end
42
43 def support_call?(*)
44 false
45 end
46
47 def send_message?(*)
48 false
49 end
50
51 def validate_credit_card_transaction!(_amount, _declines)
52 # Give a more ambiguous error so they don't know they're tombed.
53 raise DeclinedError
54 end
55
56 def create_subaccount?(*)
57 false
58 end
59
60 def to_s
61 "Tomb"
62 end
63 end
64
65 class Basement
66 TrustLevel.register do |manual:, settled_amount:, **|
67 new if manual == "Basement" || (!manual && settled_amount < 10)
68 end
69
70 def max_top_up_amount
71 35
72 end
73
74 def max_declines
75 2
76 end
77
78 def write_cdr?
79 true
80 end
81
82 def support_call?(rate, concurrency)
83 rate <= 0.02 && concurrency < 1
84 end
85
86 def send_message?(messages_today)
87 messages_today < 40
88 end
89
90 def validate_credit_card_transaction!(amount, declines)
91 raise DeclinedError.new(declines, max_declines) if declines > max_declines
92 return unless amount > max_top_up_amount
93
94 raise AmountTooHighError.new(amount, max_top_up_amount)
95 end
96
97 def create_subaccount?(already_have)
98 already_have < 2
99 end
100
101 def to_s
102 "Basement"
103 end
104 end
105
106 class Paragon
107 TrustLevel.register do |manual:, settled_amount:, **|
108 new if manual == "Paragon" || (!manual && settled_amount > 60)
109 end
110
111 def max_top_up_amount
112 500
113 end
114
115 def max_declines
116 3
117 end
118
119 def write_cdr?
120 true
121 end
122
123 def support_call?(_, concurrency)
124 concurrency < 10
125 end
126
127 def send_message?(messages_today)
128 messages_today < 700
129 end
130
131 def validate_credit_card_transaction!(amount, declines)
132 raise DeclinedError.new(declines, max_declines) if declines > max_declines
133 return unless amount > max_top_up_amount
134
135 raise AmountTooHighError.new(amount, max_top_up_amount)
136 end
137
138 def create_subaccount?(already_have)
139 already_have < 10
140 end
141
142 def to_s
143 "Paragon"
144 end
145 end
146
147 class Olympias
148 TrustLevel.register do |manual:, **|
149 new if manual == "Olympias"
150 end
151
152 def write_cdr?
153 true
154 end
155
156 def support_call?(*)
157 true
158 end
159
160 def send_message?(*)
161 true
162 end
163
164 def validate_credit_card_transaction!(*) end
165
166 def create_subaccount?(*)
167 true
168 end
169
170 def to_s
171 "Olympias"
172 end
173 end
174
175 class Customer
176 TrustLevel.register do |manual:, plan_name:, **|
177 if manual && manual != "Customer"
178 Sentry.capture_message("Unknown TrustLevel: #{manual}")
179 end
180
181 new(plan_name)
182 end
183
184 EXPENSIVE_ROUTE = {
185 "usd_beta_unlimited-v20210223" => 0.9,
186 "USD" => 0.9,
187 "cad_beta_unlimited-v20210223" => 1.1,
188 "CAD" => 1.1
189 }.freeze
190
191 def initialize(plan_name)
192 @max_rate = EXPENSIVE_ROUTE.fetch(plan_name, 0.1)
193 end
194
195 def max_top_up_amount
196 130
197 end
198
199 def max_declines
200 2
201 end
202
203 def write_cdr?
204 true
205 end
206
207 def support_call?(rate, concurrency)
208 rate <= @max_rate && concurrency < 4
209 end
210
211 def send_message?(messages_today)
212 messages_today < 500
213 end
214
215 def validate_credit_card_transaction!(amount, declines)
216 raise DeclinedError.new(declines, max_declines) if declines > max_declines
217 return unless amount > max_top_up_amount
218
219 raise AmountTooHighError.new(amount, max_top_up_amount)
220 end
221
222 def create_subaccount?(already_have)
223 already_have < 2
224 end
225
226 def to_s
227 "Customer"
228 end
229 end
230end