code refactor

This commit is contained in:
MaysWind
2021-03-21 19:04:06 +08:00
parent 1decdd2222
commit 1acb36913a
3 changed files with 178 additions and 151 deletions
+7 -151
View File
@@ -7,6 +7,7 @@ import (
"github.com/mayswind/lab/pkg/core"
"github.com/mayswind/lab/pkg/errs"
"github.com/mayswind/lab/pkg/exporters"
"github.com/mayswind/lab/pkg/log"
"github.com/mayswind/lab/pkg/models"
"github.com/mayswind/lab/pkg/services"
@@ -15,11 +16,10 @@ import (
)
const pageCountForDataExport = 1000
const csvHeaderLine = "Time,Type,Category,Sub Category,Account,Amount,Account2,Account2 Amount,Tags,Comment\n"
const csvDataLineFormat = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"
// DataManagementsApi represents data management api
type DataManagementsApi struct {
exporter *exporters.CSVFileExporter
tokens *services.TokenService
users *services.UserService
accounts *services.AccountService
@@ -31,6 +31,7 @@ type DataManagementsApi struct {
// Initialize a data management api singleton instance
var (
DataManagements = &DataManagementsApi{
exporter: &exporters.CSVFileExporter{},
tokens: services.Tokens,
users: services.Users,
accounts: services.Accounts,
@@ -101,16 +102,16 @@ func (a *DataManagementsApi) ExportDataHandler(c *core.Context) ([]byte, string,
maxTime = transactions[len(transactions)-1].TransactionTime - 1
}
result, err := a.getCSVFormatData(c, allTransactions, accountMap, categoryMap, tagMap, tagIndexs)
result, err := a.exporter.GetOutputContent(uid, allTransactions, accountMap, categoryMap, tagMap, tagIndexs)
if err != nil {
log.ErrorfWithRequestId(c, "[data_managements.ExportDataHandler] failed to get csv format exported data for \"uid:%d\", because %s", uid, err.Error())
return nil, "", errs.Or(err, errs.ErrOperationFailed)
}
fileName := a.getFileName(c)
fileName := a.getFileName()
return []byte(result), fileName, nil
return result, fileName, nil
}
// ClearDataHandler deletes all user data
@@ -163,152 +164,7 @@ func (a *DataManagementsApi) ClearDataHandler(c *core.Context) (interface{}, *er
return true, nil
}
func (a *DataManagementsApi) getCSVFormatData(c *core.Context, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexs map[int64][]int64) (string, error) {
var ret strings.Builder
ret.Grow(len(transactions) * 100)
ret.WriteString(csvHeaderLine)
for i := 0; i < len(transactions); i++ {
transaction := transactions[i]
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
continue
}
transactionTime := utils.FormatToLongDateTimeWithoutSecond(utils.ParseFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime)))
transactionType := a.getTransactionTypeName(c, transaction.Type)
category := a.getTransactionCategoryName(c, transaction.CategoryId, categoryMap)
subCategory := a.getTransactionSubCategoryName(c, transaction.CategoryId, categoryMap)
account := a.getAccountName(c, transaction.AccountId, accountMap)
amount := a.getDisplayAmount(c, transaction.Amount)
account2 := ""
account2Amount := ""
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT {
account2 = a.getAccountName(c, transaction.RelatedAccountId, accountMap)
account2Amount = a.getDisplayAmount(c, transaction.RelatedAccountAmount)
}
tags := a.getTags(c, transaction.TransactionId, allTagIndexs, tagMap)
comment := a.getComment(c, transaction.Comment)
ret.WriteString(fmt.Sprintf(csvDataLineFormat, transactionTime, transactionType, category, subCategory, account, amount, account2, account2Amount, tags, comment))
}
return ret.String(), nil
}
func (a *DataManagementsApi) getTransactionTypeName(c *core.Context, transactionDbType models.TransactionDbType) string {
if transactionDbType == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
return "Balance Modification"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_INCOME {
return "Income"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_EXPENSE {
return "Expense"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionDbType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
return "Transfer"
} else {
return ""
}
}
func (a *DataManagementsApi) getTransactionCategoryName(c *core.Context, categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if !exists {
return ""
}
if category.ParentCategoryId == 0 {
return category.Name
}
parentCategory, exists := categoryMap[category.ParentCategoryId]
if !exists {
return ""
}
return parentCategory.Name
}
func (a *DataManagementsApi) getTransactionSubCategoryName(c *core.Context, categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if exists {
return category.Name
} else {
return ""
}
}
func (a *DataManagementsApi) getAccountName(c *core.Context, accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return account.Name
} else {
return ""
}
}
func (a *DataManagementsApi) getDisplayAmount(c *core.Context, amount int64) string {
displayAmount := utils.Int64ToString(amount)
integer := utils.SubString(displayAmount, 0, len(displayAmount)-2)
decimals := utils.SubString(displayAmount, -2, 2)
if integer == "" {
integer = "0"
} else if integer == "-" {
integer = "-0"
}
if len(decimals) == 0 {
decimals = "00"
} else if len(decimals) == 1 {
decimals = "0" + decimals
}
return integer + "." + decimals
}
func (a *DataManagementsApi) getTags(c *core.Context, transactionId int64, allTagIndexs map[int64][]int64, tagMap map[int64]*models.TransactionTag) string {
tagIndexs, exists := allTagIndexs[transactionId]
if !exists {
return ""
}
var ret strings.Builder
for i := 0; i < len(tagIndexs); i++ {
if i > 0 {
ret.WriteString(";")
}
tagIndex := tagIndexs[i]
tag, exists := tagMap[tagIndex]
if !exists {
continue
}
ret.WriteString(tag.Name)
}
return ret.String()
}
func (a *DataManagementsApi) getComment(c *core.Context, comment string) string {
comment = strings.Replace(comment, ",", " ", -1)
comment = strings.Replace(comment, "\r\n", " ", -1)
comment = strings.Replace(comment, "\n", " ", -1)
return comment
}
func (a *DataManagementsApi) getFileName(c *core.Context) string {
func (a *DataManagementsApi) getFileName() string {
currentTime := utils.FormatToLongDateTimeWithoutSecond(time.Now())
currentTime = strings.Replace(currentTime, "-", "_", -1)
currentTime = strings.Replace(currentTime, " ", "_", -1)
+162
View File
@@ -0,0 +1,162 @@
package exporters
import (
"fmt"
"strings"
"github.com/mayswind/lab/pkg/models"
"github.com/mayswind/lab/pkg/utils"
)
// CSVFileExporter defines the structure of csv file exporter
type CSVFileExporter struct {
DataExporter
}
const csvHeaderLine = "Time,Type,Category,Sub Category,Account,Amount,Account2,Account2 Amount,Tags,Comment\n"
const csvDataLineFormat = "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n"
func (e *CSVFileExporter) GetOutputContent(uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexs map[int64][]int64) ([]byte, error) {
var ret strings.Builder
ret.Grow(len(transactions) * 100)
ret.WriteString(csvHeaderLine)
for i := 0; i < len(transactions); i++ {
transaction := transactions[i]
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
continue
}
transactionTime := utils.FormatToLongDateTimeWithoutSecond(utils.ParseFromUnixTime(utils.GetUnixTimeFromTransactionTime(transaction.TransactionTime)))
transactionType := e.getTransactionTypeName(transaction.Type)
category := e.getTransactionCategoryName(transaction.CategoryId, categoryMap)
subCategory := e.getTransactionSubCategoryName(transaction.CategoryId, categoryMap)
account := e.getAccountName(transaction.AccountId, accountMap)
amount := e.getDisplayAmount(transaction.Amount)
account2 := ""
account2Amount := ""
if transaction.Type == models.TRANSACTION_DB_TYPE_TRANSFER_OUT {
account2 = e.getAccountName(transaction.RelatedAccountId, accountMap)
account2Amount = e.getDisplayAmount(transaction.RelatedAccountAmount)
}
tags := e.getTags(transaction.TransactionId, allTagIndexs, tagMap)
comment := e.getComment(transaction.Comment)
ret.WriteString(fmt.Sprintf(csvDataLineFormat, transactionTime, transactionType, category, subCategory, account, amount, account2, account2Amount, tags, comment))
}
return []byte(ret.String()), nil
}
func (e *CSVFileExporter) getTransactionTypeName( transactionDbType models.TransactionDbType) string {
if transactionDbType == models.TRANSACTION_DB_TYPE_MODIFY_BALANCE {
return "Balance Modification"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_INCOME {
return "Income"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_EXPENSE {
return "Expense"
} else if transactionDbType == models.TRANSACTION_DB_TYPE_TRANSFER_OUT || transactionDbType == models.TRANSACTION_DB_TYPE_TRANSFER_IN {
return "Transfer"
} else {
return ""
}
}
func (e *CSVFileExporter) getTransactionCategoryName( categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if !exists {
return ""
}
if category.ParentCategoryId == 0 {
return category.Name
}
parentCategory, exists := categoryMap[category.ParentCategoryId]
if !exists {
return ""
}
return parentCategory.Name
}
func (e *CSVFileExporter) getTransactionSubCategoryName( categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if exists {
return category.Name
} else {
return ""
}
}
func (e *CSVFileExporter) getAccountName( accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return account.Name
} else {
return ""
}
}
func (e *CSVFileExporter) getDisplayAmount( amount int64) string {
displayAmount := utils.Int64ToString(amount)
integer := utils.SubString(displayAmount, 0, len(displayAmount)-2)
decimals := utils.SubString(displayAmount, -2, 2)
if integer == "" {
integer = "0"
} else if integer == "-" {
integer = "-0"
}
if len(decimals) == 0 {
decimals = "00"
} else if len(decimals) == 1 {
decimals = "0" + decimals
}
return integer + "." + decimals
}
func (e *CSVFileExporter) getTags( transactionId int64, allTagIndexs map[int64][]int64, tagMap map[int64]*models.TransactionTag) string {
tagIndexs, exists := allTagIndexs[transactionId]
if !exists {
return ""
}
var ret strings.Builder
for i := 0; i < len(tagIndexs); i++ {
if i > 0 {
ret.WriteString(";")
}
tagIndex := tagIndexs[i]
tag, exists := tagMap[tagIndex]
if !exists {
continue
}
ret.WriteString(tag.Name)
}
return ret.String()
}
func (e *CSVFileExporter) getComment( comment string) string {
comment = strings.Replace(comment, ",", " ", -1)
comment = strings.Replace(comment, "\r\n", " ", -1)
comment = strings.Replace(comment, "\n", " ", -1)
return comment
}
+9
View File
@@ -0,0 +1,9 @@
package exporters
import "github.com/mayswind/lab/pkg/models"
// DataExporter defines the structure of data exporter
type DataExporter interface {
// GetOutputContent returns the exported data
GetOutputContent(uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexs map[int64][]int64) ([]byte, error)
}