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 write_cdr?
36 false
37 end
38
39 def support_call?(*)
40 false
41 end
42
43 def send_message?(*)
44 false
45 end
46
47 # Validates a credit card transaction for a Tomb trust level user.
48 # Users at this level cannot make credit card transactions.
49 # @param _amount [BigDecimal] The amount of the transaction (ignored).
50 # @param _declines [Integer] The number of recent declines (ignored).
51 # @raise [DeclinedError] Always raised to prevent transactions.
52 def validate_credit_card_transaction!(_amount, _declines)
53 # Give a more ambiguous error so they don't know they're tombed.
54 raise DeclinedError
55 end
56
57 def create_subaccount?(*)
58 false
59 end
60
61 def to_s
62 "Tomb"
63 end
64
65 # The maximum amount a user at Tomb trust level can top up.
66 # @return [Integer] Always 0 for Tomb level.
67 def max_top_up_amount
68 0
69 end
70 end
71
72 class Basement
73 TrustLevel.register do |manual:, settled_amount:, **|
74 new if manual == "Basement" || (!manual && settled_amount < 10)
75 end
76
77 def write_cdr?
78 true
79 end
80
81 def support_call?(rate, concurrency)
82 rate <= 0.02 && concurrency < 1
83 end
84
85 def send_message?(messages_today)
86 messages_today < 40
87 end
88
89 # Validates a credit card transaction for a Basement trust level user.
90 # @param amount [BigDecimal] The amount of the transaction.
91 # @param declines [Integer] The number of recent declines for the customer.
92 # @raise [DeclinedError] if the number of declines exceeds `max_declines`.
93 # @raise [AmountTooHighError] if the transaction amount exceeds `max_top_up_amount`.
94 def validate_credit_card_transaction!(amount, declines)
95 raise DeclinedError.new(declines, max_declines) if declines > max_declines
96 return unless amount > max_top_up_amount
97
98 raise AmountTooHighError.new(amount, max_top_up_amount)
99 end
100
101 def create_subaccount?(already_have)
102 already_have < 2
103 end
104
105 def to_s
106 "Basement"
107 end
108
109 # The maximum amount a user at Basement trust level can top up.
110 # @return [Integer]
111 def max_top_up_amount
112 35
113 end
114
115 protected
116
117 # The maximum number of credit card declines allowed for a Basement user
118 # before further transactions are blocked.
119 # @return [Integer]
120 def max_declines
121 2
122 end
123 end
124
125 class Paragon
126 TrustLevel.register do |manual:, settled_amount:, **|
127 new if manual == "Paragon" || (!manual && settled_amount > 60)
128 end
129
130 def write_cdr?
131 true
132 end
133
134 def support_call?(_, concurrency)
135 concurrency < 10
136 end
137
138 def send_message?(messages_today)
139 messages_today < 700
140 end
141
142 # Validates a credit card transaction for a Paragon trust level user.
143 # @param amount [BigDecimal] The amount of the transaction.
144 # @param declines [Integer] The number of recent declines for the customer.
145 # @raise [DeclinedError] if the number of declines exceeds `max_declines`.
146 # @raise [AmountTooHighError] if the transaction amount exceeds `max_top_up_amount`.
147 def validate_credit_card_transaction!(amount, declines)
148 raise DeclinedError.new(declines, max_declines) if declines > max_declines
149 return unless amount > max_top_up_amount
150
151 raise AmountTooHighError.new(amount, max_top_up_amount)
152 end
153
154 def create_subaccount?(already_have)
155 already_have < 10
156 end
157
158 def to_s
159 "Paragon"
160 end
161
162 # The maximum amount a user at Paragon trust level can top up.
163 # @return [Integer]
164 def max_top_up_amount
165 500
166 end
167
168 protected
169
170 # The maximum number of credit card declines allowed for a Paragon user
171 # before further transactions are blocked.
172 # @return [Integer]
173 def max_declines
174 3
175 end
176 end
177
178 class Olympias
179 TrustLevel.register do |manual:, **|
180 new if manual == "Olympias"
181 end
182
183 def write_cdr?
184 true
185 end
186
187 def support_call?(*)
188 true
189 end
190
191 def send_message?(*)
192 true
193 end
194
195 # Validates a credit card transaction for an Olympias trust level user.
196 # Users at this level have no restrictions on credit card transactions through this method.
197 # @param _amount [BigDecimal] The amount of the transaction (ignored).
198 # @param _declines [Integer] The number of recent declines (ignored).
199 # @return [void]
200 def validate_credit_card_transaction!(*) end
201
202 def create_subaccount?(*)
203 true
204 end
205
206 def to_s
207 "Olympias"
208 end
209 end
210
211 class Customer
212 TrustLevel.register do |manual:, plan_name:, **|
213 if manual && manual != "Customer"
214 Sentry.capture_message("Unknown TrustLevel: #{manual}")
215 end
216
217 new(plan_name)
218 end
219
220 EXPENSIVE_ROUTE = {
221 "usd_beta_unlimited-v20210223" => 0.9,
222 "USD" => 0.9,
223 "cad_beta_unlimited-v20210223" => 1.1,
224 "CAD" => 1.1
225 }.freeze
226
227 def initialize(plan_name)
228 @max_rate = EXPENSIVE_ROUTE.fetch(plan_name, 0.1)
229 end
230
231 def write_cdr?
232 true
233 end
234
235 def support_call?(rate, concurrency)
236 rate <= @max_rate && concurrency < 4
237 end
238
239 def send_message?(messages_today)
240 messages_today < 500
241 end
242
243 # Validates a credit card transaction for a Customer trust level user.
244 # @param amount [BigDecimal] The amount of the transaction.
245 # @param declines [Integer] The number of recent declines for the customer.
246 # @raise [DeclinedError] if the number of declines exceeds `max_declines`.
247 # @raise [AmountTooHighError] if the transaction amount exceeds `max_top_up_amount`.
248 def validate_credit_card_transaction!(amount, declines)
249 raise DeclinedError.new(declines, max_declines) if declines > max_declines
250 return unless amount > max_top_up_amount
251
252 raise AmountTooHighError.new(amount, max_top_up_amount)
253 end
254
255 def create_subaccount?(already_have)
256 already_have < 2
257 end
258
259 def to_s
260 "Customer"
261 end
262
263 # The maximum amount a user at Customer trust level can top up.
264 # @return [Integer]
265 def max_top_up_amount
266 130
267 end
268
269 protected
270
271 # The maximum number of credit card declines allowed for a Customer user
272 # before further transactions are blocked.
273 # @return [Integer]
274 def max_declines
275 2
276 end
277 end
278end