mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 16:07:33 +08:00
support setting decimal separator and digit grouping symbol
This commit is contained in:
@@ -109,6 +109,14 @@ export function getObjectOwnFieldCount(object) {
|
||||
return count;
|
||||
}
|
||||
|
||||
export function replaceAll(value, originalValue, targetValue) {
|
||||
return value.replaceAll(new RegExp(originalValue, 'g'), targetValue);
|
||||
}
|
||||
|
||||
export function removeAll(value, originalValue) {
|
||||
return replaceAll(value, originalValue, '');
|
||||
}
|
||||
|
||||
export function limitText(value, maxLength) {
|
||||
let length = 0;
|
||||
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
import { isNumber } from './common.js';
|
||||
import { appendThousandsSeparator } from './numeral.js';
|
||||
|
||||
export function numericCurrencyToString(num, enableThousandsSeparator, trimTailZero) {
|
||||
let str = num.toString();
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
let integer = '0';
|
||||
let decimals = '00';
|
||||
|
||||
if (str.length > 2) {
|
||||
integer = str.substring(0, str.length - 2);
|
||||
decimals = str.substring(str.length - 2);
|
||||
} else if (str.length === 2) {
|
||||
decimals = str;
|
||||
} else if (str.length === 1) {
|
||||
decimals = '0' + str;
|
||||
}
|
||||
|
||||
if (trimTailZero) {
|
||||
if (decimals.charAt(0) === '0' && decimals.charAt(1) === '0') {
|
||||
decimals = '';
|
||||
} else if (decimals.charAt(0) !== '0' && decimals.charAt(1) === '0') {
|
||||
decimals = decimals.charAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
integer = appendThousandsSeparator(integer, enableThousandsSeparator);
|
||||
|
||||
if (decimals !== '') {
|
||||
str = `${integer}.${decimals}`;
|
||||
} else {
|
||||
str = integer;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
str = `-${str}`;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
export function stringCurrencyToNumeric(str) {
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sign = negative ? -1 : 1;
|
||||
|
||||
if (str.indexOf(',')) {
|
||||
str = str.replaceAll(/,/g, '');
|
||||
}
|
||||
|
||||
let dotPos = str.indexOf('.');
|
||||
|
||||
if (dotPos < 0) {
|
||||
return sign * parseInt(str) * 100;
|
||||
} else if (dotPos === 0) {
|
||||
str = '0' + str;
|
||||
dotPos++;
|
||||
}
|
||||
|
||||
const integer = str.substring(0, dotPos);
|
||||
const decimals = str.substring(dotPos + 1, str.length);
|
||||
|
||||
if (decimals.length < 1) {
|
||||
return sign * parseInt(integer) * 100;
|
||||
} else if (decimals.length === 1) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals) * 10;
|
||||
} else if (decimals.length === 2) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals);
|
||||
} else {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals.substring(0, 2));
|
||||
}
|
||||
}
|
||||
|
||||
export function getExchangedAmount(amount, fromRate, toRate) {
|
||||
const exchangeRate = parseFloat(toRate) / parseFloat(fromRate);
|
||||
|
||||
if (!isNumber(exchangeRate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return amount * exchangeRate;
|
||||
}
|
||||
|
||||
export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) {
|
||||
if (!fromExchangeRate || !toExchangeRate) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (baseAmount === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getExchangedAmount(baseAmount, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
}
|
||||
|
||||
export function getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator) {
|
||||
if (rateStr.indexOf('.') < 0) {
|
||||
return appendThousandsSeparator(rateStr, isEnableThousandsSeparator);
|
||||
} else {
|
||||
let firstNonZeroPos = 0;
|
||||
|
||||
for (let i = 0; i < rateStr.length; i++) {
|
||||
if (rateStr.charAt(i) !== '.' && rateStr.charAt(i) !== '0') {
|
||||
firstNonZeroPos = Math.min(i + 4, rateStr.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const trimmedRateStr = rateStr.substring(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf('.') + 2)));
|
||||
return appendThousandsSeparator(trimmedRateStr, isEnableThousandsSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, isEnableThousandsSeparator) {
|
||||
if (!amount1 || !amount2 || amount1 === amount2) {
|
||||
if (!fromExchangeRate || !fromExchangeRate.rate || !toExchangeRate || !toExchangeRate.rate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
amount1 = fromExchangeRate.rate;
|
||||
amount2 = toExchangeRate.rate;
|
||||
}
|
||||
|
||||
amount1 = parseFloat(amount1);
|
||||
amount2 = parseFloat(amount2);
|
||||
|
||||
if (amount1 > amount2) {
|
||||
const rateStr = (amount1 / amount2).toString();
|
||||
const displayRateStr = getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator);
|
||||
return `${displayRateStr} : 1`;
|
||||
} else {
|
||||
const rateStr = (amount2 / amount1).toString();
|
||||
const displayRateStr = getDisplayExchangeRateAmount(rateStr, isEnableThousandsSeparator);
|
||||
return `1 : ${displayRateStr}`;
|
||||
}
|
||||
}
|
||||
+251
-93
@@ -1,6 +1,7 @@
|
||||
import moment from 'moment-timezone';
|
||||
|
||||
import { defaultLanguage, allLanguages } from '@/locales/index.js';
|
||||
import numeral from '@/consts/numeral.js';
|
||||
import datetime from '@/consts/datetime.js';
|
||||
import timezone from '@/consts/timezone.js';
|
||||
import currency from '@/consts/currency.js';
|
||||
@@ -11,6 +12,7 @@ import statistics from '@/consts/statistics.js';
|
||||
import {
|
||||
isString,
|
||||
isNumber,
|
||||
isBoolean,
|
||||
getTextBefore,
|
||||
getTextAfter,
|
||||
copyObjectTo,
|
||||
@@ -36,8 +38,12 @@ import {
|
||||
} from './datetime.js';
|
||||
|
||||
import {
|
||||
numericCurrencyToString
|
||||
} from './currency.js';
|
||||
appendDigitGroupingSymbol,
|
||||
parseAmount,
|
||||
formatAmount,
|
||||
formatExchangeRateAmount,
|
||||
getAdaptiveDisplayAmountRate
|
||||
} from './numeral.js';
|
||||
|
||||
import {
|
||||
getCategorizedAccounts,
|
||||
@@ -781,6 +787,231 @@ function getAllTimezoneTypesUsedForStatistics(currentTimezone, translateFn) {
|
||||
];
|
||||
}
|
||||
|
||||
function getAllDecimalSeparators(translateFn) {
|
||||
const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator');
|
||||
return getNumeralSeparatorFormats(translateFn, numeral.allDecimalSeparator, numeral.allDecimalSeparatorArray, defaultDecimalSeparatorTypeName, numeral.defaultDecimalSeparator);
|
||||
}
|
||||
|
||||
function getAllDigitGroupingSymbols(translateFn) {
|
||||
const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol');
|
||||
return getNumeralSeparatorFormats(translateFn, numeral.allDigitGroupingSymbol, numeral.allDigitGroupingSymbolArray, defaultDigitGroupingSymbolTypeName, numeral.defaultDigitGroupingSymbol);
|
||||
}
|
||||
|
||||
function getNumeralSeparatorFormats(translateFn, allSeparatorMap, allSeparatorArray, localeDefaultTypeName, systemDefaultType) {
|
||||
let defaultSeparatorType = allSeparatorMap[localeDefaultTypeName];
|
||||
|
||||
if (!defaultSeparatorType) {
|
||||
defaultSeparatorType = systemDefaultType;
|
||||
}
|
||||
|
||||
const ret = [];
|
||||
|
||||
ret.push({
|
||||
type: numeral.defaultValue,
|
||||
symbol: defaultSeparatorType.symbol,
|
||||
displayName: `${translateFn('Language Default')} (${defaultSeparatorType.symbol})`
|
||||
});
|
||||
|
||||
for (let i = 0; i < allSeparatorArray.length; i++) {
|
||||
const type = allSeparatorArray[i];
|
||||
|
||||
ret.push({
|
||||
type: type.type,
|
||||
symbol: type.symbol,
|
||||
displayName: `${translateFn('numeral.' + type.name)} (${type.symbol})`
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getAllDigitGroupingTypes(translateFn) {
|
||||
const defaultDigitGroupingTypeName = translateFn('default.digitGrouping');
|
||||
let defaultDigitGroupingType = numeral.allDigitGroupingType[defaultDigitGroupingTypeName];
|
||||
|
||||
if (!defaultDigitGroupingType) {
|
||||
defaultDigitGroupingType = numeral.defaultDigitGroupingType;
|
||||
}
|
||||
|
||||
const ret = [];
|
||||
|
||||
ret.push({
|
||||
type: numeral.defaultValue,
|
||||
displayName: `${translateFn('Language Default')} (${translateFn('numeral.' + defaultDigitGroupingType.name)})`
|
||||
});
|
||||
|
||||
for (let i = 0; i < numeral.allDigitGroupingTypeArray.length; i++) {
|
||||
const type = numeral.allDigitGroupingTypeArray[i];
|
||||
|
||||
ret.push({
|
||||
type: type.type,
|
||||
displayName: translateFn('numeral.' + type.name)
|
||||
});
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getCurrentDecimalSeparator(translateFn, decimalSeparator) {
|
||||
let decimalSeparatorType = numeral.allDecimalSeparatorMap[decimalSeparator];
|
||||
|
||||
if (!decimalSeparatorType) {
|
||||
const defaultDecimalSeparatorTypeName = translateFn('default.decimalSeparator');
|
||||
decimalSeparatorType = numeral.allDecimalSeparator[defaultDecimalSeparatorTypeName];
|
||||
|
||||
if (!decimalSeparatorType) {
|
||||
decimalSeparatorType = numeral.defaultDecimalSeparator;
|
||||
}
|
||||
}
|
||||
|
||||
return decimalSeparatorType.symbol;
|
||||
}
|
||||
|
||||
function getCurrentDigitGroupingSymbol(translateFn, digitGroupingSymbol) {
|
||||
let digitGroupingSymbolType = numeral.allDigitGroupingSymbolMap[digitGroupingSymbol];
|
||||
|
||||
if (!digitGroupingSymbolType) {
|
||||
const defaultDigitGroupingSymbolTypeName = translateFn('default.digitGroupingSymbol');
|
||||
digitGroupingSymbolType = numeral.allDigitGroupingSymbol[defaultDigitGroupingSymbolTypeName];
|
||||
|
||||
if (!digitGroupingSymbolType) {
|
||||
digitGroupingSymbolType = numeral.defaultDigitGroupingSymbol;
|
||||
}
|
||||
}
|
||||
|
||||
return digitGroupingSymbolType.symbol;
|
||||
}
|
||||
|
||||
function getCurrentDigitGroupingType(translateFn, digitGrouping) {
|
||||
let digitGroupingType = numeral.allDigitGroupingTypeMap[digitGrouping];
|
||||
|
||||
if (!digitGroupingType) {
|
||||
const defaultDigitGroupingTypeName = translateFn('default.digitGrouping');
|
||||
digitGroupingType = numeral.allDigitGroupingType[defaultDigitGroupingTypeName];
|
||||
|
||||
if (!digitGroupingType) {
|
||||
digitGroupingType = numeral.defaultDigitGroupingType;
|
||||
}
|
||||
}
|
||||
|
||||
return digitGroupingType.type;
|
||||
}
|
||||
|
||||
function getNumberFormatOptions(translateFn, userStore) {
|
||||
return {
|
||||
decimalSeparator: getCurrentDecimalSeparator(translateFn, userStore.currentUserDecimalSeparator),
|
||||
digitGroupingSymbol: getCurrentDigitGroupingSymbol(translateFn, userStore.currentUserDigitGroupingSymbol),
|
||||
digitGrouping: getCurrentDigitGroupingType(translateFn, userStore.currentUserDigitGrouping),
|
||||
};
|
||||
}
|
||||
|
||||
function getNumberWithDigitGroupingSymbol(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return appendDigitGroupingSymbol(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getParsedAmountNumber(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return parseAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getFormatedAmount(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return formatAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getFormatedAmountWithCurrency(value, currencyCode, translateFn, userStore, settingsStore, notConvertValue) {
|
||||
if (!isNumber(value) && !isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!notConvertValue) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
const hasIncompleteFlag = isString(value) && value.charAt(value.length - 1) === '+';
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value.substring(0, value.length - 1);
|
||||
}
|
||||
|
||||
value = formatAmount(value, numberFormatOptions);
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value + '+';
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBoolean(currencyCode) && !currencyCode) {
|
||||
currencyCode = userStore.currentUserDefaultCurrency;
|
||||
} else if (isBoolean(currencyCode) && !currencyCode) {
|
||||
currencyCode = '';
|
||||
}
|
||||
|
||||
const currencyDisplayMode = settingsStore.appSettings.currencyDisplayMode;
|
||||
|
||||
if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Symbol) {
|
||||
const currencyInfo = currency.all[currencyCode];
|
||||
let currencySymbol = currency.defaultCurrencySymbol;
|
||||
|
||||
if (currencyInfo && currencyInfo.symbol) {
|
||||
currencySymbol = currencyInfo.symbol;
|
||||
} else if (currencyInfo && currencyInfo.code) {
|
||||
currencySymbol = currencyInfo.code;
|
||||
}
|
||||
|
||||
return translateFn('format.currency.symbol', {
|
||||
amount: value,
|
||||
symbol: currencySymbol
|
||||
});
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Code) {
|
||||
return `${value} ${currencyCode}`;
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Name) {
|
||||
const currencyName = getCurrencyName(currencyCode, translateFn);
|
||||
return `${value} ${currencyName}`;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function getFormatedExchangeRateAmount(value, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return formatExchangeRateAmount(value, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, translateFn, userStore) {
|
||||
const numberFormatOptions = getNumberFormatOptions(translateFn, userStore);
|
||||
return getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, numberFormatOptions);
|
||||
}
|
||||
|
||||
function getAmountPrependAndAppendText(currencyCode, translateFn, userStore, settingsStore) {
|
||||
const placeholder = '***';
|
||||
const finalText = getFormatedAmountWithCurrency(placeholder, currencyCode, translateFn, userStore, settingsStore, true);
|
||||
|
||||
if (!finalText) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let prependText = getTextBefore(finalText, placeholder);
|
||||
|
||||
if (prependText) {
|
||||
prependText = prependText.trim();
|
||||
}
|
||||
|
||||
let appendText = getTextAfter(finalText, placeholder);
|
||||
|
||||
if (appendText) {
|
||||
appendText = appendText.trim();
|
||||
}
|
||||
|
||||
return {
|
||||
prependText: prependText,
|
||||
appendText: appendText
|
||||
};
|
||||
}
|
||||
|
||||
function getAllAccountCategories(translateFn) {
|
||||
const allAccountCategories = [];
|
||||
|
||||
@@ -996,91 +1227,7 @@ function getEnableDisableOptions(translateFn) {
|
||||
}];
|
||||
}
|
||||
|
||||
function getDisplayCurrency(value, currencyCode, options, translateFn) {
|
||||
if (!isNumber(value) && !isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!options.notConvertValue) {
|
||||
const hasIncompleteFlag = isString(value) && value.charAt(value.length - 1) === '+';
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value.substring(0, value.length - 1);
|
||||
}
|
||||
|
||||
value = numericCurrencyToString(value, options.enableThousandsSeparator);
|
||||
|
||||
if (hasIncompleteFlag) {
|
||||
value = value + '+';
|
||||
}
|
||||
}
|
||||
|
||||
const currencyDisplayMode = options.currencyDisplayMode;
|
||||
|
||||
if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Symbol) {
|
||||
const currencyInfo = currency.all[currencyCode];
|
||||
let currencySymbol = currency.defaultCurrencySymbol;
|
||||
|
||||
if (currencyInfo && currencyInfo.symbol) {
|
||||
currencySymbol = currencyInfo.symbol;
|
||||
} else if (currencyInfo && currencyInfo.code) {
|
||||
currencySymbol = currencyInfo.code;
|
||||
}
|
||||
|
||||
return translateFn('format.currency.symbol', {
|
||||
amount: value,
|
||||
symbol: currencySymbol
|
||||
});
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Code) {
|
||||
return `${value} ${currencyCode}`;
|
||||
} else if (currencyCode && currencyDisplayMode === currency.allCurrencyDisplayModes.Name) {
|
||||
const currencyName = getCurrencyName(currencyCode, translateFn);
|
||||
return `${value} ${currencyName}`;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
function getDisplayCurrencyPrependAndAppendText(currencyCode, currencyDisplayMode, translateFn) {
|
||||
const options = {
|
||||
currencyDisplayMode: currencyDisplayMode,
|
||||
notConvertValue: true
|
||||
};
|
||||
|
||||
const placeholder = '***';
|
||||
const finalText = getDisplayCurrency(placeholder, currencyCode, options, translateFn);
|
||||
|
||||
if (!finalText) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let prependText = getTextBefore(finalText, placeholder);
|
||||
|
||||
if (prependText) {
|
||||
prependText = prependText.trim();
|
||||
}
|
||||
|
||||
let appendText = getTextAfter(finalText, placeholder);
|
||||
|
||||
if (appendText) {
|
||||
appendText = appendText.trim();
|
||||
}
|
||||
|
||||
return {
|
||||
prependText: prependText,
|
||||
appendText: appendText
|
||||
};
|
||||
}
|
||||
|
||||
function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options, translateFn) {
|
||||
function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) {
|
||||
const categorizedAccounts = copyObjectTo(getCategorizedAccounts(allVisibleAccounts), {});
|
||||
|
||||
for (let category in categorizedAccounts) {
|
||||
@@ -1095,9 +1242,9 @@ function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisible
|
||||
const account = accountCategory.accounts[i];
|
||||
|
||||
if (showAccountBalance && account.isAsset) {
|
||||
account.displayBalance = getDisplayCurrency(account.balance, account.currency, options, translateFn);
|
||||
account.displayBalance = getFormatedAmountWithCurrency(account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else if (showAccountBalance && account.isLiability) {
|
||||
account.displayBalance = getDisplayCurrency(-account.balance, account.currency, options, translateFn);
|
||||
account.displayBalance = getFormatedAmountWithCurrency(-account.balance, account.currency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
account.displayBalance = '***';
|
||||
}
|
||||
@@ -1136,7 +1283,7 @@ function getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisible
|
||||
totalBalance = totalBalance + '+';
|
||||
}
|
||||
|
||||
accountCategory.displayBalance = getDisplayCurrency(totalBalance, defaultCurrency, options, translateFn);
|
||||
accountCategory.displayBalance = getFormatedAmountWithCurrency(totalBalance, defaultCurrency, translateFn, userStore, settingsStore);
|
||||
} else {
|
||||
accountCategory.displayBalance = '***';
|
||||
}
|
||||
@@ -1384,6 +1531,19 @@ export function i18nFunctions(i18nGlobal) {
|
||||
getAllRecentMonthDateRanges: (userStore, includeAll, includeCustom) => getAllRecentMonthDateRanges(userStore, includeAll, includeCustom, i18nGlobal.t),
|
||||
getDateRangeDisplayName: (userStore, dateType, startTime, endTime) => getDateRangeDisplayName(userStore, dateType, startTime, endTime, i18nGlobal.t),
|
||||
getAllTimezoneTypesUsedForStatistics: (currentTimezone) => getAllTimezoneTypesUsedForStatistics(currentTimezone, i18nGlobal.t),
|
||||
getAllDecimalSeparators: () => getAllDecimalSeparators(i18nGlobal.t),
|
||||
getAllDigitGroupingSymbols: () => getAllDigitGroupingSymbols(i18nGlobal.t),
|
||||
getAllDigitGroupingTypes: () => getAllDigitGroupingTypes(i18nGlobal.t),
|
||||
getCurrentDecimalSeparator: (userStore) => getCurrentDecimalSeparator(i18nGlobal.t, userStore.currentUserDecimalSeparator),
|
||||
getCurrentDigitGroupingSymbol: (userStore) => getCurrentDigitGroupingSymbol(i18nGlobal.t, userStore.currentUserDigitGroupingSymbol),
|
||||
getCurrentDigitGroupingType: (userStore) => getCurrentDigitGroupingType(i18nGlobal.t, userStore.currentUserDigitGrouping),
|
||||
appendDigitGroupingSymbol: (userStore, value) => getNumberWithDigitGroupingSymbol(value, i18nGlobal.t, userStore),
|
||||
parseAmount: (userStore, value) => getParsedAmountNumber(value, i18nGlobal.t, userStore),
|
||||
formatAmount: (userStore, value) => getFormatedAmount(value, i18nGlobal.t, userStore),
|
||||
formatAmountWithCurrency: (settingsStore, userStore, value, currencyCode) => getFormatedAmountWithCurrency(value, currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
formatExchangeRateAmount: (userStore, value) => getFormatedExchangeRateAmount(value, i18nGlobal.t, userStore),
|
||||
getAdaptiveAmountRate: (userStore, amount1, amount2, fromExchangeRate, toExchangeRate) => getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, i18nGlobal.t, userStore),
|
||||
getAmountPrependAndAppendText: (settingsStore, userStore, currencyCode) => getAmountPrependAndAppendText(currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
getAllAccountCategories: () => getAllAccountCategories(i18nGlobal.t),
|
||||
getAllAccountTypes: () => getAllAccountTypes(i18nGlobal.t),
|
||||
getAllCategoricalChartTypes: () => getAllCategoricalChartTypes(i18nGlobal.t),
|
||||
@@ -1394,9 +1554,7 @@ export function i18nFunctions(i18nGlobal) {
|
||||
getAllTransactionDefaultCategories: (categoryType, locale) => getAllTransactionDefaultCategories(categoryType, locale, i18nGlobal.t),
|
||||
getAllDisplayExchangeRates: (exchangeRatesData) => getAllDisplayExchangeRates(exchangeRatesData, i18nGlobal.t),
|
||||
getEnableDisableOptions: () => getEnableDisableOptions(i18nGlobal.t),
|
||||
getDisplayCurrency: (value, currencyCode, options) => getDisplayCurrency(value, currencyCode, options, i18nGlobal.t),
|
||||
getDisplayCurrencyPrependAndAppendText: (currencyCode, currencyDisplayMode) => getDisplayCurrencyPrependAndAppendText(currencyCode, currencyDisplayMode, i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options) => getCategorizedAccountsWithDisplayBalance(exchangeRatesStore, allVisibleAccounts, showAccountBalance, defaultCurrency, options, i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t),
|
||||
joinMultiText: (textArray) => joinMultiText(textArray, i18nGlobal.t),
|
||||
setLanguage: (locale, force) => setLanguage(i18nGlobal, locale, force),
|
||||
setTimeZone: (timezone) => setTimeZone(timezone),
|
||||
|
||||
+231
-16
@@ -1,5 +1,25 @@
|
||||
export function appendThousandsSeparator(value, enable) {
|
||||
if (!enable || value.length <= 3) {
|
||||
import numeralConstants from '@/consts/numeral.js';
|
||||
|
||||
import { isString, isNumber, removeAll } from './common.js';
|
||||
|
||||
export function appendDigitGroupingSymbol(value, options) {
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!isNumber(options.digitGrouping) || options.digitGrouping === numeralConstants.allDigitGroupingType.None.type) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value.length <= 3) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -9,35 +29,159 @@ export function appendThousandsSeparator(value, enable) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
const dotPos = value.indexOf('.');
|
||||
const integer = dotPos < 0 ? value : value.substring(0, dotPos);
|
||||
const decimals = dotPos < 0 ? '' : value.substring(dotPos + 1, value.length);
|
||||
const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol;
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
|
||||
const finalChars = [];
|
||||
let integerChars = [];
|
||||
let currentDecimalSeparator = '';
|
||||
let decimals = '';
|
||||
|
||||
for (let i = 0; i < integer.length; i++) {
|
||||
if (i % 3 === 0 && i > 0) {
|
||||
finalChars.push(',');
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
const ch = value.charAt(i);
|
||||
|
||||
if ('0' <= ch && ch <= '9') {
|
||||
integerChars.push(ch);
|
||||
} else {
|
||||
currentDecimalSeparator = ch;
|
||||
decimals = value.substring(i + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
finalChars.push(integer.charAt(integer.length - 1 - i));
|
||||
}
|
||||
|
||||
finalChars.reverse();
|
||||
let newInteger = '';
|
||||
|
||||
let newInteger = finalChars.join('');
|
||||
if (options.digitGrouping === numeralConstants.allDigitGroupingType.ThousandsSeparator.type) {
|
||||
for (let i = integerChars.length - 1, j = 0; i >= 0; i--, j++) {
|
||||
if (j % 3 === 0 && j > 0) {
|
||||
newInteger = digitGroupingSymbol + newInteger;
|
||||
}
|
||||
|
||||
newInteger = integerChars[i] + newInteger;
|
||||
}
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
newInteger = `-${newInteger}`;
|
||||
}
|
||||
|
||||
if (dotPos < 0) {
|
||||
return newInteger;
|
||||
if (currentDecimalSeparator) {
|
||||
return `${newInteger}${decimalSeparator}${decimals}`;
|
||||
} else {
|
||||
return `${newInteger}.${decimals}`;
|
||||
return newInteger;
|
||||
}
|
||||
}
|
||||
|
||||
export function parseAmount(str, options) {
|
||||
if (!isString(str)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const negative = str.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
str = str.substring(1);
|
||||
}
|
||||
|
||||
if (!str || str.length < 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const sign = negative ? -1 : 1;
|
||||
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
const digitGroupingSymbol = options.digitGroupingSymbol || numeralConstants.defaultDigitGroupingSymbol.symbol;
|
||||
|
||||
if (str.indexOf(digitGroupingSymbol) >= 0) {
|
||||
str = removeAll(str, digitGroupingSymbol);
|
||||
}
|
||||
|
||||
let decimalSeparatorPos = str.indexOf(decimalSeparator);
|
||||
|
||||
if (decimalSeparatorPos < 0) {
|
||||
return sign * parseInt(str) * 100;
|
||||
} else if (decimalSeparatorPos === 0) {
|
||||
str = '0' + str;
|
||||
decimalSeparatorPos++;
|
||||
}
|
||||
|
||||
const integer = str.substring(0, decimalSeparatorPos);
|
||||
const decimals = str.substring(decimalSeparatorPos + 1, str.length);
|
||||
|
||||
if (decimals.length < 1) {
|
||||
return sign * parseInt(integer) * 100;
|
||||
} else if (decimals.length === 1) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals) * 10;
|
||||
} else if (decimals.length === 2) {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals);
|
||||
} else {
|
||||
return sign * parseInt(integer) * 100 + sign * parseInt(decimals.substring(0, 2));
|
||||
}
|
||||
}
|
||||
|
||||
export function formatAmount(value, options) {
|
||||
if (isNumber(value)) {
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (!isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
const negative = value.charAt(0) === '-';
|
||||
|
||||
if (negative) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
|
||||
const decimalSeparator = options.decimalSeparator || numeralConstants.defaultDecimalSeparator.symbol;
|
||||
|
||||
let integer = '0';
|
||||
let decimals = '00';
|
||||
|
||||
if (value.length > 2) {
|
||||
integer = value.substring(0, value.length - 2);
|
||||
decimals = value.substring(value.length - 2);
|
||||
} else if (value.length === 2) {
|
||||
decimals = value;
|
||||
} else if (value.length === 1) {
|
||||
decimals = '0' + value;
|
||||
}
|
||||
|
||||
if (options.trimTailZero) {
|
||||
if (decimals.charAt(0) === '0' && decimals.charAt(1) === '0') {
|
||||
decimals = '';
|
||||
} else if (decimals.charAt(0) !== '0' && decimals.charAt(1) === '0') {
|
||||
decimals = decimals.charAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
integer = appendDigitGroupingSymbol(integer, options);
|
||||
|
||||
if (decimals !== '') {
|
||||
value = `${integer}${decimalSeparator}${decimals}`;
|
||||
} else {
|
||||
value = integer;
|
||||
}
|
||||
|
||||
if (negative) {
|
||||
value = `-${value}`;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
export function formatPercent(value, precision, lowPrecisionValue) {
|
||||
const ratio = Math.pow(10, precision);
|
||||
const normalizedValue = Math.floor(value * ratio);
|
||||
@@ -49,3 +193,74 @@ export function formatPercent(value, precision, lowPrecisionValue) {
|
||||
const result = normalizedValue / ratio;
|
||||
return result + '%';
|
||||
}
|
||||
|
||||
export function formatExchangeRateAmount(exchangeRateAmount, options) {
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
const rateStr = exchangeRateAmount.toString();
|
||||
const decimalSeparator = numeralConstants.allDecimalSeparator.Dot.symbol;
|
||||
|
||||
if (rateStr.indexOf(decimalSeparator) < 0) {
|
||||
return appendDigitGroupingSymbol(rateStr, options);
|
||||
} else {
|
||||
let firstNonZeroPos = 0;
|
||||
|
||||
for (let i = 0; i < rateStr.length; i++) {
|
||||
if (rateStr.charAt(i) !== decimalSeparator && rateStr.charAt(i) !== '0') {
|
||||
firstNonZeroPos = Math.min(i + 4, rateStr.length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const trimmedRateStr = rateStr.substring(0, Math.max(6, Math.max(firstNonZeroPos, rateStr.indexOf(decimalSeparator) + 2)));
|
||||
return appendDigitGroupingSymbol(trimmedRateStr, options);
|
||||
}
|
||||
}
|
||||
|
||||
export function getAdaptiveDisplayAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, options) {
|
||||
if (!amount1 || !amount2 || amount1 === amount2) {
|
||||
if (!fromExchangeRate || !fromExchangeRate.rate || !toExchangeRate || !toExchangeRate.rate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
amount1 = fromExchangeRate.rate;
|
||||
amount2 = toExchangeRate.rate;
|
||||
}
|
||||
|
||||
amount1 = parseFloat(amount1);
|
||||
amount2 = parseFloat(amount2);
|
||||
|
||||
if (amount1 > amount2) {
|
||||
const rateStr = (amount1 / amount2).toString();
|
||||
const displayRateStr = formatExchangeRateAmount(rateStr, options);
|
||||
return `${displayRateStr} : 1`;
|
||||
} else {
|
||||
const rateStr = (amount2 / amount1).toString();
|
||||
const displayRateStr = formatExchangeRateAmount(rateStr, options);
|
||||
return `1 : ${displayRateStr}`;
|
||||
}
|
||||
}
|
||||
|
||||
export function getExchangedAmount(amount, fromRate, toRate) {
|
||||
const exchangeRate = parseFloat(toRate) / parseFloat(fromRate);
|
||||
|
||||
if (!isNumber(exchangeRate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return amount * exchangeRate;
|
||||
}
|
||||
|
||||
export function getConvertedAmount(baseAmount, fromExchangeRate, toExchangeRate) {
|
||||
if (!fromExchangeRate || !toExchangeRate) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (baseAmount === '') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getExchangedAmount(baseAmount, fromExchangeRate.rate, toExchangeRate.rate);
|
||||
}
|
||||
|
||||
+5
-2
@@ -169,7 +169,7 @@ export default {
|
||||
getProfile: () => {
|
||||
return axios.get('v1/users/profile/get.json');
|
||||
},
|
||||
updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat }) => {
|
||||
updateProfile: ({ email, nickname, password, oldPassword, defaultAccountId, transactionEditScope, language, defaultCurrency, firstDayOfWeek, longDateFormat, shortDateFormat, longTimeFormat, shortTimeFormat, decimalSeparator, digitGroupingSymbol, digitGrouping }) => {
|
||||
return axios.post('v1/users/profile/update.json', {
|
||||
email,
|
||||
nickname,
|
||||
@@ -183,7 +183,10 @@ export default {
|
||||
longDateFormat,
|
||||
shortDateFormat,
|
||||
longTimeFormat,
|
||||
shortTimeFormat
|
||||
shortTimeFormat,
|
||||
decimalSeparator,
|
||||
digitGroupingSymbol,
|
||||
digitGrouping
|
||||
});
|
||||
},
|
||||
resendVerifyEmailByLoginedUser: () => {
|
||||
|
||||
@@ -13,7 +13,6 @@ const defaultSettings = {
|
||||
applicationLockWebAuthn: false,
|
||||
autoUpdateExchangeRatesData: true,
|
||||
autoGetCurrentGeoLocation: false,
|
||||
thousandsSeparator: true,
|
||||
currencyDisplayMode: currencyConstants.defaultCurrencyDisplayMode,
|
||||
showAmountInHomePage: true,
|
||||
timezoneUsedForStatisticsInHomePage: timezoneConstants.defaultTimezoneTypesUsedForStatistics,
|
||||
@@ -167,14 +166,6 @@ export function setAutoGetCurrentGeoLocation(value) {
|
||||
setOption('autoGetCurrentGeoLocation', value);
|
||||
}
|
||||
|
||||
export function isEnableThousandsSeparator() {
|
||||
return getOption('thousandsSeparator');
|
||||
}
|
||||
|
||||
export function setEnableThousandsSeparator(value) {
|
||||
setOption('thousandsSeparator', value);
|
||||
}
|
||||
|
||||
export function getCurrencyDisplayMode() {
|
||||
return getOption('currencyDisplayMode');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user