# 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