Merge branch 'credit-card-bonus'

Stephen Paul Weber created

* credit-card-bonus:
  Insert bonus when paying by credit card

Change summary

lib/transaction.rb       | 45 ++++++++++++++++++++++++++++++++++++++---
test/test_transaction.rb | 39 +++++++++++++++++++++++++++++++++--
2 files changed, 77 insertions(+), 7 deletions(-)

Detailed changes

lib/transaction.rb 🔗

@@ -1,5 +1,7 @@
 # frozen_string_literal: true
 
+require "bigdecimal"
+
 class Transaction
 	def self.sale(customer, amount:, payment_method: nil)
 		REDIS.get("jmp_pay_decline-#{customer.customer_id}").then do |declines|
@@ -43,16 +45,51 @@ class Transaction
 		@customer_id = braintree_transaction.customer_details.id
 		@transaction_id = braintree_transaction.id
 		@created_at = braintree_transaction.created_at
-		@amount = braintree_transaction.amount
+		@amount = BigDecimal.new(braintree_transaction.amount, 4)
 	end
 
 	def insert
+		EM.promise_fiber do
+			DB.transaction do
+				insert_tx
+				insert_bonus
+			end
+		end
+	end
+
+	def bonus
+		return BigDecimal.new(0) if amount <= 15
+		amount *
+			case amount
+			when (15..29.99)
+				0.01
+			when (30..139.99)
+				0.03
+			else
+				0.05
+			end
+	end
+
+protected
+
+	def insert_tx
 		params = [@customer_id, @transaction_id, @created_at, @amount]
-		DB.exec_defer(<<~SQL, params)
+		DB.exec(<<~SQL, params)
+			INSERT INTO transactions
+				(customer_id, transaction_id, created_at, amount, note)
+			VALUES
+				($1, $2, $3, $4, 'Credit card payment')
+		SQL
+	end
+
+	def insert_bonus
+		return if bonus <= 0
+		params = [@customer_id, "bonus_for_#{@transaction_id}", @created_at, bonus]
+		DB.exec(<<~SQL, params)
 			INSERT INTO transactions
-				(customer_id, transaction_id, created_at, amount)
+				(customer_id, transaction_id, created_at, amount, note)
 			VALUES
-				($1, $2, $3, $4)
+				($1, $2, $3, $4, 'Credit card payment bonus')
 		SQL
 	end
 end

test/test_transaction.rb 🔗

@@ -14,7 +14,7 @@ class TransactionTest < Minitest::Test
 			customer_details: OpenStruct.new(id: "customer"),
 			id: "transaction",
 			created_at: Time.at(0),
-			amount: 123
+			amount: 12
 		)
 
 	def test_sale_fails
@@ -85,15 +85,48 @@ class TransactionTest < Minitest::Test
 	em :test_sale
 
 	def test_insert
+		Transaction::DB.expect(:transaction, []) do |&block|
+			block.call
+			true
+		end
 		Transaction::DB.expect(
-			:exec_defer,
+			:exec,
 			EMPromise.resolve(nil),
 			[
 				String,
-				["customer", "transaction", Time.at(0), 123]
+				["customer", "transaction", Time.at(0), 12]
 			]
 		)
 		Transaction.new(FAKE_BRAINTREE_TRANSACTION).insert.sync
+		Transaction::DB.verify
 	end
 	em :test_insert
+
+	def test_insert_with_bonus
+		Transaction::DB.expect(:transaction, []) do |&block|
+			block.call
+			true
+		end
+		Transaction::DB.expect(
+			:exec,
+			EMPromise.resolve(nil),
+			[
+				String,
+				["customer", "transaction", Time.at(0), 100]
+			]
+		)
+		Transaction::DB.expect(
+			:exec,
+			EMPromise.resolve(nil),
+			[
+				String,
+				["customer", "bonus_for_transaction", Time.at(0), 3]
+			]
+		)
+		tx = FAKE_BRAINTREE_TRANSACTION.dup
+		tx.amount = 100
+		Transaction.new(tx).insert.sync
+		Transaction::DB.verify
+	end
+	em :test_insert_with_bonus
 end