From d10726d45e36a1b67d22e73bc53b96593fff7f83 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Thu, 7 Jan 2021 23:50:35 +0800 Subject: [PATCH] code refactor --- src/lib/utils.js | 20 -- src/mobile-main.js | 1 - src/store/index.js | 180 +++++++++++- src/store/mutations.js | 2 + src/store/transaction.js | 201 +++++++++++++- src/views/mobile/transactions/Edit.vue | 6 +- src/views/mobile/transactions/List.vue | 368 ++++--------------------- 7 files changed, 433 insertions(+), 345 deletions(-) diff --git a/src/lib/utils.js b/src/lib/utils.js index 476515d9..86762659 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -358,25 +358,6 @@ function getCategoryInfo(categoryId) { return null; } -function getPlainAccounts(allAccounts) { - const ret = []; - - for (let i = 0; i < allAccounts.length; i++) { - const account = allAccounts[i]; - - if (account.type === accountConstants.allAccountTypes.SingleAccount) { - ret.push(account); - } else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts) { - for (let j = 0; j < account.subAccounts.length; j++) { - const subAccount = account.subAccounts[j]; - ret.push(subAccount); - } - } - } - - return ret; -} - function getCategorizedAccounts(allAccounts) { const ret = {}; @@ -490,7 +471,6 @@ export default { generateRandomString, parseUserAgent, getCategoryInfo, - getPlainAccounts, getCategorizedAccounts, getAllFilteredAccountsBalance, }; diff --git a/src/mobile-main.js b/src/mobile-main.js index 6e0fb4b4..400e5185 100644 --- a/src/mobile-main.js +++ b/src/mobile-main.js @@ -211,7 +211,6 @@ Vue.prototype.$hideLoading = function () { return this.$f7.preloader.hide(); }; -Vue.prototype.$services = services; Vue.prototype.$user = userstate; Vue.filter('itemFieldContent', (value, fieldName, defaultValue, translate) => itemFieldContentFilter({ i18n }, value, fieldName, defaultValue, translate)); diff --git a/src/store/index.js b/src/store/index.js index 5955189a..521e6a44 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -18,6 +18,8 @@ import { UPDATE_ACCOUNT_LIST_INVALID_STATE, LOAD_TRANSACTION_LIST, + SAVE_TRANSACTION_IN_TRANSACTION_LIST, + REMOVE_TRANSACTION_FROM_TRANSACTION_LIST, UPDATE_TRANSACTION_LIST_INVALID_STATE, LOAD_TRANSACTION_CATEGORY_LIST, @@ -34,7 +36,7 @@ import { CHANGE_TAG_DISPLAY_ORDER_IN_TRANSACTION_TAG_LIST, UPDATE_TAG_VISIBILITY_IN_TRANSACTION_TAG_LIST, REMOVE_TAG_FROM_TRANSACTION_TAG_LIST, - UPDATE_TRANSACTION_TAG_LIST_INVALID_STATE + UPDATE_TRANSACTION_TAG_LIST_INVALID_STATE, } from './mutations.js'; import user from './user.js'; @@ -56,6 +58,7 @@ const stores = { allCategorizedAccounts: {}, accountListStateInvalid: true, transactions: [], + transactionsNextTimeId: 0, transactionListStateInvalid: true, allTransactionCategories: {}, allTransactionCategoriesMap: {}, @@ -73,6 +76,8 @@ const stores = { allVisiblePlainAccounts: account.allVisiblePlainAccounts, allAvailableAccountsCount: account.allAvailableAccountsCount, allVisibleAccountsCount: account.allVisibleAccountsCount, + noTransaction: transaction.noTransaction, + hasMoreTransaction: transaction.hasMoreTransaction, }, mutations: { [RESET_STATE] (state) { @@ -84,6 +89,7 @@ const stores = { state.accountListStateInvalid = true; state.transactions = []; + state.transactionsNextTimeId = 0; state.transactionListStateInvalid = true; state.allTransactionCategories = {}; @@ -115,6 +121,13 @@ const stores = { for (let i = 0; i < accounts.length; i++) { const account = accounts[i]; state.allAccountsMap[account.id] = account; + + if (account.subAccounts) { + for (let j = 0; j < account.subAccounts.length; j++) { + const subAccount = account.subAccounts[j]; + state.allAccountsMap[subAccount.id] = subAccount; + } + } } state.allCategorizedAccounts = utils.getCategorizedAccounts(accounts); @@ -133,6 +146,13 @@ const stores = { state.allAccountsMap[account.id] = account; + if (account.subAccounts) { + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + state.allAccountsMap[subAccount.id] = subAccount; + } + } + if (state.allCategorizedAccounts[account.category]) { const accountList = state.allCategorizedAccounts[account.category].accounts; accountList.push(account); @@ -150,6 +170,13 @@ const stores = { state.allAccountsMap[account.id] = account; + if (account.subAccounts) { + for (let i = 0; i < account.subAccounts.length; i++) { + const subAccount = account.subAccounts[i]; + state.allAccountsMap[subAccount.id] = subAccount; + } + } + if (state.allCategorizedAccounts[account.category]) { const accountList = state.allCategorizedAccounts[account.category].accounts; @@ -203,6 +230,17 @@ const stores = { } } + if (state.allAccountsMap[account.id] && state.allAccountsMap[account.id].subAccounts) { + const subAccounts = state.allAccountsMap[account.id].subAccounts; + + for (let i = 0; i < subAccounts.length; i++) { + const subAccount = subAccounts[i]; + if (state.allAccountsMap[subAccount.id]) { + delete state.allAccountsMap[subAccount.id]; + } + } + } + if (state.allAccountsMap[account.id]) { delete state.allAccountsMap[account.id]; } @@ -221,8 +259,131 @@ const stores = { [UPDATE_ACCOUNT_LIST_INVALID_STATE] (state, invalidState) { state.accountListStateInvalid = invalidState; }, - [LOAD_TRANSACTION_LIST] (state, transactions) { - state.transactions = transactions; + [LOAD_TRANSACTION_LIST] (state, { transactions, reload, autoExpand, defaultCurrency, accountId }) { + if (reload) { + state.transactions = []; + } + + if (transactions.items && transactions.items.length) { + let currentMonthListIndex = -1; + let currentMonthList = null; + + for (let i = 0; i < transactions.items.length; i++) { + const item = transactions.items[i]; + const transactionTime = utils.parseDateFromUnixTime(item.time); + + item.day = utils.getDay(transactionTime); + item.dayOfWeek = utils.getDayOfWeek(transactionTime); + item.sourceAccount = state.allAccountsMap[item.sourceAccountId]; + item.destinationAccount = state.allAccountsMap[item.destinationAccountId]; + item.category = state.allTransactionCategoriesMap[item.categoryId]; + item.tags = []; + + if (item.tagIds && item.tagIds.length) { + for (let j = 0; j < item.tagIds.length; j++) { + const tag = state.allTransactionTagsMap[item.tagIds[j]]; + + if (tag) { + item.tags.push(tag); + } + } + } + + const transactionYear = utils.getYear(transactionTime); + const transactionMonth = utils.getMonth(transactionTime); + const transactionYearMonth = utils.getYearAndMonth(transactionTime); + + if (currentMonthList && currentMonthList.year === transactionYear && currentMonthList.month === transactionMonth) { + currentMonthList.items.push(item); + transaction.calculateMonthTotalAmount(state, currentMonthList, defaultCurrency, accountId, true); + continue; + } + + for (let j = currentMonthListIndex + 1; j < state.transactions.length; j++) { + if (state.transactions[j].year === transactionYear && state.transactions[j].month === transactionMonth) { + currentMonthListIndex = j; + currentMonthList = state.transactions[j]; + + if (j > 0) { + transaction.calculateMonthTotalAmount(state, state.transactions[j - 1], defaultCurrency, accountId, false); + } + + break; + } + } + + if (!currentMonthList && state.transactions.length > 0) { + transaction.calculateMonthTotalAmount(state, state.transactions[state.transactions.length - 1], defaultCurrency, accountId, false); + } + + if (!currentMonthList || currentMonthList.year !== transactionYear || currentMonthList.month !== transactionMonth) { + transaction.calculateMonthTotalAmount(state, currentMonthList, defaultCurrency, accountId, false); + + state.transactions.push({ + year: transactionYear, + month: transactionMonth, + yearMonth: transactionYearMonth, + opened: autoExpand, + items: [] + }); + + currentMonthListIndex = state.transactions.length - 1; + currentMonthList = state.transactions[state.transactions.length - 1]; + } + + currentMonthList.items.push(item); + transaction.calculateMonthTotalAmount(state, currentMonthList, defaultCurrency, accountId, true); + } + } + + if (transactions.nextTimeSequenceId) { + state.transactionsNextTimeId = transactions.nextTimeSequenceId; + } else { + transaction.calculateMonthTotalAmount(state, state.transactions[state.transactions.length - 1], defaultCurrency, accountId, false); + state.transactionsNextTimeId = -1; + } + }, + [SAVE_TRANSACTION_IN_TRANSACTION_LIST] (state, { transaction, defaultCurrency, accountId }) { + for (let i = 0; i < state.transactions.length; i++) { + const transactionMonthList = state.transactions[i]; + + if (!transactionMonthList.items || + transactionMonthList.items[0].time < transaction.time || + transactionMonthList.items[transactionMonthList.items.length - 1].time > transaction.time) { + continue; + } + + for (let j = 0; j < transactionMonthList.items.length; j++) { + if (transactionMonthList.items[j].id === transaction.id) { + transactionMonthList.items.splice(j, 1, transaction); + transaction.calculateMonthTotalAmount(state, transactionMonthList, defaultCurrency, accountId, i >= state.transactions.length - 1 && state.transactionsNextTimeId > 0); + return; + } + } + } + }, + [REMOVE_TRANSACTION_FROM_TRANSACTION_LIST] (state, { transaction, defaultCurrency, accountId }) { + for (let i = 0; i < state.transactions.length; i++) { + const transactionMonthList = state.transactions[i]; + + if (!transactionMonthList.items || + transactionMonthList.items[0].time < transaction.time || + transactionMonthList.items[transactionMonthList.items.length - 1].time > transaction.time) { + continue; + } + + for (let j = 0; j < transactionMonthList.items.length; j++) { + if (transactionMonthList.items[j].id === transaction.id) { + transactionMonthList.items.splice(j, 1); + } + } + + if (transactionMonthList.items.length < 1) { + state.transactions.splice(i, 1); + } else { + transaction.calculateMonthTotalAmount(state, transactionMonthList, defaultCurrency, accountId, i >= state.transactions.length - 1 && state.transactionsNextTimeId > 0); + } + } }, [UPDATE_TRANSACTION_LIST_INVALID_STATE] (state, invalidState) { state.transactionListStateInvalid = invalidState; @@ -320,6 +481,17 @@ const stores = { } } + if (state.allTransactionCategoriesMap[category.id] && state.allTransactionCategoriesMap[category.id].subCategories) { + const subCategories = state.allTransactionCategoriesMap[category.id].subCategories; + + for (let i = 0; i < subCategories.length; i++) { + const subCategory = subCategories[i]; + if (state.allTransactionCategoriesMap[subCategory.id]) { + delete state.allTransactionCategoriesMap[subCategory.id]; + } + } + } + if (state.allTransactionCategoriesMap[category.id]) { delete state.allTransactionCategoriesMap[category.id]; } @@ -405,8 +577,10 @@ const stores = { hideAccount: account.hideAccount, deleteAccount: account.deleteAccount, + getTransactions: transaction.getTransactions, getTransaction: transaction.getTransaction, saveTransaction: transaction.saveTransaction, + deleteTransaction: transaction.deleteTransaction, loadAllCategories: transactionCategory.loadAllCategories, getCategory: transactionCategory.getCategory, diff --git a/src/store/mutations.js b/src/store/mutations.js index f0dd0733..0759881e 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -14,6 +14,8 @@ export const REMOVE_ACCOUNT_FROM_ACCOUNT_LIST = 'REMOVE_ACCOUNT_FROM_ACCOUNT_LIS export const UPDATE_ACCOUNT_LIST_INVALID_STATE = 'UPDATE_ACCOUNT_LIST_INVALID_STATE'; export const LOAD_TRANSACTION_LIST = 'LOAD_TRANSACTION_LIST'; +export const SAVE_TRANSACTION_IN_TRANSACTION_LIST = 'SAVE_TRANSACTION_IN_TRANSACTION_LIST'; +export const REMOVE_TRANSACTION_FROM_TRANSACTION_LIST = 'REMOVE_TRANSACTION_FROM_TRANSACTION_LIST'; export const UPDATE_TRANSACTION_LIST_INVALID_STATE = 'UPDATE_TRANSACTION_LIST_INVALID_STATE'; export const LOAD_TRANSACTION_CATEGORY_LIST = 'LOAD_TRANSACTION_CATEGORY_LIST'; diff --git a/src/store/transaction.js b/src/store/transaction.js index 35d202a5..25cd808e 100644 --- a/src/store/transaction.js +++ b/src/store/transaction.js @@ -1,11 +1,68 @@ +import transactionConstants from '../consts/transaction.js'; +import exchangeRates from "./exchangeRates.js"; import services from '../lib/services.js'; import logger from '../lib/logger.js'; +import utils from '../lib/utils.js'; import { - LOAD_TRANSACTION_LIST, UPDATE_ACCOUNT_LIST_INVALID_STATE, - UPDATE_TRANSACTION_LIST_INVALID_STATE + LOAD_TRANSACTION_LIST, + REMOVE_TRANSACTION_FROM_TRANSACTION_LIST, + UPDATE_TRANSACTION_LIST_INVALID_STATE, + UPDATE_ACCOUNT_LIST_INVALID_STATE, } from './mutations.js'; +function getTransactions(context, { reload, autoExpand, defaultCurrency, maxTime, minTime, type, categoryId, accountId, keyword }) { + let actualMaxTime = context.state.transactionsNextTimeId; + + if (reload && maxTime > 0) { + actualMaxTime = maxTime * 1000 + 999; + } else if (reload && maxTime <= 0) { + actualMaxTime = 0; + } + + return new Promise((resolve, reject) => { + services.getTransactions({ + maxTime: actualMaxTime, + minTime: minTime, + type: type, + categoryId: categoryId, + accountId: accountId, + keyword: keyword + }).then(response => { + const data = response.data; + + if (!data || !data.success || !data.result) { + reject({ message: 'Unable to get transaction list' }); + return; + } + + context.commit(LOAD_TRANSACTION_LIST, { + transactions: data.result, + reload: reload, + autoExpand: autoExpand, + defaultCurrency: defaultCurrency, + accountId: accountId + }); + + if (reload) { + context.commit(UPDATE_TRANSACTION_LIST_INVALID_STATE, false); + } + + resolve(data.result); + }).catch(error => { + logger.error('failed to load transaction list', error); + + if (error.response && error.response.data && error.response.data.errorMessage) { + reject({ error: error.response.data }); + } else if (!error.processed) { + reject({ message: 'Unable to get transaction list' }); + } else { + reject(error); + } + }); + }); +} + function getTransaction(context, { transactionId }) { return new Promise((resolve, reject) => { services.getTransaction({ @@ -18,9 +75,6 @@ function getTransaction(context, { transactionId }) { return; } - context.commit(LOAD_TRANSACTION_LIST, data.result); - context.commit(UPDATE_TRANSACTION_LIST_INVALID_STATE, false); - resolve(data.result); }).catch(error => { logger.error('failed to load transaction info', error); @@ -58,7 +112,12 @@ function saveTransaction(context, { transaction }) { return; } - context.commit(UPDATE_TRANSACTION_LIST_INVALID_STATE, true); + if (!transaction.id) { + context.commit(UPDATE_TRANSACTION_LIST_INVALID_STATE, true); + } else { + context.commit(UPDATE_TRANSACTION_LIST_INVALID_STATE, true); + } + context.commit(UPDATE_ACCOUNT_LIST_INVALID_STATE, true); resolve(data.result); @@ -80,7 +139,131 @@ function saveTransaction(context, { transaction }) { }); } -export default { - getTransaction, - saveTransaction +function deleteTransaction(context, { transaction, defaultCurrency, accountId, beforeResolve }) { + return new Promise((resolve, reject) => { + services.deleteTransaction({ + id: transaction.id + }).then(response => { + const data = response.data; + + if (!data || !data.success || !data.result) { + reject({ message: 'Unable to delete this transaction' }); + return; + } + + if (beforeResolve) { + beforeResolve(() => { + context.commit(REMOVE_TRANSACTION_FROM_TRANSACTION_LIST, { + transaction: transaction, + defaultCurrency: defaultCurrency, + accountId: accountId + }); + }); + } else { + context.commit(REMOVE_TRANSACTION_FROM_TRANSACTION_LIST, { + transaction: transaction, + defaultCurrency: defaultCurrency, + accountId: accountId + }); + } + + context.commit(UPDATE_ACCOUNT_LIST_INVALID_STATE, true); + + resolve(data.result); + }).catch(error => { + logger.error('failed to delete transaction', error); + + if (error.response && error.response.data && error.response.data.errorMessage) { + reject({ error: error.response.data }); + } else if (!error.processed) { + reject({ message: 'Unable to delete this transaction' }); + } else { + reject(error); + } + }); + }); +} + +function noTransaction(state) { + for (let i = 0; i < state.transactions.length; i++) { + const transactionMonthList = state.transactions[i]; + + for (let j = 0; j < transactionMonthList.items.length; j++) { + if (transactionMonthList.items[j]) { + return false; + } + } + } + + return true; +} + +function hasMoreTransaction(state) { + return state.transactionsNextTimeId > 0; +} + +function calculateMonthTotalAmount(state, transactionMonthList, defaultCurrency, accountId, incomplete) { + if (!transactionMonthList) { + return; + } + + let totalExpense = 0; + let totalIncome = 0; + let hasUnCalculatedTotalExpense = false; + let hasUnCalculatedTotalIncome = false; + + for (let i = 0; i < transactionMonthList.items.length; i++) { + const transaction = transactionMonthList.items[i]; + + if (!transaction.sourceAccount) { + continue; + } + + let amount = transaction.sourceAmount; + + if (transaction.sourceAccount.currency !== defaultCurrency) { + const balance = exchangeRates.getExchangedAmount(state)(amount, transaction.sourceAccount.currency, defaultCurrency); + + if (!utils.isNumber(balance)) { + if (transaction.type === transactionConstants.allTransactionTypes.Expense) { + hasUnCalculatedTotalExpense = true; + } else if (transaction.type === transactionConstants.allTransactionTypes.Income) { + hasUnCalculatedTotalIncome = true; + } + + continue; + } + + amount = Math.floor(balance); + } + + if (transaction.type === transactionConstants.allTransactionTypes.Expense) { + totalExpense += amount; + } else if (transaction.type === transactionConstants.allTransactionTypes.Income) { + totalIncome += amount; + } else if (transaction.type === transactionConstants.allTransactionTypes.Transfer && accountId) { + if (accountId === transaction.sourceAccountId) { + totalExpense += amount; + } else if (accountId === transaction.destinationAccountId) { + totalIncome += amount; + } + } + } + + transactionMonthList.totalAmount = { + expense: totalExpense, + incompleteExpense: incomplete || hasUnCalculatedTotalExpense, + income: totalIncome, + incompleteIncome: incomplete || hasUnCalculatedTotalIncome + }; +} + +export default { + getTransactions, + getTransaction, + saveTransaction, + deleteTransaction, + noTransaction, + hasMoreTransaction, + calculateMonthTotalAmount } diff --git a/src/views/mobile/transactions/Edit.vue b/src/views/mobile/transactions/Edit.vue index 0ecde4c9..c4b9f5a0 100644 --- a/src/views/mobile/transactions/Edit.vue +++ b/src/views/mobile/transactions/Edit.vue @@ -313,6 +313,9 @@ export default { return ''; } }, + defaultCurrency() { + return this.$store.getters.currentUserDefaultCurrency || this.$t('default.currency'); + }, allAccounts() { return this.$store.getters.allPlainAccounts; }, @@ -389,9 +392,6 @@ export default { allTags() { return this.$store.state.allTransactionTags; }, - defaultCurrency() { - return this.$store.getters.currentUserDefaultCurrency || this.$t('default.currency'); - }, hasAvailableExpenseCategories() { if (!this.allCategories || !this.allCategories[this.$constants.category.allCategoryTypes.Expense] || !this.allCategories[this.$constants.category.allCategoryTypes.Expense].length) { return false; diff --git a/src/views/mobile/transactions/List.vue b/src/views/mobile/transactions/List.vue index 1222f904..8b77b2f1 100644 --- a/src/views/mobile/transactions/List.vue +++ b/src/views/mobile/transactions/List.vue @@ -4,6 +4,7 @@ :infinite-preloader="loadingMore" :infinite-distance="400" @ptr:refresh="reload" + @page:afterin="onPageAfterIn" @infinite="loadMore(true)"> @@ -164,7 +165,7 @@ {{ transaction.day }} - {{ transaction.dayOfWeek }} + {{ `datetime.${transaction.dayOfWeek}.short` | t }}
@@ -223,7 +224,7 @@ - + {{ $t('Load More') }} @@ -371,7 +372,6 @@ export default { data() { return { - transactions: [], query: { dateType: 0, maxTime: 0, @@ -381,10 +381,6 @@ export default { accountId: '0', keyword: '' }, - allAccounts: {}, - allCategories: {}, - allTags: {}, - maxTime: 0, loading: true, loadingMore: false, transactionToDelete: null, @@ -400,18 +396,27 @@ export default { defaultCurrency() { return this.$store.getters.currentUserDefaultCurrency || this.$t('default.currency'); }, - noTransaction() { - for (let i = 0; i < this.transactions.length; i++) { - const transactionMonthList = this.transactions[i]; - - for (let j = 0; j < transactionMonthList.items.length; j++) { - if (transactionMonthList.items[j]) { - return false; - } - } + transactions() { + if (this.loading) { + return []; } - return true; + return this.$store.state.transactions; + }, + noTransaction() { + return this.$store.getters.noTransaction; + }, + hasMoreTransaction() { + return this.$store.getters.hasMoreTransaction; + }, + allAccounts() { + return this.$store.state.allAccountsMap; + }, + allCategories() { + return this.$store.state.allTransactionCategoriesMap; + }, + allTags() { + return this.$store.state.allTransactionTagsMap; } }, created() { @@ -433,6 +438,11 @@ export default { this.reload(null); }, methods: { + onPageAfterIn() { + if (this.$store.state.transactionListStateInvalid && !this.loading) { + this.reload(null); + } + }, reload(done) { const self = this; const router = self.$f7router; @@ -441,18 +451,15 @@ export default { self.loading = true; } - if (self.query.maxTime > 0) { - self.maxTime = self.query.maxTime * 1000 + 999; - } else { - self.maxTime = 0; - } - const promises = [ - self.$services.getAllAccounts({ visibleOnly: false }), - self.$services.getAllTransactionCategories({}), - self.$services.getAllTransactionTags(), - self.$services.getTransactions({ - maxTime: self.maxTime, + self.$store.dispatch('loadAllAccounts', { force: false }), + self.$store.dispatch('loadAllCategories', { force: false }), + self.$store.dispatch('loadAllTags', { force: false }), + self.$store.dispatch('getTransactions', { + reload: true, + autoExpand: true, + defaultCurrency: self.defaultCurrency, + maxTime: self.query.maxTime > 0 ? self.query.maxTime * 1000 + 999 : 0, minTime: self.query.minTime * 1000, type: self.query.type, categoryId: self.query.categoryId, @@ -461,103 +468,22 @@ export default { }) ]; - Promise.all(promises).then(responses => { + Promise.all(promises).then(() => { if (done) { done(); } - const accountData = responses[0].data; - const categoryData = responses[1].data; - const tagData = responses[2].data; - const transactionListData = responses[3].data; - - if (!accountData || !accountData.success || !accountData.result) { - self.$toast('Unable to get account list'); - if (!done) { - router.back(); - } - return; - } - - if (!categoryData || !categoryData.success || !categoryData.result) { - self.$toast('Unable to get category list'); - if (!done) { - router.back(); - } - return; - } - - if (!tagData || !tagData.success || !tagData.result) { - self.$toast('Unable to get tag list'); - if (!done) { - router.back(); - } - return; - } - - if (!transactionListData || !transactionListData.success || !transactionListData.result) { - self.$toast('Unable to get transaction list'); - if (!done) { - router.back(); - } - return; - } - - const allAccounts = self.$utilities.getPlainAccounts(accountData.result); - self.allAccounts = {}; - - for (let i = 0; i < allAccounts.length; i++) { - const account = allAccounts[i]; - self.allAccounts[account.id] = account; - } - - const allCategories = categoryData.result; - self.allCategories = {}; - - for (let categoryType in allCategories) { - if (!Object.prototype.hasOwnProperty.call(allCategories, categoryType)) { - continue; - } - - const categoryList = allCategories[categoryType]; - - for (let i = 0; i < categoryList.length; i++) { - const category = categoryList[i]; - self.allCategories[category.id] = category; - - for (let j = 0; j < category.subCategories.length; j++) { - const subCategory = category.subCategories[j]; - self.allCategories[subCategory.id] = subCategory; - } - } - } - - const allTags = tagData.result; - self.allTags = {}; - - for (let i = 0; i < allTags.length; i++) { - const tag = allTags[i]; - self.allTags[tag.id] = tag; - } - - self.transactions = []; - self.setResult(transactionListData.result, true); - self.loading = false; }).catch(error => { - self.$logger.error('failed to load transaction list', error); + self.loading = false; if (done) { done(); } - if (error.response && error.response.data && error.response.data.errorMessage) { - self.$toast({ error: error.response.data }); - if (!done) { - router.back(); - } - } else if (!error.processed) { - self.$toast('Unable to get transaction list'); + if (!error.processed) { + self.$toast(error.message || error); + if (!done) { router.back(); } @@ -567,7 +493,7 @@ export default { loadMore(autoExpand) { const self = this; - if (self.maxTime <= 0) { + if (!self.hasMoreTransaction) { return; } @@ -577,33 +503,21 @@ export default { self.loadingMore = true; - self.$services.getTransactions({ - maxTime: self.maxTime, + self.$store.dispatch('getTransactions', { + autoExpand: autoExpand, + defaultCurrency: self.defaultCurrency, minTime: self.query.minTime * 1000, type: self.query.type, categoryId: self.query.categoryId, accountId: self.query.accountId, keyword: self.query.keyword - }).then(response => { + }).then(() => { self.loadingMore = false; - - const data = response.data; - - if (!data || !data.success || !data.result) { - self.$toast('Unable to get transaction list'); - return; - } - - self.setResult(data.result, autoExpand); }).catch(error => { self.loadingMore = false; - self.$logger.error('failed to reload transaction list', error); - - if (error.response && error.response.data && error.response.data.errorMessage) { - self.$toast({ error: error.response.data }); - } else if (!error.processed) { - self.$toast('Unable to get account list'); + if (!error.processed) { + self.$toast(error.message || error); } }); }, @@ -667,9 +581,6 @@ export default { this.query.maxTime = maxTime; this.query.minTime = minTime; - console.log(this.$utilities.formatUnixTime(this.query.maxTime, 'YYYY-MM-DD HH:mm:ss')); - console.log(this.$utilities.formatUnixTime(this.query.minTime, 'YYYY-MM-DD HH:mm:ss')); - this.transactions = []; this.query.dateType = 11; @@ -750,185 +661,24 @@ export default { self.transactionToDelete = null; self.$showLoading(); - self.$services.deleteTransaction({ - id: transaction.id - }).then(response => { - self.$hideLoading(); - const data = response.data; - - if (!data || !data.success || !data.result) { - self.$toast('Unable to delete this transaction'); - return; + self.$store.dispatch('deleteTransaction', { + transaction: transaction, + defaultCurrency: self.defaultCurrency, + accountId: self.query.accountId, + beforeResolve: (done) => { + app.swipeout.delete($$(`#${self.$options.filters.transactionDomId(transaction)}`), () => { + done(); + }); } - - app.swipeout.delete($$(`#${self.$options.filters.transactionDomId(transaction)}`), () => { - for (let i = 0; i < self.transactions.length; i++) { - const transactionMonthList = self.transactions[i]; - - if (!transactionMonthList.items || - transactionMonthList.items[0].time < transaction.time || - transactionMonthList.items[transactionMonthList.items.length - 1].time > transaction.time) { - continue; - } - - for (let j = 0; j < transactionMonthList.items.length; j++) { - if (transactionMonthList.items[j].id === transaction.id) { - transactionMonthList.items.splice(j, 1); - } - } - - if (transactionMonthList.items.length < 1) { - self.transactions.splice(i, 1); - } else { - self.calculateMonthTotalAmount(transactionMonthList, i >= self.transactions.length - 1 && self.maxTime > 0); - } - } - }); + }).then(() => { + self.$hideLoading(); }).catch(error => { - self.$logger.error('failed to delete transaction', error); - self.$hideLoading(); - if (error.response && error.response.data && error.response.data.errorMessage) { - self.$toast({ error: error.response.data }); - } else if (!error.processed) { - self.$toast('Unable to delete this transaction'); + if (!error.processed) { + self.$toast(error.message || error); } }); - }, - setResult(result, autoExpand) { - if (result.items && result.items.length) { - let currentMonthListIndex = -1; - let currentMonthList = null; - - for (let i = 0; i < result.items.length; i++) { - const transaction = result.items[i]; - const transactionTime = this.$utilities.parseDateFromUnixTime(transaction.time); - transaction.day = this.$utilities.getDay(transactionTime); - transaction.dayOfWeek = this.$t(`datetime.${this.$utilities.getDayOfWeek(transactionTime)}.short`); - transaction.sourceAccount = this.allAccounts[transaction.sourceAccountId]; - transaction.destinationAccount = this.allAccounts[transaction.destinationAccountId]; - transaction.category = this.allCategories[transaction.categoryId]; - transaction.tags = []; - - if (transaction.tagIds && transaction.tagIds.length) { - for (let j = 0; j < transaction.tagIds.length; j++) { - const tag = this.allTags[transaction.tagIds[j]]; - - if (tag) { - transaction.tags.push(tag); - } - } - } - - const transactionYear = this.$utilities.getYear(transactionTime); - const transactionMonth = this.$utilities.getMonth(transactionTime); - const transactionYearMonth = this.$utilities.getYearAndMonth(transactionTime); - - if (currentMonthList && currentMonthList.year === transactionYear && currentMonthList.month === transactionMonth) { - currentMonthList.items.push(transaction); - this.calculateMonthTotalAmount(currentMonthList, true); - continue; - } - - for (let j = currentMonthListIndex + 1; j < this.transactions.length; j++) { - if (this.transactions[j].year === transactionYear && this.transactions[j].month === transactionMonth) { - currentMonthListIndex = j; - currentMonthList = this.transactions[j]; - - if (j > 0) { - this.calculateMonthTotalAmount(this.transactions[j - 1], false); - } - - break; - } - } - - if (!currentMonthList && this.transactions.length > 0) { - this.calculateMonthTotalAmount(this.transactions[this.transactions.length - 1], false); - } - - if (!currentMonthList || currentMonthList.year !== transactionYear || currentMonthList.month !== transactionMonth) { - this.calculateMonthTotalAmount(currentMonthList, false); - - this.transactions.push({ - year: transactionYear, - month: transactionMonth, - yearMonth: transactionYearMonth, - opened: autoExpand, - items: [] - }); - - currentMonthListIndex = this.transactions.length - 1; - currentMonthList = this.transactions[this.transactions.length - 1]; - } - - currentMonthList.items.push(transaction); - this.calculateMonthTotalAmount(currentMonthList, true); - } - } - - if (result.nextTimeSequenceId) { - this.maxTime = result.nextTimeSequenceId; - } else { - this.calculateMonthTotalAmount(this.transactions[this.transactions.length - 1], false); - this.maxTime = -1; - } - }, - calculateMonthTotalAmount(transactionMonthList, incomplete) { - if (!transactionMonthList) { - return; - } - - let totalExpense = 0; - let totalIncome = 0; - let hasUnCalculatedTotalExpense = false; - let hasUnCalculatedTotalIncome = false; - - for (let i = 0; i < transactionMonthList.items.length; i++) { - const transaction = transactionMonthList.items[i]; - - if (!transaction.sourceAccount) { - continue; - } - - let amount = transaction.sourceAmount; - - if (transaction.sourceAccount.currency !== this.defaultCurrency) { - const balance = this.$store.getters.getExchangedAmount(amount, transaction.sourceAccount.currency, this.defaultCurrency); - - if (!this.$utilities.isNumber(balance)) { - if (transaction.type === this.$constants.transaction.allTransactionTypes.Expense) { - hasUnCalculatedTotalExpense = true; - } else if (transaction.type === this.$constants.transaction.allTransactionTypes.Income) { - hasUnCalculatedTotalIncome = true; - } - - continue; - } - - amount = Math.floor(balance); - } - - if (transaction.type === this.$constants.transaction.allTransactionTypes.Expense) { - totalExpense += amount; - } else if (transaction.type === this.$constants.transaction.allTransactionTypes.Income) { - totalIncome += amount; - } else if (transaction.type === this.$constants.transaction.allTransactionTypes.Transfer && this.query.accountId) { - if (this.query.accountId === transaction.sourceAccountId) { - totalExpense += amount; - } else if (this.query.accountId === transaction.destinationAccountId) { - totalIncome += amount; - } - } - } - - transactionMonthList.totalAmount = { - expense: totalExpense, - incompleteExpense: incomplete || hasUnCalculatedTotalExpense, - income: totalIncome, - incompleteIncome: incomplete || hasUnCalculatedTotalIncome - }; } }, filters: {