typescript-libraries
Version:
To install this library, run:
324 lines (323 loc) • 10.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TSCurrencies = exports.TSMoney = void 0;
var TSCurrencies_1 = require("./TSCurrencies");
Object.defineProperty(exports, "TSCurrencies", { enumerable: true, get: function () { return TSCurrencies_1.TSCurrencies; } });
var isInt = function (n) {
return Number(n) === n && n % 1 === 0;
};
var decimalPlaces = function (num) {
var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
return !match ? 0 : 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 TSMoney)) {
throw new TypeError('Instance of TSMoney required');
}
};
var assertOperand = function (operand) {
if (isNaN(parseFloat(operand)) && !isFinite(operand)) {
throw new TypeError('Operand must be a number');
}
};
var getCurrencyObject = function (currency) {
var currencyObj = TSCurrencies_1.TSCurrencies[currency];
if (currencyObj) {
return currencyObj;
}
else {
for (var key in TSCurrencies_1.TSCurrencies) {
if (key.toUpperCase() === currency.toUpperCase()) {
return TSCurrencies_1.TSCurrencies[key];
}
}
}
};
var TSMoney = /** @class */ (function () {
/**
* Creates a new TSMoney instance. The created TSMoney instances is a value object thus it is immutable.
*
* @param {Number} amount
* @param {Object/String} currency
* @returns {TSMoney}
* @constructor
*/
function TSMoney(amount, currency) {
if (typeof currency === 'string') {
currency = getCurrencyObject(currency);
}
if (typeof currency !== 'object') {
throw new TypeError('Invalid currency');
}
if (!isInt(amount)) {
throw new TypeError('Amount must be an integer');
}
this.amount = amount;
this.currency = currency.code;
for (var c in TSCurrencies_1.TSCurrencies) {
if (TSCurrencies_1.TSCurrencies.hasOwnProperty(c)) {
this[c] = TSCurrencies_1.TSCurrencies[c];
}
}
Object.freeze(this);
}
TSMoney.fromInteger = function (amount, currency) {
if (typeof amount === 'object') {
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 TSMoney(amount, currency);
};
TSMoney.fromDecimal = function (amount, currency, rounder) {
if (typeof amount === 'object') {
if (amount.amount === undefined || amount.currency === undefined) {
throw new TypeError('Missing required parameters amount,currency');
}
rounder = currency;
currency = amount.currency;
amount = amount.amount;
}
if (typeof currency === 'string') {
currency = getCurrencyObject(currency);
}
if (typeof currency !== 'object') {
throw new TypeError('Invalid currency');
}
if (rounder === undefined) {
var decimals = decimalPlaces(amount);
if (decimals > currency.decimal_digits) {
throw new Error("The currency ".concat(currency.code, " supports only ").concat(currency.decimal_digits, " decimal digits"));
}
rounder = Math.round;
}
else {
if (['round', 'floor', 'ceil'].indexOf(rounder) === -1 && typeof rounder !== 'function') {
throw new TypeError('Invalid parameter rounder');
}
if (typeof rounder === 'string') {
rounder = Math[rounder];
}
}
var precisionMultiplier = Math.pow(10, currency.decimal_digits);
var resultAmount = amount * precisionMultiplier;
resultAmount = rounder(resultAmount);
return new TSMoney(resultAmount, currency);
};
/**
* Returns true if the two instances of TSMoney are equal, false otherwise.
*
* @param {TSMoney} other
* @returns {Boolean}
*/
TSMoney.prototype.equals = function (other) {
assertType(other);
return this.amount === other.amount && this.currency === other.currency;
};
/**
* Adds the two objects together creating a new TSMoney instance that holds the result of the operation.
*
* @param {TSMoney} other
* @returns {TSMoney}
*/
TSMoney.prototype.add = function (other) {
assertType(other);
assertSameCurrency(this, other);
return new TSMoney(this.amount + other.amount, this.currency);
};
/**
* Subtracts the two objects creating a new TSMoney instance that holds the result of the operation.
*
* @param {TSMoney} other
* @returns {TSMoney}
*/
TSMoney.prototype.subtract = function (other) {
assertType(other);
assertSameCurrency(this, other);
return new TSMoney(this.amount - other.amount, this.currency);
};
/**
* Multiplies the object by the multiplier returning a new TSMoney instance that holds the result of the operation.
*
* @param {Number} multiplier
* @param {Function} [fn=Math.round]
* @returns {TSMoney}
*/
TSMoney.prototype.multiply = function (multiplier, fn) {
if (typeof fn !== 'function') {
fn = Math.round;
}
assertOperand(multiplier);
return new TSMoney(fn(this.amount * multiplier), this.currency);
};
/**
* Divides the object by the multiplier returning a new TSMoney instance that holds the result of the operation.
*
* @param {Number} divisor
* @param {Function} [fn=Math.round]
* @returns {TSMoney}
*/
TSMoney.prototype.divide = function (divisor, fn) {
if (typeof fn !== 'function') {
fn = Math.round;
}
assertOperand(divisor);
return new TSMoney(fn(this.amount / divisor), this.currency);
};
/**
* Allocates fund bases on the ratios provided returing an array of objects as a product of the allocation.
*
* @param {Array} other
* @returns {Array.TSMoney}
*/
TSMoney.prototype.allocate = function (ratios) {
var _this = this;
var remainder = this.amount;
var results = [];
var total = 0;
ratios.forEach(function (ratio) {
total += ratio;
});
ratios.forEach(function (ratio) {
var share = Math.floor(_this.amount * ratio / total);
results.push(new TSMoney(share, _this.currency));
remainder -= share;
});
for (var i = 0; remainder > 0; i++) {
results[i] = new TSMoney(results[i].amount + 1, results[i].currency);
remainder--;
}
return results;
};
/**
* Compares two instances of TSMoney.
*
* @param {TSMoney} other
* @returns {Number}
*/
TSMoney.prototype.compare = function (other) {
assertType(other);
assertSameCurrency(this, other);
return this.amount === other.amount ? 0 : (this.amount > other.amount ? 1 : -1);
};
/**
* Checks whether the value represented by this object is greater than the other.
*
* @param {TSMoney} other
* @returns {boolean}
*/
TSMoney.prototype.greaterThan = function (other) {
return 1 === this.compare(other);
};
/**
* Checks whether the value represented by this object is greater or equal to the other.
*
* @param {TSMoney} other
* @returns {boolean}
*/
TSMoney.prototype.greaterThanOrEqual = function (other) {
return 0 <= this.compare(other);
};
/**
* Checks whether the value represented by this object is less than the other.
*
* @param {TSMoney} other
* @returns {boolean}
*/
TSMoney.prototype.lessThan = function (other) {
return -1 === this.compare(other);
};
/**
* Checks whether the value represented by this object is less than or equal to the other.
*
* @param {TSMoney} other
* @returns {boolean}
*/
TSMoney.prototype.lessThanOrEqual = function (other) {
return 0 >= this.compare(other);
};
/**
* Returns true if the amount is zero.
*
* @returns {boolean}
*/
TSMoney.prototype.isZero = function () {
return this.amount === 0;
};
/**
* Returns true if the amount is positive.
*
* @returns {boolean}
*/
TSMoney.prototype.isPositive = function () {
return this.amount > 0;
};
/**
* Returns true if the amount is negative.
*
* @returns {boolean}
*/
TSMoney.prototype.isNegative = function () {
return this.amount < 0;
};
/**
* Returns the decimal value as a float.
*
* @returns {number}
*/
TSMoney.prototype.toDecimal = function () {
return Number(this.toString());
};
/**
* Returns the decimal value as a string.
*
* @returns {string}
*/
TSMoney.prototype.toString = function () {
var currency = getCurrencyObject(this.currency);
return (this.amount / Math.pow(10, currency.decimal_digits)).toFixed(currency.decimal_digits);
};
/**
* Returns a serialised version of the instance.
*
* @returns {{amount: number, currency: string}}
*/
TSMoney.prototype.toJSON = function () {
return { amount: this.amount, currency: this.currency };
};
/**
* Returns the amount represented by this object.
*
* @returns {number}
*/
TSMoney.prototype.getAmount = function () {
return this.amount;
};
/**
* Returns the currency represented by this object.
*
* @returns {string}
*/
TSMoney.prototype.getCurrency = function () {
return this.currency;
};
/**
* Returns the full currency object
*/
TSMoney.prototype.getCurrencyInfo = function () {
return getCurrencyObject(this.currency);
};
return TSMoney;
}());
exports.TSMoney = TSMoney;
Object.assign(TSMoney, TSCurrencies_1.TSCurrencies);