add transaction count api

This commit is contained in:
MaysWind
2021-03-28 17:19:48 +08:00
parent 3ed9250811
commit baebee94c7
4 changed files with 133 additions and 119 deletions
+1
View File
@@ -204,6 +204,7 @@ func startWebServer(c *cli.Context) error {
apiV1Route.POST("/accounts/delete.json", bindApi(api.Accounts.AccountDeleteHandler))
// Transactions
apiV1Route.GET("/transactions/count.json", bindApi(api.Transactions.TransactionCountHandler))
apiV1Route.GET("/transactions/list.json", bindApi(api.Transactions.TransactionListHandler))
apiV1Route.GET("/transactions/list/by_month.json", bindApi(api.Transactions.TransactionListHandler))
apiV1Route.GET("/transactions/get.json", bindApi(api.Transactions.TransactionGetHandler))
+40
View File
@@ -31,6 +31,46 @@ var (
}
)
// TransactionCountHandler returns transaction total count of current user
func (a *TransactionsApi) TransactionCountHandler(c *core.Context) (interface{}, *errs.Error) {
var transactionCountReq models.TransactionCountRequest
err := c.ShouldBindQuery(&transactionCountReq)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] parse request failed, because %s", err.Error())
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
}
uid := c.GetCurrentUid()
var allCategoryIds []int64
if transactionCountReq.CategoryId > 0 {
allSubCategories, err := a.transactionCategories.GetAllCategoriesByUid(uid, 0, transactionCountReq.CategoryId)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionCountHandler] get transaction category error, because %s", err.Error())
return nil, errs.ErrOperationFailed
}
if len(allSubCategories) > 0 {
for i := 0; i < len(allSubCategories); i++ {
allCategoryIds = append(allCategoryIds, allSubCategories[i].CategoryId)
}
} else {
allCategoryIds = append(allCategoryIds, transactionCountReq.CategoryId)
}
}
totalCount, err := a.transactions.GetTransactionCount(uid, transactionCountReq.MaxTime, transactionCountReq.MinTime, transactionCountReq.Type, allCategoryIds, transactionCountReq.AccountId, transactionCountReq.Keyword)
countResp := &models.TransactionCountResponse{
Count: totalCount,
}
return countResp, nil
}
// TransactionListHandler returns transaction list of current user
func (a *TransactionsApi) TransactionListHandler(c *core.Context) (interface{}, *errs.Error) {
var transactionListReq models.TransactionListByMaxTimeRequest
+15
View File
@@ -80,6 +80,16 @@ type TransactionModifyRequest struct {
Comment string `json:"comment" binding:"max=255"`
}
// 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"`
}
// TransactionListByMaxTimeRequest represents all parameters of transaction listing by max time request
type TransactionListByMaxTimeRequest struct {
Type TransactionDbType `form:"type" binding:"min=0,max=4"`
@@ -143,6 +153,11 @@ type TransactionInfoResponse struct {
Editable bool `json:"editable"`
}
// TransactionCountResponse represents transaction count response
type TransactionCountResponse struct {
Count int64 `json:"count"`
}
// TransactionInfoPageWrapperResponse represents a response of transaction which contains items and next id
type TransactionInfoPageWrapperResponse struct {
Items TransactionInfoResponseSlice `json:"items"`
+77 -119
View File
@@ -75,68 +75,7 @@ func (s *TransactionService) GetTransactionsByMaxTime(uid int64, maxTransactionT
var transactions []*models.Transaction
var err error
condition := "uid=? AND deleted=?"
conditionParams := make([]interface{}, 0, 16)
conditionParams = append(conditionParams, uid)
conditionParams = append(conditionParams, false)
if models.TRANSACTION_DB_TYPE_MODIFY_BALANCE <= transactionType && transactionType <= models.TRANSACTION_DB_TYPE_EXPENSE {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, transactionType)
} else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
if accountId == 0 {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
} else {
condition = condition + " AND (type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN)
}
} else {
if noDuplicated && accountId == 0 {
condition = condition + " AND (type=? OR type=? OR type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_EXPENSE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
}
}
if len(categoryIds) > 0 {
var conditions strings.Builder
for i := 0; i < len(categoryIds); i++ {
if i > 0 {
conditions.WriteString(",")
}
conditions.WriteString("?")
conditionParams = append(conditionParams, categoryIds[i])
}
condition = condition + " AND category_id IN (" + conditions.String() + ")"
}
if accountId > 0 {
condition = condition + " AND account_id=?"
conditionParams = append(conditionParams, accountId)
}
if keyword != "" {
condition = condition + " AND comment LIKE ?"
conditionParams = append(conditionParams, "%%"+keyword+"%%")
}
if maxTransactionTime > 0 {
condition = condition + " AND transaction_time<=?"
conditionParams = append(conditionParams, maxTransactionTime)
}
if minTransactionTime > 0 {
condition = condition + " AND transaction_time>=?"
conditionParams = append(conditionParams, minTransactionTime)
}
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, noDuplicated)
err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, 0).OrderBy("transaction_time desc").Find(&transactions)
return transactions, err
@@ -164,65 +103,12 @@ func (s *TransactionService) GetTransactionsInMonthByPage(uid int64, year int, m
endTime := startTime.AddDate(0, 1, 0)
startTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix())
endTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix())
minTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startTime.Unix())
maxTransactionTime := utils.GetMinTransactionTimeFromUnixTime(endTime.Unix()) - 1
var transactions []*models.Transaction
condition := "uid=? AND deleted=? AND transaction_time>=? AND transaction_time<?"
conditionParams := make([]interface{}, 0, 16)
conditionParams = append(conditionParams, uid)
conditionParams = append(conditionParams, false)
conditionParams = append(conditionParams, startTransactionTime)
conditionParams = append(conditionParams, endTransactionTime)
if models.TRANSACTION_DB_TYPE_MODIFY_BALANCE <= transactionType && transactionType <= models.TRANSACTION_DB_TYPE_EXPENSE {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, transactionType)
} else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
if accountId == 0 {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
} else {
condition = condition + " AND (type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN)
}
} else {
if accountId == 0 {
condition = condition + " AND (type=? OR type=? OR type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_EXPENSE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
}
}
if len(categoryIds) > 0 {
var conditions strings.Builder
for i := 0; i < len(categoryIds); i++ {
if i > 0 {
conditions.WriteString(",")
}
conditions.WriteString("?")
conditionParams = append(conditionParams, categoryIds[i])
}
condition = condition + " AND category_id IN (" + conditions.String() + ")"
}
if accountId > 0 {
condition = condition + " AND account_id=?"
conditionParams = append(conditionParams, accountId)
}
if keyword != "" {
condition = condition + " AND comment LIKE ?"
conditionParams = append(conditionParams, "%%"+keyword+"%%")
}
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true)
err = s.UserDataDB(uid).Where(condition, conditionParams...).Limit(count, count*(page-1)).OrderBy("transaction_time desc").Find(&transactions)
return transactions, err
@@ -252,11 +138,17 @@ func (s *TransactionService) GetTransactionByTransactionId(uid int64, transactio
// GetAllTransactionCount returns total count of transactions
func (s *TransactionService) GetAllTransactionCount(uid int64) (int64, error) {
return s.GetTransactionCount(uid, 0, 0, 0, nil, 0, "")
}
// GetTransactionCount returns count of transactions
func (s *TransactionService) GetTransactionCount(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string) (int64, error) {
if uid <= 0 {
return 0, errs.ErrUserIdInvalid
}
return s.UserDataDB(uid).Where("uid=? AND deleted=?", uid, false).Count(&models.Transaction{})
condition, conditionParams := s.getTransactionQueryCondition(uid, maxTransactionTime, minTransactionTime, transactionType, categoryIds, accountId, keyword, true)
return s.UserDataDB(uid).Where(condition, conditionParams...).Count(&models.Transaction{})
}
// GetMonthTransactionCount returns total count of transactions in given year and month
@@ -1122,6 +1014,72 @@ func (s *TransactionService) GetTransactionMapByList(transactions []*models.Tran
return transactionMap
}
func (s *TransactionService) getTransactionQueryCondition(uid int64, maxTransactionTime int64, minTransactionTime int64, transactionType models.TransactionDbType, categoryIds []int64, accountId int64, keyword string, noDuplicated bool) (string, []interface{}) {
condition := "uid=? AND deleted=?"
conditionParams := make([]interface{}, 0, 16)
conditionParams = append(conditionParams, uid)
conditionParams = append(conditionParams, false)
if maxTransactionTime > 0 {
condition = condition + " AND transaction_time<=?"
conditionParams = append(conditionParams, maxTransactionTime)
}
if minTransactionTime > 0 {
condition = condition + " AND transaction_time>=?"
conditionParams = append(conditionParams, minTransactionTime)
}
if models.TRANSACTION_DB_TYPE_MODIFY_BALANCE <= transactionType && transactionType <= models.TRANSACTION_DB_TYPE_EXPENSE {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, transactionType)
} else if transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
if accountId == 0 {
condition = condition + " AND type=?"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
} else {
condition = condition + " AND (type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_IN)
}
} else {
if noDuplicated && accountId == 0 {
condition = condition + " AND (type=? OR type=? OR type=? OR type=?)"
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_MODIFY_BALANCE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_INCOME)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_EXPENSE)
conditionParams = append(conditionParams, models.TRANSACTION_DB_TYPE_TRANSFER_OUT)
}
}
if len(categoryIds) > 0 {
var conditions strings.Builder
for i := 0; i < len(categoryIds); i++ {
if i > 0 {
conditions.WriteString(",")
}
conditions.WriteString("?")
conditionParams = append(conditionParams, categoryIds[i])
}
condition = condition + " AND category_id IN (" + conditions.String() + ")"
}
if accountId > 0 {
condition = condition + " AND account_id=?"
conditionParams = append(conditionParams, accountId)
}
if keyword != "" {
condition = condition + " AND comment LIKE ?"
conditionParams = append(conditionParams, "%%"+keyword+"%%")
}
return condition, conditionParams
}
func (s *TransactionService) isAccountIdValid(transaction *models.Transaction) error {
if transaction.Type == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
if transaction.RelatedAccountId != 0 && transaction.RelatedAccountId != transaction.AccountId {