diff --git a/cmd/webserver.go b/cmd/webserver.go index b95249a7..9fd852c3 100644 --- a/cmd/webserver.go +++ b/cmd/webserver.go @@ -396,6 +396,7 @@ func startWebServer(c *core.CliContext) error { apiV1Route.POST("/transactions/batch_update/category.json", bindApi(api.Transactions.TransactionBatchUpdateCategoriesHandler)) 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)) if config.EnableDataImport { apiV1Route.POST("/transactions/parse_custom_file.json", bindApi(api.Transactions.TransactionParseImportCustomFileDataHandler)) diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index b2251a71..ed2d05c0 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -1551,6 +1551,80 @@ func (a *TransactionsApi) TransactionDeleteHandler(c *core.WebContext) (any, *er return true, nil } +// TransactionBatchDeleteHandler deletes existed transactions by request parameters for current user +func (a *TransactionsApi) TransactionBatchDeleteHandler(c *core.WebContext) (any, *errs.Error) { + var transactionBatchDeleteReq models.TransactionBatchDeleteRequest + err := c.ShouldBindJSON(&transactionBatchDeleteReq) + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchDeleteHandler] parse request failed, because %s", err.Error()) + return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) + } + + clientTimezone, err := c.GetClientTimezone() + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchDeleteHandler] cannot get client timezone, because %s", err.Error()) + return nil, errs.ErrClientTimezoneOffsetInvalid + } + + transactionIds, err := utils.StringArrayToInt64Array(transactionBatchDeleteReq.Ids) + + if err != nil { + log.Warnf(c, "[transactions.TransactionBatchDeleteHandler] 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.TransactionBatchDeleteHandler] failed to get user, because %s", err.Error()) + } + + return nil, errs.ErrUserNotFound + } + + if !a.users.IsPasswordEqualsUserPassword(transactionBatchDeleteReq.Password, user) { + return nil, errs.ErrUserPasswordWrong + } + + transactions, err := a.transactions.GetTransactionsByTransactionIds(c, uid, transactionIds) + + if err != nil { + log.Errorf(c, "[transactions.TransactionBatchDeleteHandler] 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] + transactionEditable := user.CanEditTransactionByTransactionTime(transaction.TransactionTime, clientTimezone) + + if !transactionEditable { + log.Warnf(c, "[transactions.TransactionBatchUpdateCategoriesHandler] transaction \"id:%d\" is not editable for user \"uid:%d\"", transaction.TransactionId, uid) + return nil, errs.ErrCannotModifyTransactionWithThisTransactionTime + } + } + + deletedCount := 0 + + for i := 0; i < len(transactions); i++ { + transaction := transactions[i] + err = a.transactions.DeleteTransaction(c, uid, transaction.TransactionId) + + if err != nil { + log.Errorf(c, "[transactions.TransactionBatchDeleteHandler] failed to delete transaction \"id:%d\" for user \"uid:%d\", because %s", transaction.TransactionId, uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + deletedCount++ + } + + log.Infof(c, "[transactions.TransactionBatchDeleteHandler] user \"uid:%d\" has deleted %d transactions", uid, deletedCount) + return true, nil +} + // TransactionParseImportCustomFileDataHandler returns the parsed file data by request parameters for current user func (a *TransactionsApi) TransactionParseImportCustomFileDataHandler(c *core.WebContext) (any, *errs.Error) { uid := c.GetCurrentUid() diff --git a/pkg/models/transaction.go b/pkg/models/transaction.go index 83d9858d..7085af90 100644 --- a/pkg/models/transaction.go +++ b/pkg/models/transaction.go @@ -342,6 +342,12 @@ type TransactionDeleteRequest struct { Id int64 `json:"id,string" binding:"required,min=1"` } +// TransactionBatchDeleteRequest represents all parameters of transaction batch deleting request +type TransactionBatchDeleteRequest struct { + Ids []string `json:"ids,string" binding:"required"` + Password string `json:"password" binding:"omitempty,min=6,max=128"` +} + // YearMonthRangeRequest represents all parameters of a request with year and month range type YearMonthRangeRequest struct { StartYearMonth string `form:"start_year_month"` diff --git a/src/consts/api.ts b/src/consts/api.ts index 506d315b..8c04f277 100644 --- a/src/consts/api.ts +++ b/src/consts/api.ts @@ -7,6 +7,7 @@ export const DEFAULT_API_TIMEOUT: number = 10000; // 10s export const DEFAULT_UPLOAD_API_TIMEOUT: number = 30000; // 30s export const DEFAULT_EXPORT_API_TIMEOUT: number = 180000; // 180s export const DEFAULT_IMPORT_API_TIMEOUT: number = 1800000; // 1800s +export const DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT: number = 1800000; // 1800s export const DEFAULT_CLEAR_ALL_TRANSACTIONS_API_TIMEOUT: number = 1800000; // 1800s export const DEFAULT_LLM_API_TIMEOUT: number = 600000; // 600s diff --git a/src/lib/services.ts b/src/lib/services.ts index d3469855..6ed3fd8f 100644 --- a/src/lib/services.ts +++ b/src/lib/services.ts @@ -24,6 +24,7 @@ import { DEFAULT_UPLOAD_API_TIMEOUT, DEFAULT_EXPORT_API_TIMEOUT, DEFAULT_IMPORT_API_TIMEOUT, + DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT, DEFAULT_CLEAR_ALL_TRANSACTIONS_API_TIMEOUT, DEFAULT_LLM_API_TIMEOUT, GOOGLE_MAP_JAVASCRIPT_URL, @@ -67,6 +68,7 @@ import type { TransactionBatchUpdateCategoryRequest, TransactionMoveBetweenAccountsRequest, TransactionDeleteRequest, + TransactionBatchDeleteRequest, TransactionImportRequest, TransactionListByMaxTimeRequest, TransactionListInMonthByPageRequest, @@ -613,7 +615,9 @@ export default { return axios.post>('v1/transactions/modify.json', req); }, batchUpdateTransactionCategories: (req: TransactionBatchUpdateCategoryRequest): ApiResponsePromise => { - return axios.post>('v1/transactions/batch_update/category.json', req); + return axios.post>('v1/transactions/batch_update/category.json', req, { + timeout: DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT + } as ApiRequestConfig); }, moveAllTransactionsBetweenAccounts: (req: TransactionMoveBetweenAccountsRequest): ApiResponsePromise => { return axios.post>('v1/transactions/move/all.json', req); @@ -621,6 +625,11 @@ export default { deleteTransaction: (req: TransactionDeleteRequest): ApiResponsePromise => { return axios.post>('v1/transactions/delete.json', req); }, + batchDeleteTransaction: (req: TransactionBatchDeleteRequest): ApiResponsePromise => { + return axios.post>('v1/transactions/batch_delete.json', req, { + timeout: DEFAULT_BATCH_UPDATE_TRANSACTIONS_API_TIMEOUT + } as ApiRequestConfig); + }, parseImportCustomFile: ({ fileType, fileEncoding, importFile }: { fileType: string, fileEncoding?: string, importFile: File }): ApiResponsePromise => { return axios.postForm>('v1/transactions/parse_custom_file.json', { fileType: fileType, diff --git a/src/locales/de.json b/src/locales/de.json index b926da04..92f542a5 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -134,11 +134,13 @@ "selectedCount": "{count} von {totalCount} ausgewählt", "queryIndex": "Abfrage #{index}", "youHaveUpdatedTransactions": "Sie haben {count} Transaktionen aktualisiert", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Sind Sie sicher, dass Sie {count} Transaktionen importieren möchten?", "importingTransactions": "Importiere ({process}%)", "importTransactionResult": "Sie haben {count} Transaktionen erfolgreich importiert.", "moveTransactionsInAccountTip": "Diese Aktion kann NICHT rückgängig gemacht werden. Alle Transaktionen werden von {fromAccount} nach {toAccount} verschoben.", "clearTransactionsInAccountTip": "Diese Aktion kann NICHT rückgängig gemacht werden. Ihre Transaktionsdaten in {account} werden gelöscht. Bitte geben Sie Ihr aktuelles Passwort zur Bestätigung ein.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Ein Aktivierungslink wurde an Ihre E-Mail-Adresse gesendet: {email}. Wenn Sie die E-Mail nicht erhalten haben, geben Sie bitte das Passwort erneut ein und klicken Sie auf die Schaltfläche unten, um die Bestätigungs-E-Mail erneut zu senden.", "resendValidationEmailTip": "Wenn Sie die E-Mail nicht erhalten haben, geben Sie bitte das Passwort erneut ein und klicken Sie auf die Schaltfläche unten, um die Bestätigungs-E-Mail an: {email} erneut zu senden.", "oauth2bindTip": "Sie melden sich beim Benutzer {userName} mit {providerName} an. Bitte geben Sie Ihr ezBookkeeping-Passwort zur Bestätigung ein." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Kontoliste", "This Week": "Diese Woche", "This Month": "Dieser Monat", diff --git a/src/locales/en.json b/src/locales/en.json index 8175784a..4a7a8c09 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -134,11 +134,13 @@ "selectedCount": "Selected {count} of {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "You have updated {count} transactions", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Are you sure you want to import {count} transactions?", "importingTransactions": "Importing ({process}%)", "importTransactionResult": "You have imported {count} transactions successfully.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Account activation link has been sent to your email address: {email}, If you don't receive the mail, please fill password again and click the button below to resend the validation mail.", "resendValidationEmailTip": "If you don't receive the mail, please fill password again and click the button below to resend the validation mail to: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Account List", "This Week": "This Week", "This Month": "This Month", diff --git a/src/locales/es.json b/src/locales/es.json index 7d741e3a..3dfe79d8 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -134,11 +134,13 @@ "selectedCount": "Seleccionado {count} de {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Has actualizado {count} transacciones", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "¿Seguro que deseas importar {count} transacciones?", "importingTransactions": "Importando ({process}%)", "importTransactionResult": "Has importado {count} transacciones correctamente.", "moveTransactionsInAccountTip": "NO PUEDES deshacer esta acción. Se moverán todas las transacciones de {fromAccount} a {toAccount}.", "clearTransactionsInAccountTip": "NO PUEDES deshacer esta acción. Se eliminarán todas las transacciones de {account}. Por favor introduce tu contraseña para confirmar.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "El enlace de activación de la cuenta se envió a tu dirección de correo electrónico: {email}. Si no recibes el correo, introduce nuevamente la contraseña y haz clic en el botón de abajo para reenviar el correo de validación.", "resendValidationEmailTip": "Si no recibes el correo, introduce nuevamente la contraseña y haz clic en el botón de abajo para reenviar el correo de validación a: {email}", "oauth2bindTip": "Estás iniciando sesión con el usuario {userName} usando {providerName}. Porfavor introduce tu contraseña de ezBookkeeping para verificar." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Lista de Cuentas", "This Week": "Esta Semana", "This Month": "Este Mes", diff --git a/src/locales/fr.json b/src/locales/fr.json index b7f2e228..81024080 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -134,11 +134,13 @@ "selectedCount": "Sélectionné {count} sur {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Vous avez mis à jour {count} transactions", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Êtes-vous sûr de vouloir importer {count} transactions ?", "importingTransactions": "Importation ({process}%)", "importTransactionResult": "Vous avez importé {count} transactions avec succès.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Le lien d'activation du compte a été envoyé à votre adresse e-mail : {email}, Si vous ne recevez pas le mail, veuillez remplir à nouveau le mot de passe et cliquer sur le bouton ci-dessous pour renvoyer l'e-mail de validation.", "resendValidationEmailTip": "Si vous ne recevez pas le mail, veuillez remplir à nouveau le mot de passe et cliquer sur le bouton ci-dessous pour renvoyer l'e-mail de validation à : {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Liste des comptes", "This Week": "Cette semaine", "This Month": "Ce mois", diff --git a/src/locales/it.json b/src/locales/it.json index 4ece99f5..3b78afa5 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -134,11 +134,13 @@ "selectedCount": "{count} selezionati su {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Hai aggiornato {count} transazioni", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Sei sicuro di voler importare {count} transazioni?", "importingTransactions": "Importing ({process}%)", "importTransactionResult": "Hai importato {count} transazioni.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Abbiamo inviato un link per l'attivazione del tuo account all'indirizzo {email}. Se non hai ricevuto la mail, inserisci nuovamente la password e premi il bottone per ritentare l'invio.", "resendValidationEmailTip": "Se non hai ricevuto la mail, inserisci nuovamente la password e premi il bottone per ritentare l'invio all'indirizzo: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Elenco account", "This Week": "Questa settimana", "This Month": "Questo mese", diff --git a/src/locales/ja.json b/src/locales/ja.json index d61ceb72..0dfa1eaf 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -134,11 +134,13 @@ "selectedCount": "{count} / {totalCount}を選択", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "{count}件の取引を更新しました", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "本当に{count}件の取引をインポートしますか?", "importingTransactions": "Importing ({process}%)", "importTransactionResult": "{count}件の取引を正常にインポートしました。", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "アカウントの有効化リンクがメールアドレスに送信されました:{email}、メールが届かない場合はパスワードをもう一度入力して下のボタンをクリックして認証メールを再送信してください。", "resendValidationEmailTip": "メールが届かない場合は、パスワードをもう一度入力の上、以下のボタンをクリックして検証メールを再送信してください: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "口座リスト", "This Week": "今週", "This Month": "今月", diff --git a/src/locales/kn.json b/src/locales/kn.json index dcf2615f..4690b6c7 100644 --- a/src/locales/kn.json +++ b/src/locales/kn.json @@ -134,11 +134,13 @@ "selectedCount": "{totalCount}ರಲ್ಲಿ {count} ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "ನೀವು {count} ವಹಿವಾಟುಗಳನ್ನು ನವೀಕರಿಸಿದ್ದೀರಿ", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "ನೀವು {count} ವಹಿವಾಟುಗಳನ್ನು ಆಮದು ಮಾಡಲು ಖಚಿತವಾಗಿದ್ದೀರಾ?", "importingTransactions": "ಆಮದು ಮಾಡಲಾಗುತ್ತಿದೆ ({process}%)", "importTransactionResult": "ನೀವು ಯಶಸ್ವಿಯಾಗಿ {count} ವಹಿವಾಟುಗಳನ್ನು ಆಮದು ಮಾಡಿದ್ದೀರಿ.", "moveTransactionsInAccountTip": "ಈ ಕ್ರಿಯೆಯನ್ನು ಹಿಂದಕ್ಕೆ ತರಲು ಸಾಧ್ಯವಿಲ್ಲ. ಇದು {fromAccount} ನ ಎಲ್ಲಾ ವಹಿವಾಟುಗಳನ್ನು {toAccount} ಗೆ ಸ್ಥಳಾಂತರಿಸುತ್ತದೆ.", "clearTransactionsInAccountTip": "ಈ ಕ್ರಿಯೆಯನ್ನು ಹಿಂದಕ್ಕೆ ತರಲು ಸಾಧ್ಯವಿಲ್ಲ. ಇದು {account} ನಲ್ಲಿ ನಿಮ್ಮ ಎಲ್ಲಾ ವಹಿವಾಟುಗಳನ್ನು ಅಳಿಸುತ್ತದೆ. ದೃಢೀಕರಿಸಲು ದಯವಿಟ್ಟು ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "ಖಾತೆ ಸಕ್ರಿಯಗೊಳಿಸುವ ಲಿಂಕ್ ಅನ್ನು ನಿಮ್ಮ ಈಮೇಲ್‌ಗೆ ಕಳುಹಿಸಲಾಗಿದೆ: {email}. ನೀವು ಇಮೇಲ್ ಪಡೆಯದಿದ್ದರೆ, ದಯವಿಟ್ಟು ಪಾಸ್‌ವರ್ಡ್ ಮರು ನಮೂದಿಸಿ ಮತ್ತು ಕೆಳಗಿನ ಬಟನ್ ಒತ್ತಿ ಸರೀಕರಿಸುವ ಇಮೇಲ್ ಮರು ಕಳುಹಿಸಿ.", "resendValidationEmailTip": "ನೀವು ಇಮೇಲ್ ಪಡೆಯದಿದ್ದರೆ, ದಯವಿಟ್ಟು ಪಾಸ್‌ವರ್ಡ್ ಮರು ನಮೂದಿಸಿ ಮತ್ತು ಕೆಳಗಿನ ಬಟನ್ ಒತ್ತಿ ಮರು ಸರೀಕರಿಸುವ ಇಮೇಲ್ ಕಳುಹಿಸಲಾಗುವುದು: {email}", "oauth2bindTip": "ನೀವು {providerName} ಬಳಸಿ {userName} ಬಳಕೆದಾರರಾಗಿ ಲಾಗಿನ್ ಆಗುತ್ತಿದ್ದೀರಿ. ದೃಢೀಕರಿಸಲು ದಯವಿಟ್ಟು ನಿಮ್ಮ ezBookkeeping ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "ಖಾತೆಗಳ ಪಟ್ಟಿ", "This Week": "ಈ ವಾರ", "This Month": "ಈ ತಿಂಗಳು", diff --git a/src/locales/ko.json b/src/locales/ko.json index c897a40d..5f99a481 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -134,11 +134,13 @@ "selectedCount": "{count}개 중 {totalCount}개 선택됨", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "{count}개의 거래가 업데이트되었습니다.", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "{count}개의 거래를 가져오시겠습니까?", "importingTransactions": "가져오는 중 ({process}%)", "importTransactionResult": "성공적으로 {count}개의 거래를 가져왔습니다.", "moveTransactionsInAccountTip": "이 작업은 되돌릴 수 없습니다. {fromAccount}에서 {toAccount}로 모든 거래를 이동합니다.", "clearTransactionsInAccountTip": "이 작업은 되돌릴 수 없습니다. {account}의 거래 데이터를 지웁니다. 계속하시려면 현재 비밀번호를 입력하세요.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "계정 활성화 링크가 귀하의 이메일 주소({email})로 전송되었습니다. 메일을 받지 못하신 경우, 비밀번호를 다시 입력하고 아래 버튼을 클릭하여 확인 메일을 재전송하십시오.", "resendValidationEmailTip": "메일을 받지 못하신 경우, 비밀번호를 다시 입력하고 아래 버튼을 클릭하여 확인 메일을 {email}로 재전송하십시오.", "oauth2bindTip": "{providerName}를 사용하여 {userName} 사용자로 로그인하고 있습니다. 확인을 위해 ezBookkeeping 비밀번호를 입력하세요." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "계좌 목록", "This Week": "이번 주", "This Month": "이번 달", diff --git a/src/locales/nl.json b/src/locales/nl.json index af302a06..da80aa8c 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -134,11 +134,13 @@ "selectedCount": "{count} van {totalCount} geselecteerd", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Je hebt {count} transacties bijgewerkt", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Weet je zeker dat je {count} transacties wilt importeren?", "importingTransactions": "Bezig met importeren ({process}%)", "importTransactionResult": "Je hebt {count} transacties succesvol geïmporteerd.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Een activatielink is verzonden naar je e-mailadres: {email}. Als je de e-mail niet ontvangt, vul dan je wachtwoord opnieuw in en klik op de knop hieronder om de validatiemail opnieuw te verzenden.", "resendValidationEmailTip": "Als je de e-mail niet ontvangt, vul dan je wachtwoord opnieuw in en klik op de knop hieronder om de validatiemail opnieuw te verzenden naar: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Rekeningenlijst", "This Week": "Deze week", "This Month": "Deze maand", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index 3039a469..08a32720 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -134,11 +134,13 @@ "selectedCount": "{count} de {totalCount} selecionados", "queryIndex": "Consulta #{index}", "youHaveUpdatedTransactions": "Você atualizou {count} transações", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Tem certeza de que deseja importar {count} transações?", "importingTransactions": "Importando ({process}%)", "importTransactionResult": "Você importou {count} transações com sucesso.", "moveTransactionsInAccountTip": "Você NÃO PODE desfazer esta ação. Isso moverá todas as transações de {fromAccount} para {toAccount}.", "clearTransactionsInAccountTip": "Você NÃO PODE desfazer esta ação. Isso apagará todas as transações em {account}. Por favor, insira sua senha atual para confirmar.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "O link de ativação da conta foi enviado para seu endereço de e-mail: {email}. Se você não receber o e-mail, por favor, insira a senha novamente e clique no botão abaixo para reenviar o e-mail de validação.", "resendValidationEmailTip": "Se você não receber o e-mail, por favor, insira a senha novamente e clique no botão abaixo para reenviar o e-mail de validação para: {email}", "oauth2bindTip": "Você está fazendo login como {userName} usando {providerName}. Por favor, insira sua senha do ezBookkeeping para verificar." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Lista de Contas", "This Week": "Esta Semana", "This Month": "Este Mês", diff --git a/src/locales/ru.json b/src/locales/ru.json index 7bb7154f..cdc9ac5a 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -134,11 +134,13 @@ "selectedCount": "Выбрано {count} из {totalCount}", "queryIndex": "Запрос #{index}", "youHaveUpdatedTransactions": "Вы обновили {count} транзакций", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Вы уверены, что хотите импортировать {count} транзакций?", "importingTransactions": "Импортирование ({process}%)", "importTransactionResult": "Вы успешно импортировали {count} транзакций.", "moveTransactionsInAccountTip": "Вы НЕ сможете отменить это действие. Все транзакции будут перемещены с {fromAccount} на {toAccount}.", "clearTransactionsInAccountTip": "Вы НЕ сможете отменить это действие. Все транзакции будут отчищеы с {account}. Пожалуйста введите пароль.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Ссылка для активации учетной записи была отправлена на ваш электронный адрес: {email}. Если вы не получили письмо, заполните пароль снова и нажмите кнопку ниже, чтобы отправить письмо повторно.", "resendValidationEmailTip": "Если вы не получили письмо, заполните пароль снова и нажмите кнопку ниже, чтобы отправить письмо повторно на: {email}", "oauth2bindTip": "Вы входите как пользователь {userName} используя {providerName}. Пожалуйста введите ваш ezBookkeeping пароль для подтверждения." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Список счетов", "This Week": "На этой неделе", "This Month": "В этом месяце", diff --git a/src/locales/sl.json b/src/locales/sl.json index 0a210121..e83385dd 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -134,11 +134,13 @@ "selectedCount": "Izbranih {count} od {totalCount}", "queryIndex": "Poizvedba #{index}", "youHaveUpdatedTransactions": "Posodobili ste {count} transakcij", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Ali ste prepričani, da želite uvoziti {count} transakcij?", "importingTransactions": "Uvažam ({process}%)", "importTransactionResult": "Uspešno ste uvozili {count} transakcij.", "moveTransactionsInAccountTip": "Tega dejanja NE MORETE razveljaviti. S tem boste vse transakcije premaknili iz računa {fromAccount} v račun {toAccount}.", "clearTransactionsInAccountTip": "Tega dejanja NE MORETE razveljaviti. S tem boste izbrisali podatke o transakcijah v računu {account}. Za potrditev vnesite trenutno geslo.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Povezava za aktivacijo računa je bila poslana na vaš e-poštni naslov: {email}. Če e-pošte ne prejmete, ponovno vnesite geslo in kliknite spodnji gumb, da ponovno pošljete potrditveno e-pošto.", "resendValidationEmailTip": "Če ne prejmete e-pošte, ponovno vnesite geslo in kliknite spodnji gumb, da ponovno pošljete potrditveno e-pošto na: {email}", "oauth2bindTip": "Prijavljate se v uporabniški račun {userName} z uporabo računa {providerName}. Za potrditev vnesite svoje geslo za ezBookkeeping." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Seznam računov", "This Week": "Ta teden", "This Month": "Ta mesec", diff --git a/src/locales/ta.json b/src/locales/ta.json index 604779cd..834da1af 100644 --- a/src/locales/ta.json +++ b/src/locales/ta.json @@ -134,11 +134,13 @@ "selectedCount": "{totalCount} இல் {count} தேர்ந்தெடுக்கப்பட்டது", "queryIndex": "வினவல் #{index}", "youHaveUpdatedTransactions": "நீங்கள் {count} பரிவர்த்தனைகளை புதுப்பித்துள்ளீர்கள்", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "நீங்கள் {count} பரிவர்த்தனைகளை இறக்குமதி செய்ய விரும்புகிறீர்களா?", "importingTransactions": "இறக்குமதி செய்யப்படுகிறது ({process}%)", "importTransactionResult": "நீங்கள் வெற்றிகரமாக {count} பரிவர்த்தனைகளை இறக்குமதி செய்துள்ளீர்கள்.", "moveTransactionsInAccountTip": "இந்த செயலை மீட்டெடுக்க முடியாது. இது {fromAccount} இலிருந்து அனைத்து பரிவர்த்தனைகளையும் {toAccount} க்கு மாற்றும்.", "clearTransactionsInAccountTip": "இந்த செயலை மீட்டெடுக்க முடியாது. இது {account} இல் உள்ள உங்கள் அனைத்து பரிவர்த்தனைகளையும் நீக்கும். உறுதிப்படுத்த உங்கள் தற்போதைய கடவுச்சொல்லை உள்ளிடவும்.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "கணக்கு செயல்படுத்தும் இணைப்பு உங்கள் மின்னஞ்சலுக்கு அனுப்பப்பட்டது: {email}. நீங்கள் மின்னஞ்சலைப் பெறவில்லை என்றால், கடவுச்சொல்லை மீண்டும் உள்ளிட்டு கீழே உள்ள பொத்தானை அழுத்தி சரிபார்ப்பு மின்னஞ்சலை மீண்டும் அனுப்பவும்.", "resendValidationEmailTip": "நீங்கள் மின்னஞ்சலைப் பெறவில்லை என்றால், கடவுச்சொல்லை மீண்டும் உள்ளிட்டு கீழே உள்ள பொத்தானை அழுத்தவும், சரிபார்ப்பு மின்னஞ்சல் அனுப்பப்படும்: {email}", "oauth2bindTip": "நீங்கள் {providerName} பயன்படுத்தி {userName} பயனராக உள்நுழைகிறீர்கள். உறுதிப்படுத்த உங்கள் ezBookkeeping கடவுச்சொல்லை உள்ளிடவும்." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "கணக்குகளின் பட்டியல்", "This Week": "இந்த வாரம்", "This Month": "இந்த மாதம்", diff --git a/src/locales/th.json b/src/locales/th.json index 1acccb89..cceaf788 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -134,11 +134,13 @@ "selectedCount": "เลือกแล้ว {count} จาก {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "คุณได้อัปเดตธุรกรรม {count} รายการ", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "คุณแน่ใจหรือไม่ว่าต้องการนำเข้าธุรกรรม {count} รายการ?", "importingTransactions": "กำลังนำเข้า ({process}%)", "importTransactionResult": "คุณได้นำเข้าธุรกรรม {count} รายการเรียบร้อยแล้ว", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "คุณไม่สามารถยกเลิกการกระทำนี้ได้ การกระทำนี้จะลบข้อมูลธุรกรรมทั้งหมดใน {account} โปรดป้อนรหัสผ่านปัจจุบันเพื่อยืนยัน", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "ลิงก์สำหรับเปิดใช้งานบัญชีได้ถูกส่งไปยังอีเมลของคุณแล้ว: {email} หากคุณไม่ได้รับอีเมล โปรดกรอกรหัสผ่านอีกครั้งแล้วกดปุ่มด้านล่างเพื่อส่งอีเมลยืนยันอีกครั้ง", "resendValidationEmailTip": "หากคุณไม่ได้รับอีเมล โปรดกรอกรหัสผ่านอีกครั้งแล้วกดปุ่มด้านล่างเพื่อส่งอีเมลยืนยันไปยัง: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "รายการบัญชี", "This Week": "สัปดาห์นี้", "This Month": "เดือนนี้", diff --git a/src/locales/tr.json b/src/locales/tr.json index a3639259..f1b844ff 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -134,11 +134,13 @@ "selectedCount": "{totalCount} öğeden {count} tanesi seçildi", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "{count} işlemi güncellediniz", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "{count} işlemi içe aktarmak istediğinize emin misiniz?", "importingTransactions": "İçe aktarılıyor (%{process})", "importTransactionResult": "{count} işlem başarıyla içe aktarıldı.", "moveTransactionsInAccountTip": "Bu işlem GERİ ALINAMAZ. Bu, {fromAccount} hesabındaki tüm işlemleri {toAccount} hesabına taşıyacaktır.", "clearTransactionsInAccountTip": "Bu işlem GERİ ALINAMAZ. Bu, {account} hesabındaki işlem verilerinizi silecektir. Onaylamak için lütfen mevcut şifrenizi girin.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Hesap aktivasyon bağlantısı e-posta adresinize ({email}) gönderildi. Eğer e-postayı almadıysanız, lütfen şifrenizi tekrar girin ve doğrulama postasını yeniden göndermek için aşağıdaki butona tıklayın.", "resendValidationEmailTip": "Eğer e-postayı almadıysanız, lütfen şifrenizi tekrar girin ve doğrulama postasını şu adrese yeniden göndermek için aşağıdaki butona tıklayın: {email}", "oauth2bindTip": "{providerName} kullanarak {userName} hesabına giriş yapıyorsunuz. Doğrulamak için lütfen ezBookkeeping şifrenizi girin." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Hesap Listesi", "This Week": "Bu Hafta", "This Month": "Bu Ay", diff --git a/src/locales/uk.json b/src/locales/uk.json index c56bd57e..386f33ad 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -134,11 +134,13 @@ "selectedCount": "Вибрано {count} з {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Ви оновили {count} транзакцій", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Ви впевнені, що хочете імпортувати {count} транзакцій?", "importingTransactions": "Importing ({process}%)", "importTransactionResult": "Ви успішно імпортували {count} транзакцій.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Посилання для активації облікового запису було надіслано на вашу електронну адресу: {email}. Якщо ви не отримали лист, введіть пароль ще раз і натисніть кнопку нижче, щоб надіслати лист повторно.", "resendValidationEmailTip": "Якщо ви не отримали лист, введіть пароль ще раз і натисніть кнопку нижче, щоб надіслати лист повторно на адресу: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Список рахунків", "This Week": "Цього тижня", "This Month": "Цього місяця", diff --git a/src/locales/vi.json b/src/locales/vi.json index b1033475..f8b04b5e 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -134,11 +134,13 @@ "selectedCount": "Đã chọn {count} trên {totalCount}", "queryIndex": "Query #{index}", "youHaveUpdatedTransactions": "Bạn đã cập nhật {count} giao dịch", + "youHaveDeletedTransactions": "You have deleted {count} transactions", "confirmImportTransactions": "Bạn có chắc chắn muốn nhập {count} giao dịch không?", "importingTransactions": "Importing ({process}%)", "importTransactionResult": "Bạn đã nhập thành công {count} giao dịch.", "moveTransactionsInAccountTip": "You CANNOT undo this action. This will move all transactions from {fromAccount} to {toAccount}.", "clearTransactionsInAccountTip": "You CANNOT undo this action. This will clear your transactions data in {account}. Please enter your current password to confirm.", + "deleteTransactionsTip": "You CANNOT undo this action. This will delete {count} transactions. Please enter your current password to confirm.", "accountActivationAndResendValidationEmailTip": "Liên kết kích hoạt tài khoản đã được gửi tới email của bạn: {email}. Nếu bạn không nhận được email, vui lòng nhập lại mật khẩu và nhấp nút bên dưới để gửi lại email xác nhận.", "resendValidationEmailTip": "Nếu bạn không nhận được email, vui lòng nhập lại mật khẩu và nhấp nút bên dưới để gửi lại email xác nhận tới: {email}", "oauth2bindTip": "You're signing in to the {userName} user using {providerName}. Please enter your ezBookkeeping password to verify." @@ -1851,6 +1853,8 @@ "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", + "Delete Transactions": "Delete Transactions", + "Unable to delete these transactions": "Unable to delete these transactions", "Account List": "Danh sách tài khoản", "This Week": "Tuần này", "This Month": "Tháng này", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index c5ca3583..84fb2246 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -134,11 +134,13 @@ "selectedCount": "已选择 {count} / {totalCount}", "queryIndex": "查询 #{index}", "youHaveUpdatedTransactions": "您已经更新 {count} 个交易", + "youHaveDeletedTransactions": "您已经删除 {count} 个交易", "confirmImportTransactions": "您确定要导入 {count} 个交易?", "importingTransactions": "正在导入 ({process}%)", "importTransactionResult": "您已经成功导入 {count} 个交易。", "moveTransactionsInAccountTip": "您不能撤销该操作。该操作将会把 {fromAccount} 账户中所有的交易数据移动到 {toAccount}。", "clearTransactionsInAccountTip": "您不能撤销该操作。该操作将会清除您在 {account} 账户中的交易数据。请输入您当前的密码以确认。", + "deleteTransactionsTip": "您不能撤销该操作。该操作将会删除 {count} 个交易数据。请输入您当前的密码以确认。", "accountActivationAndResendValidationEmailTip": "账号激活链接已经发送到您的邮箱地址:{email},如果您没有收到邮件,请再次输入密码并点击下方的按钮重新发送验证邮件。", "resendValidationEmailTip": "如果您没有收到邮件,请再次输入密码并点击下方的按钮重新发送验证邮件到:{email}", "oauth2bindTip": "您正在使用 {providerName} 登录 \"{userName}\" 用户,请输入你的 ezBookkeeping 的密码进行验证。" @@ -1851,6 +1853,8 @@ "Update Categories for Income Transactions": "更新收入交易的分类", "Update Categories for Transfer Transactions": "更新转账交易的分类", "Unable to update categories for transactions": "无法更新交易的分类", + "Delete Transactions": "删除交易", + "Unable to delete these transactions": "无法删除这些交易", "Account List": "账户列表", "This Week": "本周", "This Month": "本月", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index f4659fa8..18f4d65a 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -134,11 +134,13 @@ "selectedCount": "已選擇 {count} / {totalCount}", "queryIndex": "查詢 #{index}", "youHaveUpdatedTransactions": "您已經更新 {count} 個交易", + "youHaveDeletedTransactions": "您已經刪除 {count} 個交易", "confirmImportTransactions": "您確定要匯入 {count} 個交易?", "importingTransactions": "正在匯入 ({process}%)", "importTransactionResult": "您已經成功匯入 {count} 個交易。", "moveTransactionsInAccountTip": "您不能還原此操作。此操作將會把 {fromAccount} 帳戶中的所有交易資料移動到 {toAccount}。", "clearTransactionsInAccountTip": "您不能還原此操作。此操作將會清除您在 {account} 帳戶中的交易資料。請輸入您目前的密碼以確認。", + "deleteTransactionsTip": "您不能還原此操作。此操作將會刪除 {count} 個交易資料。請輸入您目前的密碼以確認。", "accountActivationAndResendValidationEmailTip": "帳號啟用連結已經傳送到您的信箱地址:{email},如果您沒有收到郵件,請再次輸入密碼並點擊下方的按鈕重新發送驗證郵件。", "resendValidationEmailTip": "如果您沒有收到郵件,請再次輸入密碼並點擊下方的按鈕重新發送驗證郵件到:{email}", "oauth2bindTip": "您正在使用 {providerName} 登入 \"{userName}\" 使用者,請輸入您的 ezBookkeeping 的密碼以進行驗證。" @@ -1851,6 +1853,8 @@ "Update Categories for Income Transactions": "更新收入交易的分類", "Update Categories for Transfer Transactions": "更新轉帳交易的分類", "Unable to update categories for transactions": "無法更新交易的分類", + "Delete Transactions": "刪除交易", + "Unable to delete these transactions": "無法刪除這些交易", "Account List": "帳戶清單", "This Week": "本週", "This Month": "本月", diff --git a/src/models/transaction.ts b/src/models/transaction.ts index 97fd0f90..27ac8fc3 100644 --- a/src/models/transaction.ts +++ b/src/models/transaction.ts @@ -572,6 +572,11 @@ export interface TransactionDeleteRequest { readonly id: string; } +export interface TransactionBatchDeleteRequest { + readonly ids: string[]; + readonly password: string; +} + export interface TransactionImportRequest { readonly transactions: TransactionCreateRequest[]; readonly clientSessionId: string; diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index 57ff7673..1bf885a1 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -610,6 +610,32 @@ export const useTransactionsStore = defineStore('transactions', () => { transactionReconciliationStatementStateInvalid.value = invalidState; } + function updateStoreInvalidState(options: { transactionList?: boolean, reconciliationStatement?: boolean, accountList?: boolean, overview?: boolean, statistics?: boolean, explorer?: boolean }): void { + if (options.transactionList && !transactionListStateInvalid.value) { + updateTransactionListInvalidState(true); + } + + if (options.reconciliationStatement && !transactionReconciliationStatementStateInvalid.value) { + updateTransactionReconciliationStatementInvalidState(true); + } + + if (options.accountList && !accountsStore.accountListStateInvalid) { + accountsStore.updateAccountListInvalidState(true); + } + + if (options.overview && !overviewStore.transactionOverviewStateInvalid) { + overviewStore.updateTransactionOverviewInvalidState(true); + } + + if (options.statistics && !statisticsStore.transactionStatisticsStateInvalid) { + statisticsStore.updateTransactionStatisticsInvalidState(true); + } + + if (options.explorer && !explorersStore.transactionExplorerStateInvalid) { + explorersStore.updateTransactionExplorerInvalidState(true); + } + } + function resetTransactions(): void { transactionsFilter.value.dateType = DateRange.All.type; transactionsFilter.value.maxTime = 0; @@ -1078,25 +1104,13 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } - if (!transactionReconciliationStatementStateInvalid.value) { - updateTransactionReconciliationStatementInvalidState(true); - } - - if (!accountsStore.accountListStateInvalid) { - accountsStore.updateAccountListInvalidState(true); - } - - if (!overviewStore.transactionOverviewStateInvalid) { - overviewStore.updateTransactionOverviewInvalidState(true); - } - - if (!statisticsStore.transactionStatisticsStateInvalid) { - statisticsStore.updateTransactionStatisticsInvalidState(true); - } - - if (!explorersStore.transactionExplorerStateInvalid) { - explorersStore.updateTransactionExplorerInvalidState(true); - } + updateStoreInvalidState({ + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); resolve(transaction); }).catch(error => { @@ -1127,25 +1141,13 @@ export const useTransactionsStore = defineStore('transactions', () => { return; } - if (!transactionListStateInvalid.value) { - updateTransactionListInvalidState(true); - } - - if (!transactionReconciliationStatementStateInvalid.value) { - updateTransactionReconciliationStatementInvalidState(true); - } - - if (!overviewStore.transactionOverviewStateInvalid) { - overviewStore.updateTransactionOverviewInvalidState(true); - } - - if (!statisticsStore.transactionStatisticsStateInvalid) { - statisticsStore.updateTransactionStatisticsInvalidState(true); - } - - if (!explorersStore.transactionExplorerStateInvalid) { - explorersStore.updateTransactionExplorerInvalidState(true); - } + updateStoreInvalidState({ + transactionList: true, + reconciliationStatement: true, + overview: true, + statistics: true, + explorer: true + }); resolve(data.result); }).catch(error => { @@ -1172,29 +1174,14 @@ export const useTransactionsStore = defineStore('transactions', () => { return; } - if (!transactionListStateInvalid.value) { - updateTransactionListInvalidState(true); - } - - if (!transactionReconciliationStatementStateInvalid.value) { - updateTransactionReconciliationStatementInvalidState(true); - } - - if (!accountsStore.accountListStateInvalid) { - accountsStore.updateAccountListInvalidState(true); - } - - if (!overviewStore.transactionOverviewStateInvalid) { - overviewStore.updateTransactionOverviewInvalidState(true); - } - - if (!statisticsStore.transactionStatisticsStateInvalid) { - statisticsStore.updateTransactionStatisticsInvalidState(true); - } - - if (!explorersStore.transactionExplorerStateInvalid) { - explorersStore.updateTransactionExplorerInvalidState(true); - } + updateStoreInvalidState({ + transactionList: true, + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); resolve(data.result); }).catch(error => { @@ -1237,25 +1224,13 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } - if (!transactionReconciliationStatementStateInvalid.value) { - updateTransactionReconciliationStatementInvalidState(true); - } - - if (!accountsStore.accountListStateInvalid) { - accountsStore.updateAccountListInvalidState(true); - } - - if (!overviewStore.transactionOverviewStateInvalid) { - overviewStore.updateTransactionOverviewInvalidState(true); - } - - if (!statisticsStore.transactionStatisticsStateInvalid) { - statisticsStore.updateTransactionStatisticsInvalidState(true); - } - - if (!explorersStore.transactionExplorerStateInvalid) { - explorersStore.updateTransactionExplorerInvalidState(true); - } + updateStoreInvalidState({ + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); resolve(data.result); }).catch(error => { @@ -1272,6 +1247,52 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } + function batchDeleteTransactions({ transactionIds, password }: { transactionIds: string[], password: string }): Promise { + return new Promise((resolve, reject) => { + services.batchDeleteTransaction({ + ids: transactionIds, + password: password + }).then(response => { + const data = response.data; + + if (!data || !data.success || !data.result) { + reject({ message: 'Unable to delete these transactions' }); + return; + } + + updateStoreInvalidState({ + transactionList: true, + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); + + resolve(data.result); + }).catch(error => { + logger.error('failed to delete transactions', error); + + updateStoreInvalidState({ + transactionList: true, + reconciliationStatement: true, + accountList: true, + overview: true, + statistics: true, + explorer: true + }); + + if (error.response && error.response.data && error.response.data.errorMessage) { + reject({ error: error.response.data }); + } else if (!error.processed) { + reject({ message: 'Unable to delete these transactions' }); + } else { + reject(error); + } + }); + }); + } + function recognizeReceiptImage({ imageFile, cancelableUuid }: { imageFile: File, cancelableUuid?: string }): Promise { return new Promise((resolve, reject) => { services.recognizeReceiptImage({ imageFile, cancelableUuid }).then(response => { @@ -1520,6 +1541,7 @@ export const useTransactionsStore = defineStore('transactions', () => { batchUpdateTransactionCategories, moveAllTransactionsBetweenAccounts, deleteTransaction, + batchDeleteTransactions, recognizeReceiptImage, cancelRecognizeReceiptImage, parseImportCustomFile, diff --git a/src/views/desktop/insights/dialogs/BatchDeleteDialog.vue b/src/views/desktop/insights/dialogs/BatchDeleteDialog.vue new file mode 100644 index 00000000..82cd665f --- /dev/null +++ b/src/views/desktop/insights/dialogs/BatchDeleteDialog.vue @@ -0,0 +1,103 @@ + + + diff --git a/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue b/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue index 58b804cc..99d92948 100644 --- a/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue +++ b/src/views/desktop/insights/tabs/ExplorerEditableDataTableTab.vue @@ -90,6 +90,12 @@ :title="tt('Update Categories for Transfer Transactions')" :disabled="!isAllSelectedTransactionsTransfer" @click="batchUpdateTransactionCategories(CategoryType.Transfer)"> + + + @@ -174,6 +180,7 @@ + @@ -181,12 +188,14 @@ import SnackBar from '@/components/desktop/SnackBar.vue'; import PaginationButtons from '@/components/desktop/PaginationButtons.vue'; import BatchUpdateCategoryDialog from '@/views/desktop/insights/dialogs/BatchUpdateCategoryDialog.vue'; +import BatchDeleteDialog from '@/views/desktop/insights/dialogs/BatchDeleteDialog.vue'; -import { ref, computed, useTemplateRef } from 'vue'; +import { ref, computed, useTemplateRef, watch } from 'vue'; import { useI18n } from '@/locales/helpers.ts'; import { useExplorerDataTablePageBase } from '@/views/base/explorer/ExplorerDataTablePageBase.ts'; +import { keys } from '@/core/base.ts'; import { CategoryType } from '@/core/category.ts'; import { TransactionType } from '@/core/transaction.ts'; import type { TransactionInsightDataItem } from '@/models/transaction.ts'; @@ -201,11 +210,13 @@ import { mdiSelectAll, mdiSelectInverse, mdiMenuDown, - mdiTextBoxEditOutline + mdiTextBoxEditOutline, + mdiDeleteOutline } from '@mdi/js'; type SnackBarType = InstanceType; type BatchUpdateCategoryDialogType = InstanceType; +type BatchDeleteDialogType = InstanceType; interface InsightsExplorerDataTableTabProps { loading?: boolean; @@ -221,6 +232,7 @@ const emit = defineEmits<{ const snackbar = useTemplateRef('snackbar'); const batchUpdateCategoryDialog = useTemplateRef('batchUpdateCategoryDialog'); +const batchDeleteDialog = useTemplateRef('batchDeleteDialog'); const { tt, @@ -305,8 +317,8 @@ function selectInvert(): void { function batchUpdateTransactionCategories(type: CategoryType): void { batchUpdateCategoryDialog.value?.open({ type: type, - updateIds: getAllSelectedTransactionIds() } - ).then(updatedCount => { + updateIds: getAllSelectedTransactionIds() + }).then(updatedCount => { if (updatedCount > 0) { snackbar.value?.showMessage('format.misc.youHaveUpdatedTransactions', { count: formatNumberToLocalizedNumerals(updatedCount) @@ -315,15 +327,48 @@ function batchUpdateTransactionCategories(type: CategoryType): void { selectedTransactions.value = {}; emit('update:transactions'); }).catch(error => { - if (!error.processed) { + if (error) { snackbar.value?.showError(error); } }); } +function batchDeleteTransactions(): void { + batchDeleteDialog.value?.open({ + updateIds: getAllSelectedTransactionIds() + }).then(updatedCount => { + if (updatedCount > 0) { + snackbar.value?.showMessage('format.misc.youHaveDeletedTransactions', { + count: formatNumberToLocalizedNumerals(updatedCount) + }); + } + selectedTransactions.value = {}; + emit('update:transactions'); + }).catch(error => { + if (error) { + snackbar.value?.showError(error); + } + emit('update:transactions'); + }); +} + function showTransaction(transaction: TransactionInsightDataItem): void { emit('click:transaction', transaction); } + +watch(() => filteredTransactions.value, newValue => { + const allAvailableTransactionIds: Record = {}; + + for (const transaction of newValue) { + allAvailableTransactionIds[transaction.id] = true; + } + + for (const transactionId of keys(selectedTransactions.value)) { + if (!allAvailableTransactionIds[transactionId]) { + delete selectedTransactions.value[transactionId]; + } + } +});