migrate overview store to composition API and typescript

This commit is contained in:
MaysWind
2025-01-09 00:19:25 +08:00
parent 1555052e1d
commit 25c8b9baf8
16 changed files with 441 additions and 395 deletions
+5
View File
@@ -1,3 +1,8 @@
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type PartialRecord<K extends keyof any, T> = {
[P in K]?: T;
}
export interface TypeAndName {
readonly type: number;
readonly name: string;
+5
View File
@@ -25,6 +25,11 @@ export interface StartEndTime {
readonly endTime: number;
}
export interface WritableStartEndTime extends StartEndTime {
startTime: number;
endTime: number;
}
export interface UnixTimeRange {
readonly minUnixTime: number;
readonly maxUnixTime: number;
+3 -3
View File
@@ -55,7 +55,7 @@ import type {
TransactionStatisticTrendsRequest,
TransactionStatisticTrendsItem,
TransactionAmountsRequestParams,
TransactionAmountsResponseItem
TransactionAmountsResponse
} from '@/models/transaction.ts';
import {
TransactionAmountsRequest
@@ -401,9 +401,9 @@ export default {
return axios.get<ApiResponse<TransactionStatisticTrendsItem[]>>(`v1/transactions/statistics/trends.json?use_transaction_timezone=${req.useTransactionTimezone}` + (queryParams.length ? '&' + queryParams.join('&') : ''));
},
getTransactionAmounts: (params: TransactionAmountsRequestParams): ApiResponsePromise<TransactionAmountsResponseItem> => {
getTransactionAmounts: (params: TransactionAmountsRequestParams): ApiResponsePromise<TransactionAmountsResponse> => {
const req = TransactionAmountsRequest.of(params);
return axios.get<ApiResponse<TransactionAmountsResponseItem>>(`v1/transactions/amounts.json?${req.buildQuery()}`);
return axios.get<ApiResponse<TransactionAmountsResponse>>(`v1/transactions/amounts.json?${req.buildQuery()}`);
},
getTransaction: (req: { id: string, withPictures: boolean | undefined }): ApiResponsePromise<TransactionInfoResponse> => {
if (!isDefined(req.withPictures)) {
+45 -76
View File
@@ -1,3 +1,4 @@
import type { PartialRecord } from '@/core/base.ts';
import type { StartEndTime } from '@/core/datetime.ts';
import type { AccountInfoResponse } from './account.ts';
@@ -126,23 +127,32 @@ export interface TransactionStatisticTrendsRequest extends YearMonthRangeRequest
readonly useTransactionTimezone: boolean;
}
export interface TransactionAmountsRequestParams {
export const ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE = [
'today', 'thisWeek', 'thisMonth', 'thisYear', 'lastMonth',
'monthBeforeLastMonth', 'monthBeforeLast2Months', 'monthBeforeLast3Months',
'monthBeforeLast4Months', 'monthBeforeLast5Months', 'monthBeforeLast6Months',
'monthBeforeLast7Months', 'monthBeforeLast8Months', 'monthBeforeLast9Months', 'monthBeforeLast10Months'
] as const;
export type TransactionAmountsRequestType = typeof ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE[number];
export interface TransactionAmountsRequestParams extends PartialRecord<TransactionAmountsRequestType, StartEndTime> {
readonly useTransactionTimezone: boolean;
readonly today: StartEndTime;
readonly thisWeek: StartEndTime;
readonly thisMonth: StartEndTime;
readonly thisYear: StartEndTime;
readonly lastMonth: StartEndTime;
readonly monthBeforeLastMonth: StartEndTime;
readonly monthBeforeLast2Months: StartEndTime;
readonly monthBeforeLast3Months: StartEndTime;
readonly monthBeforeLast4Months: StartEndTime;
readonly monthBeforeLast5Months: StartEndTime;
readonly monthBeforeLast6Months: StartEndTime;
readonly monthBeforeLast7Months: StartEndTime;
readonly monthBeforeLast8Months: StartEndTime;
readonly monthBeforeLast9Months: StartEndTime;
readonly monthBeforeLast10Months: StartEndTime;
today?: StartEndTime;
thisWeek?: StartEndTime;
thisMonth?: StartEndTime;
thisYear?: StartEndTime;
lastMonth?: StartEndTime;
monthBeforeLastMonth?: StartEndTime;
monthBeforeLast2Months?: StartEndTime;
monthBeforeLast3Months?: StartEndTime;
monthBeforeLast4Months?: StartEndTime;
monthBeforeLast5Months?: StartEndTime;
monthBeforeLast6Months?: StartEndTime;
monthBeforeLast7Months?: StartEndTime;
monthBeforeLast8Months?: StartEndTime;
monthBeforeLast9Months?: StartEndTime;
monthBeforeLast10Months?: StartEndTime;
}
export class TransactionAmountsRequest {
@@ -159,67 +169,13 @@ export class TransactionAmountsRequest {
}
public static of(params: TransactionAmountsRequestParams): TransactionAmountsRequest {
const queryParams = [];
const queryParams: string[] = [];
if (params.today) {
queryParams.push(`today_${params.today.startTime}_${params.today.endTime}`);
}
if (params.thisWeek) {
queryParams.push(`thisWeek_${params.thisWeek.startTime}_${params.thisWeek.endTime}`);
}
if (params.thisMonth) {
queryParams.push(`thisMonth_${params.thisMonth.startTime}_${params.thisMonth.endTime}`);
}
if (params.thisYear) {
queryParams.push(`thisYear_${params.thisYear.startTime}_${params.thisYear.endTime}`);
}
if (params.lastMonth) {
queryParams.push(`lastMonth_${params.lastMonth.startTime}_${params.lastMonth.endTime}`);
}
if (params.monthBeforeLastMonth) {
queryParams.push(`monthBeforeLastMonth_${params.monthBeforeLastMonth.startTime}_${params.monthBeforeLastMonth.endTime}`);
}
if (params.monthBeforeLast2Months) {
queryParams.push(`monthBeforeLast2Months_${params.monthBeforeLast2Months.startTime}_${params.monthBeforeLast2Months.endTime}`);
}
if (params.monthBeforeLast3Months) {
queryParams.push(`monthBeforeLast3Months_${params.monthBeforeLast3Months.startTime}_${params.monthBeforeLast3Months.endTime}`);
}
if (params.monthBeforeLast4Months) {
queryParams.push(`monthBeforeLast4Months_${params.monthBeforeLast4Months.startTime}_${params.monthBeforeLast4Months.endTime}`);
}
if (params.monthBeforeLast5Months) {
queryParams.push(`monthBeforeLast5Months_${params.monthBeforeLast5Months.startTime}_${params.monthBeforeLast5Months.endTime}`);
}
if (params.monthBeforeLast6Months) {
queryParams.push(`monthBeforeLast6Months_${params.monthBeforeLast6Months.startTime}_${params.monthBeforeLast6Months.endTime}`);
}
if (params.monthBeforeLast7Months) {
queryParams.push(`monthBeforeLast7Months_${params.monthBeforeLast7Months.startTime}_${params.monthBeforeLast7Months.endTime}`);
}
if (params.monthBeforeLast8Months) {
queryParams.push(`monthBeforeLast8Months_${params.monthBeforeLast8Months.startTime}_${params.monthBeforeLast8Months.endTime}`);
}
if (params.monthBeforeLast9Months) {
queryParams.push(`monthBeforeLast9Months_${params.monthBeforeLast9Months.startTime}_${params.monthBeforeLast9Months.endTime}`);
}
if (params.monthBeforeLast10Months) {
queryParams.push(`monthBeforeLast10Months_${params.monthBeforeLast10Months.startTime}_${params.monthBeforeLast10Months.endTime}`);
}
ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE.forEach((type) => {
if (params[type]) {
queryParams.push(`${type}_${params[type].startTime}_${params[type].endTime}`);
}
});
return new TransactionAmountsRequest(params.useTransactionTimezone, (queryParams.length ? queryParams.join('|') : ''));
}
@@ -254,6 +210,8 @@ export interface TransactionStatisticTrendsItem {
readonly items: TransactionStatisticResponseItem[];
}
export type TransactionAmountsResponse = PartialRecord<TransactionAmountsRequestType, TransactionAmountsResponseItem>;
export interface TransactionAmountsResponseItem {
readonly startTime: number;
readonly endTime: number;
@@ -265,3 +223,14 @@ export interface TransactionAmountsResponseItemAmountInfo {
readonly incomeAmount: number;
readonly expenseAmount: number;
}
export type TransactionOverviewResponse = PartialRecord<TransactionAmountsRequestType, TransactionOverviewResponseItem>;
export interface TransactionOverviewResponseItem {
valid: boolean;
incomeAmount: number;
expenseAmount: number;
incompleteIncomeAmount: boolean;
incompleteExpenseAmount: boolean;
amounts?: TransactionAmountsResponseItemAmountInfo[];
}
+1 -1
View File
@@ -7,7 +7,7 @@ import { useTransactionCategoriesStore } from './transactionCategory.js';
import { useTransactionTagsStore } from './transactionTag.js';
import { useTransactionTemplatesStore } from './transactionTemplate.js';
import { useTransactionsStore } from './transaction.js';
import { useOverviewStore } from './overview.js';
import { useOverviewStore } from './overview.ts';
import { useStatisticsStore } from './statistics.js';
import { useExchangeRatesStore } from './exchangeRates.ts';
-306
View File
@@ -1,306 +0,0 @@
import { defineStore } from 'pinia';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from './user.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import { isNumber, isEquals } from '@/lib/common.ts';
import {
getUnixTimeBeforeUnixTime,
getTodayFirstUnixTime,
getTodayLastUnixTime,
getThisWeekFirstUnixTime,
getThisWeekLastUnixTime,
getThisMonthFirstUnixTime,
getThisMonthLastUnixTime,
getThisYearFirstUnixTime,
getThisYearLastUnixTime
} from '@/lib/datetime.ts';
import services from '@/lib/services.ts';
import logger from '@/lib/logger.ts';
function updateTransactionDateRange(state) {
const userStore = useUserStore();
state.transactionDataRange.today.startTime = getTodayFirstUnixTime();
state.transactionDataRange.today.endTime = getTodayLastUnixTime();
state.transactionDataRange.thisWeek.startTime = getThisWeekFirstUnixTime(userStore.currentUserFirstDayOfWeek);
state.transactionDataRange.thisWeek.endTime = getThisWeekLastUnixTime(userStore.currentUserFirstDayOfWeek);
state.transactionDataRange.thisMonth.startTime = getThisMonthFirstUnixTime();
state.transactionDataRange.thisMonth.endTime = getThisMonthLastUnixTime();
state.transactionDataRange.thisYear.startTime = getThisYearFirstUnixTime();
state.transactionDataRange.thisYear.endTime = getThisYearLastUnixTime();
state.transactionDataRange.lastMonth.startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 1, 'months');
state.transactionDataRange.lastMonth.endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 1, 'months');
state.transactionDataRange.monthBeforeLastMonth.startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 2, 'months');
state.transactionDataRange.monthBeforeLastMonth.endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 2, 'months');
for (let i = 2; i <= 10; i++) {
state.transactionDataRange[`monthBeforeLast${i}Months`].startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), i + 1, 'months');
state.transactionDataRange[`monthBeforeLast${i}Months`].endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), i + 1, 'months');
}
}
export const useOverviewStore = defineStore('overview', {
state: () => ({
transactionDataRange: {
today: {
startTime: getTodayFirstUnixTime(),
endTime: getTodayLastUnixTime()
},
thisWeek: {
startTime: getThisWeekFirstUnixTime(useUserStore().currentUserFirstDayOfWeek),
endTime: getThisWeekLastUnixTime(useUserStore().currentUserFirstDayOfWeek)
},
thisMonth: {
startTime: getThisMonthFirstUnixTime(),
endTime: getThisMonthLastUnixTime()
},
thisYear: {
startTime: getThisYearFirstUnixTime(),
endTime: getThisYearLastUnixTime()
},
lastMonth: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 1, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 1, 'months')
},
monthBeforeLastMonth: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 2, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 2, 'months')
},
monthBeforeLast2Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 3, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 3, 'months')
},
monthBeforeLast3Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 4, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 4, 'months')
},
monthBeforeLast4Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 5, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 5, 'months')
},
monthBeforeLast5Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 6, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 6, 'months')
},
monthBeforeLast6Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 7, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 7, 'months')
},
monthBeforeLast7Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 8, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 8, 'months')
},
monthBeforeLast8Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 9, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 9, 'months')
},
monthBeforeLast9Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 10, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 10, 'months')
},
monthBeforeLast10Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 11, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 11, 'months')
}
},
transactionOverviewOptions: {
loadLast11Months: false
},
transactionOverviewData: {},
transactionOverviewStateInvalid: true
}),
getters: {
transactionOverview(state) {
const userStore = useUserStore();
const exchangeRatesStore = useExchangeRatesStore();
const overviewData = state.transactionOverviewData;
if (!overviewData || !overviewData.thisMonth) {
return {
thisMonth: {
valid: false,
incomeAmount: 0,
expenseAmount: 0,
incompleteIncomeAmount: false,
incompleteExpenseAmount: false
}
};
}
const finalOverviewData = {};
const defaultCurrency = userStore.currentUserDefaultCurrency;
[
'today',
'thisWeek',
'thisMonth',
'thisYear',
'lastMonth',
'monthBeforeLastMonth',
'monthBeforeLast2Months',
'monthBeforeLast3Months',
'monthBeforeLast4Months',
'monthBeforeLast5Months',
'monthBeforeLast6Months',
'monthBeforeLast7Months',
'monthBeforeLast8Months',
'monthBeforeLast9Months',
'monthBeforeLast10Months'
].forEach(field => {
if (!Object.prototype.hasOwnProperty.call(overviewData, field)) {
return;
}
const item = overviewData[field];
if (!item) {
return;
}
let totalIncomeAmount = 0;
let totalExpenseAmount = 0;
let hasUnCalculatedTotalIncome = false;
let hasUnCalculatedTotalExpense = false;
if (item.amounts) {
for (let i = 0; i < item.amounts.length; i++) {
const amount = item.amounts[i];
if (amount.currency !== defaultCurrency) {
const incomeAmount = exchangeRatesStore.getExchangedAmount(amount.incomeAmount, amount.currency, defaultCurrency);
const expenseAmount = exchangeRatesStore.getExchangedAmount(amount.expenseAmount, amount.currency, defaultCurrency);
if (isNumber(incomeAmount)) {
totalIncomeAmount += Math.floor(incomeAmount);
} else {
hasUnCalculatedTotalIncome = true;
}
if (isNumber(expenseAmount)) {
totalExpenseAmount += Math.floor(expenseAmount);
} else {
hasUnCalculatedTotalExpense = true;
}
} else {
totalIncomeAmount += amount.incomeAmount;
totalExpenseAmount += amount.expenseAmount;
}
}
}
finalOverviewData[field] = {
valid: true,
incomeAmount: totalIncomeAmount,
expenseAmount: totalExpenseAmount,
incompleteIncomeAmount: hasUnCalculatedTotalIncome,
incompleteExpenseAmount: hasUnCalculatedTotalExpense,
amounts: item.amounts || []
};
});
return finalOverviewData;
}
},
actions: {
updateTransactionOverviewInvalidState(invalidState) {
this.transactionOverviewStateInvalid = invalidState;
},
resetTransactionOverview() {
updateTransactionDateRange(this);
this.transactionOverviewOptions.loadLast11Months = false;
this.transactionOverviewData = {};
this.transactionOverviewStateInvalid = true;
},
loadTransactionOverview({ force, loadLast11Months }) {
const settingsStore = useSettingsStore();
const self = this;
let dateChanged = false;
let rangeChanged = false;
if (self.transactionDataRange.today.startTime !== getTodayFirstUnixTime()) {
dateChanged = true;
updateTransactionDateRange(self);
}
if (loadLast11Months && !self.transactionOverviewOptions.loadLast11Months) {
rangeChanged = true;
}
if (!dateChanged && !rangeChanged && !force && !self.transactionOverviewStateInvalid) {
return new Promise((resolve) => {
resolve(self.transactionOverviewData);
});
}
const requestParams = {
useTransactionTimezone: settingsStore.appSettings.timezoneUsedForStatisticsInHomePage,
today: self.transactionDataRange.today,
thisWeek: self.transactionDataRange.thisWeek,
thisMonth: self.transactionDataRange.thisMonth,
thisYear: self.transactionDataRange.thisYear
};
if (loadLast11Months) {
requestParams.lastMonth = self.transactionDataRange.lastMonth;
requestParams.monthBeforeLastMonth = self.transactionDataRange.monthBeforeLastMonth;
requestParams.monthBeforeLast2Months = self.transactionDataRange.monthBeforeLast2Months;
requestParams.monthBeforeLast3Months = self.transactionDataRange.monthBeforeLast3Months;
requestParams.monthBeforeLast4Months = self.transactionDataRange.monthBeforeLast4Months;
requestParams.monthBeforeLast5Months = self.transactionDataRange.monthBeforeLast5Months;
requestParams.monthBeforeLast6Months = self.transactionDataRange.monthBeforeLast6Months;
requestParams.monthBeforeLast7Months = self.transactionDataRange.monthBeforeLast7Months;
requestParams.monthBeforeLast8Months = self.transactionDataRange.monthBeforeLast8Months;
requestParams.monthBeforeLast9Months = self.transactionDataRange.monthBeforeLast9Months;
requestParams.monthBeforeLast10Months = self.transactionDataRange.monthBeforeLast10Months;
}
return new Promise((resolve, reject) => {
services.getTransactionAmounts(requestParams).then(response => {
const data = response.data;
if (!data || !data.success || !data.result) {
reject({ message: 'Unable to retrieve transaction overview' });
return;
}
if (self.transactionOverviewStateInvalid) {
self.updateTransactionOverviewInvalidState(false);
}
if (force && data.result && isEquals(self.transactionOverviewData, data.result)) {
reject({ message: 'Data is up to date' });
return;
}
self.transactionOverviewData = data.result;
self.transactionOverviewOptions.loadLast11Months = loadLast11Months;
resolve(data.result);
}).catch(error => {
if (force) {
logger.error('failed to force load transaction overview', error);
} else {
logger.error('failed to load transaction overview', error);
}
if (error.response && error.response.data && error.response.data.errorMessage) {
reject({ error: error.response.data });
} else if (!error.processed) {
reject({ message: 'Unable to retrieve transaction overview' });
} else {
reject(error);
}
});
});
}
}
});
+373
View File
@@ -0,0 +1,373 @@
import { type Ref, ref, computed } from 'vue';
import { defineStore } from 'pinia';
import { useSettingsStore } from './setting.ts';
import { useUserStore } from './user.ts';
import { useExchangeRatesStore } from './exchangeRates.ts';
import type { WritableStartEndTime } from '@/core/datetime.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import type {
TransactionAmountsRequestParams,
TransactionAmountsResponse,
TransactionOverviewResponse
} from '@/models/transaction.ts';
import { ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE } from '@/models/transaction.ts';
import { isNumber, isEquals } from '@/lib/common.ts';
import {
getUnixTimeBeforeUnixTime,
getTodayFirstUnixTime,
getTodayLastUnixTime,
getThisWeekFirstUnixTime,
getThisWeekLastUnixTime,
getThisMonthFirstUnixTime,
getThisMonthLastUnixTime,
getThisYearFirstUnixTime,
getThisYearLastUnixTime
} from '@/lib/datetime.ts';
import logger from '@/lib/logger.ts';
import services from '@/lib/services.ts';
interface TransactionDataRange extends Record<string, WritableStartEndTime> {
today: {
startTime: number;
endTime: number;
};
thisWeek: {
startTime: number;
endTime: number;
};
thisMonth: {
startTime: number;
endTime: number;
};
thisYear: {
startTime: number;
endTime: number;
};
lastMonth: {
startTime: number;
endTime: number;
};
monthBeforeLastMonth: {
startTime: number;
endTime: number;
};
monthBeforeLast2Months: {
startTime: number;
endTime: number;
};
monthBeforeLast3Months: {
startTime: number;
endTime: number;
};
monthBeforeLast4Months: {
startTime: number;
endTime: number;
};
monthBeforeLast5Months: {
startTime: number;
endTime: number;
};
monthBeforeLast6Months: {
startTime: number;
endTime: number;
};
monthBeforeLast7Months: {
startTime: number;
endTime: number;
};
monthBeforeLast8Months: {
startTime: number;
endTime: number;
};
monthBeforeLast9Months: {
startTime: number;
endTime: number;
};
monthBeforeLast10Months: {
startTime: number;
endTime: number;
};
}
interface TransactionOverviewOptions {
loadLast11Months: boolean;
}
export const useOverviewStore = defineStore('overview', () => {
const settingsStore = useSettingsStore();
const userStore = useUserStore();
const exchangeRatesStore = useExchangeRatesStore();
const transactionDataRange: Ref<TransactionDataRange> = ref({
today: {
startTime: getTodayFirstUnixTime(),
endTime: getTodayLastUnixTime()
},
thisWeek: {
startTime: getThisWeekFirstUnixTime(userStore.currentUserFirstDayOfWeek),
endTime: getThisWeekLastUnixTime(userStore.currentUserFirstDayOfWeek)
},
thisMonth: {
startTime: getThisMonthFirstUnixTime(),
endTime: getThisMonthLastUnixTime()
},
thisYear: {
startTime: getThisYearFirstUnixTime(),
endTime: getThisYearLastUnixTime()
},
lastMonth: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 1, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 1, 'months')
},
monthBeforeLastMonth: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 2, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 2, 'months')
},
monthBeforeLast2Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 3, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 3, 'months')
},
monthBeforeLast3Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 4, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 4, 'months')
},
monthBeforeLast4Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 5, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 5, 'months')
},
monthBeforeLast5Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 6, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 6, 'months')
},
monthBeforeLast6Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 7, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 7, 'months')
},
monthBeforeLast7Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 8, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 8, 'months')
},
monthBeforeLast8Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 9, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 9, 'months')
},
monthBeforeLast9Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 10, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 10, 'months')
},
monthBeforeLast10Months: {
startTime: getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 11, 'months'),
endTime: getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 11, 'months')
}
});
const transactionOverviewOptions: Ref<TransactionOverviewOptions> = ref({
loadLast11Months: false
});
const transactionOverviewData: Ref<TransactionAmountsResponse> = ref({});
const transactionOverviewStateInvalid: Ref<boolean> = ref(true);
const transactionOverview = computed<TransactionOverviewResponse>(() => {
const overviewData = transactionOverviewData.value;
if (!overviewData || !overviewData.thisMonth) {
return {
thisMonth: {
valid: false,
incomeAmount: 0,
expenseAmount: 0,
incompleteIncomeAmount: false,
incompleteExpenseAmount: false
}
} as TransactionOverviewResponse;
}
const finalOverviewData: TransactionOverviewResponse = {};
const defaultCurrency = userStore.currentUserDefaultCurrency;
ALL_TRANSACTION_AMOUNTS_REQUEST_TYPE.forEach(field => {
const item = overviewData[field];
if (!item) {
return;
}
let totalIncomeAmount = 0;
let totalExpenseAmount = 0;
let hasUnCalculatedTotalIncome = false;
let hasUnCalculatedTotalExpense = false;
if (item.amounts) {
for (let i = 0; i < item.amounts.length; i++) {
const amount = item.amounts[i];
if (amount.currency !== defaultCurrency) {
const incomeAmount = exchangeRatesStore.getExchangedAmount(amount.incomeAmount, amount.currency, defaultCurrency);
const expenseAmount = exchangeRatesStore.getExchangedAmount(amount.expenseAmount, amount.currency, defaultCurrency);
if (isNumber(incomeAmount)) {
totalIncomeAmount += Math.floor(incomeAmount as number);
} else {
hasUnCalculatedTotalIncome = true;
}
if (isNumber(expenseAmount)) {
totalExpenseAmount += Math.floor(expenseAmount as number);
} else {
hasUnCalculatedTotalExpense = true;
}
} else {
totalIncomeAmount += amount.incomeAmount;
totalExpenseAmount += amount.expenseAmount;
}
}
}
finalOverviewData[field] = {
valid: true,
incomeAmount: totalIncomeAmount,
expenseAmount: totalExpenseAmount,
incompleteIncomeAmount: hasUnCalculatedTotalIncome,
incompleteExpenseAmount: hasUnCalculatedTotalExpense,
amounts: item.amounts || []
};
});
return finalOverviewData;
});
function updateTransactionDateRange(): void {
transactionDataRange.value.today.startTime = getTodayFirstUnixTime();
transactionDataRange.value.today.endTime = getTodayLastUnixTime();
transactionDataRange.value.thisWeek.startTime = getThisWeekFirstUnixTime(userStore.currentUserFirstDayOfWeek);
transactionDataRange.value.thisWeek.endTime = getThisWeekLastUnixTime(userStore.currentUserFirstDayOfWeek);
transactionDataRange.value.thisMonth.startTime = getThisMonthFirstUnixTime();
transactionDataRange.value.thisMonth.endTime = getThisMonthLastUnixTime();
transactionDataRange.value.thisYear.startTime = getThisYearFirstUnixTime();
transactionDataRange.value.thisYear.endTime = getThisYearLastUnixTime();
transactionDataRange.value.lastMonth.startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 1, 'months');
transactionDataRange.value.lastMonth.endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 1, 'months');
transactionDataRange.value.monthBeforeLastMonth.startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), 2, 'months');
transactionDataRange.value.monthBeforeLastMonth.endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), 2, 'months');
for (let i = 2; i <= 10; i++) {
transactionDataRange.value[`monthBeforeLast${i}Months`].startTime = getUnixTimeBeforeUnixTime(getThisMonthFirstUnixTime(), i + 1, 'months');
transactionDataRange.value[`monthBeforeLast${i}Months`].endTime = getUnixTimeBeforeUnixTime(getThisMonthLastUnixTime(), i + 1, 'months');
}
}
function updateTransactionOverviewInvalidState(invalidState: boolean): void {
transactionOverviewStateInvalid.value = invalidState;
}
function resetTransactionOverview() {
updateTransactionDateRange();
transactionOverviewOptions.value.loadLast11Months = false;
transactionOverviewData.value = {};
transactionOverviewStateInvalid.value = true;
}
function loadTransactionOverview(params: { force: boolean, loadLast11Months: boolean }): Promise<TransactionAmountsResponse> {
let dateChanged = false;
let rangeChanged = false;
if (transactionDataRange.value.today.startTime !== getTodayFirstUnixTime()) {
dateChanged = true;
updateTransactionDateRange();
}
if (params.loadLast11Months && !transactionOverviewOptions.value.loadLast11Months) {
rangeChanged = true;
}
if (!dateChanged && !rangeChanged && !params.force && !transactionOverviewStateInvalid.value) {
return new Promise((resolve) => {
resolve(transactionOverviewData.value);
});
}
const requestParams: TransactionAmountsRequestParams = {
useTransactionTimezone: settingsStore.appSettings.timezoneUsedForStatisticsInHomePage == TimezoneTypeForStatistics.TransactionTimezone.type,
today: transactionDataRange.value.today,
thisWeek: transactionDataRange.value.thisWeek,
thisMonth: transactionDataRange.value.thisMonth,
thisYear: transactionDataRange.value.thisYear
};
if (params.loadLast11Months) {
requestParams.lastMonth = transactionDataRange.value.lastMonth;
requestParams.monthBeforeLastMonth = transactionDataRange.value.monthBeforeLastMonth;
requestParams.monthBeforeLast2Months = transactionDataRange.value.monthBeforeLast2Months;
requestParams.monthBeforeLast3Months = transactionDataRange.value.monthBeforeLast3Months;
requestParams.monthBeforeLast4Months = transactionDataRange.value.monthBeforeLast4Months;
requestParams.monthBeforeLast5Months = transactionDataRange.value.monthBeforeLast5Months;
requestParams.monthBeforeLast6Months = transactionDataRange.value.monthBeforeLast6Months;
requestParams.monthBeforeLast7Months = transactionDataRange.value.monthBeforeLast7Months;
requestParams.monthBeforeLast8Months = transactionDataRange.value.monthBeforeLast8Months;
requestParams.monthBeforeLast9Months = transactionDataRange.value.monthBeforeLast9Months;
requestParams.monthBeforeLast10Months = transactionDataRange.value.monthBeforeLast10Months;
}
return new Promise((resolve, reject) => {
services.getTransactionAmounts(requestParams).then(response => {
const data = response.data;
if (!data || !data.success || !data.result) {
reject({ message: 'Unable to retrieve transaction overview' });
return;
}
if (transactionOverviewStateInvalid.value) {
updateTransactionOverviewInvalidState(false);
}
if (params.force && data.result && isEquals(transactionOverviewData.value, data.result)) {
reject({ message: 'Data is up to date' });
return;
}
transactionOverviewData.value = data.result;
transactionOverviewOptions.value.loadLast11Months = params.loadLast11Months;
resolve(data.result);
}).catch(error => {
if (params.force) {
logger.error('failed to force load transaction overview', error);
} else {
logger.error('failed to load transaction overview', error);
}
if (error.response && error.response.data && error.response.data.errorMessage) {
reject({ error: error.response.data });
} else if (!error.processed) {
reject({ message: 'Unable to retrieve transaction overview' });
} else {
reject(error);
}
});
});
}
return {
// states
transactionDataRange,
transactionOverviewOptions,
transactionOverviewData,
transactionOverviewStateInvalid,
// computed states,
transactionOverview,
// functions
updateTransactionOverviewInvalidState,
resetTransactionOverview,
loadTransactionOverview
};
});
+1 -1
View File
@@ -4,7 +4,7 @@ import { useSettingsStore } from './setting.ts';
import { useUserStore } from './user.ts';
import { useAccountsStore } from './account.js';
import { useTransactionCategoriesStore } from './transactionCategory.js';
import { useOverviewStore } from './overview.js';
import { useOverviewStore } from './overview.ts';
import { useStatisticsStore } from './statistics.js';
import { useExchangeRatesStore } from './exchangeRates.ts';
+1 -1
View File
@@ -194,7 +194,7 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { DateRange } from '@/core/datetime.ts';
import { ThemeType } from '@/core/theme.ts';
@@ -210,7 +210,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
@@ -602,7 +602,7 @@ import { useAccountsStore } from '@/stores/account.js';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.js';
import { useTransactionTagsStore } from '@/stores/transactionTag.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
@@ -335,7 +335,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { WeekDay } from '@/core/datetime.ts';
import { SUPPORTED_IMAGE_EXTENSIONS } from '@/consts/file.ts';
+1 -1
View File
@@ -205,7 +205,7 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { DateRange } from '@/core/datetime.ts';
import { TemplateType } from '@/core/template.ts';
+1 -1
View File
@@ -76,7 +76,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { useStatisticsStore } from '@/stores/statistics.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.ts';
@@ -68,7 +68,7 @@
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.ts';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
export default {
computed: {
+1 -1
View File
@@ -337,7 +337,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.ts';
import { useUserStore } from '@/stores/user.ts';
import { useAccountsStore } from '@/stores/account.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useOverviewStore } from '@/stores/overview.ts';
import { getNameByKeyValue } from '@/lib/common.ts';
import { getCategorizedAccounts } from '@/lib/account.js';