Giter Club home page Giter Club logo

currency-conversion's Introduction

CurrencyConversion

GitHub license Hex.pm Version Coverage Status

Convert Money Amounts between currencies. This library uses an OTP worker to save current conversion rates.

Installation

The package can be installed by adding currency_conversion to your list of dependencies in mix.exs:

def deps do
  [
    {:currency_conversion, "~> 1.0"},
    {:jason, "~> 1.1"}, # When usig Fixer / Exchange Rates API,
    {:httpotion, "~> 3.1"}, # When usig Fixer / Exchange Rates API
  ]
end

Setup

CurrencyConversion is a wrapper around the currency conversion. We can define an implementation as follows:

defmodule MyApp.CurrencyConversion do
  use CurrencyConversion, otp_app: :my_app
end

If your application was generated with a supervisor (by passing --sup to mix new) you will have a lib/my_app/application.ex file containing the application start callback that defines and starts your supervisor. You just need to edit the start/2 function to start the converter as a supervisor on your application's supervisor:

def start(_type, _args) do
  children = [
    {MyApp.CurrencyConversion, []}
  ]
  opts = [strategy: :one_for_one, name: MyApp.Supervisor]
  Supervisor.start_link(children, opts)
end

Configuration

  • source - Configure which Data Source Should Be Used.
    • Type: atom
    • Default: CurrencyConversion.Source.ExchangeRatesApi
    • Restrictions: Must implement CurrencyConversion.Source behaviour
    • Given Implementations:
      • CurrencyConversion.Source.Fixer - Fixer
      • CurrencyConversion.Source.ExchangeRatesApi - Exchange Rates API
      • CurrencyConversion.Source.Test - Test Source
  • base_currency - Change the base currency that is requested when fetching rates
    • Type: atom
    • Default: :EUR
  • refresh_interval - Configure how often the data should be refreshed (in ms) or turn auto-refresh off.
    • Type: integer | :manual
    • Default: 86_400_000 (Once per Day)
    • :manual turns auto-refresh off, do refresh yourself
  • seed - Deliver the rates data manually.
    • Type: (Keyword.t() -> {:ok, CurrencyConversion.Rates.t()} | {:error, binary}) | {module :: atom, function :: atom, arity :: 1}
    • Default: Load from source
  • test_rates - Configure rates for CurrencyConversion.Source.Test source
    • Type: {atom, %{atom: float}}
    • Default: see CurrencyConversion.Source.Test.@default_rates
    • Example: {:EUR, %{CHF: 7.0}}
config :my_app, MyApp.CurrencyConversion,
  source: CurrencyConversion.Source.Fixer,
  source_api_key: "FIXER_ACCESS_KEY",
  source_protocol: "https",
  refresh_interval: 86_400_000

Custom Source

A custom source can be implemented by using the behaviour CurrencyConversion.Source and reconfiguring the source config.

It only has to implement the function load/0, which produces a struct of type %CurrencyConversion.Rates{}.

Test

To prevent HTTP calls in the Tests, configure the Test Source. (See the configuration test_rates for custom test rates.)

config :my_app, MyApp.CurrencyConversion,
  source: CurrencyConversion.Source.Test,
  refresh_interval: 86_400_000

Usage

Only the callbacks from CurrencyConversion are exposed to the user. The library money is used to represent money amounts.

Example

Change 7 swiss franks to dollars:

iex> MyApp.CurrencyConversion.convert(Money.new(7_00, :CHF), :USD)
%Money{amount: 10_50, currency: :USD}

Get supported currencies:

iex> MyApp.CurrencyConversion.get_currencies()
[:EUR, :USD, :CHF, ...]

Manually refresh exchange rates:

iex> MyApp.CurrencyConversion.refresh_rates()
:ok

currency-conversion's People

Contributors

maennchen avatar mitcheaton1 avatar strzibny avatar zacksiri avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

currency-conversion's Issues

Ability to avoid refresh on start?

I would like to avoid automatic refresh() call on the update worker start: https://github.com/jshmrtn/currency-conversion/blob/master/lib/currency_conversion/update_worker.ex#L22

The use-case is that I wish to keep a given currency exchange same during the day. If the worker gets restarted it would change the exchange rates during the day. My work-flow would be to update the worker with a manual refresh() call (this is possible).

At last I would also need a function that can load the data I provide (rather then getting them from the service provider) and use them on start. Do you think we can support this in the library? I could make an attempt on adding this functionality.

If you think there is a better way to provide same-day rates I would welcome any suggestions.

Working with Decimals?

I am thinking that it would be awesome to also support plain Decimals as an alternative to Money library that limits itself to cent values (integers as cents). Since many application save money data as decimals, this could be pretty useful (it could work without loosing any precision at all).

It is not possible to start the application when source API is down

Currently when the source API's are down the CurrencyConversion supervisor does not start because the UpdateWorker is not started.

Would it be possible to start the CurrencyConversion process using the seed data in this case? In this case the UpdateWorker would need to keep retrying to fetch the rates from the source instead of stopping.

Expected behaviour on invalid API key

When giving an invalid api key or an api key that has exceeded the authorized amount of requests (rate limit), the following error is returned and the application never starts.
''' elixir
[error] An error occured while rereshing currency rates. "Fixer API Schema has changed."
** (Mix) Could not start application currency_conversion: CurrencyConversion.Application.start(:normal, []) returned an error: shutdown: failed to start child: CurrencyConversion.UpdateWorker
** (EXIT) {:error, "Fixer API Schema has changed."}
'''

What is the recommended approach when this error happens?

Source configuration stopped working?

I am trying to write tests in my project and the following seemed not to have any effect:

config :myproject, MyProject.CurrencyExchange,
  source: CurrencyConversion.Source.Test

Can you confirm this does not work anymore? Or it's expected that it's set as:

config :myproject, CurrencyConversion,
  source: CurrencyConversion.Source.Test

?

CurrencyExchange is the exchange module:

defmodule MyProject.CurrencyExchange do
  use CurrencyConversion, otp_app: :myproject
  ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.