Change names of the Money properties and add some specs
This commit is contained in:
parent
c213e4d5d2
commit
9eedc704b5
2 changed files with 62 additions and 21 deletions
30
app/javascript/common/money.spec.ts
Normal file
30
app/javascript/common/money.spec.ts
Normal 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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -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
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue