Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce mixed currency money #14

Merged
merged 11 commits into from
Sep 29, 2022
20 changes: 20 additions & 0 deletions src/bank/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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));
});
});
});
});
22 changes: 18 additions & 4 deletions src/bank/index.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
7 changes: 5 additions & 2 deletions src/expression/index.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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);
}
Expand Down
8 changes: 7 additions & 1 deletion src/money/index.ts
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down