From e83bb8ac2fd15920c8569c84ab453aa284a7fdfa Mon Sep 17 00:00:00 2001 From: Stephen Paul Weber Date: Tue, 16 Aug 2022 15:42:33 -0500 Subject: [PATCH] When an auto top up fails, don't retry that card soon for any auto top up --- lib/low_balance.rb | 33 +++++++++++++++++--- test/test_helper.rb | 6 ++++ test/test_low_balance.rb | 66 ++++++++++++++++++++++++++++++++++++++++ test/test_web.rb | 21 +++++++++++++ 4 files changed, 122 insertions(+), 4 deletions(-) diff --git a/lib/low_balance.rb b/lib/low_balance.rb index a02445975e951fdbcea9f24f6be2565de58247ef..13dd89df34e40662db93680be0337d5b85570dec 100644 --- a/lib/low_balance.rb +++ b/lib/low_balance.rb @@ -15,9 +15,9 @@ class LowBalance end end - def self.for_no_lock(customer) - if customer.auto_top_up_amount.positive? - AutoTopUp.new(customer) + def self.for_no_lock(customer, auto: true) + if auto && customer.auto_top_up_amount.positive? + AutoTopUp.for(customer) else customer.btc_addresses.then do |btc_addresses| new(customer, btc_addresses) @@ -48,8 +48,28 @@ class LowBalance end class AutoTopUp - def initialize(customer) + def self.for(customer) + customer.payment_methods.then(&:default_payment_method).then do |method| + blocked?(method).then do |block| + next AutoTopUp.new(customer, method) if block.zero? + + log.info("#{customer.customer_id} auto top up blocked") + LowBalance.for_no_lock(customer, auto: false) + end + end + end + + def self.blocked?(method) + return EMPromise.resolve(1) if method.nil? + + REDIS.exists( + "jmp_auto_top_up_block-#{method&.unique_number_identifier}" + ) + end + + def initialize(customer, method=nil) @customer = customer + @method = method @message = Blather::Stanza::Message.new @message.from = CONFIG[:notify_from] end @@ -64,6 +84,11 @@ class LowBalance end def failed(e) + @method && REDIS.setex( + "jmp_auto_top_up_block-#{@method.unique_number_identifier}", + 60 * 60 * 24 * 7, + Time.now + ) @message.body = "Automatic top-up transaction for " \ "$#{@customer.auto_top_up_amount} failed: #{e.message}" diff --git a/test/test_helper.rb b/test/test_helper.rb index 2ed5db53f6e59014b17ff0fc43c1ab863de844c9..c7741459f7760b8feb99571784e0331c6841e19e 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -119,8 +119,14 @@ LOG = Class.new { def child(*) Minitest::Mock.new end + + def info(*); end }.new.freeze +def log + LOG +end + BLATHER = Class.new { def <<(*); end }.new.freeze diff --git a/test/test_low_balance.rb b/test/test_low_balance.rb index b8625661ebc18e9ab184270cff8912592647180c..ef0aa16fd330d69dfbd03926a83f75634a8c7eab 100644 --- a/test/test_low_balance.rb +++ b/test/test_low_balance.rb @@ -6,6 +6,7 @@ require "low_balance" ExpiringLock::REDIS = Minitest::Mock.new CustomerPlan::REDIS = Minitest::Mock.new CustomerFinancials::REDIS = Minitest::Mock.new +LowBalance::AutoTopUp::REDIS = Minitest::Mock.new class LowBalanceTest < Minitest::Test def test_for_locked @@ -43,14 +44,79 @@ class LowBalanceTest < Minitest::Test EMPromise.resolve("OK"), ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"] ) + CustomerFinancials::REDIS.expect( + :smembers, + EMPromise.resolve([]), + ["block_credit_cards"] + ) + LowBalance::AutoTopUp::REDIS.expect( + :exists, + 0, + ["jmp_auto_top_up_block-abcd"] + ) + braintree_customer = Minitest::Mock.new + CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer) + payment_methods = OpenStruct.new(payment_methods: [ + OpenStruct.new(default?: true, unique_number_identifier: "abcd") + ]) + braintree_customer.expect( + :find, + EMPromise.resolve(payment_methods), + ["test"] + ) assert_kind_of( LowBalance::AutoTopUp, LowBalance.for(customer(auto_top_up_amount: 15)).sync ) assert_mock ExpiringLock::REDIS + assert_mock CustomerFinancials::REDIS + assert_mock CustomerFinancials::BRAINTREE + assert_mock braintree_customer end em :test_for_auto_top_up + def test_for_auto_top_up_blocked + ExpiringLock::REDIS.expect( + :set, + EMPromise.resolve("OK"), + ["jmp_customer_low_balance-test", Time, "EX", 604800, "NX"] + ) + CustomerFinancials::REDIS.expect( + :smembers, + EMPromise.resolve([]), + ["block_credit_cards"] + ) + CustomerFinancials::REDIS.expect( + :smembers, + EMPromise.resolve([]), + ["jmp_customer_btc_addresses-test"] + ) + LowBalance::AutoTopUp::REDIS.expect( + :exists, + 1, + ["jmp_auto_top_up_block-blocked"] + ) + braintree_customer = Minitest::Mock.new + CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer) + payment_methods = OpenStruct.new(payment_methods: [ + OpenStruct.new(default?: true, unique_number_identifier: "blocked") + ]) + braintree_customer.expect( + :find, + EMPromise.resolve(payment_methods), + ["test"] + ) + assert_kind_of( + LowBalance, + LowBalance.for(customer(auto_top_up_amount: 15)).sync + ) + assert_mock ExpiringLock::REDIS + assert_mock CustomerFinancials::REDIS + assert_mock CustomerFinancials::BRAINTREE + assert_mock braintree_customer + end + em :test_for_auto_top_up_blocked + class AutoTopUpTest < Minitest::Test LowBalance::AutoTopUp::Transaction = Minitest::Mock.new diff --git a/test/test_web.rb b/test/test_web.rb index a850c77e97d183bd56e036e31c674cf374e2545e..9d53fb8e6a7e92c70fd27696fc8693d878419c3e 100644 --- a/test/test_web.rb +++ b/test/test_web.rb @@ -170,6 +170,27 @@ class WebTest < Minitest::Test ["jmp_customer_low_balance-customerid_topup", Time, "EX", 604800, "NX"] ) + CustomerFinancials::REDIS.expect( + :smembers, + EMPromise.resolve([]), + ["block_credit_cards"] + ) + LowBalance::AutoTopUp::REDIS.expect( + :exists, + 0, + ["jmp_auto_top_up_block-abcd"] + ) + braintree_customer = Minitest::Mock.new + CustomerFinancials::BRAINTREE.expect(:customer, braintree_customer) + payment_methods = OpenStruct.new(payment_methods: [ + OpenStruct.new(default?: true, unique_number_identifier: "abcd") + ]) + braintree_customer.expect( + :find, + EMPromise.resolve(payment_methods), + ["customerid_topup"] + ) + Customer::BLATHER.expect( :<<, nil,