mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 06:57:35 +08:00
move all transactions from one account to another account (#288)
This commit is contained in:
@@ -1114,6 +1114,63 @@ func (a *TransactionsApi) TransactionModifyHandler(c *core.WebContext) (any, *er
|
||||
return newTransactionResp, nil
|
||||
}
|
||||
|
||||
// TransactionMoveAllBetweenAccountsHandler moves all transactions from one account to another account for current user
|
||||
func (a *TransactionsApi) TransactionMoveAllBetweenAccountsHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
var transactionMoveReq models.TransactionMoveBetweenAccountsRequest
|
||||
err := c.ShouldBindJSON(&transactionMoveReq)
|
||||
|
||||
if err != nil {
|
||||
log.Warnf(c, "[transactions.TransactionMoveAllBetweenAccountsHandler] parse request failed, because %s", err.Error())
|
||||
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||
}
|
||||
|
||||
if transactionMoveReq.FromAccountId == transactionMoveReq.ToAccountId {
|
||||
return nil, errs.ErrCannotMoveTransactionToSameAccount
|
||||
}
|
||||
|
||||
uid := c.GetCurrentUid()
|
||||
accountMap, err := a.accounts.GetAccountsByAccountIds(c, uid, []int64{transactionMoveReq.FromAccountId, transactionMoveReq.ToAccountId})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionMoveAllBetweenAccountsHandler] failed to get accounts for user \"uid:%d\", because %s", uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
fromAccount, exists := accountMap[transactionMoveReq.FromAccountId]
|
||||
|
||||
if !exists {
|
||||
return nil, errs.ErrSourceAccountNotFound
|
||||
}
|
||||
|
||||
toAccount, exists := accountMap[transactionMoveReq.ToAccountId]
|
||||
|
||||
if !exists {
|
||||
return nil, errs.ErrDestinationAccountNotFound
|
||||
}
|
||||
|
||||
if fromAccount.Hidden || toAccount.Hidden {
|
||||
return nil, errs.ErrCannotMoveTransactionFromOrToHiddenAccount
|
||||
}
|
||||
|
||||
if fromAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS || toAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS {
|
||||
return nil, errs.ErrCannotMoveTransactionFromOrToParentAccount
|
||||
}
|
||||
|
||||
if fromAccount.Currency != toAccount.Currency {
|
||||
return nil, errs.ErrCannotMoveTransactionBetweenAccountsWithDifferentCurrencies
|
||||
}
|
||||
|
||||
err = a.transactions.MoveAllTransactionsBetweenAccounts(c, uid, transactionMoveReq.FromAccountId, transactionMoveReq.ToAccountId)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf(c, "[transactions.TransactionMoveAllBetweenAccountsHandler] failed to move all transactions from account \"id:%d\" to account \"id:%d\" for user \"uid:%d\", because %s", transactionMoveReq.FromAccountId, transactionMoveReq.ToAccountId, uid, err.Error())
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
log.Infof(c, "[transactions.TransactionMoveAllBetweenAccountsHandler] user \"uid:%d\" has moved all transactions from account \"id:%d\" to account \"id:%d\" successfully", uid, transactionMoveReq.FromAccountId, transactionMoveReq.ToAccountId)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// TransactionDeleteHandler deletes an existed transaction by request parameters for current user
|
||||
func (a *TransactionsApi) TransactionDeleteHandler(c *core.WebContext) (any, *errs.Error) {
|
||||
var transactionDeleteReq models.TransactionDeleteRequest
|
||||
|
||||
+41
-37
@@ -4,41 +4,45 @@ import "net/http"
|
||||
|
||||
// Error codes related to transaction
|
||||
var (
|
||||
ErrTransactionIdInvalid = NewNormalError(NormalSubcategoryTransaction, 0, http.StatusBadRequest, "transaction id is invalid")
|
||||
ErrTransactionNotFound = NewNormalError(NormalSubcategoryTransaction, 1, http.StatusBadRequest, "transaction not found")
|
||||
ErrTransactionTypeInvalid = NewNormalError(NormalSubcategoryTransaction, 2, http.StatusBadRequest, "transaction type is invalid")
|
||||
ErrTransactionSourceAndDestinationIdCannotBeEqual = NewNormalError(NormalSubcategoryTransaction, 3, http.StatusBadRequest, "transaction source and destination account id cannot be equal")
|
||||
ErrTransactionSourceAndDestinationAmountNotEqual = NewNormalError(NormalSubcategoryTransaction, 4, http.StatusBadRequest, "transaction source and destination amount not equal")
|
||||
ErrTransactionDestinationAccountCannotBeSet = NewNormalError(NormalSubcategoryTransaction, 5, http.StatusBadRequest, "transaction destination account cannot be set")
|
||||
ErrTransactionDestinationAmountCannotBeSet = NewNormalError(NormalSubcategoryTransaction, 6, http.StatusBadRequest, "transaction destination amount cannot be set")
|
||||
ErrTooMuchTransactionInOneSecond = NewNormalError(NormalSubcategoryTransaction, 7, http.StatusBadRequest, "too much transaction in one second")
|
||||
ErrBalanceModificationTransactionCannotSetCategory = NewNormalError(NormalSubcategoryTransaction, 8, http.StatusBadRequest, "balance modification transaction cannot set category")
|
||||
ErrBalanceModificationTransactionCannotChangeAccountId = NewNormalError(NormalSubcategoryTransaction, 9, http.StatusBadRequest, "balance modification transaction cannot change account id")
|
||||
ErrBalanceModificationTransactionCannotAddWhenNotEmpty = NewNormalError(NormalSubcategoryTransaction, 10, http.StatusBadRequest, "balance modification transaction cannot add when other transaction exists")
|
||||
ErrCannotAddTransactionToHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 11, http.StatusBadRequest, "cannot add transaction to hidden account")
|
||||
ErrCannotModifyTransactionInHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 12, http.StatusBadRequest, "cannot modify transaction of hidden account")
|
||||
ErrCannotDeleteTransactionInHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 13, http.StatusBadRequest, "cannot delete transaction in hidden account")
|
||||
ErrCannotAddTransactionToParentAccount = NewNormalError(NormalSubcategoryTransaction, 14, http.StatusBadRequest, "cannot add transaction to parent account")
|
||||
ErrCannotModifyTransactionInParentAccount = NewNormalError(NormalSubcategoryTransaction, 15, http.StatusBadRequest, "cannot modify transaction of parent account")
|
||||
ErrCannotDeleteTransactionInParentAccount = NewNormalError(NormalSubcategoryTransaction, 16, http.StatusBadRequest, "cannot delete transaction in parent account")
|
||||
ErrCannotCreateTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 17, http.StatusBadRequest, "cannot add transaction with this transaction time")
|
||||
ErrCannotModifyTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 18, http.StatusBadRequest, "cannot modify transaction with this transaction time")
|
||||
ErrCannotDeleteTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 19, http.StatusBadRequest, "cannot delete transaction with this transaction time")
|
||||
ErrCannotUseHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 20, http.StatusBadRequest, "cannot use hidden account")
|
||||
ErrCannotUseHiddenTransactionCategory = NewNormalError(NormalSubcategoryTransaction, 21, http.StatusBadRequest, "cannot use hidden transaction category")
|
||||
ErrCannotUseHiddenTransactionTag = NewNormalError(NormalSubcategoryTransaction, 22, http.StatusBadRequest, "cannot use hidden transaction tag")
|
||||
ErrTransactionHasTooManyTags = NewNormalError(NormalSubcategoryTransaction, 23, http.StatusBadRequest, "transaction has too many tags")
|
||||
ErrTransactionHasTooManyPictures = NewNormalError(NormalSubcategoryTransaction, 24, http.StatusBadRequest, "transaction has too many pictures")
|
||||
ErrImportFileTypeIsEmpty = NewNormalError(NormalSubcategoryTransaction, 25, http.StatusBadRequest, "import file type is empty")
|
||||
ErrImportFileTypeNotSupported = NewNormalError(NormalSubcategoryTransaction, 26, http.StatusBadRequest, "import file type not supported")
|
||||
ErrNoDataToImport = NewNormalError(NormalSubcategoryTransaction, 27, http.StatusBadRequest, "no data to import")
|
||||
ErrCannotAddTransactionBeforeBalanceModificationTransaction = NewNormalError(NormalSubcategoryTransaction, 28, http.StatusBadRequest, "cannot add transaction before balance modification transaction")
|
||||
ErrBalanceModificationTransactionCannotModifyTime = NewNormalError(NormalSubcategoryTransaction, 29, http.StatusBadRequest, "balance modification transaction cannot modify transaction time")
|
||||
ErrTransferTransactionAmountCannotBeLessThanZero = NewNormalError(NormalSubcategoryTransaction, 30, http.StatusBadRequest, "transfer transaction amount cannot be less than zero")
|
||||
ErrImportFileEncodingIsEmpty = NewNormalError(NormalSubcategoryTransaction, 31, http.StatusBadRequest, "import file encoding is empty")
|
||||
ErrImportFileEncodingNotSupported = NewNormalError(NormalSubcategoryTransaction, 32, http.StatusBadRequest, "import file encoding not supported")
|
||||
ErrImportFileColumnMappingInvalid = NewNormalError(NormalSubcategoryTransaction, 33, http.StatusBadRequest, "column mapping invalid")
|
||||
ErrImportFileTransactionTypeMappingInvalid = NewNormalError(NormalSubcategoryTransaction, 34, http.StatusBadRequest, "transaction type mapping invalid")
|
||||
ErrImportFileTransactionTimeFormatInvalid = NewNormalError(NormalSubcategoryTransaction, 35, http.StatusBadRequest, "transaction time format invalid")
|
||||
ErrImportFileTransactionTimezoneFormatInvalid = NewNormalError(NormalSubcategoryTransaction, 36, http.StatusBadRequest, "transaction time zone format invalid")
|
||||
ErrTransactionIdInvalid = NewNormalError(NormalSubcategoryTransaction, 0, http.StatusBadRequest, "transaction id is invalid")
|
||||
ErrTransactionNotFound = NewNormalError(NormalSubcategoryTransaction, 1, http.StatusBadRequest, "transaction not found")
|
||||
ErrTransactionTypeInvalid = NewNormalError(NormalSubcategoryTransaction, 2, http.StatusBadRequest, "transaction type is invalid")
|
||||
ErrTransactionSourceAndDestinationIdCannotBeEqual = NewNormalError(NormalSubcategoryTransaction, 3, http.StatusBadRequest, "transaction source and destination account id cannot be equal")
|
||||
ErrTransactionSourceAndDestinationAmountNotEqual = NewNormalError(NormalSubcategoryTransaction, 4, http.StatusBadRequest, "transaction source and destination amount not equal")
|
||||
ErrTransactionDestinationAccountCannotBeSet = NewNormalError(NormalSubcategoryTransaction, 5, http.StatusBadRequest, "transaction destination account cannot be set")
|
||||
ErrTransactionDestinationAmountCannotBeSet = NewNormalError(NormalSubcategoryTransaction, 6, http.StatusBadRequest, "transaction destination amount cannot be set")
|
||||
ErrTooMuchTransactionInOneSecond = NewNormalError(NormalSubcategoryTransaction, 7, http.StatusBadRequest, "too much transaction in one second")
|
||||
ErrBalanceModificationTransactionCannotSetCategory = NewNormalError(NormalSubcategoryTransaction, 8, http.StatusBadRequest, "balance modification transaction cannot set category")
|
||||
ErrBalanceModificationTransactionCannotChangeAccountId = NewNormalError(NormalSubcategoryTransaction, 9, http.StatusBadRequest, "balance modification transaction cannot change account id")
|
||||
ErrBalanceModificationTransactionCannotAddWhenNotEmpty = NewNormalError(NormalSubcategoryTransaction, 10, http.StatusBadRequest, "balance modification transaction cannot add when other transaction exists")
|
||||
ErrCannotAddTransactionToHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 11, http.StatusBadRequest, "cannot add transaction to hidden account")
|
||||
ErrCannotModifyTransactionInHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 12, http.StatusBadRequest, "cannot modify transaction of hidden account")
|
||||
ErrCannotDeleteTransactionInHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 13, http.StatusBadRequest, "cannot delete transaction in hidden account")
|
||||
ErrCannotAddTransactionToParentAccount = NewNormalError(NormalSubcategoryTransaction, 14, http.StatusBadRequest, "cannot add transaction to parent account")
|
||||
ErrCannotModifyTransactionInParentAccount = NewNormalError(NormalSubcategoryTransaction, 15, http.StatusBadRequest, "cannot modify transaction of parent account")
|
||||
ErrCannotDeleteTransactionInParentAccount = NewNormalError(NormalSubcategoryTransaction, 16, http.StatusBadRequest, "cannot delete transaction in parent account")
|
||||
ErrCannotCreateTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 17, http.StatusBadRequest, "cannot add transaction with this transaction time")
|
||||
ErrCannotModifyTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 18, http.StatusBadRequest, "cannot modify transaction with this transaction time")
|
||||
ErrCannotDeleteTransactionWithThisTransactionTime = NewNormalError(NormalSubcategoryTransaction, 19, http.StatusBadRequest, "cannot delete transaction with this transaction time")
|
||||
ErrCannotUseHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 20, http.StatusBadRequest, "cannot use hidden account")
|
||||
ErrCannotUseHiddenTransactionCategory = NewNormalError(NormalSubcategoryTransaction, 21, http.StatusBadRequest, "cannot use hidden transaction category")
|
||||
ErrCannotUseHiddenTransactionTag = NewNormalError(NormalSubcategoryTransaction, 22, http.StatusBadRequest, "cannot use hidden transaction tag")
|
||||
ErrTransactionHasTooManyTags = NewNormalError(NormalSubcategoryTransaction, 23, http.StatusBadRequest, "transaction has too many tags")
|
||||
ErrTransactionHasTooManyPictures = NewNormalError(NormalSubcategoryTransaction, 24, http.StatusBadRequest, "transaction has too many pictures")
|
||||
ErrImportFileTypeIsEmpty = NewNormalError(NormalSubcategoryTransaction, 25, http.StatusBadRequest, "import file type is empty")
|
||||
ErrImportFileTypeNotSupported = NewNormalError(NormalSubcategoryTransaction, 26, http.StatusBadRequest, "import file type not supported")
|
||||
ErrNoDataToImport = NewNormalError(NormalSubcategoryTransaction, 27, http.StatusBadRequest, "no data to import")
|
||||
ErrCannotAddTransactionBeforeBalanceModificationTransaction = NewNormalError(NormalSubcategoryTransaction, 28, http.StatusBadRequest, "cannot add transaction before balance modification transaction")
|
||||
ErrBalanceModificationTransactionCannotModifyTime = NewNormalError(NormalSubcategoryTransaction, 29, http.StatusBadRequest, "balance modification transaction cannot modify transaction time")
|
||||
ErrTransferTransactionAmountCannotBeLessThanZero = NewNormalError(NormalSubcategoryTransaction, 30, http.StatusBadRequest, "transfer transaction amount cannot be less than zero")
|
||||
ErrImportFileEncodingIsEmpty = NewNormalError(NormalSubcategoryTransaction, 31, http.StatusBadRequest, "import file encoding is empty")
|
||||
ErrImportFileEncodingNotSupported = NewNormalError(NormalSubcategoryTransaction, 32, http.StatusBadRequest, "import file encoding not supported")
|
||||
ErrImportFileColumnMappingInvalid = NewNormalError(NormalSubcategoryTransaction, 33, http.StatusBadRequest, "column mapping invalid")
|
||||
ErrImportFileTransactionTypeMappingInvalid = NewNormalError(NormalSubcategoryTransaction, 34, http.StatusBadRequest, "transaction type mapping invalid")
|
||||
ErrImportFileTransactionTimeFormatInvalid = NewNormalError(NormalSubcategoryTransaction, 35, http.StatusBadRequest, "transaction time format invalid")
|
||||
ErrImportFileTransactionTimezoneFormatInvalid = NewNormalError(NormalSubcategoryTransaction, 36, http.StatusBadRequest, "transaction time zone format invalid")
|
||||
ErrCannotMoveTransactionToSameAccount = NewNormalError(NormalSubcategoryTransaction, 37, http.StatusBadRequest, "cannot move transaction to same account")
|
||||
ErrCannotMoveTransactionFromOrToHiddenAccount = NewNormalError(NormalSubcategoryTransaction, 38, http.StatusBadRequest, "cannot move transaction from or to hidden account")
|
||||
ErrCannotMoveTransactionFromOrToParentAccount = NewNormalError(NormalSubcategoryTransaction, 39, http.StatusBadRequest, "cannot move transaction from or to parent account")
|
||||
ErrCannotMoveTransactionBetweenAccountsWithDifferentCurrencies = NewNormalError(NormalSubcategoryTransaction, 40, http.StatusBadRequest, "cannot move transaction between accounts with different currencies")
|
||||
)
|
||||
|
||||
@@ -279,6 +279,12 @@ type TransactionGetRequest struct {
|
||||
TrimTag bool `form:"trim_tag"`
|
||||
}
|
||||
|
||||
// TransactionMoveBetweenAccountsRequest represents all parameters of moving all transactions between accounts request
|
||||
type TransactionMoveBetweenAccountsRequest struct {
|
||||
FromAccountId int64 `json:"fromAccountId,string" binding:"required,min=1"`
|
||||
ToAccountId int64 `json:"toAccountId,string" binding:"required,min=1"`
|
||||
}
|
||||
|
||||
// TransactionDeleteRequest represents all parameters of transaction deleting request
|
||||
type TransactionDeleteRequest struct {
|
||||
Id int64 `json:"id,string" binding:"required,min=1"`
|
||||
|
||||
@@ -1168,6 +1168,219 @@ func (s *TransactionService) ModifyTransaction(c core.Context, transaction *mode
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TransactionService) MoveAllTransactionsBetweenAccounts(c core.Context, uid int64, fromAccountId int64, toAccountId int64) error {
|
||||
if uid <= 0 {
|
||||
return errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
if fromAccountId <= 0 || toAccountId <= 0 {
|
||||
return errs.ErrAccountIdInvalid
|
||||
}
|
||||
|
||||
if fromAccountId == toAccountId {
|
||||
return errs.ErrCannotMoveTransactionToSameAccount
|
||||
}
|
||||
|
||||
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
|
||||
// get and verify from and to account
|
||||
fromAccount := &models.Account{}
|
||||
has, err := sess.ID(fromAccountId).Where("uid=? AND deleted=?", uid, false).Get(fromAccount)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return errs.ErrAccountNotFound
|
||||
}
|
||||
|
||||
toAccount := &models.Account{}
|
||||
has, err = sess.ID(toAccountId).Where("uid=? AND deleted=?", uid, false).Get(toAccount)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
return errs.ErrAccountNotFound
|
||||
}
|
||||
|
||||
if fromAccount.Hidden || toAccount.Hidden {
|
||||
return errs.ErrCannotMoveTransactionFromOrToHiddenAccount
|
||||
}
|
||||
|
||||
if fromAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS || toAccount.Type == models.ACCOUNT_TYPE_MULTI_SUB_ACCOUNTS {
|
||||
return errs.ErrCannotMoveTransactionFromOrToParentAccount
|
||||
}
|
||||
|
||||
if fromAccount.Currency != toAccount.Currency {
|
||||
return errs.ErrCannotMoveTransactionBetweenAccountsWithDifferentCurrencies
|
||||
}
|
||||
|
||||
// combine balance modification transaction
|
||||
var balanceModificationTransactions []*models.Transaction
|
||||
err = sess.Where("uid=? AND deleted=? AND type=? AND (account_id=? OR account_id=?)", uid, false, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE, fromAccountId, toAccountId).Find(&balanceModificationTransactions)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(balanceModificationTransactions) > 2 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has more than 2 balance modification transactions in account \"id:%d\" and account \"id:%d\", cannot combine balance modification transaction", uid, fromAccountId, toAccountId)
|
||||
return errs.ErrOperationFailed
|
||||
} else if len(balanceModificationTransactions) == 2 && balanceModificationTransactions[0].AccountId != balanceModificationTransactions[1].AccountId {
|
||||
// if two balance modification transactions exist, merge the amounts into the earlier one and delete the later transaction
|
||||
var earlierTransaction *models.Transaction
|
||||
var laterTransaction *models.Transaction
|
||||
|
||||
if balanceModificationTransactions[0].TransactionTime < balanceModificationTransactions[1].TransactionTime {
|
||||
earlierTransaction = balanceModificationTransactions[0]
|
||||
laterTransaction = balanceModificationTransactions[1]
|
||||
} else {
|
||||
earlierTransaction = balanceModificationTransactions[1]
|
||||
laterTransaction = balanceModificationTransactions[0]
|
||||
}
|
||||
|
||||
earlierTransaction.Amount += laterTransaction.Amount
|
||||
earlierTransaction.RelatedAccountAmount += laterTransaction.RelatedAccountAmount
|
||||
earlierTransaction.UpdatedUnixTime = time.Now().Unix()
|
||||
|
||||
updatedRows, err := sess.ID(earlierTransaction.TransactionId).Cols("amount", "related_account_amount", "updated_unix_time").Where("uid=? AND deleted=?", uid, false).Update(earlierTransaction)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if updatedRows < 1 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] failed to update earlier balance modification transaction")
|
||||
return errs.ErrDatabaseOperationFailed
|
||||
}
|
||||
|
||||
laterTransaction.Deleted = true
|
||||
laterTransaction.DeletedUnixTime = time.Now().Unix()
|
||||
|
||||
deletedRows, err := sess.ID(laterTransaction.TransactionId).Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).Update(laterTransaction)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if deletedRows < 1 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] failed to delete later balance modification transaction")
|
||||
return errs.ErrDatabaseOperationFailed
|
||||
}
|
||||
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has combined two balance modification transactions \"id:%d\" and \"id:%d\", retained transaction is \"id:%d\"", uid, earlierTransaction.TransactionId, laterTransaction.TransactionId, earlierTransaction.TransactionId)
|
||||
} else if len(balanceModificationTransactions) == 1 {
|
||||
// when merging a new balance modification transaction, if its date is later than the account's earliest transaction, update the balance modification transaction time accordingly
|
||||
anotherAccountId := int64(0)
|
||||
|
||||
if balanceModificationTransactions[0].AccountId == fromAccountId {
|
||||
anotherAccountId = toAccountId
|
||||
} else if balanceModificationTransactions[0].AccountId == toAccountId {
|
||||
anotherAccountId = fromAccountId
|
||||
} else {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has a balance modification transaction \"id:%d\" which account id is neither \"%d\" nor \"%d\"", uid, balanceModificationTransactions[0].TransactionId, fromAccountId, toAccountId)
|
||||
return errs.ErrOperationFailed
|
||||
}
|
||||
|
||||
earliestTransaction := &models.Transaction{}
|
||||
has, err := sess.Where("uid=? AND deleted=? AND account_id=?", uid, false, anotherAccountId).OrderBy("transaction_time asc").Limit(1).Get(earliestTransaction)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has && balanceModificationTransactions[0].TransactionTime > earliestTransaction.TransactionTime {
|
||||
balanceModificationTransaction := balanceModificationTransactions[0]
|
||||
balanceModificationTransaction.TransactionTime = utils.GetMinTransactionTimeFromUnixTime(utils.GetUnixTimeFromTransactionTime(earliestTransaction.TransactionTime) - 1)
|
||||
balanceModificationTransaction.UpdatedUnixTime = time.Now().Unix()
|
||||
|
||||
if balanceModificationTransaction.TransactionTime < 0 {
|
||||
balanceModificationTransaction.TransactionTime = 0
|
||||
}
|
||||
|
||||
updatedRows, err := sess.ID(balanceModificationTransaction.TransactionId).Cols("transaction_time", "updated_unix_time").Where("uid=? AND deleted=?", uid, false).Update(balanceModificationTransaction)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if updatedRows < 1 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] failed to update balance modification transaction time")
|
||||
return errs.ErrDatabaseOperationFailed
|
||||
}
|
||||
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has updated balance modification transaction \"id:%d\" time to %d, because earliest transaction time in account \"id:%d\" is %d", uid, balanceModificationTransaction.TransactionId, balanceModificationTransaction.TransactionTime, toAccountId, earliestTransaction.TransactionTime)
|
||||
}
|
||||
}
|
||||
|
||||
// update all transactions of from account
|
||||
updateModel := &models.Transaction{
|
||||
AccountId: toAccountId,
|
||||
UpdatedUnixTime: time.Now().Unix(),
|
||||
}
|
||||
|
||||
updatedRows, err := sess.Cols("account_id", "updated_unix_time").Where("uid=? AND deleted=? AND account_id=?", uid, false, fromAccountId).Update(updateModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updatedRows > 0 {
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has moved %d transactions from account \"id:%d\" to account \"id:%d\"", uid, updatedRows, fromAccountId, toAccountId)
|
||||
}
|
||||
|
||||
// update all related transactions of from account
|
||||
updateRelatedModel := &models.Transaction{
|
||||
RelatedAccountId: toAccountId,
|
||||
UpdatedUnixTime: time.Now().Unix(),
|
||||
}
|
||||
|
||||
relatedUpdatedRows, err := sess.Cols("related_account_id", "updated_unix_time").Where("uid=? AND deleted=? AND related_account_id=?", uid, false, fromAccountId).Update(updateRelatedModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if updatedRows > 0 {
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has moved %d related transactions from account \"id:%d\" to account \"id:%d\"", uid, relatedUpdatedRows, fromAccountId, toAccountId)
|
||||
}
|
||||
|
||||
// delete all transfer transactions which related account id and account id are both
|
||||
deletedModel := &models.Transaction{
|
||||
Deleted: true,
|
||||
DeletedUnixTime: time.Now().Unix(),
|
||||
}
|
||||
|
||||
deletedRows, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=? AND (type=? OR type=?) AND account_id=? AND related_account_id=?", uid, false, models.TRANSACTION_DB_TYPE_TRANSFER_OUT, models.TRANSACTION_DB_TYPE_TRANSFER_IN, toAccountId, toAccountId).Update(deletedModel)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if deletedRows > 0 {
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has deleted %d transactions which account id and related account id are both \"%d\"", uid, deletedRows, toAccountId)
|
||||
}
|
||||
|
||||
// update account balance
|
||||
if fromAccount.Balance != 0 {
|
||||
toAccount.UpdatedUnixTime = time.Now().Unix()
|
||||
updatedRows, err := sess.ID(toAccount.AccountId).SetExpr("balance", fmt.Sprintf("balance+(%d)", fromAccount.Balance)).Cols("updated_unix_time").Where("uid=? AND deleted=?", uid, false).Update(toAccount)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if updatedRows < 1 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] failed to update to account balance")
|
||||
return errs.ErrDatabaseOperationFailed
|
||||
}
|
||||
|
||||
log.Infof(c, "[transactions.MoveAllTransactionsBetweenAccounts] user \"uid:%d\" has updated account \"id:%d\" balance from %d to %d", uid, toAccountId, toAccount.Balance, toAccount.Balance+fromAccount.Balance)
|
||||
|
||||
fromAccount.Balance = 0
|
||||
fromAccount.UpdatedUnixTime = time.Now().Unix()
|
||||
updatedRows, err = sess.ID(fromAccount.AccountId).Cols("balance", "updated_unix_time").Where("uid=? AND deleted=?", fromAccount.Uid, false).Update(fromAccount)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
} else if updatedRows < 1 {
|
||||
log.Errorf(c, "[transactions.MoveAllTransactionsBetweenAccounts] failed to update from account balance")
|
||||
return errs.ErrDatabaseOperationFailed
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DeleteTransaction deletes an existed transaction from database
|
||||
func (s *TransactionService) DeleteTransaction(c core.Context, uid int64, transactionId int64) error {
|
||||
if uid <= 0 {
|
||||
|
||||
Reference in New Issue
Block a user