trust_level.rb

  1# frozen_string_literal: true
  2
  3require "delegate"
  4
  5module TrustLevel
  6	def self.for(
  7		customer:, settled_amount: 0, manual: nil,
  8		activated: nil, invited: false, activater: nil
  9	)
 10		@levels.each do |level|
 11			tl = level.call(
 12				customer: customer,
 13				settled_amount: settled_amount, activated: activated,
 14				manual: manual, invited: invited, activater: activater
 15			)
 16			return manual ? Manual.new(tl) : tl if tl
 17		end
 18
 19		raise "No TrustLevel matched"
 20	end
 21
 22	def self.register(&maybe_mk)
 23		@levels ||= []
 24		@levels << maybe_mk
 25	end
 26
 27	class Manual < SimpleDelegator
 28		def to_s
 29			"Manual(#{super})"
 30		end
 31	end
 32
 33	class Tomb
 34		TrustLevel.register do |manual:, **|
 35			new if manual == "Tomb"
 36		end
 37
 38		def invite?
 39			false
 40		end
 41
 42		def write_cdr?
 43			false
 44		end
 45
 46		def support_call?(*)
 47			false
 48		end
 49
 50		def send_message?(*)
 51			false
 52		end
 53
 54		# Validates a credit card transaction for a Tomb trust level user.
 55		# Users at this level cannot make credit card transactions.
 56		# @param _amount [BigDecimal] The amount of the transaction (ignored).
 57		# @param _declines [Integer] The number of recent declines (ignored).
 58		# @raise [DeclinedError] Always raised to prevent transactions.
 59		def validate_credit_card_transaction!(_amount, _declines)
 60			# Give a more ambiguous error so they don't know they're tombed.
 61			raise DeclinedError
 62		end
 63
 64		def create_subaccount?(*)
 65			false
 66		end
 67
 68		def to_s
 69			"Tomb"
 70		end
 71
 72		# The maximum amount a user at Tomb trust level can top up.
 73		# @return [Integer] Always 0 for Tomb level.
 74		def max_top_up_amount
 75			0
 76		end
 77	end
 78
 79	class Cellar
 80		TrustLevel.register do |manual:, activated:, invited:, activater:, **|
 81			new if manual == "Cellar" || (!manual && !activater && !invited && \
 82				(!activated || activated > Time.parse("2026-03-03 16:30")))
 83		end
 84
 85		def invite?
 86			false
 87		end
 88
 89		def write_cdr?
 90			true
 91		end
 92
 93		def support_call?(*)
 94			false
 95		end
 96
 97		def send_message?(*)
 98			false
 99		end
