~singpolyma/sgx-jmp

3a71f5f536c020915f10b5faf82504965674b4c8 — Stephen Paul Weber 1 year, 9 months ago a0ebeca
Limit size of credit card transaction by trust level
3 files changed, 65 insertions(+), 9 deletions(-)

M lib/transaction.rb
M lib/trust_level.rb
M test/test_transaction.rb
M lib/transaction.rb => lib/transaction.rb +8 -6
@@ 2,27 2,29 @@

require "bigdecimal"

require_relative "trust_level_repo"

class Transaction
	def self.sale(customer, amount:, payment_method: nil)
		resolve_payment_method(customer, payment_method).then do |selected_method|
		resolve_payment_method(customer, payment_method, amount).then do |selected|
			BRAINTREE.transaction.sale(
				amount: amount,
				merchant_account_id: customer.merchant_account,
				options: { submit_for_settlement: true },
				payment_method_token: selected_method.token
				payment_method_token: selected.token
			).then do |response|
				new(decline_guard(customer, response))
			end
		end
	end

	def self.resolve_payment_method(customer, payment_method)
	def self.resolve_payment_method(customer, payment_method, amount)
		EMPromise.all([
			REDIS.exists("jmp_customer_credit_card_lock-#{customer.customer_id}"),
			customer.declines,
			TrustLevelRepo.new.find(customer), customer.declines,
			payment_method || customer.payment_methods.then(&:default_payment_method)
		]).then do |(lock, declines, selected_method)|
			raise "Declined" if declines >= 2
		]).then do |(lock, tl, declines, selected_method)|
			raise "Declined" unless tl.credit_card_transaction?(amount, declines)
			raise "Too many payments recently" if lock == 1
			raise "No valid payment method on file" unless selected_method


M lib/trust_level.rb => lib/trust_level.rb +16 -0
@@ 40,6 40,10 @@ module TrustLevel
			false
		end

		def credit_card_transaction?(*)
			false
		end

		def to_s
			"Tomb"
		end


@@ 58,6 62,10 @@ module TrustLevel
			messages_today < 200
		end

		def credit_card_transaction?(amount, declines)
			amount <= 35 && declines <= 2
		end

		def to_s
			"Basement"
		end


@@ 76,6 84,10 @@ module TrustLevel
			messages_today < 700
		end

		def credit_card_transaction?(amount, declines)
			amount <= 500 && declines <= 3
		end

		def to_s
			"Paragon"
		end


@@ 107,6 119,10 @@ module TrustLevel
			messages_today < 500
		end

		def credit_card_transaction?(amount, declines)
			amount <= 100 && declines <= 2
		end

		def to_s
			"Customer"
		end

M test/test_transaction.rb => test/test_transaction.rb +41 -3
@@ 7,6 7,8 @@ require "transaction"
Transaction::DB = Minitest::Mock.new
Transaction::BRAINTREE = Minitest::Mock.new
Transaction::REDIS = Minitest::Mock.new
TrustLevelRepo::REDIS = Minitest::Mock.new
TrustLevelRepo::DB = Minitest::Mock.new

class TransactionTest < Minitest::Test
	FAKE_BRAINTREE_TRANSACTION =


@@ 23,6 25,16 @@ class TransactionTest < Minitest::Test
			EMPromise.resolve(0),
			["jmp_customer_credit_card_lock-test"]
		)
		TrustLevelRepo::REDIS.expect(
			:get,
			EMPromise.resolve("Customer"),
			["jmp_customer_trust_level-test"]
		)
		TrustLevelRepo::DB.expect(
			:query_one,
			EMPromise.resolve({}),
			[String, "test", Hash]
		)
		CustomerFinancials::REDIS.expect(
			:get,
			EMPromise.resolve("1"),


@@ 50,12 62,14 @@ class TransactionTest < Minitest::Test
		assert_raises("declined") do
			Transaction.sale(
				customer(plan_name: "test_usd"),
				amount: 123,
				amount: 99,
				payment_method: OpenStruct.new(token: "token")
			).sync
		end
		assert_mock CustomerFinancials::REDIS
		assert_mock Transaction::REDIS
		assert_mock TrustLevelRepo::REDIS
		assert_mock TrustLevelRepo::DB
	end
	em :test_sale_fails



@@ 65,6 79,16 @@ class TransactionTest < Minitest::Test
			EMPromise.resolve(1),
			["jmp_customer_credit_card_lock-test"]
		)
		TrustLevelRepo::REDIS.expect(
			:get,
			EMPromise.resolve("Customer"),
			["jmp_customer_trust_level-test"]
		)
		TrustLevelRepo::DB.expect(
			:query_one,
			EMPromise.resolve({}),
			[String, "test", Hash]
		)
		CustomerFinancials::REDIS.expect(
			:get,
			EMPromise.resolve("0"),


@@ 79,6 103,8 @@ class TransactionTest < Minitest::Test
		end
		assert_mock CustomerFinancials::REDIS
		assert_mock Transaction::REDIS
		assert_mock TrustLevelRepo::REDIS
		assert_mock TrustLevelRepo::DB
	end
	em :test_sale_locked



@@ 88,6 114,16 @@ class TransactionTest < Minitest::Test
			EMPromise.resolve(0),
			["jmp_customer_credit_card_lock-test"]
		)
		TrustLevelRepo::REDIS.expect(
			:get,
			EMPromise.resolve("Customer"),
			["jmp_customer_trust_level-test"]
		)
		TrustLevelRepo::DB.expect(
			:query_one,
			EMPromise.resolve({}),
			[String, "test", Hash]
		)
		CustomerFinancials::REDIS.expect(
			:get,
			EMPromise.resolve("1"),


@@ 104,7 140,7 @@ class TransactionTest < Minitest::Test
				)
			),
			[{
				amount: 123,
				amount: 99,
				payment_method_token: "token",
				merchant_account_id: "merchant_usd",
				options: { submit_for_settlement: true }


@@ 117,12 153,14 @@ class TransactionTest < Minitest::Test
		)
		result = Transaction.sale(
			customer(plan_name: "test_usd"),
			amount: 123,
			amount: 99,
			payment_method: OpenStruct.new(token: "token")
		).sync
		assert_kind_of Transaction, result
		assert_mock CustomerFinancials::REDIS
		assert_mock Transaction::REDIS
		assert_mock TrustLevelRepo::REDIS
		assert_mock TrustLevelRepo::DB
	end
	em :test_sale