support batch update tags for transactions

This commit is contained in:
MaysWind
2026-04-26 00:52:44 +08:00
parent bab7a0041b
commit 1e38d1b18b
29 changed files with 924 additions and 6 deletions
+158 -4
View File
@@ -1033,7 +1033,7 @@ func (s *TransactionService) ModifyTransaction(c core.Context, transaction *mode
}
// Get and verify tags
err = s.isTagsValid(sess, transaction, transactionTagIndexes, addTagIds)
err = s.isTagsValid(sess, transaction.Uid, transactionTagIndexes, addTagIds)
if err != nil {
return err
@@ -1373,6 +1373,160 @@ func (s *TransactionService) BatchUpdateTransactionsCategory(c core.Context, uid
})
}
// BatchAddTagsToTransactions batch adds tags to transactions
func (s *TransactionService) BatchAddTagsToTransactions(c core.Context, uid int64, transactions []*models.Transaction, addTransactionTagIds map[int64][]int64) error {
if uid <= 0 {
return errs.ErrUserIdInvalid
}
if len(addTransactionTagIds) < 1 {
return errs.ErrTransactionIdInvalid
}
now := time.Now().Unix()
transactionTagIndexes := make([]*models.TransactionTagIndex, 0, len(addTransactionTagIds))
transactionsMap := make(map[int64]*models.Transaction, len(transactions))
transactionTagIdsMap := make(map[int64]bool, 0)
for i := 0; i < len(transactions); i++ {
transaction := transactions[i]
transactionsMap[transaction.TransactionId] = transaction
}
for transactionId, tagIds := range addTransactionTagIds {
if transactionId <= 0 {
return errs.ErrTransactionIdInvalid
}
transaction, exists := transactionsMap[transactionId]
if !exists || transaction == nil {
return errs.ErrTransactionNotFound
}
tagIds = utils.ToUniqueInt64Slice(tagIds)
for i := 0; i < len(tagIds); i++ {
tagId := tagIds[i]
if tagId <= 0 {
return errs.ErrTransactionTagIdInvalid
}
transactionTagIndexes = append(transactionTagIndexes, &models.TransactionTagIndex{
Uid: uid,
Deleted: false,
TransactionTime: transaction.TransactionTime,
TagId: tagId,
TransactionId: transactionId,
CreatedUnixTime: now,
UpdatedUnixTime: now,
})
transactionTagIdsMap[tagId] = true
}
}
tagIndexUuids := s.GenerateUuids(uuid.UUID_TYPE_TAG_INDEX, uint16(len(transactionTagIndexes)))
if len(tagIndexUuids) < len(transactionTagIndexes) {
return errs.ErrCannotAddTagsToTooManyTransactionsOneTime
}
for i := 0; i < len(transactionTagIndexes); i++ {
transactionTagIndexes[i].TagIndexId = tagIndexUuids[i]
}
tagIds := make([]int64, 0, len(transactionTagIdsMap))
for tagId := range transactionTagIdsMap {
tagIds = append(tagIds, tagId)
}
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
// Get and verify tags
err := s.isTagsValid(sess, uid, transactionTagIndexes, tagIds)
if err != nil {
return err
}
for i := 0; i < len(transactionTagIndexes); i++ {
transactionTagIndex := transactionTagIndexes[i]
_, err := sess.Insert(transactionTagIndex)
if err != nil {
return err
}
}
return nil
})
}
// BatchRemoveTagsFromTransactions batch removes tags from transactions
func (s *TransactionService) BatchRemoveTagsFromTransactions(c core.Context, uid int64, transactionIds []int64, tagIds []int64) error {
if uid <= 0 {
return errs.ErrUserIdInvalid
}
if len(transactionIds) < 1 {
return errs.ErrTransactionIdInvalid
}
uniqueTransactionIds := utils.ToUniqueInt64Slice(transactionIds)
uniqueTagIds := utils.ToUniqueInt64Slice(tagIds)
now := time.Now().Unix()
tagIndexUpdateModel := &models.TransactionTagIndex{
Deleted: true,
DeletedUnixTime: now,
}
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
deletedRows, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).In("transaction_id", uniqueTransactionIds).In("tag_id", uniqueTagIds).Update(tagIndexUpdateModel)
if err != nil {
return err
} else if deletedRows < 1 {
return errs.ErrTransactionTagNotFound
}
return nil
})
}
// BatchClearAllTagsFromTransactions batch clears all tags from transactions
func (s *TransactionService) BatchClearAllTagsFromTransactions(c core.Context, uid int64, transactionIds []int64) error {
if uid <= 0 {
return errs.ErrUserIdInvalid
}
if len(transactionIds) < 1 {
return errs.ErrTransactionIdInvalid
}
uniqueTransactionIds := utils.ToUniqueInt64Slice(transactionIds)
now := time.Now().Unix()
tagIndexUpdateModel := &models.TransactionTagIndex{
Deleted: true,
DeletedUnixTime: now,
}
return s.UserDataDB(uid).DoTransaction(c, func(sess *xorm.Session) error {
deletedRows, err := sess.Cols("deleted", "deleted_unix_time").Where("uid=? AND deleted=?", uid, false).In("transaction_id", uniqueTransactionIds).Update(tagIndexUpdateModel)
if err != nil {
return err
} else if deletedRows < 1 {
return errs.ErrTransactionTagNotFound
}
return nil
})
}
// MoveAllTransactionsBetweenAccounts moves all transactions from one account to another account, and combine balance modification transactions if necessary
func (s *TransactionService) MoveAllTransactionsBetweenAccounts(c core.Context, uid int64, fromAccountId int64, toAccountId int64) error {
if uid <= 0 {
@@ -2317,7 +2471,7 @@ func (s *TransactionService) doCreateTransaction(c core.Context, database *datas
}
// Get and verify tags
err = s.isTagsValid(sess, transaction, transactionTagIndexes, tagIds)
err = s.isTagsValid(sess, transaction.Uid, transactionTagIndexes, tagIds)
if err != nil {
return err
@@ -2954,10 +3108,10 @@ func (s *TransactionService) isCategoryValid(sess *xorm.Session, transaction *mo
return nil
}
func (s *TransactionService) isTagsValid(sess *xorm.Session, transaction *models.Transaction, transactionTagIndexes []*models.TransactionTagIndex, tagIds []int64) error {
func (s *TransactionService) isTagsValid(sess *xorm.Session, uid int64, transactionTagIndexes []*models.TransactionTagIndex, tagIds []int64) error {
if len(transactionTagIndexes) > 0 {
var tags []*models.TransactionTag
err := sess.Where("uid=? AND deleted=?", transaction.Uid, false).In("tag_id", tagIds).Find(&tags)
err := sess.Where("uid=? AND deleted=?", uid, false).In("tag_id", tagIds).Find(&tags)
if err != nil {
return err