mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-18 00:34:28 +08:00
support filtering transaction amount
This commit is contained in:
@@ -59,7 +59,7 @@ func (a *TransactionsApi) TransactionCountHandler(c *core.Context) (any, *errs.E
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
totalCount, err := a.transactions.GetTransactionCount(c, uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, allAccountIds, transactionCountReq.Keyword)
|
||||
totalCount, err := a.transactions.GetTransactionCount(c, uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, allAccountIds, transactionCountReq.AmountFilter, transactionCountReq.Keyword)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[transactions.TransactionCountHandler] failed to get transaction count for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -118,7 +118,7 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (any, *errs.Er
|
||||
var totalCount int64
|
||||
|
||||
if transactionListReq.WithCount {
|
||||
totalCount, err = a.transactions.GetTransactionCount(c, uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword)
|
||||
totalCount, err = a.transactions.GetTransactionCount(c, uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.AmountFilter, transactionListReq.Keyword)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transaction count for user \"uid:%d\", because %s", uid, err.Error())
|
||||
@@ -126,7 +126,7 @@ func (a *TransactionsApi) TransactionListHandler(c *core.Context) (any, *errs.Er
|
||||
}
|
||||
}
|
||||
|
||||
transactions, err := a.transactions.GetTransactionsByMaxTime(c, uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, true, true)
|
||||
transactions, err := a.transactions.GetTransactionsByMaxTime(c, uid, transactionListReq.MaxTime, transactionListReq.MinTime, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.AmountFilter, transactionListReq.Keyword, transactionListReq.Page, transactionListReq.Count, true, true)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[transactions.TransactionListHandler] failed to get transactions earlier than \"%d\" for user \"uid:%d\", because %s", transactionListReq.MaxTime, uid, err.Error())
|
||||
@@ -206,7 +206,7 @@ func (a *TransactionsApi) TransactionMonthListHandler(c *core.Context) (any, *er
|
||||
return nil, errs.Or(err, errs.ErrOperationFailed)
|
||||
}
|
||||
|
||||
transactions, err := a.transactions.GetTransactionsInMonthByPage(c, uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.Keyword)
|
||||
transactions, err := a.transactions.GetTransactionsInMonthByPage(c, uid, transactionListReq.Year, transactionListReq.Month, transactionListReq.Type, allCategoryIds, allAccountIds, transactionListReq.AmountFilter, transactionListReq.Keyword)
|
||||
|
||||
if err != nil {
|
||||
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthListHandler] failed to get transactions in month \"%d-%d\" for user \"uid:%d\", because %s", transactionListReq.Year, transactionListReq.Month, uid, err.Error())
|
||||
|
||||
@@ -82,3 +82,8 @@ func GetParameterInvalidCurrencyMessage(field string) string {
|
||||
func GetParameterInvalidHexRGBColorMessage(field string) string {
|
||||
return fmt.Sprintf("parameter \"%s\" is invalid color", field)
|
||||
}
|
||||
|
||||
// GetParameterInvalidAmountFilterMessage returns specific error message for invalid amount filter parameter error
|
||||
func GetParameterInvalidAmountFilterMessage(field string) string {
|
||||
return fmt.Sprintf("parameter \"%s\" is invalid amount filter", field)
|
||||
}
|
||||
|
||||
@@ -94,12 +94,13 @@ type TransactionModifyRequest struct {
|
||||
|
||||
// TransactionCountRequest represents transaction count request
|
||||
type TransactionCountRequest struct {
|
||||
Type TransactionDbType `form:"type" binding:"min=0,max=4"`
|
||||
CategoryId int64 `form:"category_id" binding:"min=0"`
|
||||
AccountId int64 `form:"account_id" binding:"min=0"`
|
||||
Keyword string `form:"keyword"`
|
||||
MaxTime int64 `form:"max_time" binding:"min=0"`
|
||||
MinTime int64 `form:"min_time" binding:"min=0"`
|
||||
Type TransactionDbType `form:"type" binding:"min=0,max=4"`
|
||||
CategoryId int64 `form:"category_id" binding:"min=0"`
|
||||
AccountId int64 `form:"account_id" binding:"min=0"`
|
||||
AmountFilter string `form:"amount_filter" binding:"validAmountFilter"`
|
||||
Keyword string `form:"keyword"`
|
||||
MaxTime int64 `form:"max_time" binding:"min=0"`
|
||||
MinTime int64 `form:"min_time" binding:"min=0"`
|
||||
}
|
||||
|
||||
// TransactionListByMaxTimeRequest represents all parameters of transaction listing by max time request
|
||||
@@ -107,6 +108,7 @@ type TransactionListByMaxTimeRequest struct {
|
||||
Type TransactionDbType `form:"type" binding:"min=0,max=4"`
|
||||
CategoryId int64 `form:"category_id" binding:"min=0"`
|
||||
AccountId int64 `form:"account_id" binding:"min=0"`
|
||||
AmountFilter string `form:"amount_filter" binding:"validAmountFilter"`
|
||||
Keyword string `form:"keyword"`
|
||||
MaxTime int64 `form:"max_time" binding:"min=0"`
|
||||
MinTime int64 `form:"min_time" binding:"min=0"`
|
||||
@@ -125,6 +127,7 @@ type TransactionListInMonthByPageRequest struct {
|
||||
Type TransactionDbType `form:"type" binding:"min=0,max=4"`
|
||||
CategoryId int64 `form:"category_id" binding:"min=0"`
|
||||
AccountId int64 `form:"account_id" binding:"min=0"`
|
||||
AmountFilter string `form:"amount_filter" binding:"validAmountFilter"`
|
||||
Keyword string `form:"keyword"`
|
||||
TrimAccount bool `form:"trim_account"`
|
||||
TrimCategory bool `form:"trim_category"`
|
||||
|
||||
@@ -73,11 +73,11 @@ func (s *TransactionService) GetAllTransactions(c *core.Context, uid int64, page
|
||||
|
||||
// GetAllTransactionsByMaxTime returns all transactions before given time
|
||||
func (s *TransactionService) GetAllTransactionsByMaxTime(c *core.Context, uid int64, maxTransactionTime int64, count int32, noDuplicated bool) ([]*models.Transaction, error) {
|
||||
return s.GetTransactionsByMaxTime(c, uid, maxTransactionTime, 0, 0, nil, nil, "", 1, count, false, noDuplicated)
|
||||
return s.GetTransactionsByMaxTime(c, uid, maxTransactionTime, 0, 0, nil, nil, "", "", 1, count, false, noDuplicated)
|
||||
}
|
||||
|
||||
// GetTransactionsByMaxTime returns transactions before given time
|
||||
func (s *TransactionService) GetTransactionsByMaxTime(c *core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, page int32, count int32, needOneMoreItem bool, noDuplicated bool) ([]*models.Transaction, error) {
|
||||
func (s *TransactionService) GetTransactionsByMaxTime(c *core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, amountFilter string, keyword string, page int32, count int32, needOneMoreItem bool, noDuplicated bool) ([]*models.Transaction, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
@@ -101,14 +101,14 @@ func (s *TransactionService) GetTransactionsByMaxTime(c *core.Context, uid int64
|
||||
actualCount++
|
||||
}
|
||||
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, noDuplicated)
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, amountFilter, keyword, noDuplicated)
|
||||
err = s.UserDataDB(uid).NewSession(c).Where(condition, conditionParams...).Limit(int(actualCount), int(count*(page-1))).OrderBy("transaction_time desc").Find(&transactions)
|
||||
|
||||
return transactions, err
|
||||
}
|
||||
|
||||
// GetTransactionsInMonthByPage returns all transactions in given year and month
|
||||
func (s *TransactionService) GetTransactionsInMonthByPage(c *core.Context, uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string) ([]*models.Transaction, error) {
|
||||
func (s *TransactionService) GetTransactionsInMonthByPage(c *core.Context, uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, amountFilter string, keyword string) ([]*models.Transaction, error) {
|
||||
if uid <= 0 {
|
||||
return nil, errs.ErrUserIdInvalid
|
||||
}
|
||||
@@ -121,7 +121,7 @@ func (s *TransactionService) GetTransactionsInMonthByPage(c *core.Context, uid i
|
||||
|
||||
var transactions []*models.Transaction
|
||||
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true)
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, amountFilter, keyword, true)
|
||||
err = s.UserDataDB(uid).NewSession(c).Where(condition, conditionParams...).OrderBy("transaction_time desc").Find(&transactions)
|
||||
|
||||
transactionsInMonth := make([]*models.Transaction, 0, len(transactions))
|
||||
@@ -163,11 +163,11 @@ func (s *TransactionService) GetTransactionByTransactionId(c *core.Context, uid
|
||||
|
||||
// GetAllTransactionCount returns total count of transactions
|
||||
func (s *TransactionService) GetAllTransactionCount(c *core.Context, uid int64) (int64, error) {
|
||||
return s.GetTransactionCount(c, uid, 0, 0, 0, nil, nil, "")
|
||||
return s.GetTransactionCount(c, uid, 0, 0, 0, nil, nil, "", "")
|
||||
}
|
||||
|
||||
// GetMonthTransactionCount returns total count of transactions in given year and month
|
||||
func (s *TransactionService) GetMonthTransactionCount(c *core.Context, uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, utcOffset int16) (int64, error) {
|
||||
func (s *TransactionService) GetMonthTransactionCount(c *core.Context, uid int64, year int32, month int32, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, amountFilter string, keyword string, utcOffset int16) (int64, error) {
|
||||
if uid <= 0 {
|
||||
return 0, errs.ErrUserIdInvalid
|
||||
}
|
||||
@@ -183,16 +183,16 @@ func (s *TransactionService) GetMonthTransactionCount(c *core.Context, uid int64
|
||||
minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix())
|
||||
maxTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix()) - 1
|
||||
|
||||
return s.GetTransactionCount(c, uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword)
|
||||
return s.GetTransactionCount(c, uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, amountFilter, keyword)
|
||||
}
|
||||
|
||||
// GetTransactionCount returns count of transactions
|
||||
func (s *TransactionService) GetTransactionCount(c *core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string) (int64, error) {
|
||||
func (s *TransactionService) GetTransactionCount(c *core.Context, uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, amountFilter string, keyword string) (int64, error) {
|
||||
if uid <= 0 {
|
||||
return 0, errs.ErrUserIdInvalid
|
||||
}
|
||||
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, keyword, true)
|
||||
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountIds, amountFilter, keyword, true)
|
||||
return s.UserDataDB(uid).NewSession(c).Where(condition, conditionParams...).Count(&models.Transaction{})
|
||||
}
|
||||
|
||||
@@ -1331,7 +1331,7 @@ func (s *TransactionService) GetTransactionMapByList(transactions []*models.Tran
|
||||
return transactionMap
|
||||
}
|
||||
|
||||
func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, keyword string, noDuplicated bool) (string, []any) {
|
||||
func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountIds []int64, amountFilter string, keyword string, noDuplicated bool) (string, []any) {
|
||||
condition := "uid=? AND deleted=?"
|
||||
conditionParams := make([]any, 0, 16)
|
||||
conditionParams = append(conditionParams, uid)
|
||||
@@ -1399,6 +1399,58 @@ func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransact
|
||||
condition = condition + " AND account_id IN (" + conditions.String() + ")"
|
||||
}
|
||||
|
||||
if amountFilter != "" {
|
||||
amountFilterItems := strings.Split(amountFilter, ":")
|
||||
|
||||
if len(amountFilterItems) == 2 && amountFilterItems[0] == "gt" {
|
||||
value, err := utils.StringToInt64(amountFilterItems[1])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND amount > ?"
|
||||
conditionParams = append(conditionParams, value)
|
||||
}
|
||||
} else if len(amountFilterItems) == 2 && amountFilterItems[0] == "lt" {
|
||||
value, err := utils.StringToInt64(amountFilterItems[1])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND amount < ?"
|
||||
conditionParams = append(conditionParams, value)
|
||||
}
|
||||
} else if len(amountFilterItems) == 2 && amountFilterItems[0] == "eq" {
|
||||
value, err := utils.StringToInt64(amountFilterItems[1])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND amount = ?"
|
||||
conditionParams = append(conditionParams, value)
|
||||
}
|
||||
} else if len(amountFilterItems) == 2 && amountFilterItems[0] == "ne" {
|
||||
value, err := utils.StringToInt64(amountFilterItems[1])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND amount <> ?"
|
||||
conditionParams = append(conditionParams, value)
|
||||
}
|
||||
} else if len(amountFilterItems) == 3 && amountFilterItems[0] == "bt" {
|
||||
value1, err := utils.StringToInt64(amountFilterItems[1])
|
||||
value2, err := utils.StringToInt64(amountFilterItems[2])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND amount >= ? AND amount <= ?"
|
||||
conditionParams = append(conditionParams, value1)
|
||||
conditionParams = append(conditionParams, value2)
|
||||
}
|
||||
} else if len(amountFilterItems) == 3 && amountFilterItems[0] == "nb" {
|
||||
value1, err := utils.StringToInt64(amountFilterItems[1])
|
||||
value2, err := utils.StringToInt64(amountFilterItems[2])
|
||||
|
||||
if err == nil {
|
||||
condition = condition + " AND (amount < ? OR amount > ?)"
|
||||
conditionParams = append(conditionParams, value1)
|
||||
conditionParams = append(conditionParams, value2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if keyword != "" {
|
||||
condition = condition + " AND comment LIKE ?"
|
||||
conditionParams = append(conditionParams, "%%"+keyword+"%%")
|
||||
|
||||
@@ -110,6 +110,8 @@ func getValidationErrorText(err validator.FieldError) string {
|
||||
return errs.GetParameterInvalidCurrencyMessage(fieldName)
|
||||
case "validHexRGBColor":
|
||||
return errs.GetParameterInvalidHexRGBColorMessage(fieldName)
|
||||
case "validAmountFilter":
|
||||
return errs.GetParameterInvalidAmountFilterMessage(fieldName)
|
||||
}
|
||||
|
||||
return errs.GetParameterInvalidMessage(fieldName)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package validators
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
// ValidAmountFilter returns whether the given amount filter is valid
|
||||
func ValidAmountFilter(fl validator.FieldLevel) bool {
|
||||
if value, ok := fl.Field().Interface().(string); ok {
|
||||
if value == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
amountFilterItems := strings.Split(value, ":")
|
||||
|
||||
if len(amountFilterItems) < 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
amount1, err := utils.StringToInt64(amountFilterItems[1])
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if amountFilterItems[0] == "gt" || amountFilterItems[0] == "lt" || amountFilterItems[0] == "eq" || amountFilterItems[0] == "ne" {
|
||||
if len(amountFilterItems) != 2 {
|
||||
return false
|
||||
}
|
||||
} else if amountFilterItems[0] == "bt" || amountFilterItems[0] == "nb" {
|
||||
if len(amountFilterItems) != 3 {
|
||||
return false
|
||||
}
|
||||
|
||||
amount2, err := utils.StringToInt64(amountFilterItems[2])
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if amount2 < amount1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user