diff --git a/src/bank/index.spec.ts b/src/bank/index.spec.ts index 6b7750a..1b23bc7 100644 --- a/src/bank/index.spec.ts +++ b/src/bank/index.spec.ts @@ -3,6 +3,13 @@ import Expression, { Sum } from '../expression'; import Money from '../money'; describe('Bank', () => { + describe('rates', () => { + it('should return 1 if currencies are the same', () => { + const bank: Bank = new Bank(); + expect(bank.rate('USD', 'USD')).toEqual(1); + }); + }); + describe('reduce', () => { describe('sum', () => { it('should reduce a sum expression', () => { @@ -13,6 +20,19 @@ describe('Bank', () => { expect(result).toEqual(Money.dollar(7)); }); + + it('should reduce Money', () => { + const bank: Bank = new Bank(); + const result: Money = bank.reduce(Money.dollar(1), 'USD'); + expect(result).toEqual(Money.dollar(1)); + }); + + it('should reduce mixed Money currencies', () => { + const bank: Bank = new Bank(); + bank.addRate('CHF', 'USD', 2); + const result: Money = bank.reduce(Money.franc(2), 'USD'); + expect(result).toEqual(Money.dollar(1)); + }); }); }); }); diff --git a/src/bank/index.ts b/src/bank/index.ts index 9379b29..9f9e7de 100644 --- a/src/bank/index.ts +++ b/src/bank/index.ts @@ -1,9 +1,23 @@ import Money from '../money'; -import Expression, { Sum } from '../expression'; +import Expression from '../expression'; export default class Bank { - reduce(to: Expression, currency: string): Money { - const sum: Sum = to as Sum; - return sum.reduce(currency); + private _rates: Object; + + constructor() { + this._rates = {}; + } + + reduce(source: Expression, to: string): Money { + return source.reduce(this, to); + } + + rate(from: string, to: string): number { + if (from === to) return 1; + return this._rates[`${from}-${to}`]; + } + + addRate(from: string, to: string, rate: number): void { + this._rates[`${from}-${to}`] = rate; } } diff --git a/src/expression/index.ts b/src/expression/index.ts index 8a99c6d..429f204 100644 --- a/src/expression/index.ts +++ b/src/expression/index.ts @@ -1,6 +1,9 @@ +import Bank from '../bank'; import Money from '../money'; -export default interface Expression {} +export default interface Expression { + reduce(bank: Bank, to: string): Money; +} export class Sum implements Expression { private _augend: Money; @@ -19,7 +22,7 @@ export class Sum implements Expression { return this._addend; } - reduce(to: string): Money { + reduce(bank: Bank, to: string): Money { const amount: number = this.augend.amount + this.addend.amount; return new Money(amount, to); } diff --git a/src/money/index.ts b/src/money/index.ts index df29a59..b3c00c2 100644 --- a/src/money/index.ts +++ b/src/money/index.ts @@ -1,6 +1,7 @@ +import Bank from '../bank'; import Expression, { Sum } from '../expression'; -export default class Money { +export default class Money implements Expression { private _amount: number; private _currency: string; @@ -34,6 +35,11 @@ export default class Money { return new Sum(this, addend); } + reduce(bank: Bank, to: string): Money { + const rate: number = bank.rate(this.currency, to); + return new Money(this.amount / rate, to); + } + get currency(): string { return this._currency; }