class Commissioner::Calculator

Constants

AmountUnknown
CommissionerArityInvalid
DEFAULT_ORDER
HELP_MESSAGE

Public Class Methods

new(params, config:, order: DEFAULT_ORDER) click to toggle source
# File lib/commissioner/calculator.rb, line 81
def initialize(params, config:, order: DEFAULT_ORDER)
  @charged_amount = guess_amount(params[:charged_amount], params[:charged_currency])
  @received_amount = guess_amount(params[:received_amount], params[:received_currency])

  @exchange_commission = params[:exchange_commission] || 0
  @commission = params[:commission] || 0

  unless config.exchanger.is_a?(Proc) && config.exchanger.arity == 3
    raise CommissionerArityInvalid, "'exchanger' setting must be a lambda with arity of 3"
  end

  @exchanger = config.exchanger
  @order = order
  @rounding_mode =
    case config.rounding_mode
    when :up
      BigDecimal::ROUND_UP
    when :down
      BigDecimal::ROUND_DOWN
    when :half_even
      BigDecimal::ROUND_HALF_EVEN
    else
      BigDecimal::ROUND_HALF_UP
    end
end

Public Instance Methods

calculate() click to toggle source
# File lib/commissioner/calculator.rb, line 107
def calculate
  @result = OpenStruct.new(
    received_amount: @received_amount,
    charged_amount: @charged_amount,
    fee: 0,
    exchange_fee: 0,
    exchange_rate: 0
  )

  if !empty?(@charged_amount) && @received_amount.zero?
    calculate_for_charged
  elsif !empty?(@received_amount) && @charged_amount.zero?
    calculate_for_received
  else
    raise AmountUnknown, HELP_MESSAGE
  end

  @result
end

Private Instance Methods

calculate_for_charged() click to toggle source
# File lib/commissioner/calculator.rb, line 133
def calculate_for_charged
  operator = Operator.new(
    from_currency: @charged_amount.currency.to_s,
    to_currency: @received_amount.currency.to_s,
    amount: @charged_amount,
    commission: @commission,
    exchange_commission: @exchange_commission,
    exchanger: @exchanger,
    rounding_mode: @rounding_mode,
    commission_action: :reduce
  )

  operator.apply_order(@order)

  @result.received_amount = operator.amount
  @result.fee = operator.fee if operator.fee
  @result.exchange_fee = operator.exchange_fee if operator.exchange_fee
  @result.exchange_rate = operator.exchange_rate
end
calculate_for_received() click to toggle source
# File lib/commissioner/calculator.rb, line 153
def calculate_for_received
  operator = Operator.new(
    from_currency: @charged_amount.currency.to_s,
    to_currency: @received_amount.currency.to_s,
    amount: @received_amount,
    commission: @commission,
    exchange_commission: @exchange_commission,
    exchanger: @exchanger,
    rounding_mode: @rounding_mode,
    commission_action: :add
  )

  operator.apply_order(@order.reverse)

  @result.charged_amount = operator.amount
  @result.fee = operator.fee if operator.fee
  @result.exchange_fee = operator.exchange_fee if operator.exchange_fee
  @result.exchange_rate = operator.exchange_rate
end
empty?(amount) click to toggle source
# File lib/commissioner/calculator.rb, line 129
def empty?(amount)
  amount.nil? || amount.zero?
end
guess_amount(amount, currency) click to toggle source
# File lib/commissioner/calculator.rb, line 173
def guess_amount(amount, currency)
  case amount
  when Money
    amount
  when Numeric
    Money.from_amount(amount, currency) if currency.is_a?(String)
  when NilClass
    Money.new(0, currency) if currency.is_a?(String)
  end
end