Class: Attio::Util::CurrencyFormatter

Inherits:
Object
  • Object
show all
Defined in:
lib/attio/util/currency_formatter.rb

Overview

Utility class for formatting currency amounts

Constant Summary collapse

CURRENCY_SYMBOLS =

Map of currency codes to their symbols

{
  "USD" => "$",
  "EUR" => "",
  "GBP" => "£",
  "JPY" => "¥",
  "CNY" => "¥",
  "INR" => "",
  "KRW" => "",
  "CAD" => "$",
  "AUD" => "$",
  "CHF" => "CHF ",
  "SEK" => "SEK ",
  "NOK" => "NOK ",
  "DKK" => "DKK ",
  "PLN" => "",
  "BRL" => "R$",
  "MXN" => "$",
  "NZD" => "$",
  "SGD" => "$",
  "HKD" => "$",
  "ZAR" => "R",
  "THB" => "฿",
  "PHP" => "",
  "IDR" => "Rp",
  "MYR" => "RM",
  "VND" => "",
  "TRY" => "",
  "RUB" => "",
  "UAH" => "",
  "ILS" => "",
  "AED" => "د.إ",
  "SAR" => "",
  "CLP" => "$",
  "COP" => "$",
  "PEN" => "S/",
  "ARS" => "$"
}.freeze
NO_DECIMAL_CURRENCIES =

Currencies that typically don't use decimal places

%w[JPY KRW VND IDR CLP].freeze

Class Method Summary collapse

Class Method Details

.decimal_places_for(currency_code) ⇒ Integer

Determine the number of decimal places for a currency

Parameters:

  • currency_code (String)

    The ISO 4217 currency code

Returns:

  • (Integer)

    Number of decimal places



108
109
110
111
# File 'lib/attio/util/currency_formatter.rb', line 108

def decimal_places_for(currency_code)
  currency_code = currency_code.to_s.upcase
  NO_DECIMAL_CURRENCIES.include?(currency_code) ? 0 : 2
end

.format(amount, currency_code = "USD", options = {}) ⇒ String

Format an amount with the appropriate currency symbol

Parameters:

  • amount (Numeric)

    The amount to format

  • currency_code (String) (defaults to: "USD")

    The ISO 4217 currency code

  • options (Hash) (defaults to: {})

    Formatting options

Options Hash (options):

  • :decimal_places (Integer)

    Number of decimal places (auto-determined by default)

  • :thousands_separator (String)

    Character for thousands separation (default: ",")

  • :decimal_separator (String)

    Character for decimal separation (default: ".")

Returns:

  • (String)

    The formatted currency string



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/attio/util/currency_formatter.rb', line 58

def format(amount, currency_code = "USD", options = {})
  currency_code = currency_code.to_s.upcase
  symbol = symbol_for(currency_code)

  # Determine decimal places
  decimal_places = options[:decimal_places] || decimal_places_for(currency_code)
  thousands_sep = options[:thousands_separator] || ","
  decimal_sep = options[:decimal_separator] || "."

  # Handle zero amounts
  if amount == 0
    if decimal_places > 0
      return "#{symbol}0#{decimal_sep}#{"0" * decimal_places}"
    else
      return "#{symbol}0"
    end
  end

  # Handle negative amounts
  negative = amount < 0
  abs_amount = amount.abs

  # Format the amount
  if decimal_places == 0
    # No decimal places
    formatted = format_with_separators(abs_amount.to_i, thousands_sep)
    formatted = "-#{formatted}" if negative
    "#{symbol}#{formatted}"
  else
    # With decimal places
    whole = abs_amount.to_i
    decimal = ((abs_amount - whole) * (10**decimal_places)).round
    formatted_whole = format_with_separators(whole, thousands_sep)
    formatted_whole = "-#{formatted_whole}" if negative
    formatted_decimal = decimal.to_s.rjust(decimal_places, "0")
    "#{symbol}#{formatted_whole}#{decimal_sep}#{formatted_decimal}"
  end
end

.format_number(amount, currency_code = "USD", options = {}) ⇒ String

Format just the numeric part without currency symbol

Parameters:

  • amount (Numeric)

    The amount to format

  • currency_code (String) (defaults to: "USD")

    The ISO 4217 currency code

  • options (Hash) (defaults to: {})

    Formatting options (same as format method)

Returns:

  • (String)

    The formatted number without currency symbol



125
126
127
128
129
# File 'lib/attio/util/currency_formatter.rb', line 125

def format_number(amount, currency_code = "USD", options = {})
  result = format(amount, currency_code, options)
  symbol = symbol_for(currency_code)
  result.sub(/^#{Regexp.escape(symbol)}/, "")
end

.symbol_for(currency_code) ⇒ String

Get the currency symbol for a given code

Parameters:

  • currency_code (String)

    The ISO 4217 currency code

Returns:

  • (String)

    The currency symbol or code with space



100
101
102
103
# File 'lib/attio/util/currency_formatter.rb', line 100

def symbol_for(currency_code)
  currency_code = currency_code.to_s.upcase
  CURRENCY_SYMBOLS[currency_code] || "#{currency_code} "
end

.uses_decimals?(currency_code) ⇒ Boolean

Check if a currency typically uses decimal places

Parameters:

  • currency_code (String)

    The ISO 4217 currency code

Returns:

  • (Boolean)

    True if the currency uses decimals



116
117
118
# File 'lib/attio/util/currency_formatter.rb', line 116

def uses_decimals?(currency_code)
  decimal_places_for(currency_code) > 0
end