code refactor

This commit is contained in:
MaysWind
2024-09-10 23:26:54 +08:00
parent 9db4a2430a
commit 27c4afd41b
4 changed files with 164 additions and 130 deletions
@@ -35,10 +35,19 @@ const (
DATA_TABLE_DESCRIPTION DataTableColumn = 14 DATA_TABLE_DESCRIPTION DataTableColumn = 14
) )
// DataTableTransactionDataConverter defines the structure of data table importer for transaction data // DataTableTransactionDataExporter defines the structure of plain text data table exporter for transaction data
type DataTableTransactionDataConverter struct { type DataTableTransactionDataExporter struct {
dataColumnMapping map[DataTableColumn]string
transactionTypeMapping map[models.TransactionDbType]string
columnSeparator string
lineSeparator string
geoLocationSeparator string
transactionTagSeparator string
}
// DataTableTransactionDataImporter defines the structure of plain text data table importer for transaction data
type DataTableTransactionDataImporter struct {
dataColumnMapping map[DataTableColumn]string dataColumnMapping map[DataTableColumn]string
transactionTypeMapping map[models.TransactionDbType]string
transactionTypeNameMapping map[string]models.TransactionDbType transactionTypeNameMapping map[string]models.TransactionDbType
columnSeparator string columnSeparator string
lineSeparator string lineSeparator string
@@ -46,7 +55,7 @@ type DataTableTransactionDataConverter struct {
transactionTagSeparator string transactionTagSeparator string
} }
func (c *DataTableTransactionDataConverter) buildExportedContent(ctx core.Context, dataTableBuilder DataTableBuilder, uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexes map[int64][]int64) error { func (c *DataTableTransactionDataExporter) buildExportedContent(ctx core.Context, dataTableBuilder DataTableBuilder, uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexes map[int64][]int64) error {
for i := 0; i < len(transactions); i++ { for i := 0; i < len(transactions); i++ {
transaction := transactions[i] transaction := transactions[i]
@@ -82,7 +91,112 @@ func (c *DataTableTransactionDataConverter) buildExportedContent(ctx core.Contex
return nil return nil
} }
func (c *DataTableTransactionDataConverter) parseImportedData(ctx core.Context, user *models.User, dataTable ImportedDataTable, defaultTimezoneOffset int16, accountMap map[string]*models.Account, categoryMap map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionTag, error) { func (c *DataTableTransactionDataExporter) getDisplayTransactionTypeName(transactionDbType models.TransactionDbType) string {
transactionTypeName, exists := c.transactionTypeMapping[transactionDbType]
if !exists {
return ""
}
return transactionTypeName
}
func (c *DataTableTransactionDataExporter) getExportedTransactionCategoryName(categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if !exists {
return ""
}
if category.ParentCategoryId == 0 {
return c.replaceDelimiters(category.Name)
}
parentCategory, exists := categoryMap[category.ParentCategoryId]
if !exists {
return ""
}
return c.replaceDelimiters(parentCategory.Name)
}
func (c *DataTableTransactionDataExporter) getExportedTransactionSubCategoryName(categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if exists {
return c.replaceDelimiters(category.Name)
} else {
return ""
}
}
func (c *DataTableTransactionDataExporter) getExportedAccountName(accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return c.replaceDelimiters(account.Name)
} else {
return ""
}
}
func (c *DataTableTransactionDataExporter) getAccountCurrency(accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return c.replaceDelimiters(account.Currency)
} else {
return ""
}
}
func (c *DataTableTransactionDataExporter) getExportedGeographicLocation(transaction *models.Transaction) string {
if transaction.GeoLongitude != 0 || transaction.GeoLatitude != 0 {
return fmt.Sprintf("%f%s%f", transaction.GeoLongitude, c.geoLocationSeparator, transaction.GeoLatitude)
}
return ""
}
func (c *DataTableTransactionDataExporter) getExportedTags(transactionId int64, allTagIndexes map[int64][]int64, tagMap map[int64]*models.TransactionTag) string {
tagIndexes, exists := allTagIndexes[transactionId]
if !exists {
return ""
}
var ret strings.Builder
for i := 0; i < len(tagIndexes); i++ {
tagIndex := tagIndexes[i]
tag, exists := tagMap[tagIndex]
if !exists {
continue
}
if ret.Len() > 0 {
ret.WriteString(c.transactionTagSeparator)
}
ret.WriteString(strings.Replace(tag.Name, c.transactionTagSeparator, " ", -1))
}
return c.replaceDelimiters(ret.String())
}
func (c *DataTableTransactionDataExporter) replaceDelimiters(text string) string {
text = strings.Replace(text, "\r\n", " ", -1)
text = strings.Replace(text, "\r", " ", -1)
text = strings.Replace(text, "\n", " ", -1)
text = strings.Replace(text, c.columnSeparator, " ", -1)
text = strings.Replace(text, c.lineSeparator, " ", -1)
return text
}
func (c *DataTableTransactionDataImporter) parseImportedData(ctx core.Context, user *models.User, dataTable ImportedDataTable, defaultTimezoneOffset int16, accountMap map[string]*models.Account, categoryMap map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionTag, error) {
if dataTable.DataRowCount() < 1 { if dataTable.DataRowCount() < 1 {
log.Errorf(ctx, "[data_table_transaction_data_converter.parseImportedData] cannot parse import data for user \"uid:%d\", because data table row count is less 1", user.Uid) log.Errorf(ctx, "[data_table_transaction_data_converter.parseImportedData] cannot parse import data for user \"uid:%d\", because data table row count is less 1", user.Uid)
return nil, nil, nil, nil, errs.ErrOperationFailed return nil, nil, nil, nil, errs.ErrOperationFailed
@@ -389,7 +503,7 @@ func (c *DataTableTransactionDataConverter) parseImportedData(ctx core.Context,
return allNewTransactions, allNewAccounts, allNewSubCategories, allNewTags, nil return allNewTransactions, allNewAccounts, allNewSubCategories, allNewTags, nil
} }
func (c *DataTableTransactionDataConverter) getTransactionDbType(transactionTypeName string) (models.TransactionDbType, error) { func (c *DataTableTransactionDataImporter) getTransactionDbType(transactionTypeName string) (models.TransactionDbType, error) {
transactionType, exists := c.transactionTypeNameMapping[transactionTypeName] transactionType, exists := c.transactionTypeNameMapping[transactionTypeName]
if !exists { if !exists {
@@ -399,7 +513,7 @@ func (c *DataTableTransactionDataConverter) getTransactionDbType(transactionType
return transactionType, nil return transactionType, nil
} }
func (c *DataTableTransactionDataConverter) getTransactionCategoryType(transactionType models.TransactionDbType) (models.TransactionCategoryType, error) { func (c *DataTableTransactionDataImporter) getTransactionCategoryType(transactionType models.TransactionDbType) (models.TransactionCategoryType, error) {
if transactionType == models.TRANSACTION_DB_TYPE_INCOME { if transactionType == models.TRANSACTION_DB_TYPE_INCOME {
return models.CATEGORY_TYPE_INCOME, nil return models.CATEGORY_TYPE_INCOME, nil
} else if transactionType == models.TRANSACTION_DB_TYPE_EXPENSE { } else if transactionType == models.TRANSACTION_DB_TYPE_EXPENSE {
@@ -411,112 +525,7 @@ func (c *DataTableTransactionDataConverter) getTransactionCategoryType(transacti
} }
} }
func (c *DataTableTransactionDataConverter) getDisplayTransactionTypeName(transactionDbType models.TransactionDbType) string { func (c *DataTableTransactionDataImporter) createNewAccountModel(uid int64, accountName string, currency string) *models.Account {
transactionTypeName, exists := c.transactionTypeMapping[transactionDbType]
if !exists {
return ""
}
return transactionTypeName
}
func (c *DataTableTransactionDataConverter) getExportedTransactionCategoryName(categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if !exists {
return ""
}
if category.ParentCategoryId == 0 {
return c.replaceDelimiters(category.Name)
}
parentCategory, exists := categoryMap[category.ParentCategoryId]
if !exists {
return ""
}
return c.replaceDelimiters(parentCategory.Name)
}
func (c *DataTableTransactionDataConverter) getExportedTransactionSubCategoryName(categoryId int64, categoryMap map[int64]*models.TransactionCategory) string {
category, exists := categoryMap[categoryId]
if exists {
return c.replaceDelimiters(category.Name)
} else {
return ""
}
}
func (c *DataTableTransactionDataConverter) getExportedAccountName(accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return c.replaceDelimiters(account.Name)
} else {
return ""
}
}
func (c *DataTableTransactionDataConverter) getAccountCurrency(accountId int64, accountMap map[int64]*models.Account) string {
account, exists := accountMap[accountId]
if exists {
return c.replaceDelimiters(account.Currency)
} else {
return ""
}
}
func (c *DataTableTransactionDataConverter) getExportedGeographicLocation(transaction *models.Transaction) string {
if transaction.GeoLongitude != 0 || transaction.GeoLatitude != 0 {
return fmt.Sprintf("%f%s%f", transaction.GeoLongitude, c.geoLocationSeparator, transaction.GeoLatitude)
}
return ""
}
func (c *DataTableTransactionDataConverter) getExportedTags(transactionId int64, allTagIndexes map[int64][]int64, tagMap map[int64]*models.TransactionTag) string {
tagIndexes, exists := allTagIndexes[transactionId]
if !exists {
return ""
}
var ret strings.Builder
for i := 0; i < len(tagIndexes); i++ {
tagIndex := tagIndexes[i]
tag, exists := tagMap[tagIndex]
if !exists {
continue
}
if ret.Len() > 0 {
ret.WriteString(c.transactionTagSeparator)
}
ret.WriteString(strings.Replace(tag.Name, c.transactionTagSeparator, " ", -1))
}
return c.replaceDelimiters(ret.String())
}
func (c *DataTableTransactionDataConverter) replaceDelimiters(text string) string {
text = strings.Replace(text, "\r\n", " ", -1)
text = strings.Replace(text, "\r", " ", -1)
text = strings.Replace(text, "\n", " ", -1)
text = strings.Replace(text, c.columnSeparator, " ", -1)
text = strings.Replace(text, c.lineSeparator, " ", -1)
return text
}
func (c *DataTableTransactionDataConverter) createNewAccountModel(uid int64, accountName string, currency string) *models.Account {
return &models.Account{ return &models.Account{
Uid: uid, Uid: uid,
Name: accountName, Name: accountName,
@@ -524,7 +533,7 @@ func (c *DataTableTransactionDataConverter) createNewAccountModel(uid int64, acc
} }
} }
func (c *DataTableTransactionDataConverter) createNewTransactionCategoryModel(uid int64, categoryName string, transactionCategoryType models.TransactionCategoryType) *models.TransactionCategory { func (c *DataTableTransactionDataImporter) createNewTransactionCategoryModel(uid int64, categoryName string, transactionCategoryType models.TransactionCategoryType) *models.TransactionCategory {
return &models.TransactionCategory{ return &models.TransactionCategory{
Uid: uid, Uid: uid,
Name: categoryName, Name: categoryName,
@@ -532,7 +541,7 @@ func (c *DataTableTransactionDataConverter) createNewTransactionCategoryModel(ui
} }
} }
func (c *DataTableTransactionDataConverter) createNewTransactionTagModel(uid int64, tagName string) *models.TransactionTag { func (c *DataTableTransactionDataImporter) createNewTransactionTagModel(uid int64, tagName string) *models.TransactionTag {
return &models.TransactionTag{ return &models.TransactionTag{
Uid: uid, Uid: uid,
Name: tagName, Name: tagName,
@@ -2,23 +2,33 @@ package converters
// ezBookKeepingTransactionDataCSVFileConverter defines the structure of CSV file converter // ezBookKeepingTransactionDataCSVFileConverter defines the structure of CSV file converter
type ezBookKeepingTransactionDataCSVFileConverter struct { type ezBookKeepingTransactionDataCSVFileConverter struct {
ezBookKeepingTransactionDataPlainTextConverter ezBookKeepingTransactionDataPlainTextExporter
ezBookKeepingTransactionDataPlainTextImporter
} }
// Initialize an ezbookkeeping transaction data csv file converter singleton instance // Initialize an ezbookkeeping transaction data csv file converter singleton instance
var ( var (
EzBookKeepingTransactionDataCSVFileConverter = &ezBookKeepingTransactionDataCSVFileConverter{ EzBookKeepingTransactionDataCSVFileConverter = &ezBookKeepingTransactionDataCSVFileConverter{
ezBookKeepingTransactionDataPlainTextConverter{ ezBookKeepingTransactionDataPlainTextExporter{
DataTableTransactionDataConverter: DataTableTransactionDataConverter{ DataTableTransactionDataExporter: DataTableTransactionDataExporter{
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
columnSeparator: ",",
lineSeparator: "\n",
geoLocationSeparator: " ",
transactionTagSeparator: ";",
},
columns: ezbookkeepingDataColumns,
},
ezBookKeepingTransactionDataPlainTextImporter{
DataTableTransactionDataImporter: DataTableTransactionDataImporter{
dataColumnMapping: ezbookkeepingDataColumnNameMapping, dataColumnMapping: ezbookkeepingDataColumnNameMapping,
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
transactionTypeNameMapping: ezbookkeepingNameTransactionTypeMapping, transactionTypeNameMapping: ezbookkeepingNameTransactionTypeMapping,
columnSeparator: ",", columnSeparator: ",",
lineSeparator: "\n", lineSeparator: "\n",
geoLocationSeparator: " ", geoLocationSeparator: " ",
transactionTagSeparator: ";", transactionTagSeparator: ";",
}, },
columns: ezbookkeepingDataColumns,
}, },
} }
) )
@@ -5,12 +5,17 @@ import (
"github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/models"
) )
// ezBookKeepingTransactionDataPlainTextConverter defines the structure of plain file converter for transaction data // ezBookKeepingTransactionDataPlainTextExporter defines the structure of ezbookkeeping plain text exporter for transaction data
type ezBookKeepingTransactionDataPlainTextConverter struct { type ezBookKeepingTransactionDataPlainTextExporter struct {
DataTableTransactionDataConverter DataTableTransactionDataExporter
columns []DataTableColumn columns []DataTableColumn
} }
// ezBookKeepingTransactionDataPlainTextImporter defines the structure of ezbookkeeping plain text importer for transaction data
type ezBookKeepingTransactionDataPlainTextImporter struct {
DataTableTransactionDataImporter
}
var ezbookkeepingDataColumnNameMapping = map[DataTableColumn]string{ var ezbookkeepingDataColumnNameMapping = map[DataTableColumn]string{
DATA_TABLE_TRANSACTION_TIME: "Time", DATA_TABLE_TRANSACTION_TIME: "Time",
DATA_TABLE_TRANSACTION_TIMEZONE: "Timezone", DATA_TABLE_TRANSACTION_TIMEZONE: "Timezone",
@@ -61,7 +66,7 @@ var ezbookkeepingDataColumns = []DataTableColumn{
} }
// ToExportedContent returns the exported transaction plain text data // ToExportedContent returns the exported transaction plain text data
func (c *ezBookKeepingTransactionDataPlainTextConverter) ToExportedContent(ctx core.Context, uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexes map[int64][]int64) ([]byte, error) { func (c *ezBookKeepingTransactionDataPlainTextExporter) ToExportedContent(ctx core.Context, uid int64, transactions []*models.Transaction, accountMap map[int64]*models.Account, categoryMap map[int64]*models.TransactionCategory, tagMap map[int64]*models.TransactionTag, allTagIndexes map[int64][]int64) ([]byte, error) {
dataTableBuilder := createNewezbookkeepingTransactionPlainTextDataTableBuilder(len(transactions), c.columns, c.dataColumnMapping, c.columnSeparator, c.lineSeparator) dataTableBuilder := createNewezbookkeepingTransactionPlainTextDataTableBuilder(len(transactions), c.columns, c.dataColumnMapping, c.columnSeparator, c.lineSeparator)
err := c.buildExportedContent(ctx, dataTableBuilder, uid, transactions, accountMap, categoryMap, tagMap, allTagIndexes) err := c.buildExportedContent(ctx, dataTableBuilder, uid, transactions, accountMap, categoryMap, tagMap, allTagIndexes)
@@ -73,7 +78,7 @@ func (c *ezBookKeepingTransactionDataPlainTextConverter) ToExportedContent(ctx c
} }
// ParseImportedData returns the imported data by parsing the transaction plain text data // ParseImportedData returns the imported data by parsing the transaction plain text data
func (c *ezBookKeepingTransactionDataPlainTextConverter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, categoryMap map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionTag, error) { func (c *ezBookKeepingTransactionDataPlainTextImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, categoryMap map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionTag, error) {
dataTable, err := createNewezbookkeepingTransactionPlainTextDataTable(string(data), c.columnSeparator, c.lineSeparator) dataTable, err := createNewezbookkeepingTransactionPlainTextDataTable(string(data), c.columnSeparator, c.lineSeparator)
if err != nil { if err != nil {
@@ -2,23 +2,33 @@ package converters
// ezBookKeepingTransactionDataTSVFileConverter defines the structure of TSV file converter // ezBookKeepingTransactionDataTSVFileConverter defines the structure of TSV file converter
type ezBookKeepingTransactionDataTSVFileConverter struct { type ezBookKeepingTransactionDataTSVFileConverter struct {
ezBookKeepingTransactionDataPlainTextConverter ezBookKeepingTransactionDataPlainTextExporter
ezBookKeepingTransactionDataPlainTextImporter
} }
// Initialize an ezbookkeeping transaction data tsv file converter singleton instance // Initialize an ezbookkeeping transaction data tsv file converter singleton instance
var ( var (
EzBookKeepingTransactionDataTSVFileConverter = &ezBookKeepingTransactionDataTSVFileConverter{ EzBookKeepingTransactionDataTSVFileConverter = &ezBookKeepingTransactionDataTSVFileConverter{
ezBookKeepingTransactionDataPlainTextConverter{ ezBookKeepingTransactionDataPlainTextExporter{
DataTableTransactionDataConverter: DataTableTransactionDataConverter{ DataTableTransactionDataExporter: DataTableTransactionDataExporter{
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
columnSeparator: "\t",
lineSeparator: "\n",
geoLocationSeparator: " ",
transactionTagSeparator: ";",
},
columns: ezbookkeepingDataColumns,
},
ezBookKeepingTransactionDataPlainTextImporter{
DataTableTransactionDataImporter: DataTableTransactionDataImporter{
dataColumnMapping: ezbookkeepingDataColumnNameMapping, dataColumnMapping: ezbookkeepingDataColumnNameMapping,
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
transactionTypeNameMapping: ezbookkeepingNameTransactionTypeMapping, transactionTypeNameMapping: ezbookkeepingNameTransactionTypeMapping,
columnSeparator: "\t", columnSeparator: "\t",
lineSeparator: "\n", lineSeparator: "\n",
geoLocationSeparator: " ", geoLocationSeparator: " ",
transactionTagSeparator: ";", transactionTagSeparator: ";",
}, },
columns: ezbookkeepingDataColumns,
}, },
} }
) )