mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 16:54:25 +08:00
data management page shows all user data statistics
This commit is contained in:
@@ -187,6 +187,7 @@ func startWebServer(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
|
apiV1Route.GET("/data/statistics.json", bindApi(api.DataManagements.DataStatisticsHandler))
|
||||||
apiV1Route.POST("/data/clear.json", bindApi(api.DataManagements.ClearDataHandler))
|
apiV1Route.POST("/data/clear.json", bindApi(api.DataManagements.ClearDataHandler))
|
||||||
|
|
||||||
// Accounts
|
// Accounts
|
||||||
|
|||||||
@@ -118,6 +118,47 @@ func (a *DataManagementsApi) ExportDataHandler(c *core.Context) ([]byte, string,
|
|||||||
return result, fileName, nil
|
return result, fileName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DataStatisticsHandler returns user data statistics
|
||||||
|
func (a *DataManagementsApi) DataStatisticsHandler(c *core.Context) (interface{}, *errs.Error) {
|
||||||
|
uid := c.GetCurrentUid()
|
||||||
|
totalAccountCount, err := a.accounts.GetTotalAccountCountByUid(uid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total account count for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
totalTransactionCategoryCount, err := a.categories.GetTotalCategoryCountByUid(uid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction category count for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
totalTransactionTagCount, err := a.tags.GetTotalTagCountByUid(uid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction tag count for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
totalTransactionCount, err := a.transactions.GetTotalTransactionCountByUid(uid)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorfWithRequestId(c, "[data_managements.DataStatisticsHandler] failed to get total transaction count for user \"uid:%d\", because %s", uid, err.Error())
|
||||||
|
return nil, errs.ErrOperationFailed
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStatisticsResp := &models.DataStatisticsResponse{
|
||||||
|
TotalAccountCount: totalAccountCount,
|
||||||
|
TotalTransactionCategoryCount: totalTransactionCategoryCount,
|
||||||
|
TotalTransactionTagCount: totalTransactionTagCount,
|
||||||
|
TotalTransactionCount: totalTransactionCount,
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataStatisticsResp, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ClearDataHandler deletes all user data
|
// ClearDataHandler deletes all user data
|
||||||
func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *errs.Error) {
|
func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *errs.Error) {
|
||||||
var clearDataReq models.ClearDataRequest
|
var clearDataReq models.ClearDataRequest
|
||||||
|
|||||||
@@ -4,3 +4,11 @@ package models
|
|||||||
type ClearDataRequest struct {
|
type ClearDataRequest struct {
|
||||||
Password string `json:"password" binding:"omitempty,min=6,max=128"`
|
Password string `json:"password" binding:"omitempty,min=6,max=128"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DataStatisticsResponse represents a view-object of user data statistic
|
||||||
|
type DataStatisticsResponse struct {
|
||||||
|
TotalAccountCount int64 `json:"totalAccountCount,string"`
|
||||||
|
TotalTransactionCategoryCount int64 `json:"totalTransactionCategoryCount,string"`
|
||||||
|
TotalTransactionTagCount int64 `json:"totalTransactionTagCount,string"`
|
||||||
|
TotalTransactionCount int64 `json:"totalTransactionCount,string"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTotalAccountCountByUid returns total account count of user
|
||||||
|
func (s *AccountService) GetTotalAccountCountByUid(uid int64) (int64, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return 0, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.Account{})
|
||||||
|
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllAccountsByUid returns all account models of user
|
// GetAllAccountsByUid returns all account models of user
|
||||||
func (s *AccountService) GetAllAccountsByUid(uid int64) ([]*models.Account, error) {
|
func (s *AccountService) GetAllAccountsByUid(uid int64) ([]*models.Account, error) {
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTotalCategoryCountByUid returns total category count of user
|
||||||
|
func (s *TransactionCategoryService) GetTotalCategoryCountByUid(uid int64) (int64, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return 0, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.TransactionCategory{})
|
||||||
|
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllCategoriesByUid returns all transaction category models of user
|
// GetAllCategoriesByUid returns all transaction category models of user
|
||||||
func (s *TransactionCategoryService) GetAllCategoriesByUid(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) ([]*models.TransactionCategory, error) {
|
func (s *TransactionCategoryService) GetAllCategoriesByUid(uid int64, categoryType models.TransactionCategoryType, parentCategoryId int64) ([]*models.TransactionCategory, error) {
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTotalTagCountByUid returns total tag count of user
|
||||||
|
func (s *TransactionTagService) GetTotalTagCountByUid(uid int64) (int64, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return 0, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.TransactionTag{})
|
||||||
|
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllTagsByUid returns all transaction tag models of user
|
// GetAllTagsByUid returns all transaction tag models of user
|
||||||
func (s *TransactionTagService) GetAllTagsByUid(uid int64) ([]*models.TransactionTag, error) {
|
func (s *TransactionTagService) GetAllTagsByUid(uid int64) ([]*models.TransactionTag, error) {
|
||||||
if uid <= 0 {
|
if uid <= 0 {
|
||||||
|
|||||||
@@ -32,6 +32,17 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// GetTotalTransactionCountByUid returns total transaction count of user
|
||||||
|
func (s *TransactionService) GetTotalTransactionCountByUid(uid int64) (int64, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return 0, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.Transaction{})
|
||||||
|
|
||||||
|
return count, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetAllTransactions returns all transactions
|
// GetAllTransactions returns all transactions
|
||||||
func (s *TransactionService) GetAllTransactions(uid int64, pageCount int32, noDuplicated bool) ([]*models.Transaction, error) {
|
func (s *TransactionService) GetAllTransactions(uid int64, pageCount int32, noDuplicated bool) ([]*models.Transaction, error) {
|
||||||
maxTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
|
maxTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(time.Now().Unix())
|
||||||
|
|||||||
@@ -167,6 +167,9 @@ export default {
|
|||||||
password
|
password
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getUserDataStatistics: () => {
|
||||||
|
return axios.get('v1/data/statistics.json');
|
||||||
|
},
|
||||||
clearData: ({ password }) => {
|
clearData: ({ password }) => {
|
||||||
return axios.post('v1/data/clear.json', {
|
return axios.post('v1/data/clear.json', {
|
||||||
password
|
password
|
||||||
|
|||||||
@@ -811,6 +811,7 @@ export default {
|
|||||||
'Are you sure you want to delete this account?': 'Are you sure you want to delete this account?',
|
'Are you sure you want to delete this account?': 'Are you sure you want to delete this account?',
|
||||||
'Unable to delete this account': 'Unable to delete this account',
|
'Unable to delete this account': 'Unable to delete this account',
|
||||||
'Transaction': 'Transaction',
|
'Transaction': 'Transaction',
|
||||||
|
'Transactions': 'Transactions',
|
||||||
'Add Transaction': 'Add Transaction',
|
'Add Transaction': 'Add Transaction',
|
||||||
'Edit Transaction': 'Edit Transaction',
|
'Edit Transaction': 'Edit Transaction',
|
||||||
'Modify Balance': 'Modify Balance',
|
'Modify Balance': 'Modify Balance',
|
||||||
@@ -897,6 +898,7 @@ export default {
|
|||||||
'Your profile has been successfully updated': 'Your profile has been successfully updated',
|
'Your profile has been successfully updated': 'Your profile has been successfully updated',
|
||||||
'Unable to update user profile': 'Unable to update user profile',
|
'Unable to update user profile': 'Unable to update user profile',
|
||||||
'Data Management': 'Data Management',
|
'Data Management': 'Data Management',
|
||||||
|
'Unable to get user statistics data': 'Unable to get user statistics data',
|
||||||
'Export Data': 'Export Data',
|
'Export Data': 'Export Data',
|
||||||
'Clear User Data': 'Clear User Data',
|
'Clear User Data': 'Clear User Data',
|
||||||
'Are you sure you want to clear all data?': 'Are you sure you want to clear all data?',
|
'Are you sure you want to clear all data?': 'Are you sure you want to clear all data?',
|
||||||
|
|||||||
@@ -811,6 +811,7 @@ export default {
|
|||||||
'Are you sure you want to delete this account?': '您确定要删除该账户?',
|
'Are you sure you want to delete this account?': '您确定要删除该账户?',
|
||||||
'Unable to delete this account': '无法删除该账户',
|
'Unable to delete this account': '无法删除该账户',
|
||||||
'Transaction': '交易',
|
'Transaction': '交易',
|
||||||
|
'Transactions': '交易',
|
||||||
'Add Transaction': '添加交易',
|
'Add Transaction': '添加交易',
|
||||||
'Edit Transaction': '编辑交易',
|
'Edit Transaction': '编辑交易',
|
||||||
'Modify Balance': '修改余额',
|
'Modify Balance': '修改余额',
|
||||||
@@ -897,6 +898,7 @@ export default {
|
|||||||
'Your profile has been successfully updated': '您的用户信息更新成功',
|
'Your profile has been successfully updated': '您的用户信息更新成功',
|
||||||
'Unable to update user profile': '无法更新用户信息',
|
'Unable to update user profile': '无法更新用户信息',
|
||||||
'Data Management': '数据管理',
|
'Data Management': '数据管理',
|
||||||
|
'Unable to get user statistics data': '无法获取用户统计数据',
|
||||||
'Export Data': '导出数据',
|
'Export Data': '导出数据',
|
||||||
'Clear User Data': '清除用户数据',
|
'Clear User Data': '清除用户数据',
|
||||||
'Are you sure you want to clear all data?': '您确定要清除所有数据?',
|
'Are you sure you want to clear all data?': '您确定要清除所有数据?',
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ import {
|
|||||||
logout,
|
logout,
|
||||||
getCurrentUserProfile,
|
getCurrentUserProfile,
|
||||||
updateUserProfile,
|
updateUserProfile,
|
||||||
|
getUserDataStatistics,
|
||||||
clearUserData,
|
clearUserData,
|
||||||
clearUserInfoState,
|
clearUserInfoState,
|
||||||
resetState,
|
resetState,
|
||||||
@@ -945,6 +946,7 @@ const stores = {
|
|||||||
logout,
|
logout,
|
||||||
getCurrentUserProfile,
|
getCurrentUserProfile,
|
||||||
updateUserProfile,
|
updateUserProfile,
|
||||||
|
getUserDataStatistics,
|
||||||
clearUserData,
|
clearUserData,
|
||||||
clearUserInfoState,
|
clearUserInfoState,
|
||||||
resetState,
|
resetState,
|
||||||
|
|||||||
@@ -282,6 +282,31 @@ export function updateUserProfile(context, { profile, currentPassword }) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getUserDataStatistics() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
services.getUserDataStatistics().then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
if (!data || !data.success || !data.result) {
|
||||||
|
reject({ message: 'Unable to get user statistics data' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(data.result);
|
||||||
|
}).catch(error => {
|
||||||
|
logger.error('failed to get user statistics data', 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 user statistics data' });
|
||||||
|
} else {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function clearUserData(context, { password }) {
|
export function clearUserData(context, { password }) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
services.clearData({
|
services.clearData({
|
||||||
|
|||||||
@@ -1,7 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<f7-page>
|
<f7-page @page:afterin="onPageAfterIn">
|
||||||
<f7-navbar :title="$t('Data Management')" :back-link="$t('Back')"></f7-navbar>
|
<f7-navbar :title="$t('Data Management')" :back-link="$t('Back')"></f7-navbar>
|
||||||
|
|
||||||
|
<f7-card class="skeleton-text" v-if="loading">
|
||||||
|
<f7-card-content class="no-safe-areas" :padding="false">
|
||||||
|
<f7-list>
|
||||||
|
<f7-list-item title="Accounts" after="Count"></f7-list-item>
|
||||||
|
<f7-list-item title="Transaction Categories" after="Count"></f7-list-item>
|
||||||
|
<f7-list-item title="Transaction Tags" after="Count"></f7-list-item>
|
||||||
|
<f7-list-item title="Transactions" after="Count"></f7-list-item>
|
||||||
|
</f7-list>
|
||||||
|
</f7-card-content>
|
||||||
|
</f7-card>
|
||||||
|
|
||||||
|
<f7-card v-else-if="!loading">
|
||||||
|
<f7-card-content class="no-safe-areas" :padding="false">
|
||||||
|
<f7-list>
|
||||||
|
<f7-list-item :title="$t('Accounts')" :after="dataStatistics.totalAccountCount"></f7-list-item>
|
||||||
|
<f7-list-item :title="$t('Transaction Categories')" :after="dataStatistics.totalTransactionCategoryCount"></f7-list-item>
|
||||||
|
<f7-list-item :title="$t('Transaction Tags')" :after="dataStatistics.totalTransactionTagCount"></f7-list-item>
|
||||||
|
<f7-list-item :title="$t('Transactions')" :after="dataStatistics.totalTransactionCount"></f7-list-item>
|
||||||
|
</f7-list>
|
||||||
|
</f7-card-content>
|
||||||
|
</f7-card>
|
||||||
|
|
||||||
<f7-card>
|
<f7-card>
|
||||||
<f7-card-content class="no-safe-areas" :padding="false">
|
<f7-card-content class="no-safe-areas" :padding="false">
|
||||||
<f7-list>
|
<f7-list>
|
||||||
@@ -26,6 +48,9 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
loading: true,
|
||||||
|
loadingError: null,
|
||||||
|
dataStatistics: null,
|
||||||
currentPasswordForClearData: '',
|
currentPasswordForClearData: '',
|
||||||
clearingData: false,
|
clearingData: false,
|
||||||
showInputPasswordSheetForClearData: false,
|
showInputPasswordSheetForClearData: false,
|
||||||
@@ -39,7 +64,27 @@ export default {
|
|||||||
return this.$settings.isDataExportingEnabled();
|
return this.$settings.isDataExportingEnabled();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
created() {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
self.loading = true;
|
||||||
|
|
||||||
|
self.$store.dispatch('getUserDataStatistics').then(dataStatistics => {
|
||||||
|
self.dataStatistics = dataStatistics;
|
||||||
|
self.loading = false;
|
||||||
|
}).catch(error => {
|
||||||
|
if (error.processed) {
|
||||||
|
self.loading = false;
|
||||||
|
} else {
|
||||||
|
self.loadingError = error;
|
||||||
|
self.$toast(error.message || error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
onPageAfterIn() {
|
||||||
|
this.$routeBackOnError('loadingError');
|
||||||
|
},
|
||||||
clearData(password) {
|
clearData(password) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user