mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-21 18:24:26 +08:00
add transaction statistics api
This commit is contained in:
@@ -224,6 +224,9 @@ func startWebServer(c *cli.Context) error {
|
|||||||
apiV1Route.POST("/transaction/tags/move.json", bindApi(api.TransactionTags.TagMoveHandler))
|
apiV1Route.POST("/transaction/tags/move.json", bindApi(api.TransactionTags.TagMoveHandler))
|
||||||
apiV1Route.POST("/transaction/tags/delete.json", bindApi(api.TransactionTags.TagDeleteHandler))
|
apiV1Route.POST("/transaction/tags/delete.json", bindApi(api.TransactionTags.TagDeleteHandler))
|
||||||
|
|
||||||
|
// Statistics
|
||||||
|
apiV1Route.GET("/statistics/transaction.json", bindApi(api.Statistics.TransactionStatisticsHandler))
|
||||||
|
|
||||||
// Exchange Rates
|
// Exchange Rates
|
||||||
apiV1Route.GET("/exchange_rates/latest.json", bindApi(api.ExchangeRates.LatestExchangeRateHandler))
|
apiV1Route.GET("/exchange_rates/latest.json", bindApi(api.ExchangeRates.LatestExchangeRateHandler))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mayswind/lab/pkg/core"
|
||||||
|
"github.com/mayswind/lab/pkg/errs"
|
||||||
|
"github.com/mayswind/lab/pkg/log"
|
||||||
|
"github.com/mayswind/lab/pkg/models"
|
||||||
|
"github.com/mayswind/lab/pkg/services"
|
||||||
|
)
|
||||||
|
|
||||||
|
// StatisticApi represents statistic api
|
||||||
|
type StatisticApi struct {
|
||||||
|
transactions *services.TransactionService
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize an statistic api singleton instance
|
||||||
|
var (
|
||||||
|
Statistics = &StatisticApi{
|
||||||
|
transactions: services.Transactions,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// TransactionStatisticsHandler returns transaction statistics of current user
|
||||||
|
func (a *StatisticApi) TransactionStatisticsHandler(c *core.Context) (interface{}, *errs.Error) {
|
||||||
|
var statisticReq models.TransactionStatisticRequest
|
||||||
|
err := c.ShouldBindQuery(&statisticReq)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.WarnfWithRequestId(c, "[statistics.TransactionOverviewHandler] parse request failed, because %s", err.Error())
|
||||||
|
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
uid := c.GetCurrentUid()
|
||||||
|
totalAmounts, err := a.transactions.GetAccountsAndCategoriesTotalIncomeAndExpense(uid, statisticReq.StartTime, statisticReq.EndTime)
|
||||||
|
|
||||||
|
statisticResp := &models.TransactionStatisticResponse{
|
||||||
|
StartTime: statisticReq.StartTime,
|
||||||
|
EndTime: statisticReq.EndTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
statisticResp.Items = make([]*models.TransactionStatisticResponseItem, len(totalAmounts))
|
||||||
|
|
||||||
|
for i := 0; i < len(totalAmounts); i++ {
|
||||||
|
totalAmountItem := totalAmounts[i]
|
||||||
|
statisticResp.Items[i] = &models.TransactionStatisticResponseItem{
|
||||||
|
CategoryId: totalAmountItem.CategoryId,
|
||||||
|
AccountId: totalAmountItem.AccountId,
|
||||||
|
TotalAmount: totalAmountItem.Amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statisticResp, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// TransactionStatisticRequest represents all parameters of transaction statistic request
|
||||||
|
type TransactionStatisticRequest struct {
|
||||||
|
StartTime int64 `form:"start_time" binding:"min=0"`
|
||||||
|
EndTime int64 `form:"end_time" binding:"min=0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionStatisticResponse represents an item of transaction overview
|
||||||
|
type TransactionStatisticResponse struct {
|
||||||
|
StartTime int64 `json:"startTime"`
|
||||||
|
EndTime int64 `json:"endTime"`
|
||||||
|
Items []*TransactionStatisticResponseItem `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionStatisticResponseItem represents total amount item for an response
|
||||||
|
type TransactionStatisticResponseItem struct {
|
||||||
|
CategoryId int64 `json:"categoryId,string"`
|
||||||
|
AccountId int64 `json:"accountId,string"`
|
||||||
|
TotalAmount int64 `json:"amount"`
|
||||||
|
}
|
||||||
@@ -955,6 +955,25 @@ func (s *TransactionService) GetAccountsTotalIncomeAndExpense(uid int64, startUn
|
|||||||
return incomeAmounts, expenseAmounts, nil
|
return incomeAmounts, expenseAmounts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAccountsAndCategoriesTotalIncomeAndExpense returns the every accounts and categories total income and expense amount by specific date range
|
||||||
|
func (s *TransactionService) GetAccountsAndCategoriesTotalIncomeAndExpense(uid int64, startUnixTime int64, endUnixTime int64) ([]*models.Transaction, error) {
|
||||||
|
if uid <= 0 {
|
||||||
|
return nil, errs.ErrUserIdInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
startTransactionTime := utils.GetMinTransactionTimeFromUnixTime(startUnixTime)
|
||||||
|
endTransactionTime := utils.GetMaxTransactionTimeFromUnixTime(endUnixTime)
|
||||||
|
|
||||||
|
var transactionTotalAmounts []*models.Transaction
|
||||||
|
err := s.UserDataDB(uid).Select("uid, category_id, account_id, SUM(amount) as amount").Where("uid=? AND deleted=? AND (type=? OR type=?) AND transaction_time>=? AND transaction_time<=?", uid, false, models.TRANSACTION_DB_TYPE_INCOME, models.TRANSACTION_DB_TYPE_EXPENSE, startTransactionTime, endTransactionTime).GroupBy("category_id, account_id").Find(&transactionTotalAmounts)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactionTotalAmounts, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetTransactionMapByList returns a transaction map by a list
|
// GetTransactionMapByList returns a transaction map by a list
|
||||||
func (s *TransactionService) GetTransactionMapByList(transactions []*models.Transaction) map[int64]*models.Transaction {
|
func (s *TransactionService) GetTransactionMapByList(transactions []*models.Transaction) map[int64]*models.Transaction {
|
||||||
transactionMap := make(map[int64]*models.Transaction)
|
transactionMap := make(map[int64]*models.Transaction)
|
||||||
|
|||||||
Reference in New Issue
Block a user