add more statistic data on Data Table tab of Insights Explorer page

This commit is contained in:
MaysWind
2026-03-07 18:33:53 +08:00
parent 3b58dcbc4d
commit 1336377598
21 changed files with 245 additions and 11 deletions
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Kontoliste",
"This Week": "Diese Woche",
"This Month": "Dieser Monat",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Account List",
"This Week": "This Week",
"This Month": "This Month",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Recuento de transacciones",
"Average Amount": "Importe Medio",
"Median Amount": "Importe Mediano",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Lista de Cuentas",
"This Week": "Esta Semana",
"This Month": "Este Mes",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Liste des comptes",
"This Week": "Cette semaine",
"This Month": "Ce mois",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Elenco account",
"This Week": "Questa settimana",
"This Month": "Questo mese",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "口座リスト",
"This Week": "今週",
"This Month": "今月",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "ಖಾತೆಗಳ ಪಟ್ಟಿ",
"This Week": "ಈ ವಾರ",
"This Month": "ಈ ತಿಂಗಳು",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "거래 수",
"Average Amount": "평균 금액",
"Median Amount": "중간 금액",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "계좌 목록",
"This Week": "이번 주",
"This Month": "이번 달",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Rekeningenlijst",
"This Week": "Deze week",
"This Month": "Deze maand",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Lista de Contas",
"This Week": "Esta Semana",
"This Month": "Este Mês",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Количество транзакций",
"Average Amount": "Средняя сумма",
"Median Amount": "Медиана сумм",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Список счетов",
"This Week": "На этой неделе",
"This Month": "В этом месяце",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Število transakcij",
"Average Amount": "Povprečni znesek",
"Median Amount": "Mediana zneska",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Seznam računov",
"This Week": "Ta teden",
"This Month": "Ta mesec",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "பரிவர்த்தனை எண்ணிக்கை",
"Average Amount": "சராசரி தொகை",
"Median Amount": "நடுநிலை தொகை",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "கணக்குகளின் பட்டியல்",
"This Week": "இந்த வாரம்",
"This Month": "இந்த மாதம்",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "รายการบัญชี",
"This Week": "สัปดาห์นี้",
"This Month": "เดือนนี้",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Hesap Listesi",
"This Week": "Bu Hafta",
"This Month": "Bu Ay",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Список рахунків",
"This Week": "Цього тижня",
"This Month": "Цього місяця",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "Transaction Count",
"Average Amount": "Average Amount",
"Median Amount": "Median Amount",
"90th Percentile Amount": "90th Percentile Amount",
"Top 5 Amount Share": "Top 5 Amount Share",
"Transactions for 80% of Amount": "Transactions for 80% of Amount",
"Range (Max - Min)": "Range (Max - Min)",
"Interquartile Range (Q3 - Q1)": "Interquartile Range (Q3 - Q1)",
"Variance": "Variance",
"Standard Deviation": "Standard Deviation",
"Account List": "Danh sách tài khoản",
"This Week": "Tuần này",
"This Month": "Tháng này",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "交易数量",
"Average Amount": "平均金额",
"Median Amount": "中位数金额",
"90th Percentile Amount": "90百分位金额",
"Top 5 Amount Share": "前5大金额占比",
"Transactions for 80% of Amount": "贡献80%金额的交易占比",
"Range (Max - Min)": "极差 (最大值 - 最小值)",
"Interquartile Range (Q3 - Q1)": "四分位距 (Q3 - Q1)",
"Variance": "方差",
"Standard Deviation": "标准差",
"Account List": "账户列表",
"This Week": "本周",
"This Month": "本月",
+7
View File
@@ -1784,6 +1784,13 @@
"Transaction Count": "交易數量",
"Average Amount": "平均金額",
"Median Amount": "中位數金額",
"90th Percentile Amount": "90百分位數金額",
"Top 5 Amount Share": "前5大金額占比",
"Transactions for 80% of Amount": "貢獻80%金額的交易占比",
"Range (Max - Min)": "極差 (最大值 - 最小值)",
"Interquartile Range (Q3 - Q1)": "四分位距 (Q3 - Q1)",
"Variance": "變異數",
"Standard Deviation": "標準差",
"Account List": "帳戶清單",
"This Week": "本週",
"This Month": "本月",
+70 -10
View File
@@ -8,7 +8,7 @@ import { useTransactionCategoriesStore } from './transactionCategory.ts';
import { useTransactionTagsStore } from './transactionTag.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import { type BeforeResolveFunction, itemAndIndex, keys, values } from '@/core/base.ts';
import { type BeforeResolveFunction, itemAndIndex, reversed, keys, values } from '@/core/base.ts';
import { AmountFilterType } from '@/core/numeral.ts';
import { DateRangeScene, DateRange } from '@/core/datetime.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
@@ -114,10 +114,20 @@ export interface CategoriedTransactionExplorerDataItem extends SeriesInfo {
export interface InsightsExplorerTransactionStatisticData {
totalCount: number;
totalAmount: number;
totalIncome: number;
totalExpense: number;
netIncome: number;
averageAmount: number;
medianAmount: number;
p90Amount: number;
top5AmountShare: number;
transactionsFor80PercentAmount: number;
minimumAmount: number;
maximumAmount: number;
range: number;
interquartileRange: number;
variance: number;
standardDeviation: number;
}
export const useExplorersStore = defineStore('explorers', () => {
@@ -591,10 +601,20 @@ export const useExplorersStore = defineStore('explorers', () => {
const statisticData: InsightsExplorerTransactionStatisticData = {
totalCount: 0,
totalAmount: 0,
totalIncome: 0,
totalExpense: 0,
netIncome: 0,
averageAmount: 0,
medianAmount: 0,
p90Amount: 0,
top5AmountShare: 0,
transactionsFor80PercentAmount: 0,
minimumAmount: Number.MAX_SAFE_INTEGER,
maximumAmount: Number.MIN_SAFE_INTEGER
maximumAmount: Number.MIN_SAFE_INTEGER,
range: 0,
interquartileRange: 0,
variance: 0,
standardDeviation: 0
};
const sourceAmounts: number[] = [];
@@ -603,6 +623,12 @@ export const useExplorersStore = defineStore('explorers', () => {
statisticData.totalCount++;
statisticData.totalAmount += transaction.sourceAmount;
if (transaction.type === TransactionType.Income) {
statisticData.totalIncome += transaction.sourceAmount;
} else if (transaction.type === TransactionType.Expense) {
statisticData.totalExpense += transaction.sourceAmount;
}
if (transaction.sourceAmount >= 0 && transaction.sourceAmount < statisticData.minimumAmount) {
statisticData.minimumAmount = transaction.sourceAmount;
}
@@ -614,14 +640,7 @@ export const useExplorersStore = defineStore('explorers', () => {
sourceAmounts.push(transaction.sourceAmount);
}
if (statisticData.totalCount > 0) {
statisticData.averageAmount = Math.trunc(statisticData.totalAmount / statisticData.totalCount);
}
if (sourceAmounts.length > 0) {
sourceAmounts.sort((a, b) => a - b);
statisticData.medianAmount = sourceAmounts[Math.floor(sourceAmounts.length / 2)] as number;
}
statisticData.netIncome = statisticData.totalIncome - statisticData.totalExpense;
if (statisticData.minimumAmount === Number.MAX_SAFE_INTEGER) {
statisticData.minimumAmount = 0;
@@ -631,6 +650,47 @@ export const useExplorersStore = defineStore('explorers', () => {
statisticData.maximumAmount = 0;
}
if (statisticData.totalCount > 0) {
statisticData.averageAmount = Math.trunc(statisticData.totalAmount / statisticData.totalCount);
}
statisticData.range = statisticData.maximumAmount - statisticData.minimumAmount;
if (sourceAmounts.length > 0) {
sourceAmounts.sort((a, b) => a - b);
statisticData.medianAmount = sourceAmounts[Math.floor(sourceAmounts.length / 2)] as number;
statisticData.p90Amount = sourceAmounts[Math.floor(sourceAmounts.length * 9 / 10)] as number;
const q1 = sourceAmounts[Math.floor(sourceAmounts.length / 4)] as number;
const q3 = sourceAmounts[Math.floor(sourceAmounts.length * 3 / 4)] as number;
statisticData.interquartileRange = q3 - q1;
}
if (sourceAmounts.length > 5) {
const top5Count = Math.ceil(sourceAmounts.length * 0.05);
const top5AmountSum = sourceAmounts.slice(-top5Count).reduce((sum, amount) => sum + amount, 0);
statisticData.top5AmountShare = statisticData.totalAmount > 0 ? 100.0 * top5AmountSum / statisticData.totalAmount : 0;
} else {
statisticData.top5AmountShare = 100.0;
}
const eightyPercentAmountThreshold: number = 0.8 * statisticData.totalAmount;
let cumulativeAmount: number = 0;
let cumulativeCount: number = 0;
for (const amount of reversed(sourceAmounts)) {
cumulativeAmount += amount;
cumulativeCount++;
if (cumulativeAmount >= eightyPercentAmountThreshold) {
statisticData.transactionsFor80PercentAmount = 100.0 * cumulativeCount / statisticData.totalCount;
break;
}
}
const sumOfSquaredDifferences: number = sourceAmounts.reduce((sum, amount) => sum + Math.pow(amount / 100.0 - statisticData.averageAmount / 100.0, 2), 0);
statisticData.variance = sourceAmounts.length > 0 ? sumOfSquaredDifferences / sourceAmounts.length : 0;
statisticData.standardDeviation = Math.sqrt(statisticData.variance);
return statisticData;
});
@@ -48,6 +48,18 @@
<td>{{ tt('Total Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.totalAmount) }}</td>
</tr>
<tr>
<td>{{ tt('Total Income') }}</td>
<td class="text-end text-income">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.totalIncome) }}</td>
</tr>
<tr>
<td>{{ tt('Total Expense') }}</td>
<td class="text-end text-expense">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.totalExpense) }}</td>
</tr>
<tr>
<td>{{ tt('Net Income') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.netIncome) }}</td>
</tr>
<tr>
<td>{{ tt('Average Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.averageAmount) }}</td>
@@ -56,6 +68,18 @@
<td>{{ tt('Median Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.medianAmount) }}</td>
</tr>
<tr>
<td>{{ tt('90th Percentile Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.p90Amount) }}</td>
</tr>
<tr>
<td>{{ tt('Top 5 Amount Share') }}</td>
<td class="text-end">{{ formatPercentToLocalizedNumerals(filteredTransactionsStatistic.top5AmountShare, 2, '<0.01') }}</td>
</tr>
<tr>
<td>{{ tt('Transactions for 80% of Amount') }}</td>
<td class="text-end">{{ formatPercentToLocalizedNumerals(filteredTransactionsStatistic.transactionsFor80PercentAmount, 2, '<0.01') }}</td>
</tr>
<tr>
<td>{{ tt('Minimum Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.minimumAmount) }}</td>
@@ -64,6 +88,22 @@
<td>{{ tt('Maximum Amount') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.maximumAmount) }}</td>
</tr>
<tr>
<td>{{ tt('Range (Max - Min)') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.range) }}</td>
</tr>
<tr>
<td>{{ tt('Interquartile Range (Q3 - Q1)') }}</td>
<td class="text-end">{{ formatAmountToLocalizedNumeralsWithCurrency(filteredTransactionsStatistic.interquartileRange) }}</td>
</tr>
<tr>
<td>{{ tt('Variance') }}</td>
<td class="text-end">{{ formatNumberToLocalizedNumerals(filteredTransactionsStatistic.variance, 2) }}</td>
</tr>
<tr>
<td>{{ tt('Standard Deviation') }}</td>
<td class="text-end">{{ formatNumberToLocalizedNumerals(filteredTransactionsStatistic.standardDeviation, 2) }}</td>
</tr>
</tbody>
</v-table>
</v-tooltip>
@@ -210,7 +250,8 @@ const {
formatDateTimeToGregorianDefaultDateTime,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
formatAmountToLocalizedNumeralsWithCurrency,
formatNumberToLocalizedNumerals
formatNumberToLocalizedNumerals,
formatPercentToLocalizedNumerals
} = useI18n();
const settingsStore = useSettingsStore();