@@ -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
@@ -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
@@ -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