Files
ezbookkeeping/src/stores/overview.js
T

307 lines
14 KiB
JavaScript

import { defineStore } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from './user.js';
import { useExchangeRatesStore } from './exchangeRates.js';
import { isNumber, isEquals } from '@/lib/common.js';
import {
getUnixTimeBeforeUnixTime,
getTodayFirstUnixTime,
getTodayLastUnixTime,
getThisWeekFirstUnixTime,
getThisWeekLastUnixTime,
getThisMonthFirstUnixTime,
getThisMonthLastUnixTime,
getThisYearFirstUnixTime,
getThisYearLastUnixTime
} from '@/lib/datetime.js';
import services from '@/lib/services.js';
import logger from '@/lib/logger.js';
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);
}
});
});
}
}
});