diff --git a/cmd/webserver.go b/cmd/webserver.go index 9fd852c3..1d57096c 100644 --- a/cmd/webserver.go +++ b/cmd/webserver.go @@ -394,6 +394,7 @@ func startWebServer(c *core.CliContext) error { apiV1Route.POST("/transactions/add.json", bindApi(api.Transactions.TransactionCreateHandler)) apiV1Route.POST("/transactions/modify.json", bindApi(api.Transactions.TransactionModifyHandler)) apiV1Route.POST("/transactions/batch_update/category.json", bindApi(api.Transactions.TransactionBatchUpdateCategoriesHandler)) + apiV1Route.POST("/transactions/batch_update/account.json", bindApi(api.Transactions.TransactionBatchUpdateAccountsHandler)) apiV1Route.POST("/transactions/move/all.json", bindApi(api.Transactions.TransactionMoveAllBetweenAccountsHandler)) apiV1Route.POST("/transactions/delete.json", bindApi(api.Transactions.TransactionDeleteHandler)) apiV1Route.POST("/transactions/batch_delete.json", bindApi(api.Transactions.TransactionBatchDeleteHandler)) diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index ed2d05c0..051dcdf9 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -1437,6 +1437,157 @@ func (a *TransactionsApi) TransactionBatchUpdateCategoriesHandler(c *core.WebCon return true, nil } +// TransactionBatchUpdateAccountsHandler batch updates accounts of transactions by request parameters for current user +func (a *TransactionsApi) TransactionBatchUpdateAccountsHandler(c *core.WebContext) (any, *errs.Error) { + var transactionBatchUpdateReq models.TransactionBatchUpdateAccountRequest + err := c.ShouldBindJSON(&transactionBatchUpdateReq) + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] parse request failed, because %s", err.Error()) + return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) + } + + clientTimezone, err := c.GetClientTimezone() + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot get client timezone, because %s", err.Error()) + return nil, errs.ErrClientTimezoneOffsetInvalid + } + + transactionIds, err := utils.StringArrayToInt64Array(transactionBatchUpdateReq.TransactionIds) + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] parse transaction ids failed, because %s", err.Error()) + return nil, errs.ErrTransactionIdInvalid + } + + uid := c.GetCurrentUid() + user, err := a.users.GetUserById(c, uid) + + if err != nil { + if !errs.IsCustomError(err) { + log.Errorf(c, "[transactions.TransactionBatchUpdateAccountsHandler] failed to get user, because %s", err.Error()) + } + + return nil, errs.ErrUserNotFound + } + + allAccounts, err := a.accounts.GetAllAccountsByUid(c, uid) + + if err != nil { + log.Errorf(c, "[transactions.TransactionBatchUpdateAccountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + accountMap := a.accounts.GetAccountMapByList(allAccounts) + account, exists := accountMap[transactionBatchUpdateReq.AccountId] + + if !exists || account == nil { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] account \"id:%d\" does not exist for user \"uid:%d\"", transactionBatchUpdateReq.AccountId, uid) + return nil, errs.ErrAccountNotFound + } + + if account.Hidden { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] account \"id:%d\" is hidden for user \"uid:%d\"", account.AccountId, uid) + return nil, errs.ErrCannotMoveTransactionFromOrToHiddenAccount + } + + if account.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] account \"id:%d\" is a parent account, cannot be used for transaction of user \"uid:%d\"", account.AccountId, uid) + return nil, errs.ErrCannotModifyTransactionInParentAccount + } + + transactions, err := a.transactions.GetTransactionsByTransactionIds(c, uid, transactionIds) + + if err != nil { + log.Errorf(c, "[transactions.TransactionBatchUpdateAccountsHandler] failed to get transactions for user \"uid:%d\", because %s", uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + for i := 0; i < len(transactions); i++ { + transaction := transactions[i] + + if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot modify transaction \"id:%d\" for user \"uid:%d\", because transaction type is transfer in", transaction.TransactionId, uid) + return nil, errs.ErrTransactionTypeInvalid + } + + if transactionBatchUpdateReq.IsDestinationAccount && transaction.Type != models.TRANSACTION_DB_TYPE_TRANSFER_OUT { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot update destination account of non-transfer transaction \"id:%d\" for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrTransactionDestinationAccountCannotBeSet + } + + if !transactionBatchUpdateReq.IsDestinationAccount && account.AccountId == transaction.RelatedAccountId { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot update account to same destination account of transaction \"id:%d\" for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrTransactionSourceAndDestinationIdCannotBeEqual + } else if transactionBatchUpdateReq.IsDestinationAccount && account.AccountId == transaction.AccountId { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot update destination account to same source account of transaction \"id:%d\" for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrTransactionSourceAndDestinationIdCannotBeEqual + } + + var oldAccount *models.Account + + if !transactionBatchUpdateReq.IsDestinationAccount { + oldAccount = accountMap[transaction.AccountId] + } else if transactionBatchUpdateReq.IsDestinationAccount { + oldAccount = accountMap[transaction.RelatedAccountId] + } + + if oldAccount == nil { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] the original account of transaction \"id:%d\" does not exist for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrAccountNotFound + } + + if oldAccount.Hidden { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] the original account of transaction \"id:%d\" is hidden for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrCannotMoveTransactionFromOrToHiddenAccount + } + + if oldAccount.Currency != account.Currency { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] cannot update account of transaction \"id:%d\", because the original account currency \"%s\" is different from updated account currency \"%s\" for user \"uid:%d\"", transaction.TransactionId, oldAccount.Currency, account.Currency, uid) + return nil, errs.ErrCannotMoveTransactionBetweenAccountsWithDifferentCurrencies + } + + transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone) + + if !transactionEditable { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] transaction \"id:%d\" is not editable for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime + } + } + + updatedCount := 0 + + for i := 0; i < len(transactions); i++ { + transaction := transactions[i] + + if !transactionBatchUpdateReq.IsDestinationAccount && transaction.AccountId != account.AccountId { + transaction.AccountId = account.AccountId + } else if transactionBatchUpdateReq.IsDestinationAccount && transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT && transaction.RelatedAccountId != account.AccountId { + transaction.RelatedAccountId = account.AccountId + } else { + log.Warnf(c, "[transactions.TransactionBatchUpdateAccountsHandler] skip updating transaction \"id:%d\", because the original account is same as updated account for user \"uid:%d\"", transaction.TransactionId, uid) + continue + } + + err = a.transactions.ModifyTransaction(c, transaction, 0, nil, nil, nil, nil) + + if err != nil { + log.Errorf(c, "[transactions.TransactionBatchUpdateAccountsHandler] failed to update transaction \"id:%d\" for user \"uid:%d\", because %s", transaction.TransactionId, uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + updatedCount++ + } + + if updatedCount < 1 { + return nil, errs.ErrNothingWillBeUpdated + } + + log.Infof(c, "[transactions.TransactionBatchUpdateAccountsHandler] user \"uid:%d\" has batch updated account of %d transactions successfully", uid, updatedCount) + return true, nil +} + // TransactionMoveAllBetweenAccountsHandler moves all transactions from one account to another account for current user func (a *TransactionsApi) TransactionMoveAllBetweenAccountsHandler(c *core.WebContext) (any, *errs.Error) { var transactionMoveReq models.TransactionMoveBetweenAccountsRequest diff --git a/pkg/models/transaction.go b/pkg/models/transaction.go index 7085af90..fc1ca3b6 100644 --- a/pkg/models/transaction.go +++ b/pkg/models/transaction.go @@ -331,6 +331,13 @@ type TransactionBatchUpdateCategoryRequest struct { CategoryId int64 `json:"categoryId,string" binding:"required"` } +// TransactionBatchUpdateAccountRequest represents all parameters of transaction batch update account request +type TransactionBatchUpdateAccountRequest struct { + TransactionIds []string `json:"transactionIds,string" binding:"required"` + AccountId int64 `json:"accountId,string" binding:"required"` + IsDestinationAccount bool `json:"isDestinationAccount"` +} + // TransactionMoveBetweenAccountsRequest represents all parameters of moving all transactions between accounts request type TransactionMoveBetweenAccountsRequest struct { FromAccountId int64 `json:"fromAccountId,string" binding:"required,min=1"` diff --git a/src/lib/services.ts b/src/lib/services.ts index 6ed3fd8f..4462052c 100644 --- a/src/lib/services.ts +++ b/src/lib/services.ts @@ -66,6 +66,7 @@ import type { TransactionCreateRequest, TransactionModifyRequest, TransactionBatchUpdateCategoryRequest, + TransactionBatchUpdateAccountRequest, TransactionMoveBetweenAccountsRequest, TransactionDeleteRequest, TransactionBatchDeleteRequest, @@ -619,6 +620,11 @@ export default { timeout: DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT } as ApiRequestConfig); }, + batchUpdateTransactionAccounts: (req: TransactionBatchUpdateAccountRequest): ApiResponsePromise => { + return axios.post>('v1/transactions/batch_update/account.json', req, { + timeout: DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT + } as ApiRequestConfig); + }, moveAllTransactionsBetweenAccounts: (req: TransactionMoveBetweenAccountsRequest): ApiResponsePromise => { return axios.post>('v1/transactions/move/all.json', req); }, diff --git a/src/locales/de.json b/src/locales/de.json index 92f542a5..19d7fec4 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Kontoliste", diff --git a/src/locales/en.json b/src/locales/en.json index 4a7a8c09..143c9255 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Account List", diff --git a/src/locales/es.json b/src/locales/es.json index 3dfe79d8..8b49c1f5 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Lista de Cuentas", diff --git a/src/locales/fr.json b/src/locales/fr.json index 81024080..ad1b25fc 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Liste des comptes", diff --git a/src/locales/it.json b/src/locales/it.json index 3b78afa5..9a01c88b 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Elenco account", diff --git a/src/locales/ja.json b/src/locales/ja.json index 0dfa1eaf..7d9334ef 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "口座リスト", diff --git a/src/locales/kn.json b/src/locales/kn.json index 4690b6c7..16312d09 100644 --- a/src/locales/kn.json +++ b/src/locales/kn.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "ಖಾತೆಗಳ ಪಟ್ಟಿ", diff --git a/src/locales/ko.json b/src/locales/ko.json index 5f99a481..99c304de 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "계좌 목록", diff --git a/src/locales/nl.json b/src/locales/nl.json index da80aa8c..b834bcd9 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Rekeningenlijst", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index 08a32720..e49b9c7f 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Lista de Contas", diff --git a/src/locales/ru.json b/src/locales/ru.json index cdc9ac5a..94e24754 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Список счетов", diff --git a/src/locales/sl.json b/src/locales/sl.json index e83385dd..cfddf552 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Seznam računov", diff --git a/src/locales/ta.json b/src/locales/ta.json index 834da1af..d404ab79 100644 --- a/src/locales/ta.json +++ b/src/locales/ta.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "கணக்குகளின் பட்டியல்", diff --git a/src/locales/th.json b/src/locales/th.json index cceaf788..71916bdc 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "รายการบัญชี", diff --git a/src/locales/tr.json b/src/locales/tr.json index f1b844ff..6cfca038 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Hesap Listesi", diff --git a/src/locales/uk.json b/src/locales/uk.json index 386f33ad..36a82c32 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Список рахунків", diff --git a/src/locales/vi.json b/src/locales/vi.json index f8b04b5e..1a56cd44 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "Update Categories for Income Transactions", "Update Categories for Transfer Transactions": "Update Categories for Transfer Transactions", "Unable to update categories for transactions": "Unable to update categories for transactions", + "Update Accounts for Transactions": "Update Accounts for Transactions", + "Update Destination Accounts for Transactions": "Update Destination Accounts for Transactions", + "Unable to update accounts for transactions": "Unable to update accounts for transactions", "Delete Transactions": "Delete Transactions", "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Danh sách tài khoản", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 84fb2246..8f83bec0 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "更新收入交易的分类", "Update Categories for Transfer Transactions": "更新转账交易的分类", "Unable to update categories for transactions": "无法更新交易的分类", + "Update Accounts for Transactions": "更新交易的账户", + "Update Destination Accounts for Transactions": "更新交易的目标账户", + "Unable to update accounts for transactions": "无法更新交易的账户", "Delete Transactions": "删除交易", "Unable to delete these transactions": "无法删除这些交易", "Account List": "账户列表", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 18f4d65a..f8b5f71b 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1853,6 +1853,9 @@ "Update Categories for Income Transactions": "更新收入交易的分類", "Update Categories for Transfer Transactions": "更新轉帳交易的分類", "Unable to update categories for transactions": "無法更新交易的分類", + "Update Accounts for Transactions": "更新交易的帳戶", + "Update Destination Accounts for Transactions": "更新交易的目標帳戶", + "Unable to update accounts for transactions": "無法更新交易的帳戶", "Delete Transactions": "刪除交易", "Unable to delete these transactions": "無法刪除這些交易", "Account List": "帳戶清單", diff --git a/src/models/transaction.ts b/src/models/transaction.ts index 27ac8fc3..a21d49eb 100644 --- a/src/models/transaction.ts +++ b/src/models/transaction.ts @@ -563,6 +563,12 @@ export interface TransactionBatchUpdateCategoryRequest { readonly categoryId: string; } +export interface TransactionBatchUpdateAccountRequest { + readonly transactionIds: string[]; + readonly accountId: string; + readonly isDestinationAccount: boolean; +} + export interface TransactionMoveBetweenAccountsRequest { readonly fromAccountId: string; readonly toAccountId: string; diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index 1bf885a1..4109a3a9 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -1164,6 +1164,40 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } + function batchUpdateTransactionAccounts({ transactionIds, accountId, isDestinationAccount }: { transactionIds: string[], accountId: string, isDestinationAccount: boolean }): Promise { + return new Promise((resolve, reject) => { + services.batchUpdateTransactionAccounts({ transactionIds, accountId, isDestinationAccount }).then(response => { + const data = response.data; + + if (!data || !data.success || !data.result) { + reject({ message: 'Unable to update accounts for transactions' }); + return; + } + + updateStoreInvalidState({ + transactionList: true, + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); + + resolve(data.result); + }).catch(error => { + logger.error('failed to update accounts for transactions', error); + + if (error.response && error.response.data && error.response.data.errorMessage) { + reject({ error: error.response.data }); + } else if (!error.processed) { + reject({ message: 'Unable to update accounts for transactions' }); + } else { + reject(error); + } + }); + }); + } + function moveAllTransactionsBetweenAccounts({ fromAccountId, toAccountId }: { fromAccountId: string, toAccountId: string }): Promise { return new Promise((resolve, reject) => { services.moveAllTransactionsBetweenAccounts({ fromAccountId, toAccountId }).then(response => { @@ -1539,6 +1573,7 @@ export const useTransactionsStore = defineStore('transactions', () => { getTransaction, saveTransaction, batchUpdateTransactionCategories, + batchUpdateTransactionAccounts, moveAllTransactionsBetweenAccounts, deleteTransaction, batchDeleteTransactions, diff --git a/src/views/desktop/insights/dialogs/BatchUpdateAccountDialog.vue b/src/views/desktop/insights/dialogs/BatchUpdateAccountDialog.vue new file mode 100644 index 00000000..16e7913d --- /dev/null +++ b/src/views/desktop/insights/dialogs/BatchUpdateAccountDialog.vue @@ -0,0 +1,166 @@ + + + diff --git a/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue b/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue index 99d92948..3b73ccdb 100644 --- a/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue +++ b/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue @@ -91,6 +91,15 @@ :disabled="!isAllSelectedTransactionsTransfer" @click="batchUpdateTransactionCategories(CategoryType.Transfer)"> + + + + @@ -188,6 +198,7 @@ import SnackBar from '@/components/desktop/SnackBar.vue'; import PaginationButtons from '@/components/desktop/PaginationButtons.vue'; import BatchUpdateCategoryDialog from '@/views/desktop/insights/dialogs/BatchUpdateCategoryDialog.vue'; +import BatchUpdateAccountDialog from '@/views/desktop/insights/dialogs/BatchUpdateAccountDialog.vue'; import BatchDeleteDialog from '@/views/desktop/insights/dialogs/BatchDeleteDialog.vue'; import { ref, computed, useTemplateRef, watch } from 'vue'; @@ -216,6 +227,7 @@ import { type SnackBarType = InstanceType; type BatchUpdateCategoryDialogType = InstanceType; +type BatchUpdateAccountDialogType = InstanceType; type BatchDeleteDialogType = InstanceType; interface InsightsExplorerDataTableTabProps { @@ -232,6 +244,7 @@ const emit = defineEmits<{ const snackbar = useTemplateRef('snackbar'); const batchUpdateCategoryDialog = useTemplateRef('batchUpdateCategoryDialog'); +const batchUpdateAccountDialog = useTemplateRef('batchUpdateAccountDialog'); const batchDeleteDialog = useTemplateRef('batchDeleteDialog'); const { @@ -333,6 +346,25 @@ function batchUpdateTransactionCategories(type: CategoryType): void { }); } +function batchUpdateTransactionAccounts(isDestinationAccount: boolean): void { + batchUpdateAccountDialog.value?.open({ + isDestinationAccount: isDestinationAccount, + updateIds: getAllSelectedTransactionIds() + }).then(updatedCount => { + if (updatedCount > 0) { + snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', { + count: formatNumberToLocalizedNumerals(updatedCount) + }); + } + selectedTransactions.value = {}; + emit('update:transactions'); + }).catch(error => { + if (error) { + snackbar.value?.showError(error); + } + }); +} + function batchDeleteTransactions(): void { batchDeleteDialog.value?.open({ updateIds: getAllSelectedTransactionIds()