# frozen_string_literal: true
require "bigdecimal"
require "time"
require "value_semantics/monkey_patched"
class Transaction
value_semantics do
customer_id String
transaction_id String
created_at Time, coerce: ->(x) { Time.parse(x.to_s) }
settled_after Time, coerce: ->(x) { Time.parse(x.to_s) }
amount BigDecimal, coerce: ->(x) { BigDecimal(x, 4) }
note String
end
def insert
EM.promise_fiber do
DB.transaction do
insert_tx
insert_bonus
end
end
end
def total
amount + bonus
end
def bonus
return BigDecimal(0) if amount <= 15
amount *
case amount
when (15..29.99)
0.01
when (30..139.99)
0.03
else
0.05
end
end
def to_s
plus = " + #{'%.4f' % bonus} bonus"
"$#{'%.2f' % amount}#{plus if bonus.positive?}"
end
protected
def insert_tx
params = [
@customer_id, @transaction_id, @created_at, @settled_after, @amount, @note
]
DB.exec(<<~SQL, params)
INSERT INTO transactions
(customer_id, transaction_id, created_at, settled_after, amount, note)
VALUES
($1, $2, $3, $4, $5, $6)
SQL
end
def insert_bonus
return if bonus <= 0
params = [
@customer_id, "bonus_for_#{@transaction_id}", @created_at,
@settled_after, bonus, "#{@note} bonus"
]
DB.exec(<<~SQL, params)
INSERT INTO transactions
(customer_id, transaction_id, created_at, settled_after, amount, note)
VALUES
($1, $2, $3, $4, $5, $6)
SQL
end
end