add api for getting total income/expense amounts by month

This commit is contained in:
MaysWind
2021-03-29 00:57:16 +08:00
parent f57f56b9ea
commit ead072ed31
8 changed files with 277 additions and 0 deletions
+109
View File
@@ -2,6 +2,7 @@ package api
import (
"sort"
"strings"
"github.com/mayswind/lab/pkg/core"
"github.com/mayswind/lab/pkg/errs"
@@ -11,6 +12,8 @@ import (
"github.com/mayswind/lab/pkg/utils"
)
const pageCountForLoadTransactionAmounts = 1000
// TransactionsApi represents transaction api
type TransactionsApi struct {
transactions *services.TransactionService
@@ -335,6 +338,112 @@ func (a *TransactionsApi) TransactionAmountsHandler(c *core.Context) (interface{
return amountsResp, nil
}
// TransactionMonthAmountsHandler returns every month transaction amounts of current user
func (a *TransactionsApi) TransactionMonthAmountsHandler(c *core.Context) (interface{}, *errs.Error) {
var transactionAmountsReq models.TransactionMonthAmountsRequest
err := c.ShouldBindQuery(&transactionAmountsReq)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] parse request failed, because %s", err.Error())
return nil, errs.NewIncompleteOrIncorrectSubmissionError(err)
}
utcOffset, err := c.GetClientTimezoneOffset()
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] cannot get client timezone offset, because %s", err.Error())
return nil, errs.ErrClientTimezoneOffsetInvalid
}
startTime, endTime, err := transactionAmountsReq.GetStartTimeAndEndTime(utcOffset)
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] parse request start or end date failed, because %s", err.Error())
return nil, errs.ErrParameterInvalid
}
uid := c.GetCurrentUid()
accounts, err := a.accounts.GetAllAccountsByUid(uid)
accountMap := a.accounts.GetAccountMapByList(accounts)
if err != nil {
log.ErrorfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] failed to get all accounts for user \"uid:%d\", because %s", uid, err.Error())
return nil, errs.ErrOperationFailed
}
totalAmounts, err := a.transactions.GetAccountsMonthTotalIncomeAndExpense(uid, startTime, endTime, pageCountForLoadTransactionAmounts)
amountsMap := make(map[string]map[string]*models.TransactionAmountsResponseItemAmountInfo)
for yearMonth, monthAccountsAmounts := range totalAmounts {
for accountId, monthAccountAmounts := range monthAccountsAmounts {
account, exists := accountMap[accountId]
if !exists {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] cannot find account for account \"id:%d\" of user \"uid:%d\", because %s", accountId, uid)
continue
}
monthTotalAmounts, exists := amountsMap[yearMonth]
if !exists {
monthTotalAmounts = make(map[string]*models.TransactionAmountsResponseItemAmountInfo)
amountsMap[yearMonth] = monthTotalAmounts
}
monthTotalAmount, exists := monthTotalAmounts[account.Currency]
if !exists {
monthTotalAmount = &models.TransactionAmountsResponseItemAmountInfo{
Currency: account.Currency,
IncomeAmount: 0,
ExpenseAmount: 0,
}
}
monthTotalAmount.IncomeAmount += monthAccountAmounts.TotalIncomeAmount
monthTotalAmount.ExpenseAmount += monthAccountAmounts.TotalExpenseAmount
monthTotalAmounts[account.Currency] = monthTotalAmount
}
}
amountsResp := make(models.TransactionMonthAmountsResponseItemSlice, 0)
for yearMonth, monthTotalAmounts := range amountsMap {
yearMonthItems := strings.Split(yearMonth, "-")
year, err := utils.StringToInt32(yearMonthItems[0])
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] cannot get year from year-month item \"%s\" for user \"uid:%d\", because %s", yearMonth, uid)
continue
}
month, err := utils.StringToInt32(yearMonthItems[1])
if err != nil {
log.WarnfWithRequestId(c, "[transactions.TransactionMonthAmountsHandler] cannot get month from year-month item \"%s\" for user \"uid:%d\", because %s", yearMonth, uid)
continue
}
amounts := make([]*models.TransactionAmountsResponseItemAmountInfo, 0, len(monthTotalAmounts))
for _, monthTotalAmount := range monthTotalAmounts {
amounts = append(amounts, monthTotalAmount)
}
amountsResp = append(amountsResp, &models.TransactionMonthAmountsResponseItem{
Year: year,
Month: month,
Amounts: amounts,
})
}
sort.Sort(amountsResp)
return amountsResp, nil
}
// TransactionGetHandler returns one specific transaction of current user
func (a *TransactionsApi) TransactionGetHandler(c *core.Context) (interface{}, *errs.Error) {
var transactionGetReq models.TransactionGetRequest