~singpolyma/sgx-jmp

e83bb8ac2fd15920c8569c84ab453aa284a7fdfa — Stephen Paul Weber 7 months ago 940aa18
When an auto top up fails, don't retry that card soon

for any auto top up
4 files changed, 122 insertions(+), 4 deletions(-)

M lib/low_balance.rb
M test/test_helper.rb
M test/test_low_balance.rb
M test/test_web.rb
M lib/low_balance.rb => lib/low_balance.rb +29 -4
@@ 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}"

M test/test_helper.rb => test/test_helper.rb +6 -0
@@ 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

M test/test_low_balance.rb => test/test_low_balance.rb +66 -0
@@ 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


M test/test_web.rb => test/test_web.rb +21 -0
@@ 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,