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