From 73643803122f8da9873afbb0720d70b8a6f509c0 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 20 Mar 2022 21:54:48 +0800 Subject: [PATCH] support filter by parent account in transaction list page --- pkg/api/transactions.go | 51 ++++++++++++++++++++++++-- pkg/services/accounts.go | 16 ++++++++ pkg/services/transactions.go | 42 +++++++++++++-------- src/store/index.js | 8 +++- src/store/transaction.js | 9 ++++- src/views/mobile/transactions/List.vue | 5 ++- 6 files changed, 107 insertions(+), 24 deletions(-) diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index 56322e29..57562cbe 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -46,6 +46,13 @@ func (a *TransactionsApi) TransactionCountHandler(c *core.Context) (interface{}, uid := c.GetCurrentUid() + allAccountIds, err := a.getAccountOrSubAccountIds(transactionCountReq.AccountId, uid) + + if err != nil { + log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] get account error, because %s", err.Error()) + return nil, errs.ErrOperationFailed + } + allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionCountReq.CategoryId, uid) if err != nil { @@ -53,7 +60,7 @@ func (a *TransactionsApi) TransactionCountHandler(c *core.Context) (interface{}, return nil, errs.ErrOperationFailed } - totalCount, err := a.transactions.GetTransactionCount(uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, transactionCountReq.AccountId, transactionCountReq.Keyword) + totalCount, err := a.transactions.GetTransactionCount(uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, allAccountIds, transactionCountReq.Keyword) countResp := &models.TransactionCountResponse{ TotalCount: totalCount, @@ -90,6 +97,13 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (interface{}, return nil, errs.ErrUserNotFound } + allAccountIds, err := a.getAccountOrSubAccountIds(transactionListReq.AccountId, uid) + + if err != nil { + log.WarnfWithRequestId(c, "[transactions.TransactionListHandler] get account error, because %s", err.Error()) + return nil, errs.ErrOperationFailed + } + allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionListReq.CategoryId, uid) if err != nil { @@ -97,7 +111,7 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (interface{}, return nil, errs.ErrOperationFailed } - transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Count+1, true) + transactions, err := a.transactions.GetTransactionsByMaxTime(uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, transactionListReq.Count+1, true) if err != nil { log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error()) @@ -159,6 +173,13 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.Context) (interfac return nil, errs.ErrUserNotFound } + allAccountIds, err := a.getAccountOrSubAccountIds(transactionListReq.AccountId, uid) + + if err != nil { + log.WarnfWithRequestId(c, "[transactions.TransactionMonthListHandler] get account error, because %s", err.Error()) + return nil, errs.ErrOperationFailed + } + allCategoryIds, err := a.getCategoryOrSubCategoryIds(transactionListReq.CategoryId, uid) if err != nil { @@ -166,14 +187,14 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.Context) (interfac return nil, errs.ErrOperationFailed } - transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, utcOffset) + transactions, err := a.transactions.GetTransactionsInMonthByPage(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, utcOffset) if err != nil { log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error()) return nil, errs.ErrOperationFailed } - totalCount, err := a.transactions.GetMonthTransactionCount(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, transactionListReq.AccountId, transactionListReq.Keyword, utcOffset) + totalCount, err := a.transactions.GetMonthTransactionCount(uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, utcOffset) if err != nil { log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transaction count in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error()) @@ -826,6 +847,28 @@ func (a *TransactionsApi) filterTransactions(c *core.Context, uid int64, transac return finalTransactions } +func (a *TransactionsApi) getAccountOrSubAccountIds(accountId int64, uid int64) ([]int64, error) { + var allAccountIds []int64 + + if accountId > 0 { + allSubAccounts, err := a.accounts.GetSubAccountsByAccountId(uid, accountId) + + if err != nil { + return nil, err + } + + if len(allSubAccounts) > 0 { + for i := 0; i < len(allSubAccounts); i++ { + allAccountIds = append(allAccountIds, allSubAccounts[i].AccountId) + } + } else { + allAccountIds = append(allAccountIds, accountId) + } + } + + return allAccountIds, nil +} + func (a *TransactionsApi) getCategoryOrSubCategoryIds(categoryId int64, uid int64) ([]int64, error) { var allCategoryIds []int64 diff --git a/pkg/services/accounts.go b/pkg/services/accounts.go index 0e3880a4..023cd3b7 100644 --- a/pkg/services/accounts.go +++ b/pkg/services/accounts.go @@ -58,6 +58,22 @@ func (s *AccountService) GetAccountAndSubAccountsByAccountId(uid int64, accountI return accounts, err } +// GetSubAccountsByAccountId returns sub account models according to account id +func (s *AccountService) GetSubAccountsByAccountId(uid int64, accountId int64) ([]*models.Account, error) { + if uid <= 0 { + return nil, errs.ErrUserIdInvalid + } + + if accountId <= 0 { + return nil, errs.ErrAccountIdInvalid + } + + var accounts []*models.Account + err := s.UserDataDB(uid).Where("uid=? AND deleted=? AND parent_account_id=?", uid, false, accountId).OrderBy("display_order asc").Find(&accounts) + + return accounts, err +} + // GetAccountsByAccountIds returns account models according to account ids func (s *AccountService) GetAccountsByAccountIds(uid int64, accountIds []int64) (map[int64]*models.Account, error) { if uid <= 0 { diff --git a/pkg/services/transactions.go b/pkg/services/transactions.go index b62f49d2..dceee420 100644 --- a/pkg/services/transactions.go +++ b/pkg/services/transactions.go @@ -59,11 +59,11 @@ func (s *TransactionService) GetAllTransactions(uid int64, pageCount int, noDupl // GetAllTransactionsByMaxTime returns all transactions before given time func (s *TransactionService) GetAllTransactionsByMaxTime(uid int64, maxTransactionTime int64, count int, noDuplicated bool) ([]*models.Transaction, error) { - return s.GetTransactionsByMaxTime(uid, maxTransactionTime, 0, 0, nil, 0, "", count, noDuplicated) + return s.GetTransactionsByMaxTime(uid, maxTransactionTime, 0, 0, nil, nil, "", count, noDuplicated) } // GetTransactionsByMaxTime returns transactions before given time -func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, count int, noDuplicated bool) ([]*models.Transaction, error) { +func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, count int, noDuplicated bool) ([]*models.Transaction, error) { if uid <= 0 { return nil, errs.ErrUserIdInvalid } @@ -75,14 +75,14 @@ func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionT var transactions []*models.Transaction var err error - condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, noDuplicated) + condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, noDuplicated) err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, 0).OrderBy("transaction_time desc").Find(&transactions) return transactions, err } // GetTransactionsInMonthByPage returns transactions in given year and month -func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, page int, count int, utcOffset int16) ([]*models.Transaction, error) { +func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, page int, count int, utcOffset int16) ([]*models.Transaction, error) { if uid <= 0 { return nil, errs.ErrUserIdInvalid } @@ -108,7 +108,7 @@ func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, m var transactions []*models.Transaction - condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true) + condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true) err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, count*(page-1)).OrderBy("transaction_time desc").Find(&transactions) return transactions, err @@ -138,11 +138,11 @@ func (s *TransactionService) GetTransactionByTransactionId(uid int64, transactio // GetAllTransactionCount returns total count of transactions func (s *TransactionService) GetAllTransactionCount(uid int64) (int64, error) { - return s.GetTransactionCount(uid, 0, 0, 0, nil, 0, "") + return s.GetTransactionCount(uid, 0, 0, 0, nil, nil, "") } // GetMonthTransactionCount returns total count of transactions in given year and month -func (s *TransactionService) GetMonthTransactionCount(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, utcOffset int16) (int64, error) { +func (s *TransactionService) GetMonthTransactionCount(uid int64, year int, month int, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, utcOffset int16) (int64, error) { if uid <= 0 { return 0, errs.ErrUserIdInvalid } @@ -158,16 +158,16 @@ func (s *TransactionService) GetMonthTransactionCount(uid int64, year int, month minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix()) maxTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix()) - 1 - return s.GetTransactionCount(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword) + return s.GetTransactionCount(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword) } // GetTransactionCount returns count of transactions -func (s *TransactionService) GetTransactionCount(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string) (int64, error) { +func (s *TransactionService) GetTransactionCount(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string) (int64, error) { if uid <= 0 { return 0, errs.ErrUserIdInvalid } - condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true) + condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true) return s.UserDataDB(uid).Where(condition, conditionParams...).Count(&models.Transaction{}) } @@ -1085,7 +1085,7 @@ func (s *TransactionService) GetTransactionMapByList(transactions []*models.Tran return transactionMap } -func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, noDuplicated bool) (string, []interface{}) { +func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, noDuplicated bool) (string, []interface{}) { condition := "uid=? AND deleted=?" conditionParams := make([]interface{}, 0, 16) conditionParams = append(conditionParams, uid) @@ -1105,7 +1105,7 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact condition = condition + " AND type=?" conditionParams = append(conditionParams, transactionType) } else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN { - if accountId == 0 { + if len(accountIds) == 0 { condition = condition + " AND type=?" conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT) } else { @@ -1114,7 +1114,7 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN) } } else { - if noDuplicated && accountId == 0 { + if noDuplicated && len(accountIds) == 0 { condition = condition + " AND (type=? OR type=? OR type=? OR type=?)" conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE) conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME) @@ -1138,9 +1138,19 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact condition = condition + " AND category_id IN (" + conditions.String() + ")" } - if accountId > 0 { - condition = condition + " AND account_id=?" - conditionParams = append(conditionParams, accountId) + if len(accountIds) > 0 { + var conditions strings.Builder + + for i := 0; i < len(accountIds); i++ { + if i > 0 { + conditions.WriteString(",") + } + + conditions.WriteString("?") + conditionParams = append(conditionParams, accountIds[i]) + } + + condition = condition + " AND account_id IN (" + conditions.String() + ")" } if keyword != "" { diff --git a/src/store/index.js b/src/store/index.js index 5e50f192..8d70a9ff 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -593,7 +593,13 @@ const stores = { } if ((state.transactionsFilter.categoryId && state.transactionsFilter.categoryId !== '0' && state.transactionsFilter.categoryId !== transaction.categoryId) || - (state.transactionsFilter.accountId && state.transactionsFilter.accountId !== '0' && state.transactionsFilter.accountId !== transaction.sourceAccountId && state.transactionsFilter.accountId !== transaction.destinationAccountId)) { + (state.transactionsFilter.accountId && state.transactionsFilter.accountId !== '0' && + state.transactionsFilter.accountId !== transaction.sourceAccountId && + state.transactionsFilter.accountId !== transaction.destinationAccountId && + (!transaction.sourceAccount || state.transactionsFilter.accountId !== transaction.sourceAccount.parentId) && + (!transaction.destinationAccount || state.transactionsFilter.accountId !== transaction.destinationAccount.parentId) + ) + ) { transactionMonthList.items.splice(j, 1); } else { transactionMonthList.items.splice(j, 1, transaction); diff --git a/src/store/transaction.js b/src/store/transaction.js index f9b8647d..bf128189 100644 --- a/src/store/transaction.js +++ b/src/store/transaction.js @@ -320,7 +320,7 @@ export function calculateMonthTotalAmount(state, transactionMonthList, defaultCu let amount = transaction.sourceAmount; let account = transaction.sourceAccount; - if (accountId && transaction.destinationAccount && transaction.destinationAccount.id === accountId) { + if (accountId && transaction.destinationAccount && (transaction.destinationAccount.id === accountId || transaction.destinationAccount.parentId === accountId)) { amount = transaction.destinationAmount; account = transaction.destinationAccount; } @@ -354,6 +354,13 @@ export function calculateMonthTotalAmount(state, transactionMonthList, defaultCu totalExpense += amount; } else if (accountId === transaction.destinationAccountId) { totalIncome += amount; + } else if (transaction.sourceAccount && accountId === transaction.sourceAccount.parentId && + transaction.destinationAccount && accountId === transaction.destinationAccount.parentId) { + // Do Nothing + } else if (transaction.sourceAccount && accountId === transaction.sourceAccount.parentId) { + totalExpense += amount; + } else if (transaction.destinationAccount && accountId === transaction.destinationAccount.parentId) { + totalIncome += amount; } } } diff --git a/src/views/mobile/transactions/List.vue b/src/views/mobile/transactions/List.vue index b1f12a96..e9257097 100644 --- a/src/views/mobile/transactions/List.vue +++ b/src/views/mobile/transactions/List.vue @@ -329,8 +329,9 @@
- {{ transaction.sourceAmount | finalAmount(transaction.hideAmount) | currency(transaction.sourceAccount.currency) }} - {{ transaction.destinationAmount | finalAmount(transaction.hideAmount) | currency(transaction.destinationAccount.currency) }} + {{ transaction.sourceAmount | finalAmount(transaction.hideAmount) | currency(transaction.sourceAccount.currency) }} + {{ transaction.destinationAmount | finalAmount(transaction.hideAmount) | currency(transaction.destinationAccount.currency) }} +