mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-20 01:34:24 +08:00
add candlestick chart for account balance trends
This commit is contained in:
@@ -368,17 +368,20 @@ func (a *TransactionsApi) TransactionReconciliationStatementHandler(c *core.WebC
|
|||||||
|
|
||||||
for i := 0; i < len(transactionResult); i++ {
|
for i := 0; i < len(transactionResult); i++ {
|
||||||
transactionResult := transactionResult[i]
|
transactionResult := transactionResult[i]
|
||||||
accountBalance := int64(0)
|
accountOpeningBalance := int64(0)
|
||||||
|
accountClosingBalance := int64(0)
|
||||||
|
|
||||||
if transactionWithBalance, exists := transactionAccountBalanceMap[transactionResult.Id]; exists {
|
if transactionWithBalance, exists := transactionAccountBalanceMap[transactionResult.Id]; exists {
|
||||||
accountBalance = transactionWithBalance.AccountBalance
|
accountOpeningBalance = transactionWithBalance.AccountOpeningBalance
|
||||||
|
accountClosingBalance = transactionWithBalance.AccountClosingBalance
|
||||||
} else {
|
} else {
|
||||||
log.Warnf(c, "[transactions.TransactionReconciliationStatementHandler] missing account balance for transaction \"id:%d\" of user \"uid:%d\"", transactionResult.Id, uid)
|
log.Warnf(c, "[transactions.TransactionReconciliationStatementHandler] missing account balance for transaction \"id:%d\" of user \"uid:%d\"", transactionResult.Id, uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
responseItems[i] = &models.TransactionReconciliationStatementResponseItem{
|
responseItems[i] = &models.TransactionReconciliationStatementResponseItem{
|
||||||
TransactionInfoResponse: transactionResult,
|
TransactionInfoResponse: transactionResult,
|
||||||
AccountBalance: accountBalance,
|
AccountOpeningBalance: accountOpeningBalance,
|
||||||
|
AccountClosingBalance: accountClosingBalance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ type Transaction struct {
|
|||||||
// TransactionWithAccountBalance represents a transaction item with account balance
|
// TransactionWithAccountBalance represents a transaction item with account balance
|
||||||
type TransactionWithAccountBalance struct {
|
type TransactionWithAccountBalance struct {
|
||||||
*Transaction
|
*Transaction
|
||||||
AccountBalance int64
|
AccountOpeningBalance int64
|
||||||
|
AccountClosingBalance int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionGeoLocationRequest represents all parameters of transaction geographic location info update request
|
// TransactionGeoLocationRequest represents all parameters of transaction geographic location info update request
|
||||||
@@ -338,7 +339,8 @@ type TransactionInfoPageWrapperResponse2 struct {
|
|||||||
// TransactionReconciliationStatementResponseItem represents a transaction reconciliation statement response
|
// TransactionReconciliationStatementResponseItem represents a transaction reconciliation statement response
|
||||||
type TransactionReconciliationStatementResponseItem struct {
|
type TransactionReconciliationStatementResponseItem struct {
|
||||||
*TransactionInfoResponse
|
*TransactionInfoResponse
|
||||||
AccountBalance int64 `json:"accountBalance"`
|
AccountOpeningBalance int64 `json:"accountOpeningBalance"`
|
||||||
|
AccountClosingBalance int64 `json:"accountClosingBalance"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionReconciliationStatementResponse represents the response of all transaction reconciliation statement response
|
// TransactionReconciliationStatementResponse represents the response of all transaction reconciliation statement response
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c cor
|
|||||||
totalOutflows := int64(0)
|
totalOutflows := int64(0)
|
||||||
openingBalance := int64(0)
|
openingBalance := int64(0)
|
||||||
accumulatedBalance := int64(0)
|
accumulatedBalance := int64(0)
|
||||||
|
lastAccumulatedBalance := int64(0)
|
||||||
|
|
||||||
for i := len(allTransactions) - 1; i >= 0; i-- {
|
for i := len(allTransactions) - 1; i >= 0; i-- {
|
||||||
transaction := allTransactions[i]
|
transaction := allTransactions[i]
|
||||||
@@ -163,6 +164,7 @@ func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c cor
|
|||||||
|
|
||||||
if transaction.TransactionTime < minTransactionTime {
|
if transaction.TransactionTime < minTransactionTime {
|
||||||
openingBalance = accumulatedBalance
|
openingBalance = accumulatedBalance
|
||||||
|
lastAccumulatedBalance = accumulatedBalance
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,10 +185,12 @@ func (s *TransactionService) GetAllTransactionsWithAccountBalanceByMaxTime(c cor
|
|||||||
}
|
}
|
||||||
|
|
||||||
transactionsAndAccountBalance := &models.TransactionWithAccountBalance{
|
transactionsAndAccountBalance := &models.TransactionWithAccountBalance{
|
||||||
Transaction: transaction,
|
Transaction: transaction,
|
||||||
AccountBalance: accumulatedBalance,
|
AccountOpeningBalance: lastAccumulatedBalance,
|
||||||
|
AccountClosingBalance: accumulatedBalance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastAccumulatedBalance = accumulatedBalance
|
||||||
allTransactionsAndAccountBalance = append(allTransactionsAndAccountBalance, transactionsAndAccountBalance)
|
allTransactionsAndAccountBalance = append(allTransactionsAndAccountBalance, transactionsAndAccountBalance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import type { AccountInfoResponse } from '@/models/account.ts';
|
|||||||
import type { TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
|
import type { TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
|
||||||
|
|
||||||
import { isDefined, isArray } from '@/lib/common.ts';
|
import { isDefined, isArray } from '@/lib/common.ts';
|
||||||
|
import { sumAmounts } from '@/lib/numeral.ts';
|
||||||
import {
|
import {
|
||||||
getYearAndMonthFromUnixTime,
|
getYearAndMonthFromUnixTime,
|
||||||
getYearFirstUnixTimeBySpecifiedUnixTime,
|
getYearFirstUnixTimeBySpecifiedUnixTime,
|
||||||
@@ -27,13 +28,19 @@ import {
|
|||||||
import { getAllDateRangesByYearMonthRange } from '@/lib/statistics.ts';
|
import { getAllDateRangesByYearMonthRange } from '@/lib/statistics.ts';
|
||||||
|
|
||||||
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
export interface AccountBalanceUnixTimeAndBalanceRange extends UnixTimeRange {
|
||||||
minUnixTimeBalance: number;
|
minUnixTimeOpeningBalance: number;
|
||||||
maxUnixTimeBalance: number;
|
minUnixTimeClosingBalance: number;
|
||||||
|
maxUnixTimeClosingBalance: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AccountBalanceTrendsChartItem {
|
export interface AccountBalanceTrendsChartItem {
|
||||||
displayDate: string;
|
displayDate: string;
|
||||||
amount: number;
|
openingBalance: number;
|
||||||
|
closingBalance: number;
|
||||||
|
minimumBalance: number;
|
||||||
|
maximumBalance: number;
|
||||||
|
medianBalance: number;
|
||||||
|
averageBalance: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommonAccountBalanceTrendsChartProps {
|
export interface CommonAccountBalanceTrendsChartProps {
|
||||||
@@ -52,19 +59,22 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
}
|
}
|
||||||
|
|
||||||
let minUnixTime = Number.MAX_SAFE_INTEGER, maxUnixTime = 0;
|
let minUnixTime = Number.MAX_SAFE_INTEGER, maxUnixTime = 0;
|
||||||
let minUnixTimeBalance = 0, maxUnixTimeBalance = 0;
|
let minUnixTimeOpeningBalance = 0;
|
||||||
|
let minUnixTimeClosingBalance = 0;
|
||||||
|
let maxUnixTimeClosingBalance = 0;
|
||||||
|
|
||||||
for (let i = 0; i < props.items.length; i++) {
|
for (let i = 0; i < props.items.length; i++) {
|
||||||
const item = props.items[i];
|
const item = props.items[i];
|
||||||
|
|
||||||
if (item.time < minUnixTime) {
|
if (item.time < minUnixTime) {
|
||||||
minUnixTime = item.time;
|
minUnixTime = item.time;
|
||||||
minUnixTimeBalance = item.accountBalance;
|
minUnixTimeOpeningBalance = item.accountOpeningBalance;
|
||||||
|
minUnixTimeClosingBalance = item.accountClosingBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.time > maxUnixTime) {
|
if (item.time > maxUnixTime) {
|
||||||
maxUnixTime = item.time;
|
maxUnixTime = item.time;
|
||||||
maxUnixTimeBalance = item.accountBalance;
|
maxUnixTimeClosingBalance = item.accountClosingBalance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +85,9 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
return {
|
return {
|
||||||
minUnixTime: minUnixTime,
|
minUnixTime: minUnixTime,
|
||||||
maxUnixTime: maxUnixTime,
|
maxUnixTime: maxUnixTime,
|
||||||
minUnixTimeBalance: minUnixTimeBalance,
|
minUnixTimeOpeningBalance: minUnixTimeOpeningBalance,
|
||||||
maxUnixTimeBalance: maxUnixTimeBalance
|
minUnixTimeClosingBalance: minUnixTimeClosingBalance,
|
||||||
|
maxUnixTimeClosingBalance: maxUnixTimeClosingBalance
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -125,7 +136,12 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
dayDataItemsMap[dateRangeMinUnixTime] = dataItems;
|
dayDataItemsMap[dateRangeMinUnixTime] = dataItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastAmount = dataDateRange.value.minUnixTimeBalance;
|
let lastOpeningBalance = dataDateRange.value.minUnixTimeOpeningBalance;
|
||||||
|
let lastClosingBalance = dataDateRange.value.minUnixTimeClosingBalance;
|
||||||
|
let lastMinimumBalance = lastClosingBalance;
|
||||||
|
let lastMaximumBalance = lastClosingBalance;
|
||||||
|
let lastMedianBalance = lastClosingBalance;
|
||||||
|
let lastAverageBalance = lastClosingBalance;
|
||||||
|
|
||||||
for (let i = 0; i < allDateRanges.value.length; i++) {
|
for (let i = 0; i < allDateRanges.value.length; i++) {
|
||||||
const dateRange = allDateRanges.value[i];
|
const dateRange = allDateRanges.value[i];
|
||||||
@@ -146,29 +162,56 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isArray(dataItems)) {
|
if (isArray(dataItems)) {
|
||||||
let lastUnixTime = 0;
|
if (dataItems.length < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < dataItems.length; i++) {
|
dataItems.sort(function (data1: TransactionReconciliationStatementResponseItem, data2: TransactionReconciliationStatementResponseItem) {
|
||||||
const dataItem = dataItems[i];
|
return data1.time - data2.time;
|
||||||
|
});
|
||||||
|
|
||||||
if (dataItem.time >= lastUnixTime) {
|
const openingBalance = dataItems[0].accountOpeningBalance;
|
||||||
lastUnixTime = dataItem.time;
|
const closingBalance = dataItems[dataItems.length - 1].accountClosingBalance;
|
||||||
|
const minimumBalance = Math.min(...dataItems.map(item => item.accountClosingBalance));
|
||||||
|
const maximumBalance = Math.max(...dataItems.map(item => item.accountClosingBalance));
|
||||||
|
const medianBalance = dataItems[Math.floor(dataItems.length / 2)].accountClosingBalance;
|
||||||
|
const averageBalance = Math.floor(sumAmounts(dataItems.map(item => item.accountClosingBalance)) / dataItems.length);
|
||||||
|
|
||||||
if (props.account.isAsset) {
|
if (props.account.isAsset) {
|
||||||
lastAmount = dataItem.accountBalance;
|
lastOpeningBalance = openingBalance;
|
||||||
} else if (props.account.isLiability) {
|
lastClosingBalance = closingBalance;
|
||||||
lastAmount = -dataItem.accountBalance;
|
lastMinimumBalance = minimumBalance;
|
||||||
} else {
|
lastMaximumBalance = maximumBalance;
|
||||||
lastAmount = dataItem.accountBalance;
|
lastMedianBalance = medianBalance;
|
||||||
}
|
lastAverageBalance = averageBalance;
|
||||||
}
|
} else if (props.account.isLiability) {
|
||||||
|
lastOpeningBalance = -openingBalance;
|
||||||
|
lastClosingBalance = -closingBalance;
|
||||||
|
lastMinimumBalance = -minimumBalance;
|
||||||
|
lastMaximumBalance = -maximumBalance;
|
||||||
|
lastMedianBalance = -medianBalance;
|
||||||
|
lastAverageBalance = -averageBalance;
|
||||||
|
} else {
|
||||||
|
lastOpeningBalance = openingBalance;
|
||||||
|
lastClosingBalance = closingBalance;
|
||||||
|
lastMinimumBalance = minimumBalance;
|
||||||
|
lastMaximumBalance = maximumBalance;
|
||||||
|
lastMedianBalance = medianBalance;
|
||||||
|
lastAverageBalance = averageBalance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push({
|
ret.push({
|
||||||
displayDate: displayDate,
|
displayDate: displayDate,
|
||||||
amount: lastAmount
|
openingBalance: lastOpeningBalance,
|
||||||
|
closingBalance: lastClosingBalance,
|
||||||
|
minimumBalance: lastMinimumBalance,
|
||||||
|
maximumBalance: lastMaximumBalance,
|
||||||
|
medianBalance: lastMedianBalance,
|
||||||
|
averageBalance: lastAverageBalance
|
||||||
});
|
});
|
||||||
|
|
||||||
|
lastOpeningBalance = lastClosingBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -10,11 +10,17 @@ import type { CallbackDataParams } from 'echarts/types/dist/shared';
|
|||||||
import { useI18n } from '@/locales/helpers.ts';
|
import { useI18n } from '@/locales/helpers.ts';
|
||||||
import { type CommonAccountBalanceTrendsChartProps, useAccountBalanceTrendsChartBase } from '@/components/base/AccountBalanceTrendsChartBase.ts'
|
import { type CommonAccountBalanceTrendsChartProps, useAccountBalanceTrendsChartBase } from '@/components/base/AccountBalanceTrendsChartBase.ts'
|
||||||
|
|
||||||
|
import { useUserStore } from '@/stores/user.ts';
|
||||||
|
|
||||||
|
import type { NameValue } from '@/core/base.ts';
|
||||||
import type { ColorValue } from '@/core/color.ts';
|
import type { ColorValue } from '@/core/color.ts';
|
||||||
import { ThemeType } from '@/core/theme.ts';
|
import { ThemeType } from '@/core/theme.ts';
|
||||||
import { TrendChartType } from '@/core/statistics.ts';
|
import { AccountBalanceTrendChartType } from '@/core/statistics.ts';
|
||||||
import { DEFAULT_CHART_COLORS } from '@/consts/color.ts';
|
import { DEFAULT_CHART_COLORS } from '@/consts/color.ts';
|
||||||
|
|
||||||
|
import { isArray } from '@/lib/common.ts';
|
||||||
|
import { getExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
|
||||||
|
|
||||||
interface DesktopAccountBalanceTrendsChartProps extends CommonAccountBalanceTrendsChartProps {
|
interface DesktopAccountBalanceTrendsChartProps extends CommonAccountBalanceTrendsChartProps {
|
||||||
legendName: string;
|
legendName: string;
|
||||||
skeleton?: boolean;
|
skeleton?: boolean;
|
||||||
@@ -26,21 +32,26 @@ interface AccountBalanceTrendsChartDataItem {
|
|||||||
name: string;
|
name: string;
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
color: ColorValue;
|
color: ColorValue;
|
||||||
|
color0?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
borderColor0?: string;
|
||||||
};
|
};
|
||||||
selected: boolean;
|
selected: boolean;
|
||||||
type: string;
|
type: string;
|
||||||
areaStyle?: object;
|
areaStyle?: object;
|
||||||
stack: string;
|
stack: string;
|
||||||
animation: boolean;
|
animation: boolean;
|
||||||
data: number[];
|
data: (number | number[])[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<DesktopAccountBalanceTrendsChartProps>();
|
const props = defineProps<DesktopAccountBalanceTrendsChartProps>();
|
||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { formatAmountWithCurrency } = useI18n();
|
const { tt, formatAmountWithCurrency } = useI18n();
|
||||||
const { allDataItems, allDisplayDateRanges } = useAccountBalanceTrendsChartBase(props);
|
const { allDataItems, allDisplayDateRanges } = useAccountBalanceTrendsChartBase(props);
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
|
const isDarkMode = computed<boolean>(() => theme.global.name.value === ThemeType.Dark);
|
||||||
|
|
||||||
const allSeries = computed<AccountBalanceTrendsChartDataItem[]>(() => {
|
const allSeries = computed<AccountBalanceTrendsChartDataItem[]>(() => {
|
||||||
@@ -57,15 +68,32 @@ const allSeries = computed<AccountBalanceTrendsChartDataItem[]>(() => {
|
|||||||
data: []
|
data: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (props.type === TrendChartType.Area.type) {
|
if (props.type === AccountBalanceTrendChartType.Area.type) {
|
||||||
series.areaStyle = {};
|
series.areaStyle = {};
|
||||||
} else if (props.type === TrendChartType.Column.type) {
|
} else if (props.type === AccountBalanceTrendChartType.Column.type) {
|
||||||
series.type = 'bar';
|
series.type = 'bar';
|
||||||
|
} else if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
|
||||||
|
const expenseIncomeAmountColor = getExpenseAndIncomeAmountColor(userStore.currentUserExpenseAmountColor, userStore.currentUserIncomeAmountColor, isDarkMode.value);
|
||||||
|
series.type = 'candlestick';
|
||||||
|
series.itemStyle.color = expenseIncomeAmountColor.incomeAmountColor;
|
||||||
|
series.itemStyle.color0 = expenseIncomeAmountColor.expenseAmountColor;
|
||||||
|
series.itemStyle.borderColor = expenseIncomeAmountColor.incomeAmountColor;
|
||||||
|
series.itemStyle.borderColor0 = expenseIncomeAmountColor.expenseAmountColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < allDataItems.value.length; i++) {
|
for (let i = 0; i < allDataItems.value.length; i++) {
|
||||||
const item = allDataItems.value[i];
|
const item = allDataItems.value[i];
|
||||||
series.data.push(item.amount);
|
|
||||||
|
if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
|
||||||
|
series.data.push([
|
||||||
|
item.openingBalance,
|
||||||
|
item.closingBalance,
|
||||||
|
item.minimumBalance,
|
||||||
|
item.maximumBalance
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
series.data.push(item.closingBalance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [series];
|
return [series];
|
||||||
@@ -82,7 +110,14 @@ const yAxisWidth = computed<number>(() => {
|
|||||||
|
|
||||||
for (let i = 0; i < allSeries.value.length; i++) {
|
for (let i = 0; i < allSeries.value.length; i++) {
|
||||||
for (let j = 0; j < allSeries.value[i].data.length; j++) {
|
for (let j = 0; j < allSeries.value[i].data.length; j++) {
|
||||||
const value = allSeries.value[i].data[j];
|
const data = allSeries.value[i].data[j];
|
||||||
|
let value: number;
|
||||||
|
|
||||||
|
if (isArray(data)) {
|
||||||
|
value = data[1]; // for candlestick, use closing balance
|
||||||
|
} else {
|
||||||
|
value = data as number; // for line or bar chart
|
||||||
|
}
|
||||||
|
|
||||||
if (value > maxValue) {
|
if (value > maxValue) {
|
||||||
maxValue = value;
|
maxValue = value;
|
||||||
@@ -134,13 +169,54 @@ const chartOptions = computed<object>(() => {
|
|||||||
color: isDarkMode.value ? '#eee' : '#333'
|
color: isDarkMode.value ? '#eee' : '#333'
|
||||||
},
|
},
|
||||||
formatter: (params: CallbackDataParams[]) => {
|
formatter: (params: CallbackDataParams[]) => {
|
||||||
const amount = params[0].data as number;
|
if (props.type === AccountBalanceTrendChartType.Candlestick.type) {
|
||||||
const value = formatAmountWithCurrency(amount, props.account.currency);
|
const dataIndex = params[0].dataIndex;
|
||||||
|
const dataItem = allDataItems.value[dataIndex];
|
||||||
|
const displayItems: NameValue[] = [
|
||||||
|
{
|
||||||
|
name: tt('Opening Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.openingBalance, props.account.currency)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Closing Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.closingBalance, props.account.currency)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Minimum Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.minimumBalance, props.account.currency)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Maximum Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.maximumBalance, props.account.currency)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Median Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.medianBalance, props.account.currency)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: tt('Average Balance'),
|
||||||
|
value: formatAmountWithCurrency(dataItem.averageBalance, props.account.currency)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
return `${params[0].name}<br/>`
|
let tooltip = `${params[0].name} ${props.legendName}<br/>`;
|
||||||
+ '<div><span class="chart-pointer" style="background-color: #' + DEFAULT_CHART_COLORS[0] + '"></span>'
|
|
||||||
+ `<span>${props.legendName}</span><span style="margin-left: 20px; float: right">${value}</span><br/>`
|
for (let i = 0; i < displayItems.length; i++) {
|
||||||
+ '</div>';
|
tooltip += `<div><span class="chart-pointer" style="background-color: #${DEFAULT_CHART_COLORS[i]}"></span>`
|
||||||
|
+ `<span>${displayItems[i].name}</span><span style="margin-left: 20px; float: right">${displayItems[i].value}</span><br/>`
|
||||||
|
+ `</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tooltip;
|
||||||
|
} else {
|
||||||
|
const amount = params[0].data as number;
|
||||||
|
const value = formatAmountWithCurrency(amount, props.account.currency);
|
||||||
|
|
||||||
|
return `${params[0].name}<br/>`
|
||||||
|
+ '<div><span class="chart-pointer" style="background-color: #' + DEFAULT_CHART_COLORS[0] + '"></span>'
|
||||||
|
+ `<span>${props.legendName}</span><span style="margin-left: 20px; float: right">${value}</span><br/>`
|
||||||
|
+ '</div>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
:style="`top: ${virtualDataItems.topPosition}px`"
|
:style="`top: ${virtualDataItems.topPosition}px`"
|
||||||
:virtual-list-index="item.index"
|
:virtual-list-index="item.index"
|
||||||
:title="item.displayDate"
|
:title="item.displayDate"
|
||||||
:after="formatAmountWithCurrency(item.amount, account.currency)"
|
:after="formatAmountWithCurrency(item.closingBalance, account.currency)"
|
||||||
v-for="item in virtualDataItems.items"
|
v-for="item in virtualDataItems.items"
|
||||||
>
|
>
|
||||||
<template #media>
|
<template #media>
|
||||||
@@ -90,19 +90,24 @@ const virtualDataItems = ref<MobileAccountBalanceTrendsChartVirtualListData>({
|
|||||||
|
|
||||||
const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() => {
|
const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() => {
|
||||||
const ret: MobileAccountBalanceTrendsChartItem[] = [];
|
const ret: MobileAccountBalanceTrendsChartItem[] = [];
|
||||||
let maxAmount = 0;
|
let maxClosingBalance = 0;
|
||||||
|
|
||||||
for (let i = 0; i < allDataItems.value.length; i++) {
|
for (let i = 0; i < allDataItems.value.length; i++) {
|
||||||
const dataItem = allDataItems.value[i];
|
const dataItem = allDataItems.value[i];
|
||||||
|
|
||||||
if (dataItem.amount > maxAmount) {
|
if (dataItem.closingBalance > maxClosingBalance) {
|
||||||
maxAmount = dataItem.amount;
|
maxClosingBalance = dataItem.closingBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
const finalDataItem: MobileAccountBalanceTrendsChartItem = {
|
const finalDataItem: MobileAccountBalanceTrendsChartItem = {
|
||||||
index: i,
|
index: i,
|
||||||
displayDate: dataItem.displayDate,
|
displayDate: dataItem.displayDate,
|
||||||
amount: dataItem.amount,
|
openingBalance: dataItem.openingBalance,
|
||||||
|
closingBalance: dataItem.closingBalance,
|
||||||
|
medianBalance: dataItem.medianBalance,
|
||||||
|
averageBalance: dataItem.averageBalance,
|
||||||
|
minimumBalance: dataItem.minimumBalance,
|
||||||
|
maximumBalance: dataItem.maximumBalance,
|
||||||
color: `#${DEFAULT_CHART_COLORS[0]}`,
|
color: `#${DEFAULT_CHART_COLORS[0]}`,
|
||||||
percent: 0.0
|
percent: 0.0
|
||||||
};
|
};
|
||||||
@@ -111,8 +116,8 @@ const allVirtualListItems = computed<MobileAccountBalanceTrendsChartItem[]>(() =
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < ret.length; i++) {
|
for (let i = 0; i < ret.length; i++) {
|
||||||
if (maxAmount > 0 && ret[i].amount > 0) {
|
if (maxClosingBalance > 0 && ret[i].closingBalance > 0) {
|
||||||
ret[i].percent = 100.0 * ret[i].amount / maxAmount;
|
ret[i].percent = 100.0 * ret[i].closingBalance / maxClosingBalance;
|
||||||
} else {
|
} else {
|
||||||
ret[i].percent = 0.0;
|
ret[i].percent = 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,30 @@ export class TrendChartType implements TypeAndName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class AccountBalanceTrendChartType implements TypeAndName {
|
||||||
|
private static readonly allInstances: AccountBalanceTrendChartType[] = [];
|
||||||
|
|
||||||
|
public static readonly Area = new AccountBalanceTrendChartType(0, 'Area Chart');
|
||||||
|
public static readonly Column = new AccountBalanceTrendChartType(1, 'Column Chart');
|
||||||
|
public static readonly Candlestick = new AccountBalanceTrendChartType(2, 'Candlestick Chart');
|
||||||
|
|
||||||
|
public static readonly Default = TrendChartType.Column;
|
||||||
|
|
||||||
|
public readonly type: number;
|
||||||
|
public readonly name: string;
|
||||||
|
|
||||||
|
private constructor(type: number, name: string) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
|
||||||
|
AccountBalanceTrendChartType.allInstances.push(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static values(): TrendChartType[] {
|
||||||
|
return AccountBalanceTrendChartType.allInstances;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class ChartDataType implements TypeAndName {
|
export class ChartDataType implements TypeAndName {
|
||||||
private static readonly allInstances: ChartDataType[] = [];
|
private static readonly allInstances: ChartDataType[] = [];
|
||||||
private static readonly allInstancesByType: Record<number, ChartDataType> = {};
|
private static readonly allInstancesByType: Record<number, ChartDataType> = {};
|
||||||
|
|||||||
+2
-1
@@ -52,7 +52,7 @@ import 'vuetify/styles';
|
|||||||
|
|
||||||
import * as echarts from 'echarts/core';
|
import * as echarts from 'echarts/core';
|
||||||
import { CanvasRenderer } from 'echarts/renderers';
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
import { LineChart, BarChart, PieChart } from 'echarts/charts';
|
import { LineChart, BarChart, PieChart, CandlestickChart } from 'echarts/charts';
|
||||||
import {
|
import {
|
||||||
GridComponent,
|
GridComponent,
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
@@ -487,6 +487,7 @@ echarts.use([
|
|||||||
LineChart,
|
LineChart,
|
||||||
BarChart,
|
BarChart,
|
||||||
PieChart,
|
PieChart,
|
||||||
|
CandlestickChart,
|
||||||
GridComponent,
|
GridComponent,
|
||||||
TooltipComponent,
|
TooltipComponent,
|
||||||
LegendComponent
|
LegendComponent
|
||||||
|
|||||||
+11
-1
@@ -1,7 +1,17 @@
|
|||||||
import { type NumberFormatOptions, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
|
import { type NumberFormatOptions, DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
|
||||||
import { DEFAULT_DECIMAL_NUMBER_COUNT, MAX_SUPPORTED_DECIMAL_NUMBER_COUNT } from '@/consts/numeral.ts';
|
import { DEFAULT_DECIMAL_NUMBER_COUNT, MAX_SUPPORTED_DECIMAL_NUMBER_COUNT } from '@/consts/numeral.ts';
|
||||||
|
|
||||||
import {isString, isNumber, replaceAll, removeAll } from './common.ts';
|
import { isString, isNumber, replaceAll, removeAll } from './common.ts';
|
||||||
|
|
||||||
|
export function sumAmounts(amounts: number[]): number {
|
||||||
|
let sum = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < amounts.length; i++) {
|
||||||
|
sum += amounts[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
export function appendDigitGroupingSymbol(value: number | string, options: NumberFormatOptions): string {
|
export function appendDigitGroupingSymbol(value: number | string, options: NumberFormatOptions): string {
|
||||||
let textualValue = '';
|
let textualValue = '';
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Balkendiagramm",
|
"Bar Chart": "Balkendiagramm",
|
||||||
"Area Chart": "Flächendiagramm",
|
"Area Chart": "Flächendiagramm",
|
||||||
"Column Chart": "Säulendiagramm",
|
"Column Chart": "Säulendiagramm",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Sortieren nach",
|
"Sort by": "Sortieren nach",
|
||||||
"Map": "Karte",
|
"Map": "Karte",
|
||||||
"Provider": "Anbieter",
|
"Provider": "Anbieter",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Ausgaben nach Konto",
|
"Expense By Account": "Ausgaben nach Konto",
|
||||||
"Expense By Primary Category": "Ausgaben nach Primärkategorie",
|
"Expense By Primary Category": "Ausgaben nach Primärkategorie",
|
||||||
"Expense By Secondary Category": "Ausgaben nach Sekundärkategorie",
|
"Expense By Secondary Category": "Ausgaben nach Sekundärkategorie",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Bar Chart",
|
"Bar Chart": "Bar Chart",
|
||||||
"Area Chart": "Area Chart",
|
"Area Chart": "Area Chart",
|
||||||
"Column Chart": "Column Chart",
|
"Column Chart": "Column Chart",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Sort by",
|
"Sort by": "Sort by",
|
||||||
"Map": "Map",
|
"Map": "Map",
|
||||||
"Provider": "Provider",
|
"Provider": "Provider",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Expense By Account",
|
"Expense By Account": "Expense By Account",
|
||||||
"Expense By Primary Category": "Expense By Primary Category",
|
"Expense By Primary Category": "Expense By Primary Category",
|
||||||
"Expense By Secondary Category": "Expense By Secondary Category",
|
"Expense By Secondary Category": "Expense By Secondary Category",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Gráfico de barras",
|
"Bar Chart": "Gráfico de barras",
|
||||||
"Area Chart": "Gráfico de área",
|
"Area Chart": "Gráfico de área",
|
||||||
"Column Chart": "Gráfico de columnas",
|
"Column Chart": "Gráfico de columnas",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Ordenar por",
|
"Sort by": "Ordenar por",
|
||||||
"Map": "Mapa",
|
"Map": "Mapa",
|
||||||
"Provider": "Proveedor",
|
"Provider": "Proveedor",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Gasto por cuenta",
|
"Expense By Account": "Gasto por cuenta",
|
||||||
"Expense By Primary Category": "Gasto por categoría primaria",
|
"Expense By Primary Category": "Gasto por categoría primaria",
|
||||||
"Expense By Secondary Category": "Gasto por categoría secundaria",
|
"Expense By Secondary Category": "Gasto por categoría secundaria",
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ import {
|
|||||||
StatisticsAnalysisType,
|
StatisticsAnalysisType,
|
||||||
CategoricalChartType,
|
CategoricalChartType,
|
||||||
TrendChartType,
|
TrendChartType,
|
||||||
|
AccountBalanceTrendChartType,
|
||||||
ChartDataType,
|
ChartDataType,
|
||||||
ChartSortingType,
|
ChartSortingType,
|
||||||
ChartDateAggregationType
|
ChartDateAggregationType
|
||||||
@@ -1934,6 +1935,7 @@ export function useI18n() {
|
|||||||
getAllAccountTypes: () => getLocalizedDisplayNameAndType(AccountType.values()),
|
getAllAccountTypes: () => getLocalizedDisplayNameAndType(AccountType.values()),
|
||||||
getAllCategoricalChartTypes: () => getLocalizedDisplayNameAndType(CategoricalChartType.values()),
|
getAllCategoricalChartTypes: () => getLocalizedDisplayNameAndType(CategoricalChartType.values()),
|
||||||
getAllTrendChartTypes: () => getLocalizedDisplayNameAndType(TrendChartType.values()),
|
getAllTrendChartTypes: () => getLocalizedDisplayNameAndType(TrendChartType.values()),
|
||||||
|
getAllAccountBalanceTrendChartTypes: () => getLocalizedDisplayNameAndType(AccountBalanceTrendChartType.values()),
|
||||||
getAllStatisticsChartDataTypes: (analysisType: StatisticsAnalysisType) => getLocalizedDisplayNameAndType(ChartDataType.values(analysisType)),
|
getAllStatisticsChartDataTypes: (analysisType: StatisticsAnalysisType) => getLocalizedDisplayNameAndType(ChartDataType.values(analysisType)),
|
||||||
getAllStatisticsSortingTypes: () => getLocalizedDisplayNameAndType(ChartSortingType.values()),
|
getAllStatisticsSortingTypes: () => getLocalizedDisplayNameAndType(ChartSortingType.values()),
|
||||||
getAllStatisticsDateAggregationTypes: () => getLocalizedChartDateAggregationTypeAndDisplayName(true),
|
getAllStatisticsDateAggregationTypes: () => getLocalizedChartDateAggregationTypeAndDisplayName(true),
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Grafico a barre",
|
"Bar Chart": "Grafico a barre",
|
||||||
"Area Chart": "Grafico ad area",
|
"Area Chart": "Grafico ad area",
|
||||||
"Column Chart": "Grafico a colonne",
|
"Column Chart": "Grafico a colonne",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Ordina per",
|
"Sort by": "Ordina per",
|
||||||
"Map": "Mappa",
|
"Map": "Mappa",
|
||||||
"Provider": "Fornitore",
|
"Provider": "Fornitore",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Spesa per conto",
|
"Expense By Account": "Spesa per conto",
|
||||||
"Expense By Primary Category": "Spesa per categoria principale",
|
"Expense By Primary Category": "Spesa per categoria principale",
|
||||||
"Expense By Secondary Category": "Spesa per categoria secondaria",
|
"Expense By Secondary Category": "Spesa per categoria secondaria",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "棒グラフ",
|
"Bar Chart": "棒グラフ",
|
||||||
"Area Chart": "エリアチャート",
|
"Area Chart": "エリアチャート",
|
||||||
"Column Chart": "列チャート",
|
"Column Chart": "列チャート",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "ソート順",
|
"Sort by": "ソート順",
|
||||||
"Map": "地図",
|
"Map": "地図",
|
||||||
"Provider": "プロバイダー",
|
"Provider": "プロバイダー",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "口座別の支出",
|
"Expense By Account": "口座別の支出",
|
||||||
"Expense By Primary Category": "一次カテゴリ別の支出",
|
"Expense By Primary Category": "一次カテゴリ別の支出",
|
||||||
"Expense By Secondary Category": "二次カテゴリ別の支出",
|
"Expense By Secondary Category": "二次カテゴリ別の支出",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Gráfico de Barras",
|
"Bar Chart": "Gráfico de Barras",
|
||||||
"Area Chart": "Gráfico de Área",
|
"Area Chart": "Gráfico de Área",
|
||||||
"Column Chart": "Gráfico de Colunas",
|
"Column Chart": "Gráfico de Colunas",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Ordenar por",
|
"Sort by": "Ordenar por",
|
||||||
"Map": "Mapa",
|
"Map": "Mapa",
|
||||||
"Provider": "Provedor",
|
"Provider": "Provedor",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Despesa por Conta",
|
"Expense By Account": "Despesa por Conta",
|
||||||
"Expense By Primary Category": "Despesa por Categoria Primária",
|
"Expense By Primary Category": "Despesa por Categoria Primária",
|
||||||
"Expense By Secondary Category": "Despesa por Categoria Secundária",
|
"Expense By Secondary Category": "Despesa por Categoria Secundária",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Гистограмма",
|
"Bar Chart": "Гистограмма",
|
||||||
"Area Chart": "Диаграмма с областями",
|
"Area Chart": "Диаграмма с областями",
|
||||||
"Column Chart": "Столбчатая диаграмма",
|
"Column Chart": "Столбчатая диаграмма",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Сортировать по",
|
"Sort by": "Сортировать по",
|
||||||
"Map": "Карта",
|
"Map": "Карта",
|
||||||
"Provider": "Провайдер",
|
"Provider": "Провайдер",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Расходы по счетам",
|
"Expense By Account": "Расходы по счетам",
|
||||||
"Expense By Primary Category": "Расходы по основной категории",
|
"Expense By Primary Category": "Расходы по основной категории",
|
||||||
"Expense By Secondary Category": "Расходы по вторичной категории",
|
"Expense By Secondary Category": "Расходы по вторичной категории",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Гістограма",
|
"Bar Chart": "Гістограма",
|
||||||
"Area Chart": "Діаграма з областями",
|
"Area Chart": "Діаграма з областями",
|
||||||
"Column Chart": "Стовпчикова діаграма",
|
"Column Chart": "Стовпчикова діаграма",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Сортувати за",
|
"Sort by": "Сортувати за",
|
||||||
"Map": "Карта",
|
"Map": "Карта",
|
||||||
"Provider": "Провайдер",
|
"Provider": "Провайдер",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Витрати за рахунками",
|
"Expense By Account": "Витрати за рахунками",
|
||||||
"Expense By Primary Category": "Витрати за основними категоріями",
|
"Expense By Primary Category": "Витрати за основними категоріями",
|
||||||
"Expense By Secondary Category": "Витрати за другорядними категоріями",
|
"Expense By Secondary Category": "Витрати за другорядними категоріями",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "Biểu đồ cột",
|
"Bar Chart": "Biểu đồ cột",
|
||||||
"Area Chart": "Biểu đồ diện tích",
|
"Area Chart": "Biểu đồ diện tích",
|
||||||
"Column Chart": "Biểu đồ cột",
|
"Column Chart": "Biểu đồ cột",
|
||||||
|
"Candlestick Chart": "Candlestick Chart",
|
||||||
"Sort by": "Sắp xếp theo",
|
"Sort by": "Sắp xếp theo",
|
||||||
"Map": "Bản đồ",
|
"Map": "Bản đồ",
|
||||||
"Provider": "Nhà cung cấp",
|
"Provider": "Nhà cung cấp",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "Total Transactions",
|
"Total Transactions": "Total Transactions",
|
||||||
"Opening Balance": "Opening Balance",
|
"Opening Balance": "Opening Balance",
|
||||||
"Closing Balance": "Closing Balance",
|
"Closing Balance": "Closing Balance",
|
||||||
|
"Minimum Balance": "Minimum Balance",
|
||||||
|
"Maximum Balance": "Maximum Balance",
|
||||||
|
"Median Balance": "Median Balance",
|
||||||
|
"Average Balance": "Average Balance",
|
||||||
"Expense By Account": "Chi phí theo tài khoản",
|
"Expense By Account": "Chi phí theo tài khoản",
|
||||||
"Expense By Primary Category": "Chi phí theo danh mục chính",
|
"Expense By Primary Category": "Chi phí theo danh mục chính",
|
||||||
"Expense By Secondary Category": "Chi phí theo danh mục phụ",
|
"Expense By Secondary Category": "Chi phí theo danh mục phụ",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "条形图",
|
"Bar Chart": "条形图",
|
||||||
"Area Chart": "面积图",
|
"Area Chart": "面积图",
|
||||||
"Column Chart": "柱状图",
|
"Column Chart": "柱状图",
|
||||||
|
"Candlestick Chart": "K线图",
|
||||||
"Sort by": "排序方式",
|
"Sort by": "排序方式",
|
||||||
"Map": "地图",
|
"Map": "地图",
|
||||||
"Provider": "提供者",
|
"Provider": "提供者",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "总交易数",
|
"Total Transactions": "总交易数",
|
||||||
"Opening Balance": "期初余额",
|
"Opening Balance": "期初余额",
|
||||||
"Closing Balance": "期末余额",
|
"Closing Balance": "期末余额",
|
||||||
|
"Minimum Balance": "最小余额",
|
||||||
|
"Maximum Balance": "最大余额",
|
||||||
|
"Median Balance": "中位数余额",
|
||||||
|
"Average Balance": "平均余额",
|
||||||
"Expense By Account": "账户支出",
|
"Expense By Account": "账户支出",
|
||||||
"Expense By Primary Category": "一级分类支出",
|
"Expense By Primary Category": "一级分类支出",
|
||||||
"Expense By Secondary Category": "二级分类支出",
|
"Expense By Secondary Category": "二级分类支出",
|
||||||
|
|||||||
@@ -1432,6 +1432,7 @@
|
|||||||
"Bar Chart": "長條圖",
|
"Bar Chart": "長條圖",
|
||||||
"Area Chart": "面積圖",
|
"Area Chart": "面積圖",
|
||||||
"Column Chart": "柱狀圖",
|
"Column Chart": "柱狀圖",
|
||||||
|
"Candlestick Chart": "K線圖",
|
||||||
"Sort by": "排序方式",
|
"Sort by": "排序方式",
|
||||||
"Map": "地圖",
|
"Map": "地圖",
|
||||||
"Provider": "提供者",
|
"Provider": "提供者",
|
||||||
@@ -1849,6 +1850,10 @@
|
|||||||
"Total Transactions": "總交易數",
|
"Total Transactions": "總交易數",
|
||||||
"Opening Balance": "期初餘額",
|
"Opening Balance": "期初餘額",
|
||||||
"Closing Balance": "期末餘額",
|
"Closing Balance": "期末餘額",
|
||||||
|
"Minimum Balance": "最小餘額",
|
||||||
|
"Maximum Balance": "最大餘額",
|
||||||
|
"Median Balance": "中位數餘額",
|
||||||
|
"Average Balance": "平均餘額",
|
||||||
"Expense By Account": "帳戶支出",
|
"Expense By Account": "帳戶支出",
|
||||||
"Expense By Primary Category": "一級分類支出",
|
"Expense By Primary Category": "一級分類支出",
|
||||||
"Expense By Secondary Category": "二級分類支出",
|
"Expense By Secondary Category": "二級分類支出",
|
||||||
|
|||||||
@@ -662,7 +662,8 @@ export interface TransactionInfoPageWrapperResponse2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionReconciliationStatementResponseItem extends TransactionInfoResponse {
|
export interface TransactionReconciliationStatementResponseItem extends TransactionInfoResponse {
|
||||||
readonly accountBalance: number;
|
readonly accountOpeningBalance: number;
|
||||||
|
readonly accountClosingBalance: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransactionReconciliationStatementResponse {
|
export interface TransactionReconciliationStatementResponse {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import {
|
|||||||
export function useReconciliationStatementPageBase() {
|
export function useReconciliationStatementPageBase() {
|
||||||
const {
|
const {
|
||||||
tt,
|
tt,
|
||||||
getAllTrendChartTypes,
|
getAllAccountBalanceTrendChartTypes,
|
||||||
getAllStatisticsDateAggregationTypesWithShortName,
|
getAllStatisticsDateAggregationTypesWithShortName,
|
||||||
getCurrentDigitGroupingSymbol,
|
getCurrentDigitGroupingSymbol,
|
||||||
formatUnixTimeToLongDateTime,
|
formatUnixTimeToLongDateTime,
|
||||||
@@ -59,7 +59,7 @@ export function useReconciliationStatementPageBase() {
|
|||||||
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
|
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
|
||||||
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
|
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
|
||||||
|
|
||||||
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllTrendChartTypes());
|
const allChartTypes = computed<TypeAndDisplayName[]>(() => getAllAccountBalanceTrendChartTypes());
|
||||||
const allDateAggregationTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsDateAggregationTypesWithShortName());
|
const allDateAggregationTypes = computed<TypeAndDisplayName[]>(() => getAllStatisticsDateAggregationTypesWithShortName());
|
||||||
|
|
||||||
const currentAccount = computed(() => allAccountsMap.value[accountId.value]);
|
const currentAccount = computed(() => allAccountsMap.value[accountId.value]);
|
||||||
@@ -187,9 +187,9 @@ export function useReconciliationStatementPageBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isLiabilityAccount) {
|
if (isLiabilityAccount) {
|
||||||
return formatAmountWithCurrency(-transaction.accountBalance, currency);
|
return formatAmountWithCurrency(-transaction.accountClosingBalance, currency);
|
||||||
} else {
|
} else {
|
||||||
return formatAmountWithCurrency(transaction.accountBalance, currency);
|
return formatAmountWithCurrency(transaction.accountClosingBalance, currency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,9 +234,9 @@ export function useReconciliationStatementPageBase() {
|
|||||||
let displayAccountBalance = '';
|
let displayAccountBalance = '';
|
||||||
|
|
||||||
if (isCurrentLiabilityAccount.value) {
|
if (isCurrentLiabilityAccount.value) {
|
||||||
displayAccountBalance = removeAll(formatAmount(-transaction.accountBalance), digitGroupingSymbol);
|
displayAccountBalance = removeAll(formatAmount(-transaction.accountClosingBalance), digitGroupingSymbol);
|
||||||
} else {
|
} else {
|
||||||
displayAccountBalance = removeAll(formatAmount(transaction.accountBalance), digitGroupingSymbol);
|
displayAccountBalance = removeAll(formatAmount(transaction.accountClosingBalance), digitGroupingSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
let description = transaction.comment || '';
|
let description = transaction.comment || '';
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
|
|||||||
import { useTransactionsStore } from '@/stores/transaction.ts';
|
import { useTransactionsStore } from '@/stores/transaction.ts';
|
||||||
|
|
||||||
import { TransactionType } from '@/core/transaction.ts';
|
import { TransactionType } from '@/core/transaction.ts';
|
||||||
import { TrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
|
import { AccountBalanceTrendChartType, ChartDateAggregationType } from '@/core/statistics.ts';
|
||||||
import { KnownFileType } from '@/core/file.ts';
|
import { KnownFileType } from '@/core/file.ts';
|
||||||
import { Transaction, type TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
|
import { Transaction, type TransactionReconciliationStatementResponseItem } from '@/models/transaction.ts';
|
||||||
|
|
||||||
@@ -295,6 +295,7 @@ import {
|
|||||||
mdiCheck,
|
mdiCheck,
|
||||||
mdiChartBar,
|
mdiChartBar,
|
||||||
mdiChartAreasplineVariant,
|
mdiChartAreasplineVariant,
|
||||||
|
mdiChartWaterfall,
|
||||||
mdiCalendarTodayOutline,
|
mdiCalendarTodayOutline,
|
||||||
mdiCalendarMonthOutline,
|
mdiCalendarMonthOutline,
|
||||||
mdiLayersTripleOutline,
|
mdiLayersTripleOutline,
|
||||||
@@ -356,8 +357,9 @@ const transactionCategoriesStore = useTransactionCategoriesStore();
|
|||||||
const transactionsStore = useTransactionsStore();
|
const transactionsStore = useTransactionsStore();
|
||||||
|
|
||||||
const chartTypeIconMap = {
|
const chartTypeIconMap = {
|
||||||
[TrendChartType.Column.type]: mdiChartBar,
|
[AccountBalanceTrendChartType.Column.type]: mdiChartBar,
|
||||||
[TrendChartType.Area.type]: mdiChartAreasplineVariant,
|
[AccountBalanceTrendChartType.Area.type]: mdiChartAreasplineVariant,
|
||||||
|
[AccountBalanceTrendChartType.Candlestick.type]: mdiChartWaterfall,
|
||||||
};
|
};
|
||||||
|
|
||||||
const chartDataDateAggregationTypeIconMap = {
|
const chartDataDateAggregationTypeIconMap = {
|
||||||
@@ -376,7 +378,7 @@ const loading = ref<boolean>(false);
|
|||||||
const currentPage = ref<number>(1);
|
const currentPage = ref<number>(1);
|
||||||
const countPerPage = ref<number>(10);
|
const countPerPage = ref<number>(10);
|
||||||
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
const showAccountBalanceTrendsCharts = ref<boolean>(false);
|
||||||
const chartType = ref<number>(TrendChartType.Default.type);
|
const chartType = ref<number>(AccountBalanceTrendChartType.Default.type);
|
||||||
const chartDataDateAggregationType = ref<number | undefined>(undefined);
|
const chartDataDateAggregationType = ref<number | undefined>(undefined);
|
||||||
|
|
||||||
let rejectFunc: ((reason?: unknown) => void) | null = null;
|
let rejectFunc: ((reason?: unknown) => void) | null = null;
|
||||||
@@ -459,7 +461,7 @@ function open(options: { accountId: string, startTime: number, endTime: number }
|
|||||||
currentPage.value = 1;
|
currentPage.value = 1;
|
||||||
countPerPage.value = 10;
|
countPerPage.value = 10;
|
||||||
showAccountBalanceTrendsCharts.value = false;
|
showAccountBalanceTrendsCharts.value = false;
|
||||||
chartType.value = TrendChartType.Default.type;
|
chartType.value = AccountBalanceTrendChartType.Default.type;
|
||||||
chartDataDateAggregationType.value = undefined;
|
chartDataDateAggregationType.value = undefined;
|
||||||
showState.value = true;
|
showState.value = true;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user