From ecd2752690a1a1cd78c4800668e248b551e20f2a Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Mon, 23 May 2022 08:56:20 -0500 Subject: [PATCH] Only one credit card transaction per customer per day --- lib/transaction.rb | 13 +++++++++++-- test/test_transaction.rb | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/lib/transaction.rb b/lib/transaction.rb index 83e8e15..ff8ce7b 100644 --- a/lib/transaction.rb +++ b/lib/transaction.rb @@ -18,10 +18,12 @@ class Transaction def self.resolve_payment_method(customer, payment_method) EMPromise.all([ + REDIS.exists("jmp_customer_credit_card_lock-#{customer.customer_id}"), customer.declines, payment_method || customer.payment_methods.then(&:default_payment_method) - ]).then do |(declines, selected_method)| + ]).then do |(lock, declines, selected_method)| raise "Declined" if declines >= 2 + raise "Too many payments recently" if lock == 1 raise "No valid payment method on file" unless selected_method selected_method @@ -29,7 +31,14 @@ class Transaction end def self.decline_guard(customer, response) - return response.transaction if response.success? + if response.success? + REDIS.setex( + "jmp_customer_credit_card_lock-#{customer.customer_id}", + 60 * 60 * 24, + "1" + ) + return response.transaction + end customer.mark_decline raise response.message diff --git a/test/test_transaction.rb b/test/test_transaction.rb index 5bb348d..e6a02c6 100644 --- a/test/test_transaction.rb +++ b/test/test_transaction.rb @@ -18,6 +18,11 @@ class TransactionTest < Minitest::Test ) def test_sale_fails + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(0), + ["jmp_customer_credit_card_lock-test"] + ) CustomerFinancials::REDIS.expect( :get, EMPromise.resolve("1"), @@ -50,10 +55,39 @@ class TransactionTest < Minitest::Test ).sync end assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS end em :test_sale_fails + def test_sale_locked + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(1), + ["jmp_customer_credit_card_lock-test"] + ) + CustomerFinancials::REDIS.expect( + :get, + EMPromise.resolve("0"), + ["jmp_pay_decline-test"] + ) + assert_raises("locked") do + Transaction.sale( + customer(plan_name: "test_usd"), + amount: 123, + payment_method: OpenStruct.new(token: "token") + ).sync + end + assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS + end + em :test_sale_locked + def test_sale + Transaction::REDIS.expect( + :exists, + EMPromise.resolve(0), + ["jmp_customer_credit_card_lock-test"] + ) CustomerFinancials::REDIS.expect( :get, EMPromise.resolve("1"), @@ -76,6 +110,11 @@ class TransactionTest < Minitest::Test options: { submit_for_settlement: true } }] ) + Transaction::REDIS.expect( + :setex, + EMPromise.resolve(1), + ["jmp_customer_credit_card_lock-test", 86400, "1"] + ) result = Transaction.sale( customer(plan_name: "test_usd"), amount: 123, @@ -83,6 +122,7 @@ class TransactionTest < Minitest::Test ).sync assert_kind_of Transaction, result assert_mock CustomerFinancials::REDIS + assert_mock Transaction::REDIS end em :test_sale -- 2.38.5