100
101		def validate_credit_card_transaction!(amount, declines)
102			raise DeclinedError.new(declines, max_declines) if declines > max_declines
103			return unless amount > max_top_up_amount
104
105			raise AmountTooHighError.new(amount, max_top_up_amount)
106		end
107
108		def create_subaccount?(*)
109			false
110		end
111
112		def to_s
113			"Cellar"
114		end
115
116		def max_top_up_amount
117			35
118		end
119
120	protected
121
122		def max_declines
123			2
124		end
125	end
126
127	class Basement
128		TrustLevel.register do |manual:, settled_amount:, **|
129			new if manual == "Basement" || (!manual && settled_amount < 10)
130		end
131
132		def invite?
133			true
134		end
135
136		def write_cdr?
137			true
138		end
139
140		def support_call?(rate, concurrency)
141			rate <= 0.02 && concurrency < 1
142		end
143
144		def send_message?(messages_today)
145			messages_today < 40
146		end
147
148		# Validates a credit card transaction for a Basement trust level user.
149		# @param amount [BigDecimal] The amount of the transaction.
150		# @param declines [Integer] The number of recent declines for the customer.
151		# @raise [DeclinedError] if the number of declines exceeds `max_declines`.
152		# @raise [AmountTooHighError] if the transaction amount exceeds
153		# `max_top_up_amount`.
154		def validate_credit_card_transaction!(amount, declines)
155			raise DeclinedError.new(declines, max_declines) if declines > max_declines
156			return unless amount > max_top_up_amount
157
158			raise AmountTooHighError.new(amount, max_top_up_amount)
159		end
160
161		def create_subaccount?(already_have)
162			already_have < 2
163		end
164
165		def to_s
166			"Basement"
167		end
168
169		# The maximum amount a user at Basement trust level can top up.
170		# @return [Integer]
171		def max_top_up_amount
172			35
173		end
174
175	protected
176
177		# The maximum number of credit card declines allowed for a Basement user
178		# before further transactions are blocked.
179		# @return [Integer]
180		def max_declines
181			2
182		end
183	end
184
185	class Paragon
186		TrustLevel.register do |manual:, settled_amount:, **|
187			new if manual == "Paragon" || (!manual && settled_amount > 60)
188		end
189
190		def invite?
191			true
192		end
193
194		def write_cdr?
195			true
196		end
197
198		def support_call?(_, concurrency)
199			concurrency < 10 ? :anyroute : false
200		end
201
202		def send_message?(messages_today)
203			messages_today < 700
204		end
205
206		# Validates a credit card transaction for a Paragon trust level user.
207		# @param amount [BigDecimal] The amount of the transaction.
208		# @param declines [Integer] The number of recent declines for the customer.
209		# @raise [DeclinedError] if the number of declines exceeds `max_declines`.
210		# @raise [AmountTooHighError] if the transaction amount exceeds
211		# `max_top_up_amount`.
212		def validate_credit_card_transaction!(amount, declines)
213			raise DeclinedError.new(declines, max_declines) if declines > max_declines
214			return unless amount > max_top_up_amount
215
216			raise AmountTooHighError.new(amount, max_top_up_amount)
217		end
218
219		def create_subaccount?(already_have)
220			already_have < 10
221		end
222
223		def to_s
224			"Paragon"
225		end
226
227		# The maximum amount a user at Paragon trust level can top up.
228		# @return [Integer]
229		def max_top_up_amount
230			500
231		end
232
233	protected
234
235		# The maximum number of credit card declines allowed for a Paragon user
236		# before further transactions are blocked.
237		# @return [Integer]
238		def max_declines
239			3
240		end
241	end
242
243	class Olympias
244		TrustLevel.register do |manual:, **|
245			new if manual == "Olympias"
246		end
247
248		def invite?
249			true
250		end
251
252		def write_cdr?
253			true
254		end
255
256		def support_call?(*)
257			:anyroute
258		end
259
260		def send_message?(*)
261			true
262		end
263
264		# Validates a credit card transaction for an Olympias trust level user.
265		# Users at this level have no restrictions on credit card transactions
266		# through this method.
267		# @return [void]
268		def validate_credit_card_transaction!(*) end
269
270		def create_subaccount?(*)
271			true
272		end
273
274		def to_s
275			"Olympias"
276		end
277	end
278
279	class Customer
280		TrustLevel.register do |manual:, customer:, **|
281			if manual && manual != "Customer"
282				Sentry.capture_message("Unknown TrustLevel: #{manual}")
283			end
284
285			new(customer.plan_name)
286		end
287
288		EXPENSIVE_ROUTE = {
289			"usd_beta_unlimited-v20210223" => 0.9,
290			"USD" => 0.9,
291			"cad_beta_unlimited-v20210223" => 1.1,
292			"CAD" => 1.1
293		}.freeze
294
295		def initialize(plan_name)
296			@max_rate = EXPENSIVE_ROUTE.fetch(plan_name, 0.1)
297		end
298
299		def invite?
300			true
301		end
302
303		def write_cdr?
304			true
305		end
306
307		def support_call?(rate, concurrency)
308			rate <= @max_rate && concurrency < 4 ? :anyroute : false
309		end
310
311		def send_message?(messages_today)
312			messages_today < 500
313		end
314
315		# Validates a credit card transaction for a Customer trust level user.
316		# @param amount [BigDecimal] The amount of the transaction.
317		# @param declines [Integer] The number of recent declines for the customer.
318		# @raise [DeclinedError] if the number of declines exceeds `max_declines`.
319		# @raise [AmountTooHighError] if the transaction amount exceeds
320		# `max_top_up_amount`.
321		def validate_credit_card_transaction!(amount, declines)
322			raise DeclinedError.new(declines, max_declines) if declines > max_declines
323			return unless amount > max_top_up_amount
324
325			raise AmountTooHighError.new(amount, max_top_up_amount)
326		end
327
328		def create_subaccount?(already_have)
329			already_have < 2
330		end
331
332		def to_s
333			"Customer"
334		end
335
336		# The maximum amount a user at Customer trust level can top up.
337		# @return [Integer]
338		def max_top_up_amount
339			130
340		end
341
342	protected
343
344		# The maximum number of credit card declines allowed for a Customer user
345		# before further transactions are blocked.
346		# @return [Integer]
347		def max_declines
348			2
349		end
350	end
351end