Money v0.0.2 Money

Money implements a set of functions to store, retrieve and perform arithmetic on a %Money{} type that is composed of a currency code and a currency amount.

Money is very opinionated in the interests of serving as a dependable library that can underpin accounting and financial applications. In its initial release it can be expected that this contract may not be fully met. But thats the contract.

How is this opinion expressed:

  1. Money must always have both a amount and a currency code.

  2. The currency code must always be valid.

  3. Money arithmetic can only be performed when both operands are of the same currency.

  4. Money amounts are represented as a Decimal.

  5. Money is serialised to the database as a custom Postgres type that includes both the amount and the currency. Therefore for Ecto serialization Postgres is assumed as the data store. Serialization is entirely optional.

  6. All arithmetic functions work in fixed point decimal. No rounding occurs automatically (unless expressly called out for a function).

  7. Explicit rounding obeys the rounding rules for a given currency. The rounding rules are defined by the Unicode consortium in its CLDR repository as implemented by the hex package ex_cldr. These rules define the number of fractional digits for a currency and the rounding increment where appropriate.

Summary

Functions

Add two %Money{} structs

Divide a %Money{} by a number

Returns a boolean indicating if two %Money{} structs are equal

Multiply a %Money{} by a number

Returns a %Money{} struct from a tuple consistenting of a currency code and a currency amount

Returns a %Money{} struct from a currency code and a currency amount

Round a %Money{} struct into the acceptable range for the defined currency

Returns the number of fractional digits to which money is rounded

Split a %Money{} amount into a number of parts maintaining the currency’s precision and rounding and ensuring that the parts sum to the original amount

Subtract one %Money{} struct from another

Returns the value part of a Money{} as a Decimal

Returns a formatted string representation of a Money{}

Types

t()
t

Functions

add(money1, money2)

Add two %Money{} structs.

Example

Money.add Money.new(:USD, 200), Money.new(:USD, 100)
$300.00
cmp(arg1, arg2)
compare(arg1, arg2)
div(money, number)
div(Money.t, number) :: Money.t

Divide a %Money{} by a number.

  • money is a %Money{} struct

  • number is an integer or float

Note that dividing one %Money{} by another is not supported.

Example

Money.div Money.new(:USD, 200), 2
$100.00
equal?(arg1, arg2)
equal?(Money.t, Money.t) :: boolean

Returns a boolean indicating if two %Money{} structs are equal

mult(money, number)
mult(Money.t, number) :: Money.t

Multiply a %Money{} by a number.

  • money is a %Money{} struct

  • number is an integer or float

Note that multipling one %Money{} by another is not supported.

Example

Money.mult Money.new(:USD, 200), 2
$400.00
new(arg)
new({binary, number}) :: Money.t

Returns a %Money{} struct from a tuple consistenting of a currency code and a currency amount.

  • currency_code is an ISO4217 three-character binary

  • amount is an integer or a float

This function is typically called from Ecto when its loading a %Money{} struct from the database.

new(amount, currency_code)
new(number, binary) :: Money.t

Returns a %Money{} struct from a currency code and a currency amount.

  • currency_code is an ISO4217 three-character binary

  • amount is an integer or a float

This function is typically called from Ecto when its loading a %Money{} struct from the database.

round(money, opts \\ [])

Round a %Money{} struct into the acceptable range for the defined currency.

  • money is a %Money{} struct

  • opts is a keyword list with the following keys:

  • :rounding_mode that defines how the number will be rounded. See Decimal.Context. The default is :half_even which is also known as “banker’s rounding”

  • :cash which determines whether the rounding is being applied to an accounting amount or a cash amount. Some currencies, such as the :AUD and :CHF have a cash unit increment minimum which requires a different rounding increment to an arbitrary accounting amount. The default is false.

There are two kinds of rounding applied:

  1. Round to the appropriate number of fractional digits

  2. Apply an appropriate rounding increment. Most currencies round to the same precision as the number of decimal digits, but some such as :AUD and :CHF round to a minimum such as 0.05 when its a cash amount.

Examples

Money.round Money.new(123.7456, :CHF), cash: true
CHF125.00

Money.round Money.new(123.7456, :CHF)
CHF123.75

Money.round Money.new(123.7456, :JPY)
¥124
round_to_nearest(money, opts \\ [])
rounding()

Returns the number of fractional digits to which money is rounded.

This value is used to set the fractional digits in the Postgres migration and for rounding purposes.

split(money, parts)

Split a %Money{} amount into a number of parts maintaining the currency’s precision and rounding and ensuring that the parts sum to the original amount.

  • money is a %Money{} struct

  • parts is an integer number of parts into which the money is split

Returns a tuple {dividend, remainder} as the function result derived as follows:

  1. Round the money amount to the required currency precision using Money.round/1

  2. Divide the result of step 1 by the integer divisor

  3. Round the result of the division to the precision of the currency using Money.round/1

  4. Return two numbers: the result of the division and any remainder that could not be applied given the precision of the currency.

Examples

Money.split Money.new(123.5, :JPY), 3
{¥41, ¥1}

Money.split Money.new(123.4, :JPY), 3
{¥41, ¥0}

Money.split Money.new(123.7, :USD), 9
{$13.74, $0.04}
sub(money1, money2)

Subtract one %Money{} struct from another.

Example

Money.sub Money.new(:USD, 200), Money.new(:USD, 100)
$100.00
to_decimal(money)

Returns the value part of a Money{} as a Decimal

to_string(money, options \\ [])

Returns a formatted string representation of a Money{}.

Formatting is performed according to the rules defined by CLDR. See Cldr.Number.to_string/2 for formatting options. The default is to format as a currency which applies the appropriate rounding and fractional digits for the currency.

Examples

iex> Money.to_string Money.new(:USD, 1234)
"$1,234.00"

iex> Money.to_string Money.new(:JPY, 1234)
"¥1,234"

iex> Money.to_string Money.new(:THB, 1234)
"THB1,234.00"

iex> Money.to_string Money.new(:USD, 1234), format: :long
"1,234.00 US dollars"