From efa41b75fd8b15ad6a7eeecbd306fac90652e897 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Wed, 3 Feb 2021 00:58:46 +0800 Subject: [PATCH] add account total assets/liabilities chart --- src/components/mobile/PieChart.vue | 4 +- src/consts/statistics.js | 8 + src/locales/en.js | 5 + src/locales/zh_Hans.js | 5 + src/views/mobile/statistics/Transaction.vue | 325 +++++++++++++------- 5 files changed, 234 insertions(+), 113 deletions(-) diff --git a/src/components/mobile/PieChart.vue b/src/components/mobile/PieChart.vue index 6ce9b105..4f5d2a71 100644 --- a/src/components/mobile/PieChart.vue +++ b/src/components/mobile/PieChart.vue @@ -44,7 +44,7 @@ Name {{ selectedItem.name }} Value - {{ selectedItem.value | currency(defaultCurrency) }} + {{ selectedItem.value | currency(selectedItem.currency || defaultCurrency) }} @@ -68,6 +68,7 @@ export default { 'nameField', 'valueField', 'percentField', + 'currencyField', 'colorField', 'hiddenField', 'minValidPercent', @@ -111,6 +112,7 @@ export default { value: item[this.valueField], percent: (item[this.percentField] > 0 || item[this.percentField] === 0 || item[this.percentField] === '0') ? item[this.percentField] : (item[this.valueField] / totalValidValue * 100), actualPercent: item[this.valueField] / totalValidValue, + currency: item[this.currencyField], color: item[this.colorField] ? item[this.colorField] : 'c8c8c8', sourceItem: item }); diff --git a/src/consts/statistics.js b/src/consts/statistics.js index f3681e7f..675619a1 100644 --- a/src/consts/statistics.js +++ b/src/consts/statistics.js @@ -31,6 +31,14 @@ const allChartDataTypes = { IncomeBySecondaryCategory: { type: 5, name: 'Income By Secondary Category' + }, + AccountTotalAssets: { + type: 6, + name: 'Account Total Assets' + }, + AccountTotalLiabilities: { + type: 7, + name: 'Account Total Liabilities' } }; diff --git a/src/locales/en.js b/src/locales/en.js index c0a333a2..3fc88827 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -647,6 +647,9 @@ export default { 'No transaction data': 'No transaction data', 'Are you sure you want to delete this transaction?': 'Are you sure you want to delete this transaction?', 'Unable to delete this transaction': 'Unable to delete this transaction', + 'Total Amount': 'Total Amount', + 'Total Assets': 'Total Assets', + 'Total Liabilities': 'Total Liabilities', 'Total Expense': 'Total Expense', 'Total Income': 'Total Income', 'Expense Chart': 'Expense Chart', @@ -657,6 +660,8 @@ export default { 'Income By Account': 'Income By Account', 'Income By Primary Category': 'Income By Primary Category', 'Income By Secondary Category': 'Income By Secondary Category', + 'Account Total Assets': 'Account Total Assets', + 'Account Total Liabilities': 'Account Total Liabilities', 'Statistics Settings': 'Statistics Settings', 'Default Chart Type': 'Default Chart Type', 'Default Chart Data Type': 'Default Chart Data Type', diff --git a/src/locales/zh_Hans.js b/src/locales/zh_Hans.js index d80c6651..15bea5c3 100644 --- a/src/locales/zh_Hans.js +++ b/src/locales/zh_Hans.js @@ -647,6 +647,9 @@ export default { 'No transaction data': '没有交易数据', 'Are you sure you want to delete this transaction?': '您确定要删除该交易?', 'Unable to delete this transaction': '无法删除该交易', + 'Total Amount': '总金额', + 'Total Assets': '总资产', + 'Total Liabilities': '总负债', 'Total Expense': '总支出', 'Total Income': '总收入', 'Expense Chart': '支出图表', @@ -657,6 +660,8 @@ export default { 'Income By Account': '账户收入', 'Income By Primary Category': '一级分类收入', 'Income By Secondary Category': '二级分类收入', + 'Account Total Assets': '账户总资产', + 'Account Total Liabilities': '账户总负债', 'Statistics Settings': '统计设置', 'Default Chart Type': '默认图表类型', 'Default Chart Data Type': '默认图表数据类型', diff --git a/src/views/mobile/statistics/Transaction.vue b/src/views/mobile/statistics/Transaction.vue index 219564db..651fcfbe 100644 --- a/src/views/mobile/statistics/Transaction.vue +++ b/src/views/mobile/statistics/Transaction.vue @@ -48,13 +48,15 @@ name-field="name" value-field="totalAmount" percent-field="percent" + currency-field="currency" color-field="color" hidden-field="hidden" v-else-if="!loading" @click="clickPieChartItem" > - {{ $t('Total Expense') }} - {{ $t('Total Income') }} + + {{ query.chartDataType | totalAmountName(allChartDataTypes) | localized }} + {{ statisticsData.totalAmount | currency(defaultCurrency) }} @@ -140,8 +142,9 @@ -
{{ $t('Total Expense') }}
-
{{ $t('Total Income') }}
+
+ {{ query.chartDataType | totalAmountName(allChartDataTypes) | localized }} +
{{ statisticsData.totalAmount | currency(defaultCurrency) }} @@ -170,7 +173,7 @@
- {{ item.totalAmount | currency(defaultCurrency) }} + {{ item.totalAmount | currency(item.currency || defaultCurrency) }}
@@ -184,13 +187,13 @@ - + - + {{ dateRangeName(query) }} - + @@ -283,111 +286,32 @@ export default { }, statisticsData() { const self = this; - const combinedData = {}; + let combinedData = { + items: [], + totalAmount: 0 + }; - let allAmount = 0; - - for (let i = 0; i < self.$store.state.transactionStatistics.items.length; i++) { - const item = self.$store.state.transactionStatistics.items[i]; - - if (!item.primaryAccount || !item.account || !item.primaryCategory || !item.category) { - continue; - } - - if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByPrimaryCategory.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseBySecondaryCategory.type) { - if (item.category.type !== self.$constants.category.allCategoryTypes.Expense) { - continue; - } - } else if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByAccount.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByPrimaryCategory.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { - if (item.category.type !== self.$constants.category.allCategoryTypes.Income) { - continue; - } - } else { - continue; - } - - if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByAccount.type) { - if (self.$utilities.isNumber(item.amountInDefaultCurrency)) { - let data = combinedData[item.account.id]; - - if (data) { - data.totalAmount += item.amountInDefaultCurrency; - } else { - data = { - name: item.account.name, - type: 'account', - id: item.account.id, - icon: item.account.icon || self.$constants.icons.defaultAccountIcon.icon, - color: item.account.color || self.$constants.colors.defaultAccountColor, - hidden: item.primaryAccount.hidden || item.account.hidden, - totalAmount: item.amountInDefaultCurrency - } - } - - allAmount += item.amountInDefaultCurrency; - combinedData[item.account.id] = data; - } - } else if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByPrimaryCategory.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByPrimaryCategory.type) { - if (self.$utilities.isNumber(item.amountInDefaultCurrency)) { - let data = combinedData[item.primaryCategory.id]; - - if (data) { - data.totalAmount += item.amountInDefaultCurrency; - } else { - data = { - name: item.primaryCategory.name, - type: 'category', - id: item.primaryCategory.id, - icon: item.primaryCategory.icon || self.$constants.icons.defaultCategoryIcon.icon, - color: item.primaryCategory.color || self.$constants.colors.defaultCategoryColor, - hidden: item.primaryCategory.hidden, - totalAmount: item.amountInDefaultCurrency - } - } - - allAmount += item.amountInDefaultCurrency; - combinedData[item.primaryCategory.id] = data; - } - } else if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseBySecondaryCategory.type || - self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { - if (self.$utilities.isNumber(item.amountInDefaultCurrency)) { - let data = combinedData[item.category.id]; - - if (data) { - data.totalAmount += item.amountInDefaultCurrency; - } else { - data = { - name: item.category.name, - type: 'category', - id: item.category.id, - icon: item.category.icon || self.$constants.icons.defaultCategoryIcon.icon, - color: item.category.color || self.$constants.colors.defaultCategoryColor, - hidden: item.primaryCategory.hidden || item.category.hidden, - totalAmount: item.amountInDefaultCurrency - } - } - - allAmount += item.amountInDefaultCurrency; - combinedData[item.category.id] = data; - } - } + if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseByPrimaryCategory.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.ExpenseBySecondaryCategory.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByAccount.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeByPrimaryCategory.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { + combinedData = this.getDataItemsByTransactions(self.$store.state.transactionStatistics); + } else if (self.query.chartDataType === self.$constants.statistics.allChartDataTypes.AccountTotalAssets.type || + self.query.chartDataType === self.$constants.statistics.allChartDataTypes.AccountTotalLiabilities.type) { + combinedData = this.getDataItemsByAccounts(self.$store.getters.allPlainAccounts); } const allStatisticsItems = []; - for (let id in combinedData) { - if (!Object.prototype.hasOwnProperty.call(combinedData, id)) { + for (let id in combinedData.items) { + if (!Object.prototype.hasOwnProperty.call(combinedData.items, id)) { continue; } - const data = combinedData[id]; - data.percent = data.totalAmount * 100 / allAmount; + const data = combinedData.items[id]; + data.percent = data.totalAmount * 100 / combinedData.totalAmount; allStatisticsItems.push(data); } @@ -397,7 +321,7 @@ export default { }); return { - totalAmount: allAmount, + totalAmount: combinedData.totalAmount, items: allStatisticsItems }; } @@ -414,7 +338,7 @@ export default { let defaultChartDataType = self.$settings.getStatisticsDefaultChartDataType(); - if (defaultChartDataType < self.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || defaultChartDataType > self.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { + if (defaultChartDataType < self.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || defaultChartDataType > self.$constants.statistics.allChartDataTypes.AccountTotalLiabilities.type) { defaultChartDataType = self.$constants.statistics.defaultChartDataType; } @@ -558,6 +482,11 @@ export default { this.reload(null); }, dateRangeName(query) { + if (query.chartDataType === this.$constants.statistics.allChartDataTypes.AccountTotalAssets.type || + query.chartDataType === this.$constants.statistics.allChartDataTypes.AccountTotalLiabilities.type) { + return this.$t(this.allDateRanges.All.name); + } + if (query.dateType === this.allDateRanges.All.type) { return this.$t(this.allDateRanges.All.name); } @@ -608,6 +537,163 @@ export default { }, settings() { this.$f7router.navigate('/statistic/settings'); + }, + getDataItemsByTransactions(transactionStatistics) { + const allDataItems = {}; + let allAmount = 0; + + for (let i = 0; i < transactionStatistics.items.length; i++) { + const item = transactionStatistics.items[i]; + + if (!item.primaryAccount || !item.account || !item.primaryCategory || !item.category) { + continue; + } + + if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseByPrimaryCategory.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseBySecondaryCategory.type) { + if (item.category.type !== this.$constants.category.allCategoryTypes.Expense) { + continue; + } + } else if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeByAccount.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeByPrimaryCategory.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { + if (item.category.type !== this.$constants.category.allCategoryTypes.Income) { + continue; + } + } else { + continue; + } + + if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseByAccount.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeByAccount.type) { + if (this.$utilities.isNumber(item.amountInDefaultCurrency)) { + let data = allDataItems[item.account.id]; + + if (data) { + data.totalAmount += item.amountInDefaultCurrency; + } else { + data = { + name: item.account.name, + type: 'account', + id: item.account.id, + icon: item.account.icon || this.$constants.icons.defaultAccountIcon.icon, + color: item.account.color || this.$constants.colors.defaultAccountColor, + hidden: item.primaryAccount.hidden || item.account.hidden, + totalAmount: item.amountInDefaultCurrency + } + } + + allAmount += item.amountInDefaultCurrency; + allDataItems[item.account.id] = data; + } + } else if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseByPrimaryCategory.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeByPrimaryCategory.type) { + if (this.$utilities.isNumber(item.amountInDefaultCurrency)) { + let data = allDataItems[item.primaryCategory.id]; + + if (data) { + data.totalAmount += item.amountInDefaultCurrency; + } else { + data = { + name: item.primaryCategory.name, + type: 'category', + id: item.primaryCategory.id, + icon: item.primaryCategory.icon || this.$constants.icons.defaultCategoryIcon.icon, + color: item.primaryCategory.color || this.$constants.colors.defaultCategoryColor, + hidden: item.primaryCategory.hidden, + totalAmount: item.amountInDefaultCurrency + } + } + + allAmount += item.amountInDefaultCurrency; + allDataItems[item.primaryCategory.id] = data; + } + } else if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.ExpenseBySecondaryCategory.type || + this.query.chartDataType === this.$constants.statistics.allChartDataTypes.IncomeBySecondaryCategory.type) { + if (this.$utilities.isNumber(item.amountInDefaultCurrency)) { + let data = allDataItems[item.category.id]; + + if (data) { + data.totalAmount += item.amountInDefaultCurrency; + } else { + data = { + name: item.category.name, + type: 'category', + id: item.category.id, + icon: item.category.icon || this.$constants.icons.defaultCategoryIcon.icon, + color: item.category.color || this.$constants.colors.defaultCategoryColor, + hidden: item.primaryCategory.hidden || item.category.hidden, + totalAmount: item.amountInDefaultCurrency + } + } + + allAmount += item.amountInDefaultCurrency; + allDataItems[item.category.id] = data; + } + } + } + + return { + totalAmount: allAmount, + items: allDataItems + } + }, + getDataItemsByAccounts(accounts) { + const allDataItems = {}; + let allAmount = 0; + + for (let i = 0; i < accounts.length; i++) { + const account = accounts[i]; + + if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.AccountTotalAssets.type) { + if (!account.isAsset) { + continue; + } + } else if (this.query.chartDataType === this.$constants.statistics.allChartDataTypes.AccountTotalLiabilities.type) { + if (!account.isLiability) { + continue; + } + } + + let primaryAccount = this.$store.state.allAccountsMap[account.parentId]; + + if (!primaryAccount) { + primaryAccount = account; + } + + let amount = account.balance; + + if (account.currency !== this.defaultCurrency) { + amount = Math.floor(this.$store.getters.getExchangedAmount(amount, account.currency, this.defaultCurrency)); + + if (!this.$utilities.isNumber(amount)) { + continue; + } + } + + if (account.isLiability) { + amount = -amount; + } + + const data = { + name: account.name, + type: 'account', + id: account.id, + icon: account.icon || self.$constants.icons.defaultAccountIcon.icon, + color: account.color || self.$constants.colors.defaultAccountColor, + hidden: primaryAccount.hidden || account.hidden, + totalAmount: amount + }; + + allAmount += amount; + allDataItems[account.id] = data; + } + + return { + totalAmount: allAmount, + items: allDataItems + } } }, filters: { @@ -621,9 +707,22 @@ export default { return allChartDataTypes[chartDataTypeField].name; } } - + return 'Statistics'; }, + totalAmountName(dataType, allChartDataTypes) { + if (dataType === allChartDataTypes.IncomeByAccount.type || dataType === allChartDataTypes.IncomeByPrimaryCategory.type || dataType === allChartDataTypes.IncomeBySecondaryCategory.type) { + return 'Total Income'; + } else if (dataType === allChartDataTypes.ExpenseByAccount.type || dataType === allChartDataTypes.ExpenseByPrimaryCategory.type || dataType === allChartDataTypes.ExpenseBySecondaryCategory.type) { + return 'Total Expense'; + } else if (dataType === allChartDataTypes.AccountTotalAssets.type) { + return 'Total Assets'; + } else if (dataType === allChartDataTypes.AccountTotalLiabilities.type) { + return 'Total Liabilities'; + } + + return 'Total Amount'; + }, itemLinkUrl(item, query, allChartDataTypes) { const querys = []; @@ -633,15 +732,17 @@ export default { querys.push('type=3'); } - if (query.chartDataType === allChartDataTypes.IncomeByAccount.type || query.chartDataType === allChartDataTypes.ExpenseByAccount.type) { + if (query.chartDataType === allChartDataTypes.IncomeByAccount.type || query.chartDataType === allChartDataTypes.ExpenseByAccount.type || query.chartDataType === allChartDataTypes.AccountTotalAssets.type || query.chartDataType === allChartDataTypes.AccountTotalLiabilities.type) { querys.push('accountId=' + item.id); } else if (query.chartDataType === allChartDataTypes.IncomeByPrimaryCategory.type || query.chartDataType === allChartDataTypes.IncomeBySecondaryCategory.type || query.chartDataType === allChartDataTypes.ExpenseByPrimaryCategory.type || query.chartDataType === allChartDataTypes.ExpenseBySecondaryCategory.type) { querys.push('categoryId=' + item.id); } - querys.push('dateType=' + query.dateType); - querys.push('minTime=' + query.startTime); - querys.push('maxTime=' + query.endTime); + if (query.chartDataType !== allChartDataTypes.AccountTotalAssets.type && query.chartDataType !== allChartDataTypes.AccountTotalLiabilities.type) { + querys.push('dateType=' + query.dateType); + querys.push('minTime=' + query.startTime); + querys.push('maxTime=' + query.endTime); + } return '/transaction/list?' + querys.join('&'); }