trust_level.rb

  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