Money
A special wrapper class for semantically correct handling of monetary amounts.
It stores information about the currency and amount with precision corresponding to the smallest unit of the currency. It provides methods for operations on monetary amounts with "correct" precision and without issues related to storing fractional values in floating-point variables.
Instances of the Money class represent runtime values of fields in heap tables declared through Heap. Money.
The Money class can be used for convenient handling of monetary amounts outside the context of the heap.
Usage / Signature
import { Money } from '@app/heap'
const moneyVal = new Money(amount, currency)
Properties and Methods
-
<b id="constructor">constructor</b>(amount: number, currency: Currency)
<b>constructor</b>(moneyLike: { amount: number, currency: Currency })
<b>constructor</b>(money: Money)
<b>constructor</b>(serialized: [amount: number, currency: Currency])
The constructor of the class. It accepts both another instance ofMoney
and other formats.-
<b id="c_amount">amount</b>:
number
The amount in the specified currency. -
<b id="c_currency">currency</b>:
Currency
A three-letter international currency code (ISO 4217).
The amount can be provided with any precision but is always rounded to the number of decimal places specified in the ISO 4217 standard for the selected currency (meta-information about the currency is used from the built-in JS subsystem Intl). Rounding is done according to the "half away from zero" rule.
-
-
<b id="amount">amount</b>:
number
The quantity (amount) of currency stored in this instance. Stored as a floating-point number with precision corresponding to the currency's requirements per the ISO 4217 standard (for most currencies, this is 2 decimal places). -
<b id="currency">currency</b>:
Currency
A string with the three-letter international currency code (ISO 4217).
Arithmetic Operations
-
<b id="add">add</b>(summand: Money):
Money
Addition operation. Adds the provided monetary amount to the current one and returns the result as a new instance of Money.- An exception will be thrown if an attempt is made to add two different currencies.
- The operation is performed with integer values and is not subject to issues related to operations on floating-point numbers.
- The result is rounded according to the rules for the currency described above.
- <b id="add_summand">summand</b>:
Money
The summand - the monetary amount that should be added to the current one.
-
<b id="substract">substract</b>(subtracted: Money):
Money
Subtraction operation. Subtracts the provided monetary amount from the current one and returns the result as a new instance of Money.- An exception will be thrown if an attempt is made to subtract a currency different from the one being reduced.
- The operation is performed with integer values and is not subject to issues related to operations on floating-point numbers.
- The result is rounded according to the rules for the currency described above.
- <b id="substract_subtracted">subtracted</b>:
Money
The subtracted amount - the monetary amount by which the current one needs to be reduced.
-
<b id="multiply">multiply(multiplier: number)</b>:
Money
Multiplication operation. Multiplies the current amount by the given multiplier and returns the result as a new instance of Money with the original currency.- The operation is performed with integer values and is not subject to issues related to operations on floating-point numbers.
- The result is rounded according to the rules for the currency described above.
- <b id="multiply_multiplier">multiplier</b>:
number
The multiplier - any fractional or whole number.
-
<b id="divide">divide</b>(divider: number):
Money
Division operation. Divides the current amount by the given divisor and returns the result as a new instance of Money with the original currency.- The operation is performed with integer values and is not subject to issues related to operations on floating-point numbers.
- The result is rounded according to the rules for the currency described above.
- <b id="divide_divider">divider</b>:
number
The divisor - any fractional or whole number except zero.
Other Methods
-
<b id="format">format</b>(ctx: app. Ctx, options?: MoneyFormatOptions):
string
Returns a string with the monetary amount formatted using Number.toLocaleString().Localization rules (which country's/language's rules to format the currency) are taken from the provided context.
-
<b id="format_ctx">ctx</b>: app. Ctx
The request context from which the method "learns" which locale code (in the formaten-US
) to use in theIntl.NumberFormat
constructor. -
<b id="format_options">options</b>:
{
style, currencyDisplay, signDisplay, currencySign, useGrouping, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, minimumSignificantDigits, maximumSignificantDigits}
Formatting parameters. Almost all parameters of Intl.NumberFormat are supported. Thecurrency
parameter is not supported since it is always automatically substituted from the currency stored in the Money instance.-
<b id="format_options_style">style</b>:
'currency' | 'decimal'
(default'currency'
)
Whether to display as a regular number or a number with currency. -
<b id="format_options_currencyDisplay">currencyDisplay</b>:
'symbol' | 'code' | 'name' | 'narrowSymbol'
(default'symbol'
)
How to display the currency sign whenstyle=currency
:'symbol'
- localized currency symbol ($, €, ₽)'code'
- three-letter international code (USD, EUR, RUB)'name'
- localized name of the currency (dollar, euro, ruble)'narrowSymbol'
- abbreviated currency symbol - makes sense for some currencies that may have the same symbol - for example, in theen-AU
locale, Australian and US dollars will be displayed differently ($ and USD) forsymbol
and the same ($ and $) fornarrowSymbol
. Also, in some locales, the international code is used by default for foreign currencies;narrowSymbol
forces the use of the short symbol.
-
<b id="format_options_signDisplay">signDisplay</b>:
'always' | 'auto' | 'exceptZero' | 'never'
(default'auto'
)
When to display the sign of the numeric value.'always'
- always (for zero+
)'auto'
- only for positive values'exceptZero'
- for everything except zero'never'
- do not show the sign
-
<b id="format_options_currencySign">currencySign</b>:
'standard' | 'accounting'
(default'standard'
)
How to format negative values.'standard'
- use the minus sign (-
)'accounting'
- in many locales, in this mode, negative values are displayed in parentheses without the minus sign (e.g., in en-US(₽1,234.00)
)
-
<b id="format_options_useGrouping">useGrouping</b>:
'auto' | true | false
(default'auto'
)
Whether to use a thousands separator.'auto'
- according to locale settingstrue
- alwaysfalse
- never
-
<b id="format_options_minimumIntegerDigits">minimumIntegerDigits</b>:
number
(default1
)
The minimum number of digits displayed (from 1 to 21) in the integer part of the displayed amount. If the number of significant digits is less than this number, it is "padded" with zeros on the left to reach the required amount.This property is ignored if minimumSignificantDigits or maximumSignificantDigits are explicitly set.
-
<b id="format_options_minimumFractionDigits">minimumFractionDigits</b>:
number
(default - the number of decimal places for the currency from ISO 4217)
The minimum number of digits displayed (from 0 to 20) in the fractional part of the displayed amount. If the number of significant digits is less than this number, it is "padded" with zeros on the right to reach the required amount.This property is ignored if minimumSignificantDigits or maximumSignificantDigits are explicitly set.
-
<b id="format_options_maximumFractionDigits">maximumFractionDigits</b>:
number
(defaultmax(minimumFractionDigits, number of decimal places for the currency from ISO 4217)
)
The maximum number of digits displayed (from 0 to 20) in the fractional part of the displayed amount. If the number of significant digits exceeds this number, it is rounded according to the half-away-from-zero rule.Cannot be less than minimumFractionDigits.
This property is ignored if minimumSignificantDigits or maximumSignificantDigits are explicitly set.
-
<b id="format_options_minimumSignificantDigits">minimumSignificantDigits</b>:
number
(default1
)
The minimum number of digits displayed (from 1 to 21) in total in the integer and fractional parts of the displayed amount. If the total number of significant digits is less than this number, it is "padded" with zeros in the fractional part on the right to reach the required amount.Using this property disables the effect of minimumIntegerDigits, minimumFractionDigits, and maximumFractionDigits.
-
<b id="format_options_maximumSignificantDigits">maximumSignificantDigits</b>:
number
(default21
)
The maximum number of digits displayed (from 1 to 21) in total in the integer and fractional parts of the displayed amount. If the total number of significant digits exceeds this number, it is rounded according to the half-away-from-zero rule, so that the number of significant digits from the most significant digit to the last non-zero digit does not exceed the specified value. Rounding applies not only to the fractional part but also to the integer part: for example, the sum 1251 with maximumSignificantDigits=2 will become 1300.Cannot be less than minimumSignificantDigits.
Using this property disables the effect of minimumIntegerDigits, minimumFractionDigits, and maximumFractionDigits.
-
-
Examples
Adding a bonus, calculating interest, and displaying the result
const Balances = Heap.Table('balances', {
amount: Heap.Money(),
})
async function addBonusPlus10Percent(
ctx: app.Ctx, balanceId: string, bonus: Money,
): Promise<typeof Balances.T> {
const balance = await Balances.getById(ctx, balanceId)
return Balances.update({
id: balance.id,
amount: balance.amount.add(bonus).multiply(1.1),
})
}
const balanceWithBonus = await addBonusPlus10Percent(
ctx, req.params.id, new Money(req.params.bonus, 'USD'),
)
ctx.console.log('new balance', balanceWithBonus.amount.format(ctx, {
currencyDisplay: 'narrowSymbol',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
})