support hiding/unhiding/deleting sub-account in account list page

This commit is contained in:
MaysWind
2025-04-13 20:46:06 +08:00
parent 68b08c1e8a
commit df31be61e8
15 changed files with 329 additions and 32 deletions
+22
View File
@@ -508,6 +508,28 @@ func (a *AccountsApi) AccountDeleteHandler(c *core.WebContext) (any, *errs.Error
return true, nil
}
// SubAccountDeleteHandler deletes an existed sub-account by request parameters for current user
func (a *AccountsApi) SubAccountDeleteHandler(c *core.WebContext) (any, *errs.Error) {
var accountDeleteReq models.AccountDeleteRequest
err := c.ShouldBindJSON(&accountDeleteReq)
if err != nil {
log.Warnf(c, "[accounts.SubAccountDeleteHandler] parse request failed, because %s", err.Error())
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
}
uid := c.GetCurrentUid()
err = a.accounts.DeleteSubAccount(c, uid, accountDeleteReq.Id)
if err != nil {
log.Errorf(c, "[accounts.SubAccountDeleteHandler] failed to delete sub-account \"id:%d\" for user \"uid:%d\", because %s", accountDeleteReq.Id, uid, err.Error())
return nil, errs.Or(err, errs.ErrOperationFailed)
}
log.Infof(c, "[accounts.SubAccountDeleteHandler] user \"uid:%d\" has deleted sub-account \"id:%d\"", uid, accountDeleteReq.Id)
return true, nil
}
func (a *AccountsApi) createNewAccountModel(uid int64, accountCreateReq *models.AccountCreateRequest, isSubAccount bool, order int32) *models.Account {
accountExtend := &models.AccountExtend{}
+2
View File
@@ -22,4 +22,6 @@ var (
ErrAccountBalanceTimeNotSet = NewNormalError(NormalSubcategoryAccount, 15, http.StatusBadRequest, "account balance time is not set")
ErrCannotSetStatementDateForNonCreditCard = NewNormalError(NormalSubcategoryAccount, 16, http.StatusBadRequest, "cannot set statement date for non credit card account")
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")
)
+81 -1
View File
@@ -429,7 +429,7 @@ func (s *AccountService) DeleteAccount(c core.Context, uid int64, accountId int6
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
var accountAndSubAccounts []*models.Account
err := sess.Where("uid=? AND deleted=? AND (account_id=? OR parent_account_id=?)", uid, false, accountId, accountId).Find(&accountAndSubAccounts)
err := sess.Where("uid=? AND deleted=? AND ((account_id=? AND parent_account_id=?) OR parent_account_id=?)", uid, false, accountId, models.LevelOneAccountParentId, accountId).Find(&accountAndSubAccounts)
if err != nil {
return err
@@ -499,6 +499,86 @@ func (s *AccountService) DeleteAccount(c core.Context, uid int64, accountId int6
})
}
// DeleteSubAccount deletes an existed sub-account from database
func (s *AccountService) DeleteSubAccount(c core.Context, uid int64, accountId int64) error {
if uid <= 0 {
return errs.ErrUserIdInvalid
}
now := time.Now().Unix()
updateModel := &models.Account{
Balance: 0,
Deleted: true,
DeletedUnixTime: now,
}
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
account := &models.Account{}
has, err := sess.Cols("account_id", "uid", "deleted", "parent_account_id").Where("uid=? AND deleted=? AND account_id=? AND parent_account_id<>?", uid, false, accountId, models.LevelOneAccountParentId).Limit(1).Get(account)
if err != nil {
return err
} else if !has {
return errs.ErrSubAccountNotFound
}
subAccountsCount, err := sess.Where("uid=? AND deleted=? AND parent_account_id=?", uid, false, account.ParentAccountId).Count(&models.Account{})
if subAccountsCount <= 1 {
return errs.ErrAccountHaveNoSubAccount
}
var relatedTransactionsByAccount []*models.Transaction
err = sess.Cols("transaction_id", "uid", "deleted", "account_id", "type").Where("uid=? AND deleted=? AND account_id=?", uid, false, accountId).Limit(2).Find(&relatedTransactionsByAccount)
if err != nil {
return err
} else if len(relatedTransactionsByAccount) > 1 {
return errs.ErrSubAccountInUseCannotBeDeleted
} else if len(relatedTransactionsByAccount) > 0 {
for i := 0; i < len(relatedTransactionsByAccount); i++ {
transaction := relatedTransactionsByAccount[i]
if transaction.Type != models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
return errs.ErrSubAccountInUseCannotBeDeleted
}
}
}
deletedRows, err := sess.Cols("balance", "deleted", "deleted_unix_time").Where("uid=? AND deleted=? AND account_id=?", uid, false, accountId).Update(updateModel)
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=?", uid, false).In("transaction_id", transactionIds).Update(updateTransaction)
if err != nil {
return err
} else if deletedTransactionRows < int64(len(transactionIds)) {
return errs.ErrDatabaseOperationFailed
}
}
return err
})
}
// GetAccountMapByList returns an account map by a list
func (s *AccountService) GetAccountMapByList(accounts []*models.Account) map[int64]*models.Account {
accountMap := make(map[int64]*models.Account)