From 78ba43480b4b8ce58be37ce6def595d651a65181 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sat, 26 Apr 2025 23:36:23 +0800 Subject: [PATCH] support adding / deleting sub account after account created (#77) --- pkg/api/accounts.go | 248 ++++++++++++++++-- .../duplicate_checker_type.go | 11 +- pkg/errs/account.go | 4 +- pkg/models/account.go | 6 +- pkg/services/accounts.go | 200 +++++++++++++- src/locales/de.json | 4 +- src/locales/en.json | 4 +- src/locales/es.json | 4 +- src/locales/it.json | 4 +- src/locales/ja.json | 4 +- src/locales/ru.json | 4 +- src/locales/uk.json | 4 +- src/locales/vi.json | 4 +- src/locales/zh_Hans.json | 4 +- src/locales/zh_Hant.json | 4 +- src/models/account.ts | 14 +- src/stores/account.ts | 35 ++- .../base/accounts/AccountEditPageBase.ts | 5 + .../accounts/list/dialogs/EditDialog.vue | 17 +- src/views/mobile/accounts/EditPage.vue | 16 +- 20 files changed, 520 insertions(+), 76 deletions(-) diff --git a/pkg/api/accounts.go b/pkg/api/accounts.go index c0d99732..06eb7500 100644 --- a/pkg/api/accounts.go +++ b/pkg/api/accounts.go @@ -311,11 +311,27 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error return nil, errs.NewIncompleteOrIncorrectSubmissionError(err) } + if accountModifyReq.Id <= 0 { + return nil, errs.ErrAccountIdInvalid + } + + utcOffset, err := c.GetClientTimezoneOffset() + + if err != nil { + log.Warnf(c, "[accounts.AccountModifyHandler] cannot get client timezone offset, because %s", err.Error()) + return nil, errs.ErrClientTimezoneOffsetInvalid + } + if accountModifyReq.Category < models.ACCOUNT_CATEGORY_CASH || accountModifyReq.Category > models.ACCOUNT_CATEGORY_CERTIFICATE_OF_DEPOSIT { log.Warnf(c, "[accounts.AccountModifyHandler] account category invalid, category is %d", accountModifyReq.Category) return nil, errs.ErrAccountCategoryInvalid } + if accountModifyReq.Category != models.ACCOUNT_CATEGORY_CREDIT_CARD && accountModifyReq.CreditCardStatementDate != 0 { + log.Warnf(c, "[accounts.AccountModifyHandler] cannot set statement date with category \"%d\"", accountModifyReq.Category) + return nil, errs.ErrCannotSetStatementDateForNonCreditCard + } + uid := c.GetCurrentUid() accountAndSubAccounts, err := a.accounts.GetAccountAndSubAccountsByAccountId(c, uid, accountModifyReq.Id) @@ -331,20 +347,81 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error return nil, errs.ErrAccountNotFound } - if len(accountModifyReq.SubAccounts)+1 != len(accountAndSubAccounts) { - return nil, errs.ErrCannotAddOrDeleteSubAccountsWhenModify + if accountModifyReq.Currency != nil && mainAccount.Currency != *accountModifyReq.Currency { + return nil, errs.ErrNotSupportedChangeCurrency } - if accountModifyReq.Category != models.ACCOUNT_CATEGORY_CREDIT_CARD && accountModifyReq.CreditCardStatementDate != 0 { - log.Warnf(c, "[accounts.AccountModifyHandler] cannot set statement date with category \"%d\"", accountModifyReq.Category) - return nil, errs.ErrCannotSetStatementDateForNonCreditCard + if accountModifyReq.Balance != nil { + return nil, errs.ErrNotSupportedChangeBalance } - if mainAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + if accountModifyReq.BalanceTime != nil { + return nil, errs.ErrNotSupportedChangeBalanceTime + } + + if mainAccount.Type == models.ACCOUNT_TYPE_SINGLE_ACCOUNT { + if len(accountModifyReq.SubAccounts) > 0 { + log.Warnf(c, "[accounts.AccountModifyHandler] account cannot have any sub-accounts") + return nil, errs.ErrAccountCannotHaveSubAccounts + } + } else if mainAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + if len(accountModifyReq.SubAccounts) < 1 { + log.Warnf(c, "[accounts.AccountModifyHandler] account does not have any sub-accounts") + return nil, errs.ErrAccountHaveNoSubAccount + } + for i := 0; i < len(accountModifyReq.SubAccounts); i++ { - subAccount := accountModifyReq.SubAccounts[i] + subAccountReq := accountModifyReq.SubAccounts[i] - if subAccount.CreditCardStatementDate != 0 { + if subAccountReq.Category != accountModifyReq.Category { + log.Warnf(c, "[accounts.AccountModifyHandler] category of sub-account#%d not equals to parent", i) + return nil, errs.ErrSubAccountCategoryNotEqualsToParent + } + + if subAccountReq.Id == 0 { // create new sub-account + if subAccountReq.Currency == nil { + log.Warnf(c, "[accounts.AccountModifyHandler] sub-account#%d not set currency", i) + return nil, errs.ErrAccountCurrencyInvalid + } else if subAccountReq.Currency != nil && *subAccountReq.Currency == validators.ParentAccountCurrencyPlaceholder { + log.Warnf(c, "[accounts.AccountModifyHandler] sub-account#%d cannot set currency placeholder", i) + return nil, errs.ErrAccountCurrencyInvalid + } + + if subAccountReq.Balance == nil { + defaultBalance := int64(0) + subAccountReq.Balance = &defaultBalance + } + + if *subAccountReq.Balance == 0 { + defaultBalanceTime := int64(0) + subAccountReq.BalanceTime = &defaultBalanceTime + } + + if *subAccountReq.Balance != 0 && (subAccountReq.BalanceTime == nil || *subAccountReq.BalanceTime <= 0) { + log.Warnf(c, "[accounts.AccountModifyHandler] sub-account#%d balance time is not set", i) + return nil, errs.ErrAccountBalanceTimeNotSet + } + } else { // modify existed sub-account + subAccount, exists := accountMap[subAccountReq.Id] + + if !exists { + return nil, errs.ErrAccountNotFound + } + + if subAccountReq.Currency != nil && subAccount.Currency != *subAccountReq.Currency { + return nil, errs.ErrNotSupportedChangeCurrency + } + + if subAccountReq.Balance != nil { + return nil, errs.ErrNotSupportedChangeBalance + } + + if subAccountReq.BalanceTime != nil { + return nil, errs.ErrNotSupportedChangeBalanceTime + } + } + + if subAccountReq.CreditCardStatementDate != 0 { log.Warnf(c, "[accounts.AccountModifyHandler] sub-account#%d cannot set statement date", i) return nil, errs.ErrCannotSetStatementDateForSubAccount } @@ -353,6 +430,9 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error anythingUpdate := false var toUpdateAccounts []*models.Account + var toAddAccounts []*models.Account + var toAddAccountBalanceTimes []int64 + var toDeleteAccountIds []int64 toUpdateAccount := a.getToUpdateAccount(uid, &accountModifyReq, mainAccount, false) @@ -361,18 +441,43 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error toUpdateAccounts = append(toUpdateAccounts, toUpdateAccount) } + toDeleteAccountIds = a.getToDeleteSubAccountIds(&accountModifyReq, mainAccount, accountAndSubAccounts) + + if len(toDeleteAccountIds) > 0 { + anythingUpdate = true + } + + maxOrderId := int32(0) + + for i := 0; i < len(accountAndSubAccounts); i++ { + account := accountAndSubAccounts[i] + + if account.AccountId != mainAccount.AccountId && account.DisplayOrder > maxOrderId { + maxOrderId = account.DisplayOrder + } + } + for i := 0; i < len(accountModifyReq.SubAccounts); i++ { subAccountReq := accountModifyReq.SubAccounts[i] if _, exists := accountMap[subAccountReq.Id]; !exists { - return nil, errs.ErrAccountNotFound - } - - toUpdateSubAccount := a.getToUpdateAccount(uid, subAccountReq, accountMap[subAccountReq.Id], true) - - if toUpdateSubAccount != nil { anythingUpdate = true - toUpdateAccounts = append(toUpdateAccounts, toUpdateSubAccount) + maxOrderId = maxOrderId + 1 + newSubAccount := a.createNewSubAccountModelForModify(uid, mainAccount.Type, subAccountReq, maxOrderId) + toAddAccounts = append(toAddAccounts, newSubAccount) + + if subAccountReq.BalanceTime != nil { + toAddAccountBalanceTimes = append(toAddAccountBalanceTimes, *subAccountReq.BalanceTime) + } else { + toAddAccountBalanceTimes = append(toAddAccountBalanceTimes, 0) + } + } else { + toUpdateSubAccount := a.getToUpdateAccount(uid, subAccountReq, accountMap[subAccountReq.Id], true) + + if toUpdateSubAccount != nil { + anythingUpdate = true + toUpdateAccounts = append(toUpdateAccounts, toUpdateSubAccount) + } } } @@ -380,7 +485,43 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error return nil, errs.ErrNothingWillBeUpdated } - err = a.accounts.ModifyAccounts(c, uid, toUpdateAccounts) + if len(toAddAccounts) > 0 && a.CurrentConfig().EnableDuplicateSubmissionsCheck && accountModifyReq.ClientSessionId != "" { + found, remark := a.GetSubmissionRemark(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_SUBACCOUNT, uid, accountModifyReq.ClientSessionId) + + if found { + log.Infof(c, "[accounts.AccountModifyHandler] another account \"id:%s\" modification has been created for user \"uid:%d\"", remark, uid) + accountId, err := utils.StringToInt64(remark) + + if err == nil { + accountAndSubAccounts, err := a.accounts.GetAccountAndSubAccountsByAccountId(c, uid, accountId) + + if err != nil { + log.Errorf(c, "[accounts.AccountModifyHandler] failed to get existed account \"id:%d\" for user \"uid:%d\", because %s", accountId, uid, err.Error()) + return nil, errs.Or(err, errs.ErrOperationFailed) + } + + accountMap := a.accounts.GetAccountMapByList(accountAndSubAccounts) + mainAccount, exists := accountMap[accountId] + + if !exists { + return nil, errs.ErrOperationFailed + } + + accountInfoResp := mainAccount.ToAccountInfoResponse() + + for i := 0; i < len(accountAndSubAccounts); i++ { + if accountAndSubAccounts[i].ParentAccountId == mainAccount.AccountId { + subAccountResp := accountAndSubAccounts[i].ToAccountInfoResponse() + accountInfoResp.SubAccounts = append(accountInfoResp.SubAccounts, subAccountResp) + } + } + + return accountInfoResp, nil + } + } + } + + err = a.accounts.ModifyAccounts(c, mainAccount, toUpdateAccounts, toAddAccounts, toAddAccountBalanceTimes, toDeleteAccountIds, utcOffset) if err != nil { log.Errorf(c, "[accounts.AccountModifyHandler] failed to update account \"id:%d\" for user \"uid:%d\", because %s", accountModifyReq.Id, uid, err.Error()) @@ -389,6 +530,10 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error log.Infof(c, "[accounts.AccountModifyHandler] user \"uid:%d\" has updated account \"id:%d\" successfully", uid, accountModifyReq.Id) + if len(toAddAccounts) > 0 { + a.SetSubmissionRemarkIfEnable(duplicatechecker.DUPLICATE_CHECKER_TYPE_NEW_SUBACCOUNT, uid, accountModifyReq.ClientSessionId, utils.Int64ToString(mainAccount.AccountId)) + } + accountRespMap := make(map[int64]*models.AccountInfoResponse) for i := 0; i < len(toUpdateAccounts); i++ { @@ -405,11 +550,23 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error accountRespMap[accountResp.Id] = accountResp } + for i := 0; i < len(toAddAccounts); i++ { + account := toAddAccounts[i] + accountResp := account.ToAccountInfoResponse() + accountRespMap[accountResp.Id] = accountResp + } + + deletedAccountIds := make(map[int64]bool) + + for i := 0; i < len(toDeleteAccountIds); i++ { + deletedAccountIds[toDeleteAccountIds[i]] = true + } + for i := 0; i < len(accountAndSubAccounts); i++ { oldAccount := accountAndSubAccounts[i] _, exists := accountRespMap[oldAccount.AccountId] - if !exists { + if !exists && !deletedAccountIds[oldAccount.AccountId] { oldAccountResp := oldAccount.ToAccountInfoResponse() accountRespMap[oldAccountResp.Id] = oldAccountResp } @@ -418,8 +575,19 @@ func (a *AccountsApi) AccountModifyHandler(c *core.WebContext) (any, *errs.Error accountResp := accountRespMap[accountModifyReq.Id] for i := 0; i < len(accountAndSubAccounts); i++ { - if accountAndSubAccounts[i].ParentAccountId == accountResp.Id { - subAccountResp := accountRespMap[accountAndSubAccounts[i].AccountId] + account := accountAndSubAccounts[i] + + if account.ParentAccountId == accountResp.Id && !deletedAccountIds[account.AccountId] { + subAccountResp := accountRespMap[account.AccountId] + accountResp.SubAccounts = append(accountResp.SubAccounts, subAccountResp) + } + } + + for i := 0; i < len(toAddAccounts); i++ { + account := toAddAccounts[i] + + if account.ParentAccountId == accountResp.Id { + subAccountResp := accountRespMap[account.AccountId] accountResp.SubAccounts = append(accountResp.SubAccounts, subAccountResp) } } @@ -552,6 +720,24 @@ func (a *AccountsApi) createNewAccountModel(uid int64, accountCreateReq *models. } } +func (a *AccountsApi) createNewSubAccountModelForModify(uid int64, accountType models.AccountType, accountModifyReq *models.AccountModifyRequest, order int32) *models.Account { + accountExtend := &models.AccountExtend{} + + return &models.Account{ + Uid: uid, + Name: accountModifyReq.Name, + DisplayOrder: order, + Category: accountModifyReq.Category, + Type: accountType, + Icon: accountModifyReq.Icon, + Color: accountModifyReq.Color, + Currency: *accountModifyReq.Currency, + Balance: *accountModifyReq.Balance, + Comment: accountModifyReq.Comment, + Extend: accountExtend, + } +} + func (a *AccountsApi) createSubAccountModels(uid int64, accountCreateReq *models.AccountCreateRequest) ([]*models.Account, []int64) { if len(accountCreateReq.SubAccounts) <= 0 { return nil, nil @@ -609,3 +795,27 @@ func (a *AccountsApi) getToUpdateAccount(uid int64, accountModifyReq *models.Acc return nil } + +func (a *AccountsApi) getToDeleteSubAccountIds(accountModifyReq *models.AccountModifyRequest, mainAccount *models.Account, accountAndSubAccounts []*models.Account) []int64 { + newSubAccountIds := make(map[int64]bool, len(accountModifyReq.SubAccounts)) + + for i := 0; i < len(accountModifyReq.SubAccounts); i++ { + newSubAccountIds[accountModifyReq.SubAccounts[i].Id] = true + } + + toDeleteAccountIds := make([]int64, 0) + + for i := 0; i < len(accountAndSubAccounts); i++ { + subAccount := accountAndSubAccounts[i] + + if subAccount.AccountId == mainAccount.AccountId { + continue + } + + if _, exists := newSubAccountIds[subAccount.AccountId]; !exists { + toDeleteAccountIds = append(toDeleteAccountIds, subAccount.AccountId) + } + } + + return toDeleteAccountIds +} diff --git a/pkg/duplicatechecker/duplicate_checker_type.go b/pkg/duplicatechecker/duplicate_checker_type.go index 11c470df..a087a5dd 100644 --- a/pkg/duplicatechecker/duplicate_checker_type.go +++ b/pkg/duplicatechecker/duplicate_checker_type.go @@ -7,10 +7,11 @@ type DuplicateCheckerType uint8 const ( DUPLICATE_CHECKER_TYPE_BACKGROUND_CRON_JOB DuplicateCheckerType = 0 DUPLICATE_CHECKER_TYPE_NEW_ACCOUNT DuplicateCheckerType = 1 - DUPLICATE_CHECKER_TYPE_NEW_CATEGORY DuplicateCheckerType = 2 - DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION DuplicateCheckerType = 3 - DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE DuplicateCheckerType = 4 - DUPLICATE_CHECKER_TYPE_NEW_PICTURE DuplicateCheckerType = 5 - DUPLICATE_CHECKER_TYPE_IMPORT_TRANSACTIONS DuplicateCheckerType = 6 + DUPLICATE_CHECKER_TYPE_NEW_SUBACCOUNT DuplicateCheckerType = 2 + DUPLICATE_CHECKER_TYPE_NEW_CATEGORY DuplicateCheckerType = 3 + DUPLICATE_CHECKER_TYPE_NEW_TRANSACTION DuplicateCheckerType = 4 + DUPLICATE_CHECKER_TYPE_NEW_TEMPLATE DuplicateCheckerType = 5 + DUPLICATE_CHECKER_TYPE_NEW_PICTURE DuplicateCheckerType = 6 + DUPLICATE_CHECKER_TYPE_IMPORT_TRANSACTIONS DuplicateCheckerType = 7 DUPLICATE_CHECKER_TYPE_FAILURE_CHECK DuplicateCheckerType = 255 ) diff --git a/pkg/errs/account.go b/pkg/errs/account.go index 7c42fc04..abc2bb40 100644 --- a/pkg/errs/account.go +++ b/pkg/errs/account.go @@ -14,7 +14,6 @@ var ( ErrParentAccountCannotSetBalance = NewNormalError(NormalSubcategoryAccount, 7, http.StatusBadRequest, "parent account cannot set balance") ErrSubAccountCategoryNotEqualsToParent = NewNormalError(NormalSubcategoryAccount, 8, http.StatusBadRequest, "sub-account category not equals to parent") ErrSubAccountTypeInvalid = NewNormalError(NormalSubcategoryAccount, 9, http.StatusBadRequest, "sub-account type invalid") - ErrCannotAddOrDeleteSubAccountsWhenModify = NewNormalError(NormalSubcategoryAccount, 10, http.StatusBadRequest, "cannot add or delete sub-accounts when modify account") ErrSourceAccountNotFound = NewNormalError(NormalSubcategoryAccount, 11, http.StatusBadRequest, "source account not found") ErrDestinationAccountNotFound = NewNormalError(NormalSubcategoryAccount, 12, http.StatusBadRequest, "destination account not found") ErrAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 13, http.StatusBadRequest, "account is in use and cannot be deleted") @@ -24,4 +23,7 @@ var ( ErrCannotSetStatementDateForSubAccount = NewNormalError(NormalSubcategoryAccount, 17, http.StatusBadRequest, "cannot set statement date for sub account") ErrSubAccountNotFound = NewNormalError(NormalSubcategoryAccount, 18, http.StatusBadRequest, "sub-account not found") ErrSubAccountInUseCannotBeDeleted = NewNormalError(NormalSubcategoryAccount, 19, http.StatusBadRequest, "sub-account is in use and cannot be deleted") + ErrNotSupportedChangeCurrency = NewNormalError(NormalSubcategoryAccount, 20, http.StatusBadRequest, "not supported to modify account currency") + ErrNotSupportedChangeBalance = NewNormalError(NormalSubcategoryAccount, 21, http.StatusBadRequest, "not supported to modify account balance") + ErrNotSupportedChangeBalanceTime = NewNormalError(NormalSubcategoryAccount, 22, http.StatusBadRequest, "not supported to modify account balance time") ) diff --git a/pkg/models/account.go b/pkg/models/account.go index 6d1b0fc4..e4a2fb0c 100644 --- a/pkg/models/account.go +++ b/pkg/models/account.go @@ -101,15 +101,19 @@ type AccountCreateRequest struct { // AccountModifyRequest represents all parameters of account modification request type AccountModifyRequest struct { - Id int64 `json:"id,string" binding:"required,min=1"` + Id int64 `json:"id,string" binding:"required,min=0"` Name string `json:"name" binding:"required,notBlank,max=64"` Category AccountCategory `json:"category" binding:"required"` Icon int64 `json:"icon,string" binding:"min=1"` Color string `json:"color" binding:"required,len=6,validHexRGBColor"` + Currency *string `json:"currency" binding:"omitempty,len=3,validCurrency"` + Balance *int64 `json:"balance" binding:"omitempty"` + BalanceTime *int64 `json:"balanceTime" binding:"omitempty"` Comment string `json:"comment" binding:"max=255"` CreditCardStatementDate int `json:"creditCardStatementDate" binding:"min=0,max=28"` Hidden bool `json:"hidden"` SubAccounts []*AccountModifyRequest `json:"subAccounts" binding:"omitempty"` + ClientSessionId string `json:"clientSessionId"` } // AccountListRequest represents all parameters of account listing request diff --git a/pkg/services/accounts.go b/pkg/services/accounts.go index 2c6fd445..accf6275 100644 --- a/pkg/services/accounts.go +++ b/pkg/services/accounts.go @@ -334,21 +334,81 @@ func (s *AccountService) CreateAccounts(c core.Context, mainAccount *models.Acco } // ModifyAccounts saves an existed account model to database -func (s *AccountService) ModifyAccounts(c core.Context, uid int64, accounts []*models.Account) error { - if uid <= 0 { +func (s *AccountService) ModifyAccounts(c core.Context, mainAccount *models.Account, updateAccounts []*models.Account, addSubAccounts []*models.Account, addSubAccountBalanceTimes []int64, removeSubAccountIds []int64, utcOffset int16) error { + if mainAccount.Uid <= 0 { return errs.ErrUserIdInvalid } + needAccountUuidCount := uint16(len(addSubAccounts)) + newAccountUuids := s.GenerateUuids(uuid.UUID_TYPE_ACCOUNT, needAccountUuidCount) + + if len(newAccountUuids) < int(needAccountUuidCount) { + return errs.ErrSystemIsBusy + } + now := time.Now().Unix() - for i := 0; i < len(accounts); i++ { - accounts[i].UpdatedUnixTime = now + var addInitTransactions []*models.Transaction + + for i := 0; i < len(updateAccounts); i++ { + updateAccounts[i].UpdatedUnixTime = now } - return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error { - for i := 0; i < len(accounts); i++ { - account := accounts[i] - updatedRows, err := sess.ID(account.AccountId).Cols("name", "category", "icon", "color", "comment", "extend", "hidden", "updated_unix_time").Where("uid=? AND deleted=?", uid, false).Update(account) + if mainAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS { + defaultTransactionTime := utils.GetMinTransactionTimeFromUnixTime(now) + + for i := 0; i < len(addSubAccounts); i++ { + childAccount := addSubAccounts[i] + childAccount.AccountId = newAccountUuids[i] + childAccount.ParentAccountId = mainAccount.AccountId + childAccount.Uid = mainAccount.Uid + childAccount.Type = models.ACCOUNT_TYPE_SINGLE_ACCOUNT + childAccount.Deleted = false + childAccount.CreatedUnixTime = now + childAccount.UpdatedUnixTime = now + + if childAccount.Balance != 0 { + transactionId := s.GenerateUuid(uuid.UUID_TYPE_TRANSACTION) + + if transactionId < 1 { + return errs.ErrSystemIsBusy + } + + transactionTime := defaultTransactionTime + + if len(addSubAccountBalanceTimes) > i && addSubAccountBalanceTimes[i] > 0 { + transactionTime = utils.GetMinTransactionTimeFromUnixTime(addSubAccountBalanceTimes[i]) + } else { + defaultTransactionTime++ + } + + newTransaction := &models.Transaction{ + TransactionId: transactionId, + Uid: childAccount.Uid, + Deleted: false, + Type: models.TRANSACTION_DB_TYPE_MODIFY_BALANCE, + TransactionTime: transactionTime, + TimezoneUtcOffset: utcOffset, + AccountId: childAccount.AccountId, + Amount: childAccount.Balance, + RelatedAccountId: childAccount.AccountId, + RelatedAccountAmount: childAccount.Balance, + CreatedUnixTime: now, + UpdatedUnixTime: now, + } + + addInitTransactions = append(addInitTransactions, newTransaction) + } + } + } + + userDataDb := s.UserDataDB(mainAccount.Uid) + + return userDataDb.DoTransaction(c, func(sess *xorm.Session) error { + // update accounts + for i := 0; i < len(updateAccounts); i++ { + account := updateAccounts[i] + updatedRows, err := sess.ID(account.AccountId).Cols("name", "category", "icon", "color", "comment", "extend", "hidden", "updated_unix_time").Where("uid=? AND deleted=?", account.Uid, false).Update(account) if err != nil { return err @@ -357,6 +417,130 @@ func (s *AccountService) ModifyAccounts(c core.Context, uid int64, accounts []*m } } + // add new sub accounts + for i := 0; i < len(addSubAccounts); i++ { + account := addSubAccounts[i] + _, err := sess.Insert(account) + + if err != nil { + return err + } + } + + // add init transaction for new sub accounts + for i := 0; i < len(addInitTransactions); i++ { + transaction := addInitTransactions[i] + + insertTransactionSavePointName := "insert_transaction" + err := userDataDb.SetSavePoint(sess, insertTransactionSavePointName) + + if err != nil { + log.Errorf(c, "[accounts.ModifyAccounts] failed to set save point \"%s\", because %s", insertTransactionSavePointName, err.Error()) + return err + } + + createdRows, err := sess.Insert(transaction) + + if err != nil || createdRows < 1 { // maybe another transaction has same time + err = userDataDb.RollbackToSavePoint(sess, insertTransactionSavePointName) + + if err != nil { + log.Errorf(c, "[accounts.ModifyAccounts] failed to rollback to save point \"%s\", because %s", insertTransactionSavePointName, err.Error()) + return err + } + + sameSecondLatestTransaction := &models.Transaction{} + minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime)) + maxTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime)) + + has, err := sess.Where("uid=? AND transaction_time>=? AND transaction_time<=?", transaction.Uid, minTransactionTime, maxTransactionTime).OrderBy("transaction_time desc").Limit(1).Get(sameSecondLatestTransaction) + + if err != nil { + return err + } else if !has { + return errs.ErrDatabaseOperationFailed + } else if sameSecondLatestTransaction.TransactionTime == maxTransactionTime-1 { + return errs.ErrTooMuchTransactionInOneSecond + } + + transaction.TransactionTime = sameSecondLatestTransaction.TransactionTime + 1 + createdRows, err := sess.Insert(transaction) + + if err != nil { + return err + } else if createdRows < 1 { + return errs.ErrDatabaseOperationFailed + } + } + } + + // remove sub accounts + if len(removeSubAccountIds) > 0 { + subAccountsCount, err := sess.Where("uid=? AND deleted=? AND parent_account_id=?", mainAccount.Uid, false, mainAccount.AccountId).Count(&models.Account{}) + + if subAccountsCount <= int64(len(removeSubAccountIds)) { + return errs.ErrAccountHaveNoSubAccount + } + + var relatedTransactionsByAccount []*models.Transaction + err = sess.Cols("transaction_id", "uid", "deleted", "account_id", "type").Where("uid=? AND deleted=?", mainAccount.Uid, false).In("account_id", removeSubAccountIds).Limit(len(removeSubAccountIds) + 1).Find(&relatedTransactionsByAccount) + + if err != nil { + return err + } else if len(relatedTransactionsByAccount) > len(removeSubAccountIds) { + return errs.ErrSubAccountInUseCannotBeDeleted + } else if len(relatedTransactionsByAccount) > 0 { + accountTransactionExists := make(map[int64]bool) + + for i := 0; i < len(relatedTransactionsByAccount); i++ { + transaction := relatedTransactionsByAccount[i] + + if transaction.Type != models.TRANSACTION_DB_TYPE_MODIFY_BALANCE { + return errs.ErrAccountInUseCannotBeDeleted + } else if _, exists := accountTransactionExists[transaction.AccountId]; exists { + return errs.ErrAccountInUseCannotBeDeleted + } + + accountTransactionExists[transaction.AccountId] = true + } + } + + deleteAccountUpdateModel := &models.Account{ + Balance: 0, + Deleted: true, + DeletedUnixTime: now, + } + + deletedRows, err := sess.Cols("balance", "deleted", "deleted_unix_time").Where("uid=? AND deleted=?", mainAccount.Uid, false).In("account_id", removeSubAccountIds).Update(deleteAccountUpdateModel) + + if err != nil { + return err + } else if deletedRows < 1 { + return errs.ErrSubAccountNotFound + } + + if len(relatedTransactionsByAccount) > 0 { + updateTransaction := &models.Transaction{ + Deleted: true, + DeletedUnixTime: now, + } + + transactionIds := make([]int64, len(relatedTransactionsByAccount)) + + for i := 0; i < len(relatedTransactionsByAccount); i++ { + transactionIds[i] = relatedTransactionsByAccount[i].TransactionId + } + + deletedTransactionRows, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", mainAccount.Uid, false).In("transaction_id", transactionIds).Update(updateTransaction) + + if err != nil { + return err + } else if deletedTransactionRows < int64(len(transactionIds)) { + return errs.ErrDatabaseOperationFailed + } + } + } + return nil }) } diff --git a/src/locales/de.json b/src/locales/de.json index 680961e3..cfd9b665 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Übergeordnetes Konto kann keinen Saldo festlegen", "sub-account category not equals to parent": "Teilkonto-Kategorie entspricht nicht der übergeordneten Kategorie", "sub-account type invalid": "Teilkontotyp ist ungültig", - "cannot add or delete sub-accounts when modify account": "Unterkonten können beim Ändern des Kontos nicht hinzugefügt oder gelöscht werden", "source account not found": "Quellkonto nicht gefunden", "destination account not found": "Zielkonto nicht gefunden", "account is in use and cannot be deleted": "Konto wird verwendet und kann nicht gelöscht werden", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Abrechnungsdatum kann für Teilkonto nicht festgelegt werden", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "Transaktions-ID ist ungültig", "transaction not found": "Transaktion nicht gefunden", "transaction type is invalid": "Transaktionstyp ist ungültig", diff --git a/src/locales/en.json b/src/locales/en.json index ebfc4685..567fb0cd 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Parent account cannot set balance", "sub-account category not equals to parent": "Sub-account category does not equal to parent", "sub-account type invalid": "Sub-account type is invalid", - "cannot add or delete sub-accounts when modify account": "You cannot add or delete sub-accounts when modify account", "source account not found": "Source account is not found", "destination account not found": "Destination account is not found", "account is in use and cannot be deleted": "Account is in use and it cannot be deleted", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Cannot set statement date for sub-account", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "Transaction ID is invalid", "transaction not found": "Transaction is not found", "transaction type is invalid": "Transaction type is invalid", diff --git a/src/locales/es.json b/src/locales/es.json index 3996083f..040f7af3 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1062,7 +1062,6 @@ "parent account cannot set balance": "La cuenta principal no puede establecer el saldo", "sub-account category not equals to parent": "La categoría de subcuenta no es igual a la principal", "sub-account type invalid": "El tipo de subcuenta no es válido", - "cannot add or delete sub-accounts when modify account": "No puede agregar ni eliminar subcuentas cuando modifica la cuenta", "source account not found": "No se encuentra la cuenta de origen", "destination account not found": "No se encuentra la cuenta de destino", "account is in use and cannot be deleted": "La cuenta está en uso y no se puede eliminar", @@ -1072,6 +1071,9 @@ "cannot set statement date for sub account": "No se puede establecer la fecha del estado de cuenta para la subcuenta", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "El ID de transacción no es válido", "transaction not found": "La transacción no se encuentra", "transaction type is invalid": "El tipo de transacción no es válido", diff --git a/src/locales/it.json b/src/locales/it.json index 26c29c32..568173c3 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Il conto principale non può impostare il saldo", "sub-account category not equals to parent": "La categoria del sotto-conto non corrisponde a quella principale", "sub-account type invalid": "Tipo di sotto-conto non valido", - "cannot add or delete sub-accounts when modify account": "Non è possibile aggiungere o eliminare sotto-conti durante la modifica del conto", "source account not found": "Conto di origine non trovato", "destination account not found": "Conto di destinazione non trovato", "account is in use and cannot be deleted": "Il conto è in uso e non può essere eliminato", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Impossibile impostare la data dell'estratto conto per un sotto-conto", "sub-account not found": "Sotto-conto non trovato", "sub-account is in use and cannot be deleted": "Il sotto-conto è in uso e non può essere eliminato", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "ID transazione non valido", "transaction not found": "Transazione non trovata", "transaction type is invalid": "Tipo di transazione non valido", diff --git a/src/locales/ja.json b/src/locales/ja.json index 99fad228..1e7d5ce0 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "親口座は残高を設定できません", "sub-account category not equals to parent": "子口座のカテゴリが親と一致しません", "sub-account type invalid": "子口座タイプは無効です", - "cannot add or delete sub-accounts when modify account": "口座を変更するときに子口座を追加または削除できません", "source account not found": "元口座が見つかりません", "destination account not found": "宛先口座が見つかりません", "account is in use and cannot be deleted": "支払い方法は使用されており削除できません", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "子口座の明細日を設定できません", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "取引IDは無効です", "transaction not found": "取引が見つかりません", "transaction type is invalid": "取引タイプは無効です", diff --git a/src/locales/ru.json b/src/locales/ru.json index 69226f00..5f953858 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Родительский счет не может устанавливать баланс", "sub-account category not equals to parent": "Категория субсчета не совпадает с родительской", "sub-account type invalid": "Тип субсчета недействителен", - "cannot add or delete sub-accounts when modify account": "Нельзя добавлять или удалять субсчета при изменении счета", "source account not found": "Исходный счет не найден", "destination account not found": "Счет назначения не найден", "account is in use and cannot be deleted": "Счет используется и не может быть удален", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Нельзя установить дату выписки для субсчета", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "ID транзакции недействителен", "transaction not found": "Транзакция не найдена", "transaction type is invalid": "Тип транзакции недействителен", diff --git a/src/locales/uk.json b/src/locales/uk.json index 4ed1d114..429e09e3 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Батьківський рахунок не може встановити баланс", "sub-account category not equals to parent": "Категорія субрахунку не збігається з батьківською", "sub-account type invalid": "Тип субрахунку недійсний", - "cannot add or delete sub-accounts when modify account": "Неможливо додати або видалити субрахунки при зміні рахунку", "source account not found": "Вихідний рахунок не знайдено", "destination account not found": "Рахунок призначення не знайдено", "account is in use and cannot be deleted": "Рахунок використовується і не може бути видалений", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Неможливо встановити дату виписки для субрахунку", "sub-account not found": "Субрахунок не знайдено", "sub-account is in use and cannot be deleted": "Субрахунок використовується і не може бути видалений", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "ID транзакції недійсний", "transaction not found": "Транзакцію не знайдено", "transaction type is invalid": "Тип транзакції недійсний", diff --git a/src/locales/vi.json b/src/locales/vi.json index 7e99a3bc..5662f24e 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "Tài khoản cha không thể đặt số dư", "sub-account category not equals to parent": "Danh mục tài khoản phụ không bằng tài khoản cha", "sub-account type invalid": "Loại tài khoản phụ không hợp lệ", - "cannot add or delete sub-accounts when modify account": "Bạn không thể thêm hoặc xóa tài khoản phụ khi sửa đổi tài khoản", "source account not found": "Không tìm thấy tài khoản nguồn", "destination account not found": "Không tìm thấy tài khoản đích", "account is in use and cannot be deleted": "Tài khoản đang được sử dụng và không thể xóa", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "Cannot set statement date for sub-account", "sub-account not found": "Sub-account is not found", "sub-account is in use and cannot be deleted": "Sub-account is in use and it cannot be deleted", + "not supported to modify account currency": "Not supported to modify account currency", + "not supported to modify account balance": "Not supported to modify account balance", + "not supported to modify account balance time": "Not supported to modify account balance time", "transaction id is invalid": "ID giao dịch không hợp lệ", "transaction not found": "Không tìm thấy giao dịch", "transaction type is invalid": "Loại giao dịch không hợp lệ", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 5d9b4422..bf2270e9 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "父账户不能设置余额", "sub-account category not equals to parent": "子账户类别与父账户不同", "sub-account type invalid": "子账户类型无效", - "cannot add or delete sub-accounts when modify account": "您不能在修改账户时添加或删除子账户", "source account not found": "来源账户不存在", "destination account not found": "目标账户不存在", "account is in use and cannot be deleted": "账户正在被使用,无法删除", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "子账户不能设置账单日期", "sub-account not found": "子账户不存在", "sub-account is in use and cannot be deleted": "子账户正在被使用,无法删除", + "not supported to modify account currency": "不支持修改账户货币", + "not supported to modify account balance": "不支持修改账户余额", + "not supported to modify account balance time": "不支持修改账户余额时间", "transaction id is invalid": "交易ID无效", "transaction not found": "交易不存在", "transaction type is invalid": "交易类型无效", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 6106d015..aa4163ec 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1063,7 +1063,6 @@ "parent account cannot set balance": "父帳戶不能設定餘額", "sub-account category not equals to parent": "子帳戶類別與父帳戶不同", "sub-account type invalid": "子帳戶類型無效", - "cannot add or delete sub-accounts when modify account": "您不能在修改帳戶時新增或刪除子帳戶", "source account not found": "來源帳戶不存在", "destination account not found": "目標帳戶不存在", "account is in use and cannot be deleted": "帳戶正在被使用,無法刪除", @@ -1073,6 +1072,9 @@ "cannot set statement date for sub account": "子帳戶不能設定帳單日期", "sub-account not found": "子帳戶不存在", "sub-account is in use and cannot be deleted": "子帳戶正在被使用,無法刪除", + "not supported to modify account currency": "不支援修改帳戶貨幣", + "not supported to modify account balance": "不支援修改帳戶餘額", + "not supported to modify account balance time": "不支援修改帳戶餘額時間", "transaction id is invalid": "交易ID無效", "transaction not found": "交易不存在", "transaction type is invalid": "交易類型無效", diff --git a/src/models/account.ts b/src/models/account.ts index b6794c4a..3a22725a 100644 --- a/src/models/account.ts +++ b/src/models/account.ts @@ -186,7 +186,7 @@ export class Account implements AccountInfoResponse { }; } - public toModifyRequest(subAccounts?: Account[], parentAccount?: Account): AccountModifyRequest { + public toModifyRequest(clientSessionId: string, subAccounts?: Account[], parentAccount?: Account): AccountModifyRequest { let subAccountModifyRequests: AccountModifyRequest[] | undefined = undefined; if (this.type === AccountType.MultiSubAccounts.type) { @@ -198,21 +198,25 @@ export class Account implements AccountInfoResponse { if (subAccounts) { for (const subAccount of subAccounts) { - subAccountModifyRequests.push(subAccount.toModifyRequest(undefined, this)); + subAccountModifyRequests.push(subAccount.toModifyRequest(clientSessionId, undefined, this)); } } } return { - id: this.id, + id: this.id || '0', name: this.name, category: parentAccount ? parentAccount.category : this.category, icon: this.icon, color: this.color, + currency: parentAccount && (!this.id || this.id === '0') ? this.currency : undefined, + balance: parentAccount && (!this.id || this.id === '0') ? this.balance : undefined, + balanceTime: parentAccount && (!this.id || this.id === '0') ? this.balanceTime : undefined, comment: this.comment, creditCardStatementDate: !parentAccount && this.category === AccountCategory.CreditCard.type ? this.creditCardStatementDate : undefined, hidden: !this.visible, subAccounts: !parentAccount ? subAccountModifyRequests : undefined, + clientSessionId: !parentAccount ? clientSessionId : undefined }; } @@ -579,10 +583,14 @@ export interface AccountModifyRequest { readonly category: number; readonly icon: string; readonly color: string; + readonly currency?: string; + readonly balance?: number; + readonly balanceTime?: number; readonly comment: string; readonly creditCardStatementDate?: number; readonly hidden: boolean; readonly subAccounts?: AccountModifyRequest[]; + readonly clientSessionId?: string; } export interface AccountInfoResponse { diff --git a/src/stores/account.ts b/src/stores/account.ts index 3b963852..f0fb96cc 100644 --- a/src/stores/account.ts +++ b/src/stores/account.ts @@ -185,29 +185,38 @@ export const useAccountsStore = defineStore('accounts', () => { } } - function updateAccountToAccountList(account: Account): void { + function updateAccountToAccountList(oldAccount: Account, newAccount: Account): void { for (let i = 0; i < allAccounts.value.length; i++) { - if (allAccounts.value[i].id === account.id) { - allAccounts.value.splice(i, 1, account); + if (allAccounts.value[i].id === newAccount.id) { + allAccounts.value.splice(i, 1, newAccount); break; } } - allAccountsMap.value[account.id] = account; + if (oldAccount.subAccounts) { + for (let i = 0; i < oldAccount.subAccounts.length; i++) { + const subAccount = oldAccount.subAccounts[i]; + if (allAccountsMap.value[subAccount.id]) { + delete allAccountsMap.value[subAccount.id]; + } + } + } - if (account.subAccounts) { - for (let i = 0; i < account.subAccounts.length; i++) { - const subAccount = account.subAccounts[i]; + allAccountsMap.value[newAccount.id] = newAccount; + + if (newAccount.subAccounts) { + for (let i = 0; i < newAccount.subAccounts.length; i++) { + const subAccount = newAccount.subAccounts[i]; allAccountsMap.value[subAccount.id] = subAccount; } } - if (allCategorizedAccountsMap.value[account.category]) { - const accountList = allCategorizedAccountsMap.value[account.category].accounts; + if (allCategorizedAccountsMap.value[newAccount.category]) { + const accountList = allCategorizedAccountsMap.value[newAccount.category].accounts; for (let i = 0; i < accountList.length; i++) { - if (accountList[i].id === account.id) { - accountList.splice(i, 1, account); + if (accountList[i].id === newAccount.id) { + accountList.splice(i, 1, newAccount); break; } } @@ -847,7 +856,7 @@ export const useAccountsStore = defineStore('accounts', () => { if (!isEdit) { promise = services.addAccount(account.toCreateRequest(clientSessionId, subAccounts)); } else { - promise = services.modifyAccount(account.toModifyRequest(subAccounts)); + promise = services.modifyAccount(account.toModifyRequest(clientSessionId, subAccounts)); } promise.then(response => { @@ -868,7 +877,7 @@ export const useAccountsStore = defineStore('accounts', () => { addAccountToAccountList(newAccount); } else { if (oldAccount && oldAccount.category === newAccount.category) { - updateAccountToAccountList(newAccount); + updateAccountToAccountList(oldAccount, newAccount); } else { updateAccountListInvalidState(true); } diff --git a/src/views/base/accounts/AccountEditPageBase.ts b/src/views/base/accounts/AccountEditPageBase.ts index 32109f70..93db9707 100644 --- a/src/views/base/accounts/AccountEditPageBase.ts +++ b/src/views/base/accounts/AccountEditPageBase.ts @@ -91,6 +91,10 @@ export function useAccountEditPageBaseBase() { } } + function isNewAccount(account: Account): boolean { + return account.id === '' || account.id === '0'; + } + function isInputEmpty(): boolean { const isAccountEmpty = !!getInputEmptyProblemMessage(account.value, false); @@ -172,6 +176,7 @@ export function useAccountEditPageBaseBase() { isAccountSupportCreditCardStatementDate, // functions getAccountCreditCardStatementDate, + isNewAccount, isInputEmpty, getAccountOrSubAccountProblemMessage, addSubAccount, diff --git a/src/views/desktop/accounts/list/dialogs/EditDialog.vue b/src/views/desktop/accounts/list/dialogs/EditDialog.vue index 5e285aa4..411a5962 100644 --- a/src/views/desktop/accounts/list/dialogs/EditDialog.vue +++ b/src/views/desktop/accounts/list/dialogs/EditDialog.vue @@ -8,7 +8,7 @@ + :disabled="loading || submitting || account.type !== AccountType.MultiSubAccounts.type"> @@ -30,7 +30,7 @@ {{ tt('Sub Account') + ' #' + (idx + 1) }} @@ -109,7 +109,7 @@ v-model="selectedAccount.color" /> - @@ -128,9 +128,9 @@ v-model="account.creditCardStatementDate" > - - + v-if="(!editAccountId || isNewAccount(selectedAccount)) && (account.type === AccountType.SingleAccount.type || currentAccountIndex >= 0)"> - + @@ -236,6 +236,7 @@ const { allAccountTypes, allAvailableMonthDays, isAccountSupportCreditCardStatementDate, + isNewAccount, isInputEmpty, getAccountOrSubAccountProblemMessage, addSubAccount, @@ -288,6 +289,7 @@ function open(options?: { id?: string, currentAccount?: Account, category?: numb account.value.fillFrom(newAccount); subAccounts.value = []; currentAccountIndex.value = -1; + clientSessionId.value = generateRandomUUID(); if (options && options.id) { if (options.currentAccount) { @@ -317,7 +319,6 @@ function open(options?: { id?: string, currentAccount?: Account, category?: numb } editAccountId.value = null; - clientSessionId.value = generateRandomUUID(); loading.value = false; } diff --git a/src/views/mobile/accounts/EditPage.vue b/src/views/mobile/accounts/EditPage.vue index 199b6cbe..6402f78d 100644 --- a/src/views/mobile/accounts/EditPage.vue +++ b/src/views/mobile/accounts/EditPage.vue @@ -4,7 +4,7 @@ - + @@ -354,7 +354,6 @@ {{ tt('Sub Account') + ' #' + (idx + 1) }} @@ -420,9 +419,9 @@