Merge branch 'limit-top-up-freq'

Stephen Paul Weber created

* limit-top-up-freq:
  Only allow one credit card transaction per customer per day

Change summary

lib/transaction.rb       |  4 +++-
test/test_transaction.rb | 13 +++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)

Detailed changes

lib/transaction.rb 🔗

@@ -18,9 +18,11 @@ class Transaction
 
 	def self.resolve_payment_method(customer, payment_method)
 		EMPromise.all([
+			ExpiringLock.new("jmp_customer_credit_card_lock-#{customer.customer_id}")
+				.with(els: -> { raise "Too many transactions today" }) { nil },
 			customer.declines,
 			payment_method || customer.payment_methods.then(&:default_payment_method)
-		]).then do |(declines, selected_method)|
+		]).then do |(_, declines, selected_method)|
 			raise "Declined" if declines >= 2
 			raise "No valid payment method on file" unless selected_method
 

test/test_transaction.rb 🔗

@@ -7,6 +7,7 @@ require "transaction"
 Transaction::DB = Minitest::Mock.new
 Transaction::BRAINTREE = Minitest::Mock.new
 Transaction::REDIS = Minitest::Mock.new
+ExpiringLock::REDIS = Minitest::Mock.new
 
 class TransactionTest < Minitest::Test
 	FAKE_BRAINTREE_TRANSACTION =
@@ -18,6 +19,11 @@ class TransactionTest < Minitest::Test
 		)
 
 	def test_sale_fails
+		ExpiringLock::REDIS.expect(
+			:set,
+			EMPromise.resolve("OK"),
+			["jmp_customer_credit_card_lock-test", Time, "EX", 86400, "NX"]
+		)
 		CustomerFinancials::REDIS.expect(
 			:get,
 			EMPromise.resolve("1"),
@@ -50,10 +56,16 @@ class TransactionTest < Minitest::Test
 			).sync
 		end
 		assert_mock CustomerFinancials::REDIS
+		assert_mock ExpiringLock::REDIS
 	end
 	em :test_sale_fails
 
 	def test_sale
+		ExpiringLock::REDIS.expect(
+			:set,
+			EMPromise.resolve("OK"),
+			["jmp_customer_credit_card_lock-test", Time, "EX", 86400, "NX"]
+		)
 		CustomerFinancials::REDIS.expect(
 			:get,
 			EMPromise.resolve("1"),
@@ -83,6 +95,7 @@ class TransactionTest < Minitest::Test
 		).sync
 		assert_kind_of Transaction, result
 		assert_mock CustomerFinancials::REDIS
+		assert_mock ExpiringLock::REDIS
 	end
 	em :test_sale