UNPKG

@type-ddd/money

Version:

This package provides TypeScript type definitions for handling Money in Domain-Driven Design contexts

473 lines (472 loc) 19.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Money = exports.Locales = exports.Currencies = void 0; const rich_domain_1 = require("rich-domain"); var Currencies; (function (Currencies) { Currencies["USD"] = "USD"; Currencies["EUR"] = "EUR"; Currencies["JPY"] = "JPY"; Currencies["GBP"] = "GBP"; Currencies["AUD"] = "AUD"; Currencies["CAD"] = "CAD"; Currencies["CHF"] = "CHF"; Currencies["CNY"] = "CNY"; Currencies["SEK"] = "SEK"; Currencies["NZD"] = "NZD"; Currencies["KRW"] = "KRW"; Currencies["SGD"] = "SGD"; Currencies["NOK"] = "NOK"; Currencies["MXN"] = "MXN"; Currencies["INR"] = "INR"; Currencies["BRL"] = "BRL"; Currencies["RUB"] = "RUB"; Currencies["ZAR"] = "ZAR"; Currencies["TRY"] = "TRY"; Currencies["HKD"] = "HKD"; })(Currencies || (exports.Currencies = Currencies = {})); var Locales; (function (Locales) { Locales["en-US"] = "en-US"; Locales["en-GB"] = "en-GB"; Locales["en-CA"] = "en-CA"; Locales["en-AU"] = "en-AU"; Locales["en-NZ"] = "en-NZ"; Locales["fr-FR"] = "fr-FR"; Locales["fr-CA"] = "fr-CA"; Locales["es-ES"] = "es-ES"; Locales["es-MX"] = "es-MX"; Locales["pt-BR"] = "pt-BR"; Locales["pt-PT"] = "pt-PT"; Locales["de-DE"] = "de-DE"; Locales["it-IT"] = "it-IT"; Locales["ja-JP"] = "ja-JP"; Locales["ko-KR"] = "ko-KR"; Locales["zh-CN"] = "zh-CN"; Locales["zh-TW"] = "zh-TW"; Locales["ru-RU"] = "ru-RU"; })(Locales || (exports.Locales = Locales = {})); class Money extends rich_domain_1.ValueObject { constructor(prop) { super(prop); } value() { return this.props; } /** * @description Validate if provided value is a valid money value. * @param value The value to validate. * @returns A boolean indicating whether the provided value is a valid money value. */ static isValid(value) { return this.isValidProps(value); } /** * @description Validate if provided value is a valid money value. * @param value The value to validate. * @returns A boolean indicating whether the provided value is a valid money value. */ static isValidProps(value) { return this.validator.number(value).isSafeInteger(); } /** * @description Formats the money value as currency according to the specified currency and locale. * @param currency The currency code or enum representing the currency. Defaults to Brazilian Real (BRL). * @param locale The locale code or enum representing the locale. Defaults to Brazilian Portuguese (pt-BR). * @returns A string representing the money value formatted as currency. */ coin(currency, locale) { return Intl.NumberFormat(locale ?? Locales['pt-BR'], { currency: currency ?? Currencies.BRL, style: 'currency' }).format(this.value()); } /** * @description Performs addition with another Money object or a numeric value. * @param money The Money object or numeric value to add. * @returns A new Money object representing the result of the addition. */ sum(money) { const current = this.value(); const target = money instanceof Money ? money.value() : money; const total = this.util.number(current).sum(target, { fractionDigits: 3 }); return new Money(total); } /** * @description Performs subtraction with another Money object or a numeric value. * @param money The Money object or numeric value to subtract. * @returns A new Money object representing the result of the subtraction. */ subtract(money) { const current = this.value(); const target = money instanceof Money ? money.value() : money; const total = this.util.number(current).subtract(target, { fractionDigits: 3 }); return new Money(total); } /** * @description Performs multiplication with another Money object or a numeric value. * @param money The Money object or numeric value to multiply by. * @returns A new Money object representing the result of the multiplication. */ multiply(money) { const current = this.value(); const target = money instanceof Money ? money.value() : money; const total = this.util.number(current).multiplyBy(target, { fractionDigits: 3 }); return new Money(total); } /** * @description Performs division with another Money object or a numeric value. * @param money The Money object or numeric value to divide by. * @returns A new Money object representing the result of the division. */ divide(money) { const current = this.value(); const target = money instanceof Money ? money.value() : money; const total = this.util.number(current).divideBy(target, { fractionDigits: 3 }); return new Money(total); } /** * @description Adds a percentage to the money value. * @param percent The percentage to add. * @returns A new Money object representing the result of adding the percentage. */ addPercent(percent) { const current = this.value(); const multiply = this.util.number(current).multiplyBy(percent); const percents = this.util.number(multiply).divideBy(100); const total = this.util.number(percents).sum(current, { fractionDigits: 3 }); return new Money(total); } /** * @description Calculates the percentage of the money value. * @param percent The percentage to calculate. * @returns A new Money object representing the calculated percentage. */ percent(percent) { const current = this.value(); const multiply = this.util.number(current).multiplyBy(percent); const percents = this.util.number(multiply).divideBy(100, { fractionDigits: 3 }); return new Money(percents); } /** * @description Checks if the money value is greater than the provided value. * @param value The value to compare. * @returns A boolean indicating whether the money value is greater than the provided value. */ isGt(value) { const target = value instanceof Money ? value.value() : value; const current = this.value(); return this.validator.number(current).isGreaterThan(target); } /** * @description Checks if the money value is greater than or equal to the provided value. * @param value The value to compare. * @returns A boolean indicating whether the money value is greater than or equal to the provided value. */ isGte(value) { const target = value instanceof Money ? value.value() : value; const current = this.value(); return this.validator.number(current).isGreaterOrEqualTo(target); } /** * @description Checks if the money value is less than the provided value. * @param value The value to compare. * @returns A boolean indicating whether the money value is less than the provided value. */ isLt(value) { const target = value instanceof Money ? value.value() : value; const current = this.value(); return this.validator.number(current).isLessThan(target); } /** * @description Checks if the money value is less than or equal to the provided value. * @param value The value to compare. * @returns A boolean indicating whether the money value is less than or equal to the provided value. */ isLte(value) { const target = value instanceof Money ? value.value() : value; const current = this.value(); return this.validator.number(current).isLessOrEqualTo(target); } /** * @description Checks if the money value is equal to the provided value. * @param value The value to compare. * @returns A boolean indicating whether the money value is equal to the provided value. */ isEq(value) { const target = value instanceof Money ? value.value() : value; const current = this.value(); return this.validator.number(current).isEqualTo(target); } /** * @description Checks if the money value is positive. * @returns A boolean indicating whether the money value is positive. */ isPos() { return this.validator.number(this.props).isPositive(); } /** * @description Checks if the money value is negative. * @returns A boolean indicating whether the money value is negative. */ isNeg() { return this.validator.number(this.props).isNegative(); } /** * @description Checks if the money value is zero. * @returns A boolean indicating whether the money value is zero. */ isZero() { return this.validator.number(this.props).isEqualTo(0); } /** * @description Makes the money value positive. * @returns A new Money object with a positive value. */ makePos() { const value = this.value(); if (this.validator.number(value).isNegative()) { return new Money(value * -1); } return new Money(value); } /** * @description Makes the money value negative. * @returns A new Money object with a negative value. */ makeNeg() { const value = this.value(); if (this.validator.number(value).isPositive()) { return new Money(value * -1); } return new Money(value); } /** * @description Creates a new Money object with a value of zero. * @returns A new Money object initialized with a value of zero. */ static zero() { return new Money(0); } /** * @description Creates a new Money object with a value of one. * @returns A new Money object initialized with a value of one. */ static one() { return new Money(1); } /** * @description Creates a new Money object with a value of ten. * @returns A new Money object initialized with a value of ten. */ static ten() { return new Money(10); } /** * @description Creates a new Money object with a value of one hundred. * @returns A new Money object initialized with a value of one hundred. */ static one_hundred() { return new Money(100); } /** * @description Creates a new Money object with a value of one thousand. * @returns A new Money object initialized with a value of one thousand. */ static one_thousand() { return new Money(1000); } /** * @description Performs summation of two values. * @param a The first value to sum, which can be a number or a Money object. * @param b The second value to sum, which can be a number or a Money object. * @returns The result of the summation as a number. */ static sum(a, b) { const valueA = a instanceof Money ? a.value() : a; const valueB = b instanceof Money ? b.value() : b; return this.util.number(valueA).sum(valueB, { fractionDigits: 3 }); } /** * @description Performs division of two values. * @param a The numerator value, which can be a number or a Money object. * @param b The denominator value, which can be a number or a Money object. * @returns The result of the division as a number. */ static divide(a, b) { const valueA = a instanceof Money ? a.value() : a; const valueB = b instanceof Money ? b.value() : b; return this.util.number(valueA).divideBy(valueB, { fractionDigits: 3 }); } /** * @description Performs multiplication of two values. * @param a The first value to multiply, which can be a number or a Money object. * @param b The second value to multiply, which can be a number or a Money object. * @returns The result of the multiplication as a number. */ static multiply(a, b) { const valueA = a instanceof Money ? a.value() : a; const valueB = b instanceof Money ? b.value() : b; return this.util.number(valueA).multiplyBy(valueB, { fractionDigits: 3 }); } /** * @description Performs subtraction of two values. * @param a The minuend value, which can be a number or a Money object. * @param b The subtrahend value, which can be a number or a Money object. * @returns The result of the subtraction as a number. */ static subtract(a, b) { const valueA = a instanceof Money ? a.value() : a; const valueB = b instanceof Money ? b.value() : b; return this.util.number(valueA).subtract(valueB, { fractionDigits: 3 }); } /** * @description Rounds down the money value to the nearest integer. * @returns A new Money object representing the rounded-down value. */ floor() { const ceil = Math.floor(this.props); return new Money(ceil); } ; /** * @description Rounds up the money value to the nearest integer. * @returns A new Money object representing the rounded-up value. */ ceil() { const ceil = Math.ceil(this.props); return new Money(ceil); } /** * @description Generates a closure that performs arithmetic operations with a predefined initial value. * @param initial The initial value for arithmetic operations. * @returns An object containing functions for performing `summation`, `division`, `multiplication`, and `subtraction` with the initial value. */ static closure(initial) { return { sum: (value) => Money.sum(initial, value), divide: (value) => Money.divide(initial, value), multiply: (value) => Money.multiply(initial, value), subtract: (value) => Money.subtract(initial, value) }; } /** * @description Calculates the simple interest based on the provided rate and periods. * @param rate The interest rate as a percentage. * @param periods The number of periods over which the interest is applied. * @returns A new Money object representing the calculated interest. * @throws {Error} If either the rate or periods is negative. */ interest(rate, periods) { if (this.validator.number(rate).isNegative() || this.validator.number(periods).isNegative()) { throw new Error('period and rate must be greater than zero'); } const rateBy100 = this.util.number(rate).divideBy(100); const amount = this.util.number(this.props).multiplyBy(rateBy100); const interest = this.util.number(amount).multiplyBy(periods); return new Money(interest); } /** * @description Finds the maximum value among the provided Money objects. * @param values An array of Money objects. * @returns A new Money object representing the maximum value found. */ static max(values) { const arr = values.map((item) => item.value()); const max = Math.max(...arr); return new Money(max); } /** * @description Finds the minimum value among the provided Money objects. * @param values An array of Money objects. * @returns A new Money object representing the minimum value found. */ static min(values) { const arr = values.map((item) => item.value()); const max = Math.min(...arr); return new Money(max); } /** * @description Calculates the compound interest based on the provided rate and periods. * @param rate The interest rate as a percentage. * @param periods The number of periods over which the interest is applied. * @returns A new Money object representing the calculated compound interest. * @throws {Error} If either the rate or periods is negative. */ compoundInterest(rate, periods) { if (this.validator.number(rate).isNegative() || this.validator.number(periods).isNegative()) { throw new Error('period and rate must be greater than zero'); } ; const rateBy100 = this.util.number(rate).divideBy(100); const base = this.util.number(rateBy100).sum(1); const pow = Math.pow(base, periods); const amount = this.util.number(this.props).multiplyBy(pow); const compoundInterest = this.util.number(amount).subtract(this.props, { fractionDigits: 3 }); return new Money(compoundInterest); } /** * @description Generates a random Money value within the specified range. * @param min The minimum value of the range. * @param max The maximum value of the range. * @returns A new Money object representing a random value within the specified range. */ static random(min, max) { if (min >= max) return Money.zero(); const randomValue = Math.random() * (max - min) + min; const roundedValue = Math.round(randomValue * 100) / 100; return new Money(roundedValue); } /** * @description Calculates the average value among the provided Money objects. * @param values An array of Money objects. * @returns A new Money object representing the average value of the Money objects. */ static average(values) { const items = values.length; const calc = (prev, current) => current.sum(prev); const total = values.reduce(calc, Money.zero()); return total.divide(items); } /** * @description Converts the current Money value to another currency using the provided exchange rate. * @param exchangeRate The exchange rate, which can be a Money object representing the rate or a number. * @returns A new Money object representing the converted value. */ convertTo(exchangeRate) { const current = this.value(); const rate = exchangeRate instanceof Money ? exchangeRate.value() : exchangeRate; const value = this.util.number(current).multiplyBy(rate, { fractionDigits: 3 }); return new Money(value); } /** * @description Initializes a Money object with the provided value. * @param value The initial value for the Money object. * @returns A new Money object initialized with the provided value. * @throws {Error} If the provided value is invalid. */ static init(value) { const isValidValue = Money.isValidProps(value); if (!isValidValue) throw new Error(Money.MESSAGE); return new Money(value); } /** * @description Creates a Result object containing a Money object initialized with the provided value. * @param value The initial value for the Money object. * @returns A Result object containing either a Money object or an error message. */ static create(value) { if (!Money.isValidProps(value)) { return rich_domain_1.Result.fail(Money.MESSAGE); } return rich_domain_1.Result.Ok(new Money(value)); } ; } exports.Money = Money; Money.MESSAGE = 'Invalid money value'; exports.default = Money;