Skip to content

Commit

Permalink
feat(forex): add 'to' method to convert to another currency
Browse files Browse the repository at this point in the history
Money.forexService() is used to obtain the exchange rate.
  • Loading branch information
richardschneider committed Nov 19, 2016
1 parent dc99ba8 commit fad3087
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ the help of [semantic-release](https://github.com/semantic-release/semantic-rele
- Locale specific formatting using the [Internationalization API](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl)
- Precision decimal arithmetic using a [big number](https://www.npmjs.com/package/big.js) package
- [ISO-4217](https://en.wikipedia.org/wiki/ISO_4217) currency codes
- Currency conversion
- Uses [Martin Folwer's](http://martinfowler.com/) design pattern for [Money](http://martinfowler.com/eaaCatalog/money.html)
- Allocation of funds without loosing pennies (smallest denomination)
- Uses [Andy Earnshaw's Intl](https://github.com/andyearnshaw/Intl.js) when the environment's `Intl` package doesn't support the language.
Expand Down Expand Up @@ -97,7 +98,11 @@ And `toLocaleString`
A default locale and localeOptions is set with `Money.defaultLocale` and `Money.defaultLocaleOptions`. Both defaults are a function that return the default locale (string or array) and default locale options (object), respectively.

Money.defaultLocale = () => window.lang;


### Currency conversion

`to(currency)` returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to convert the Money into another currency. It uses `Money.forexService` to determine the exchange rate. If the exchange rate cannot be determined, then the Promise is rejected.

### Browser usage

Include the package from your project
Expand Down
22 changes: 22 additions & 0 deletions lib/money.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Money.defaultLocaleOptions = function() {
return undefined;
};

Money.forexService = function(from, to) {
return Promise.resolve(1.0); // TODO: Call a real forex service
};

Money.prototype.precision = function precision() {
let options = l10n(this.currency).resolvedOptions();
return options.maximumFractionDigits;
Expand Down Expand Up @@ -171,4 +175,22 @@ Money.prototype.isNegative = function isNegative() {
return this.amount.cmp(zero) < 0;
};

Money.prototype.to = function to(currency) {
if (!iso4217.test(currency)) {
return Promise.reject(new Error(`'${currency}' is not a valid ISO-4217 currency code`));
}
let self = this;

return Money
.forexService(self.currency, currency)
.then(rate => {
try {
return new Money(self.amount.times(rate), currency);
} catch (e) {
return Promise.reject(e);
}
})
;
};

module.exports = Money;
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
"keywords": [
"money",
"currency",
"forex",
"conversion",
"fiat",
"moolah",
"i18n",
Expand Down
44 changes: 44 additions & 0 deletions test/money.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,48 @@ describe('Money', () => {
});
});

describe('Forex', () => {

var forexService;
beforeEach(function() {
forexService = Money.forexService;
});
afterEach(function() {
Money.forexService = forexService;
});

it('should return a Promise', () => {
let nzd = new Money('100 NZD');
nzd.to('CNY').should.be.a.Promise();
});

it('should reject invalid currency code', () => {
let nzd = new Money('100 NZD');
return nzd.to('CNY-XXX')
.should.be.rejectedWith({ message: "'CNY-XXX' is not a valid ISO-4217 currency code" });
});

it('should fulfill Promise with money in the converted currency', () => {
let nzd = new Money('100 NZD');
return nzd.to('CNY').should
.finally.be.instanceOf(Money)
.and.have.property('currency', 'CNY');
});

it('should reject an undefined exchange rate', () => {
let nzd = new Money('100 NZD');
Money.forexService = () => Promise.resolve(undefined);
return nzd.to('CNY')
.should.be.rejected();
});

it('should reject an exchange rate that is not a number', () => {
let nzd = new Money('100 NZD');
Money.forexService = () => Promise.resolve('foo');
return nzd.to('CNY')
.should.be.rejected();
});

});

});

0 comments on commit fad3087

Please sign in to comment.