Change names of the Money properties and add some specs

This commit is contained in:
Eric 2020-06-26 16:31:30 -05:00 committed by Eric Schultz
parent c213e4d5d2
commit 9eedc704b5
2 changed files with 62 additions and 21 deletions

View file

@ -0,0 +1,30 @@
import {Money} from './money'
import 'jest';
describe("Money", () => {
describe('Money.fromCents',() => {
it('succeeds from a old Money object', () => {
const old = Money.fromCents(333, 'eur')
const result = Money.fromCents(old)
expect(result).toEqual(old)
expect(result).not.toBe(old)
})
it('succeeds from a json', () => {
const old = {amount:333, currency:'eur'}
const result = Money.fromCents(old)
expect(result).toEqual(old)
expect(result).toBeInstanceOf(Money)
})
it('succeeds from function parameters', () => {
const result = Money.fromCents(333, 'eur')
expect(result).toEqual({amount:333, currency:'eur'})
expect(result).toBeInstanceOf(Money)
})
})
})

View file

@ -17,6 +17,8 @@ const assertOperand = function (operand: any) {
throw new TypeError('Operand must be a number'); throw new TypeError('Operand must be a number');
}; };
type MoneyAsJson = {amount: number, currency: string}
/** /**
* Represents a monetary amount. For safety, all Money objects are immutable. All of the functions in this class create a new Money object. * Represents a monetary amount. For safety, all Money objects are immutable. All of the functions in this class create a new Money object.
* *
@ -28,7 +30,7 @@ export class Money {
readonly currency:string readonly currency:string
protected constructor(readonly amountInCents: number, currency: string) { protected constructor(readonly amount: number, currency: string) {
this.currency = currency.toLowerCase() this.currency = currency.toLowerCase()
const methodsToBind = [this.equals, this.add, this.subtract, this.multiply, this.divide, this.allocate, const methodsToBind = [this.equals, this.add, this.subtract, this.multiply, this.divide, this.allocate,
this.compare, this.greaterThan, this.greaterThanOrEqual, this.lessThan, this.compare, this.greaterThan, this.greaterThanOrEqual, this.lessThan,
@ -42,14 +44,25 @@ export class Money {
/** /**
* Create a `Money` object with the given number of cents and the ISO currency unit * Create a `Money` object with the given number of cents and the ISO currency unit
* @static * @static
* @param {number} amountInCents * @param {number} amount
* @param {string} currency * @param {string} currency
* @return Money * @return Money
* @memberof Money * @memberof Money
*/ */
static fromCents(amountInCents: number, currency: string): Money {
return new Money(amountInCents, currency) static fromCents(amount:MoneyAsJson): Money;
static fromCents(amount:Money): Money;
static fromCents(amount: number, currency: string) : Money;
static fromCents(amount: number|Money|MoneyAsJson, currency?: string): Money {
if (typeof amount === 'number')
return new Money(amount, currency);
if (amount instanceof Money)
return new Money(amount.amount, amount.currency);
else
return new Money(amount.amount, amount.currency)
} }
/** /**
* Create a `Money` object with the given number if smallest monetary units and the ISO currency. Another name for the `fromCents` function. * Create a `Money` object with the given number if smallest monetary units and the ISO currency. Another name for the `fromCents` function.
@ -68,7 +81,7 @@ export class Money {
var self = this; var self = this;
assertType(other); assertType(other);
return self.amountInCents === other.amountInCents && return self.amount === other.amount &&
self.currency === other.currency; self.currency === other.currency;
}; };
@ -83,7 +96,7 @@ export class Money {
assertType(other); assertType(other);
assertSameCurrency(self, other); assertSameCurrency(self, other);
return new Money(self.amountInCents + other.amountInCents, self.currency); return new Money(self.amount + other.amount, self.currency);
}; };
/** /**
@ -97,7 +110,7 @@ export class Money {
assertType(other); assertType(other);
assertSameCurrency(self, other); assertSameCurrency(self, other);
return new Money(self.amountInCents - other.amountInCents, self.currency); return new Money(self.amount - other.amount, self.currency);
}; };
/** /**
@ -112,7 +125,7 @@ export class Money {
fn = Math.round; fn = Math.round;
assertOperand(multiplier); assertOperand(multiplier);
var amount = fn(this.amountInCents * multiplier); var amount = fn(this.amount * multiplier);
return new Money(amount, this.currency); return new Money(amount, this.currency);
}; };
@ -129,7 +142,7 @@ export class Money {
fn = Math.round; fn = Math.round;
assertOperand(divisor); assertOperand(divisor);
var amount = fn(this.amountInCents / divisor); var amount = fn(this.amount / divisor);
return new Money(amount, this.currency); return new Money(amount, this.currency);
}; };
@ -142,7 +155,7 @@ export class Money {
*/ */
allocate(ratios: number[]): Money[] { allocate(ratios: number[]): Money[] {
var self = this; var self = this;
var remainder = self.amountInCents; var remainder = self.amount;
var results: Money[] = []; var results: Money[] = [];
var total = 0; var total = 0;
@ -151,13 +164,13 @@ export class Money {
}); });
ratios.forEach(function (ratio) { ratios.forEach(function (ratio) {
var share = Math.floor(self.amountInCents * ratio / total) var share = Math.floor(self.amount * ratio / total)
results.push(new Money(share, self.currency)); results.push(new Money(share, self.currency));
remainder -= share; remainder -= share;
}); });
for (var i = 0; remainder > 0; i++) { for (var i = 0; remainder > 0; i++) {
results[i] = new Money(results[i].amountInCents + 1, results[i].currency); results[i] = new Money(results[i].amount + 1, results[i].currency);
remainder--; remainder--;
} }
@ -176,10 +189,10 @@ export class Money {
assertType(other); assertType(other);
assertSameCurrency(self, other); assertSameCurrency(self, other);
if (self.amountInCents === other.amountInCents) if (self.amount === other.amount)
return 0; return 0;
return self.amountInCents > other.amountInCents ? 1 : -1; return self.amount > other.amount ? 1 : -1;
}; };
/** /**
@ -228,7 +241,7 @@ export class Money {
* @returns {boolean} * @returns {boolean}
*/ */
isZero(): boolean { isZero(): boolean {
return this.amountInCents === 0; return this.amount === 0;
}; };
/** /**
@ -237,7 +250,7 @@ export class Money {
* @returns {boolean} * @returns {boolean}
*/ */
isPositive(): boolean { isPositive(): boolean {
return this.amountInCents > 0; return this.amount > 0;
}; };
/** /**
@ -246,7 +259,7 @@ export class Money {
* @returns {boolean} * @returns {boolean}
*/ */
isNegative(): boolean { isNegative(): boolean {
return this.amountInCents < 0; return this.amount < 0;
}; };
/** /**
@ -254,12 +267,10 @@ export class Money {
* *
* @returns {{amount: number, currency: string}} * @returns {{amount: number, currency: string}}
*/ */
toJSON(): { amountInCents: number; currency: string; } { toJSON(): MoneyAsJson {
return { return {
amountInCents: this.amountInCents, amount: this.amount,
currency: this.currency currency: this.currency
}; };
}; };
} }