~singpolyma/sgx-jmp

ecd2752690a1a1cd78c4800668e248b551e20f2a — Stephen Paul Weber 1 year, 4 months ago c4fc3de
Only one credit card transaction per customer per day
2 files changed, 51 insertions(+), 2 deletions(-)

M lib/transaction.rb
M test/test_transaction.rb
M lib/transaction.rb => lib/transaction.rb +11 -2
@@ 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

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