add 90th percentile amount, range, interquartile range, variance, and standard deviation to the value metrics in insights explorer

This commit is contained in:
MaysWind
2026-03-07 22:18:33 +08:00
parent 8e5202b375
commit d517a1862b
6 changed files with 55 additions and 15 deletions
+1 -1
View File
@@ -81,7 +81,7 @@ export function usePieChartBase(props: CommonPieChartProps) {
accumulatedPaintPercent += finalItem.paintPercent;
finalItem.displayPercent = formatPercentToLocalizedNumerals(finalItem.percent, 2, '<0.01');
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : formatNumberToLocalizedNumerals(value);
finalItem.displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : formatNumberToLocalizedNumerals(value, 2);
validItems.push(finalItem);
}
+1 -1
View File
@@ -405,7 +405,7 @@ function getDisplayValue(value: number): string {
return formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency);
}
return formatNumberToLocalizedNumerals(value);
return formatNumberToLocalizedNumerals(value, 2);
}
function clickItem(e: ECElementEvent): void {
+1 -1
View File
@@ -84,7 +84,7 @@ const radarData = computed<RadarChartData>(() => {
const finalPercent = (isNumber(percent) && percent >= 0) ? percent : (value > 0 ? value / totalValidValue * 100 : 0);
const displayPercent = formatPercentToLocalizedNumerals(finalPercent, 2, '<0.01');
const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : formatNumberToLocalizedNumerals(value);
const displayValue = props.amountValue ? formatAmountToLocalizedNumeralsWithCurrency(value, props.defaultCurrency) : formatNumberToLocalizedNumerals(value, 2);
indicators.push({
name: name,
+20 -8
View File
@@ -260,31 +260,43 @@ export enum TransactionExplorerValueMetricType {
SourceAmountSum = 'sourceAmountSum',
SourceAmountAverage = 'sourceAmountAverage',
SourceAmountMedian = 'sourceAmountMedian',
SourceAmount90thPercentile = 'source90thPercentileAmount',
SourceAmountMinimum = 'sourceAmountMinimum',
SourceAmountMaximum = 'sourceAmountMaximum'
SourceAmountMaximum = 'sourceAmountMaximum',
SourceAmountRange = 'sourceAmountRange',
SourceAmountInterquartileRange = 'sourceAmountInterquartileRange',
SourceAmountVariance = 'sourceAmountVariance',
SourceAmountStandardDeviation = 'sourceAmountStandardDeviation'
}
export class TransactionExplorerValueMetric implements NameValue {
private static readonly allInstances: TransactionExplorerValueMetric[] = [];
private static readonly allInstancesByValue: Record<string, TransactionExplorerValueMetric> = {};
public static readonly TransactionCount = new TransactionExplorerValueMetric('Transaction Count', TransactionExplorerValueMetricType.TransactionCount, false);
public static readonly SourceAmountSum = new TransactionExplorerValueMetric('Total Amount', TransactionExplorerValueMetricType.SourceAmountSum, true);
public static readonly SourceAmountAverage = new TransactionExplorerValueMetric('Average Amount', TransactionExplorerValueMetricType.SourceAmountAverage, true);
public static readonly SourceAmountMedian = new TransactionExplorerValueMetric('Median Amount', TransactionExplorerValueMetricType.SourceAmountMedian, true);
public static readonly SourceAmountMinimum = new TransactionExplorerValueMetric('Minimum Amount', TransactionExplorerValueMetricType.SourceAmountMinimum, true);
public static readonly SourceAmountMaximum = new TransactionExplorerValueMetric('Maximum Amount', TransactionExplorerValueMetricType.SourceAmountMaximum, true);
public static readonly TransactionCount = new TransactionExplorerValueMetric('Transaction Count', TransactionExplorerValueMetricType.TransactionCount, false, true);
public static readonly SourceAmountSum = new TransactionExplorerValueMetric('Total Amount', TransactionExplorerValueMetricType.SourceAmountSum, true, true);
public static readonly SourceAmountAverage = new TransactionExplorerValueMetric('Average Amount', TransactionExplorerValueMetricType.SourceAmountAverage, true, true);
public static readonly SourceAmountMedian = new TransactionExplorerValueMetric('Median Amount', TransactionExplorerValueMetricType.SourceAmountMedian, true, true);
public static readonly SourceAmount90thPercentile = new TransactionExplorerValueMetric('90th Percentile Amount', TransactionExplorerValueMetricType.SourceAmount90thPercentile, true, true);
public static readonly SourceAmountMinimum = new TransactionExplorerValueMetric('Minimum Amount', TransactionExplorerValueMetricType.SourceAmountMinimum, true, true);
public static readonly SourceAmountMaximum = new TransactionExplorerValueMetric('Maximum Amount', TransactionExplorerValueMetricType.SourceAmountMaximum, true, true);
public static readonly SourceAmountRange = new TransactionExplorerValueMetric('Range (Max - Min)', TransactionExplorerValueMetricType.SourceAmountRange, true, true);
public static readonly SourceAmountInterquartileRange = new TransactionExplorerValueMetric('Interquartile Range (Q3 - Q1)', TransactionExplorerValueMetricType.SourceAmountInterquartileRange, true, true);
public static readonly SourceAmountVariance = new TransactionExplorerValueMetric('Variance', TransactionExplorerValueMetricType.SourceAmountVariance, false, false);
public static readonly SourceAmountStandardDeviation = new TransactionExplorerValueMetric('Standard Deviation', TransactionExplorerValueMetricType.SourceAmountStandardDeviation, false, false);
public static readonly Default = TransactionExplorerValueMetric.SourceAmountSum;
public readonly name: string;
public readonly value: TransactionExplorerValueMetricType;
public readonly isAmount: boolean;
public readonly supportSum: boolean;
private constructor(name: string, value: TransactionExplorerValueMetricType, isAmount: boolean) {
private constructor(name: string, value: TransactionExplorerValueMetricType, isAmount: boolean, supportSum: boolean) {
this.name = name;
this.value = value;
this.isAmount = isAmount;
this.supportSum = supportSum;
TransactionExplorerValueMetric.allInstances.push(this);
TransactionExplorerValueMetric.allInstancesByValue[value] = this;
+28
View File
@@ -818,10 +818,38 @@ export const useExplorersStore = defineStore('explorers', () => {
} else {
value = 0;
}
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmount90thPercentile) {
if (allSourceAmountsInDefaultCurrency.length > 0) {
allSourceAmountsInDefaultCurrency.sort((a, b) => a - b);
value = allSourceAmountsInDefaultCurrency[Math.floor(allSourceAmountsInDefaultCurrency.length * 9 / 10)] as number;
} else {
value = 0;
}
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountMinimum) {
value = minimumSourceAmountInDefaultCurrency === Number.MAX_SAFE_INTEGER ? 0 : minimumSourceAmountInDefaultCurrency;
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountMaximum) {
value = maximumSourceAmountInDefaultCurrency === Number.MIN_SAFE_INTEGER ? 0 : maximumSourceAmountInDefaultCurrency;
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountRange) {
const finalMinimumSourceAmountInDefaultCurrency = minimumSourceAmountInDefaultCurrency === Number.MAX_SAFE_INTEGER ? 0 : minimumSourceAmountInDefaultCurrency;
const finalMaximumSourceAmountInDefaultCurrency = maximumSourceAmountInDefaultCurrency === Number.MIN_SAFE_INTEGER ? 0 : maximumSourceAmountInDefaultCurrency;
value = finalMaximumSourceAmountInDefaultCurrency - finalMinimumSourceAmountInDefaultCurrency;
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountInterquartileRange) {
if (allSourceAmountsInDefaultCurrency.length > 0) {
allSourceAmountsInDefaultCurrency.sort((a, b) => a - b);
const q1 = allSourceAmountsInDefaultCurrency[Math.floor(allSourceAmountsInDefaultCurrency.length / 4)] as number;
const q3 = allSourceAmountsInDefaultCurrency[Math.floor(allSourceAmountsInDefaultCurrency.length * 3 / 4)] as number;
value = q3 - q1;
} else {
value = 0;
}
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountVariance) {
const averageSourceAmountInDefaultCurrency = allSourceAmountsInDefaultCurrency.length > 0 ? totalSourceAmountSumInDefaultCurrency / allSourceAmountsInDefaultCurrency.length / 100.0 : 0;
const sumOfSquaredDifferences = allSourceAmountsInDefaultCurrency.reduce((sum, amount) => sum + Math.pow(amount / 100.0 - averageSourceAmountInDefaultCurrency, 2), 0);
value = allSourceAmountsInDefaultCurrency.length > 0 ? sumOfSquaredDifferences / allSourceAmountsInDefaultCurrency.length : 0;
} else if (valueMetric === TransactionExplorerValueMetric.SourceAmountStandardDeviation) {
const averageSourceAmountInDefaultCurrency = allSourceAmountsInDefaultCurrency.length > 0 ? totalSourceAmountSumInDefaultCurrency / allSourceAmountsInDefaultCurrency.length / 100.0 : 0;
const sumOfSquaredDifferences = allSourceAmountsInDefaultCurrency.reduce((sum, amount) => sum + Math.pow(amount / 100.0 - averageSourceAmountInDefaultCurrency, 2), 0);
value = allSourceAmountsInDefaultCurrency.length > 0 ? Math.sqrt(sumOfSquaredDifferences / allSourceAmountsInDefaultCurrency.length) : 0;
}
dataItems.push({
@@ -92,7 +92,7 @@
:show-value="true"
:show-percent="true"
:enable-click-item="true"
:amount-value="currentExplorer.valueMetric !== TransactionExplorerValueMetric.TransactionCount.value"
:amount-value="TransactionExplorerValueMetric.valueOf(currentExplorer.valueMetric)?.isAmount"
:default-currency="defaultCurrency"
id-field="id"
name-field="name"
@@ -120,7 +120,7 @@
:items="categoryDimensionTransactionExplorerData && categoryDimensionTransactionExplorerData.length ? categoryDimensionTransactionExplorerData : []"
:show-value="true"
:show-percent="true"
:amount-value="currentExplorer.valueMetric !== TransactionExplorerValueMetric.TransactionCount.value"
:amount-value="TransactionExplorerValueMetric.valueOf(currentExplorer.valueMetric)?.isAmount"
:default-currency="defaultCurrency"
name-field="name"
value-field="totalAmount"
@@ -146,12 +146,12 @@
:one-hundred-percent-stacked="axisChart100PercentStacked"
:sorting-type="currentExplorer.chartSortingType"
:show-value="true"
:show-total-amount-in-tooltip="true"
:show-total-amount-in-tooltip="TransactionExplorerValueMetric.valueOf(currentExplorer.valueMetric)?.supportSum"
:total-name-in-tooltip="currentExplorer.valueMetric === TransactionExplorerValueMetric.TransactionCount.value ? tt('Total Transactions') : tt('Total Amount')"
:category-type-name="currentTransactionExplorerCategoryDimensionName"
:all-category-names="categoriedNamesSortedByDisplayOrder"
:items="seriesDimensionTransactionExplorerData"
:amount-value="currentExplorer.valueMetric !== TransactionExplorerValueMetric.TransactionCount.value"
:amount-value="TransactionExplorerValueMetric.valueOf(currentExplorer.valueMetric)?.isAmount"
:default-currency="defaultCurrency"
:enable-click-item="true"
id-field="id"