ts-money
Version:
Typescript port of js-money. Implementation of the Money value object.
198 lines (197 loc) • 6.19 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const lodash_1 = require("lodash");
const currency_1 = require("./currency");
var isInt = function (n) {
return Number(n) === n && n % 1 === 0;
};
var decimalPlaces = function (num) {
var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match)
return 0;
return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
};
var assertSameCurrency = function (left, right) {
if (left.currency !== right.currency)
throw new Error('Different currencies');
};
var assertType = function (other) {
if (!(other instanceof Money))
throw new TypeError('Instance of Money required');
};
var assertOperand = function (operand) {
if (lodash_1.isNaN(parseFloat(operand)) && !isFinite(operand))
throw new TypeError('Operand must be a number');
};
class Money {
constructor(amount, currency) {
if (lodash_1.isString(currency))
currency = currency_1.currencies[currency];
if (!lodash_1.isPlainObject(currency))
throw new TypeError('Invalid currency');
if (!isInt(amount))
throw new TypeError('Amount must be an integer');
this.amount = amount;
this.currency = currency.code;
Object.freeze(this);
}
static fromInteger(amount, currency) {
if (lodash_1.isObject(amount)) {
if (amount.amount === undefined || amount.currency === undefined)
throw new TypeError('Missing required parameters amount,currency');
currency = amount.currency;
amount = amount.amount;
}
if (!isInt(amount))
throw new TypeError('Amount must be an integer value');
return new Money(amount, currency);
}
static fromDecimal(amount, currency, rounder) {
if (lodash_1.isObject(amount)) {
if (amount.amount === undefined || amount.currency === undefined)
throw new TypeError('Missing required parameters amount,currency');
rounder = currency;
currency = amount.currency;
amount = amount.amount;
}
if (lodash_1.isString(currency))
currency = currency_1.currencies[currency];
if (!lodash_1.isPlainObject(currency))
throw new TypeError('Invalid currency');
if (rounder === undefined) {
var decimals = decimalPlaces(amount);
if (decimals > currency.decimal_digits)
throw new Error("The currency " + currency.code + " supports only "
+ currency.decimal_digits + " decimal digits");
}
else {
if (['round', 'floor', 'ceil'].indexOf(rounder) === -1 && typeof rounder !== 'function')
throw new TypeError('Invalid parameter rounder');
if (lodash_1.isString(rounder))
rounder = Math[rounder];
}
var precisionMultiplier = Math.pow(10, currency.decimal_digits);
var resultAmount = amount * precisionMultiplier;
if (lodash_1.isFunction(rounder))
resultAmount = rounder(resultAmount);
return new Money(resultAmount, currency);
}
;
equals(other) {
var self = this;
assertType(other);
return self.amount === other.amount &&
self.currency === other.currency;
}
;
add(other) {
var self = this;
assertType(other);
assertSameCurrency(self, other);
return new Money(self.amount + other.amount, self.currency);
}
;
subtract(other) {
var self = this;
assertType(other);
assertSameCurrency(self, other);
return new Money(self.amount - other.amount, self.currency);
}
;
multiply(multiplier, fn) {
if (!lodash_1.isFunction(fn))
fn = Math.round;
assertOperand(multiplier);
var amount = fn(this.amount * multiplier);
return new Money(amount, this.currency);
}
;
divide(divisor, fn) {
if (!lodash_1.isFunction(fn))
fn = Math.round;
assertOperand(divisor);
var amount = fn(this.amount / divisor);
return new Money(amount, this.currency);
}
;
allocate(ratios) {
var self = this;
var remainder = self.amount;
var results = [];
var total = 0;
ratios.forEach(function (ratio) {
total += ratio;
});
ratios.forEach(function (ratio) {
var share = Math.floor(self.amount * ratio / total);
results.push(new Money(share, self.currency));
remainder -= share;
});
for (var i = 0; remainder > 0; i++) {
results[i] = new Money(results[i].amount + 1, results[i].currency);
remainder--;
}
return results;
}
;
compare(other) {
var self = this;
assertType(other);
assertSameCurrency(self, other);
if (self.amount === other.amount)
return 0;
return self.amount > other.amount ? 1 : -1;
}
;
greaterThan(other) {
return 1 === this.compare(other);
}
;
greaterThanOrEqual(other) {
return 0 <= this.compare(other);
}
;
lessThan(other) {
return -1 === this.compare(other);
}
;
lessThanOrEqual(other) {
return 0 >= this.compare(other);
}
;
isZero() {
return this.amount === 0;
}
;
isPositive() {
return this.amount > 0;
}
;
isNegative() {
return this.amount < 0;
}
;
toDecimal() {
return Number(this.toString());
}
;
toString() {
var currency = currency_1.currencies[this.currency];
return (this.amount / Math.pow(10, currency.decimal_digits)).toFixed(currency.decimal_digits);
}
;
toJSON() {
return {
amount: this.amount,
currency: this.currency
};
}
;
getAmount() {
return this.amount;
}
getCurrency() {
return this.currency;
}
}
exports.Money = Money;