Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/theocodes/monetized

A lightweight solution for handling and storing money.
https://github.com/theocodes/monetized

currencies ecto money

Last synced: about 1 month ago
JSON representation

A lightweight solution for handling and storing money.

Awesome Lists containing this project

README

        

# Monetized [Unmaintained]
[![Build Status](https://travis-ci.org/theocodes/monetized.svg?branch=master)](https://travis-ci.org/theocodes/monetized)
[![Deps Status](https://beta.hexfaktor.org/badge/all/github/theocodes/monetized.svg)](https://beta.hexfaktor.org/github/theocodes/monetized)
[![Inline docs](http://inch-ci.org/github/theocodes/monetized.svg)](http://inch-ci.org/github/theocodes/monetized)

As a general rule, using floats to store money is a [bad idea](http://spin.atomicobject.com/2014/08/14/currency-rounding-errors/).

Enter Monetized. A library that aims to facilitate the handling of money through a safe way to store currency values and
and providing abstractions to perform arithmetical operations on those values.

Monetized leverages [Decimal](https://github.com/ericmj/decimal)'s ability to safely handle arbitrary precision to perform calculations
on money values.

A typical `%Monetized.Money{}` struct will contain a value in the shape of a `Decimal` struct and a currency (if any) as a string.

Requires elixir version 1.3.x or above as per ecto 2.x

## Usage

Monetized also ships with a `Ecto.Type` that gives us an easier way to store money.

```elixir

alias Monetized.Money

schema "transaction" do
field :description, :string
field :balance, Money, default: Money.zero

timestamps
end

```

By doing this we're able to pass a `%Money{}` struct to the changeset and
insert in the `Repo` since Ecto knows how to convert that struct into a primitive
type to save and back when you read from it.

```elixir

balance = Money.make("£ 100.50")
changeset = Transaction.changeset(%Transaction{}, %{description: "Invoice payment", balance: balance})

# Or

balance = %{value: "100.50", currency: "GBP"}
changeset = Transaction.changeset(%Transaction{}, %{description: "Invoice payment", balance: balance})

```

Check the [docs](http://hexdocs.pm/monetized/api-reference.html) for more.

## Other usage

```elixir
alias Monetized.Money
alias Monetized.Math

# Create with a string
iex> item_one = Money.make("£ 200.50")
#Money<200.50GBP>

# Or a float
iex> item_two = Money.make(10.25, [currency: "GBP"])
#Money<10.25GBP>

# Adding two moneys together
iex> Math.add(item_one, item_two)
#Money<210.75GBP>

# Or an integer
iex> balance = Money.make(100_000, [currency: "USD"])
#Money<100000.00USD>

# Substracting from money (currency inferred from balance)
iex> result = Math.sub(balance, 50_000)
#Money<50000.00USD>

# Getting the string representation
iex> Money.to_string(result, [currency_symbol: true])
"$ 50,000.00"

# You can also use `from_integer/2`, `from_float/2`, `from_decimal/2` and `from_string/2`
# respectively if the desired behavior is to raise when the amount is
# not of the expected type.

# If either the symbol or the currency key is found within the string,
# that currency will be used. However, if a different currency is given in the
# options, it will take precedence.

iex> Money.from_string("£ 200")
#Money<200.00GBP>

iex> Money.from_string("200 EUR")
#Money<200.00EUR>

iex> Money.from_integer(200)
#Money<200.00>

iex> Money.from_float(200.50)
#Money<200.50>

iex> decimal = Decimal.new(10.25)
...> Money.from_decimal(decimal, currency: "EUR")
#Money<10.15EUR>

iex> Money.from_integer("10")
** (FunctionClauseError) no function clause matching in Monetized.Money.from_integer/2
(monetized) lib/money.ex:204: Monetized.Money.from_integer("10", [])

```

Check the [docs](http://hexdocs.pm/monetized/api-reference.html) for more examples

## Config

```elixir
config :monetized, config: [
delimiter: ",",
separator: ".",
currency: "USD",
format: "%cs %n%s%d"
]
```

## Installation

Add monetized to your list of dependencies in `mix.exs`:

```elixir
def deps do
[{:monetized, "~> 0.5.0"}]
end

```

## TODO

- [ ] New currencies can be added through the package's config
- [ ] 1.0.0 ! yay!

## Benchmarking

```sh-session
$ mix deps.get
$ MIX_ENV=bench mix compile
$ MIX_ENV=bench mix bench
```

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for details.

## Licensing

See [LICENSE.md](LICENSE.md)