mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 01:04:25 +08:00
code refactor
This commit is contained in:
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package datatable
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
+32
-3
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package datatable
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -55,7 +55,36 @@ type DataTableTransactionDataImporter struct {
|
|||||||
// DataTableTransactionDataImporterPostProcessFunc represents item post process function of DataTableTransactionDataImporter
|
// DataTableTransactionDataImporterPostProcessFunc represents item post process function of DataTableTransactionDataImporter
|
||||||
type DataTableTransactionDataImporterPostProcessFunc func(core.Context, *models.ImportTransaction) error
|
type DataTableTransactionDataImporterPostProcessFunc func(core.Context, *models.ImportTransaction) 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 {
|
// CreateNewDataTableTransactionDataExporter returns a new data table transaction data exporter according to the specified arguments
|
||||||
|
func CreateNewDataTableTransactionDataExporter(dataColumnMapping map[DataTableColumn]string, transactionTypeMapping map[models.TransactionType]string, geoLocationSeparator string, transactionTagSeparator string) *DataTableTransactionDataExporter {
|
||||||
|
return &DataTableTransactionDataExporter{
|
||||||
|
dataColumnMapping: dataColumnMapping,
|
||||||
|
transactionTypeMapping: transactionTypeMapping,
|
||||||
|
geoLocationSeparator: geoLocationSeparator,
|
||||||
|
transactionTagSeparator: transactionTagSeparator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewDataTableTransactionDataImporter returns a new data table transaction data importer according to the specified arguments
|
||||||
|
func CreateNewDataTableTransactionDataImporter(dataColumnMapping map[DataTableColumn]string, transactionTypeMapping map[models.TransactionType]string, geoLocationSeparator string, transactionTagSeparator string) *DataTableTransactionDataImporter {
|
||||||
|
return &DataTableTransactionDataImporter{
|
||||||
|
dataColumnMapping: dataColumnMapping,
|
||||||
|
transactionTypeMapping: transactionTypeMapping,
|
||||||
|
geoLocationSeparator: geoLocationSeparator,
|
||||||
|
transactionTagSeparator: transactionTagSeparator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewSimpleDataTableTransactionDataImporterWithPostProcessFunc returns a new data table transaction data importer according to the specified arguments
|
||||||
|
func CreateNewSimpleDataTableTransactionDataImporterWithPostProcessFunc(dataColumnMapping map[DataTableColumn]string, transactionTypeMapping map[models.TransactionType]string, postProcessFunc DataTableTransactionDataImporterPostProcessFunc) *DataTableTransactionDataImporter {
|
||||||
|
return &DataTableTransactionDataImporter{
|
||||||
|
dataColumnMapping: dataColumnMapping,
|
||||||
|
transactionTypeMapping: transactionTypeMapping,
|
||||||
|
postProcessFunc: postProcessFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
@@ -192,7 +221,7 @@ func (c *DataTableTransactionDataExporter) getExportedTags(dataTableBuilder Data
|
|||||||
return dataTableBuilder.ReplaceDelimiters(ret.String())
|
return dataTableBuilder.ReplaceDelimiters(ret.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
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.ErrNotFoundTransactionDataInFile
|
return nil, nil, nil, nil, errs.ErrNotFoundTransactionDataInFile
|
||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package datatable
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
@@ -136,9 +136,10 @@ func (t *WritableDataRowIterator) Next() ImportedDataRow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNewWritableDataTable(columns []DataTableColumn) (*WritableDataTable, error) {
|
// CreateNewWritableDataTable returns a new writable data table according to the specified columns
|
||||||
|
func CreateNewWritableDataTable(columns []DataTableColumn) *WritableDataTable {
|
||||||
return &WritableDataTable{
|
return &WritableDataTable{
|
||||||
allData: make([]map[DataTableColumn]string, 0),
|
allData: make([]map[DataTableColumn]string, 0),
|
||||||
columns: columns,
|
columns: columns,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
+6
-13
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package datatable
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@@ -17,8 +17,7 @@ func TestWritableDataTableAdd(t *testing.T) {
|
|||||||
columns[3] = DATA_TABLE_ACCOUNT_NAME
|
columns[3] = DATA_TABLE_ACCOUNT_NAME
|
||||||
columns[4] = DATA_TABLE_AMOUNT
|
columns[4] = DATA_TABLE_AMOUNT
|
||||||
|
|
||||||
writableDataTable, err := createNewWritableDataTable(columns)
|
writableDataTable := CreateNewWritableDataTable(columns)
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
||||||
|
|
||||||
@@ -66,8 +65,7 @@ func TestWritableDataTableAdd_NotExistsColumn(t *testing.T) {
|
|||||||
columns := make([]DataTableColumn, 1)
|
columns := make([]DataTableColumn, 1)
|
||||||
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
||||||
|
|
||||||
writableDataTable, err := createNewWritableDataTable(columns)
|
writableDataTable := CreateNewWritableDataTable(columns)
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
expectedTransactionUnixTime := time.Now().Unix()
|
expectedTransactionUnixTime := time.Now().Unix()
|
||||||
expectedTextualTransactionTime := utils.FormatUnixTimeToLongDateTime(expectedTransactionUnixTime, time.Local)
|
expectedTextualTransactionTime := utils.FormatUnixTimeToLongDateTime(expectedTransactionUnixTime, time.Local)
|
||||||
@@ -87,9 +85,7 @@ func TestWritableDataTableGet_NotExistsRow(t *testing.T) {
|
|||||||
columns := make([]DataTableColumn, 1)
|
columns := make([]DataTableColumn, 1)
|
||||||
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
||||||
|
|
||||||
writableDataTable, err := createNewWritableDataTable(columns)
|
writableDataTable := CreateNewWritableDataTable(columns)
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
||||||
|
|
||||||
dataRow := writableDataTable.Get(0)
|
dataRow := writableDataTable.Get(0)
|
||||||
@@ -100,8 +96,7 @@ func TestWritableDataRowGetData_NotExistsColumn(t *testing.T) {
|
|||||||
columns := make([]DataTableColumn, 1)
|
columns := make([]DataTableColumn, 1)
|
||||||
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
columns[0] = DATA_TABLE_TRANSACTION_TIME
|
||||||
|
|
||||||
writableDataTable, err := createNewWritableDataTable(columns)
|
writableDataTable := CreateNewWritableDataTable(columns)
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
expectedTransactionUnixTime := time.Now().Unix()
|
expectedTransactionUnixTime := time.Now().Unix()
|
||||||
expectedTextualTransactionTime := utils.FormatUnixTimeToLongDateTime(expectedTransactionUnixTime, time.Local)
|
expectedTextualTransactionTime := utils.FormatUnixTimeToLongDateTime(expectedTransactionUnixTime, time.Local)
|
||||||
@@ -124,9 +119,7 @@ func TestWritableDataTableDataRowIterator(t *testing.T) {
|
|||||||
columns[3] = DATA_TABLE_ACCOUNT_NAME
|
columns[3] = DATA_TABLE_ACCOUNT_NAME
|
||||||
columns[4] = DATA_TABLE_AMOUNT
|
columns[4] = DATA_TABLE_AMOUNT
|
||||||
|
|
||||||
writableDataTable, err := createNewWritableDataTable(columns)
|
writableDataTable := CreateNewWritableDataTable(columns)
|
||||||
assert.Nil(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
assert.Equal(t, 0, writableDataTable.DataRowCount())
|
||||||
|
|
||||||
expectedTransactionUnixTimes := make([]int64, 3)
|
expectedTransactionUnixTimes := make([]int64, 3)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package _default
|
||||||
|
|
||||||
|
// ezBookKeepingTransactionDataCSVFileConverter defines the structure of CSV file converter
|
||||||
|
type ezBookKeepingTransactionDataCSVFileConverter struct {
|
||||||
|
ezBookKeepingTransactionDataPlainTextConverter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize an ezbookkeeping transaction data csv file converter singleton instance
|
||||||
|
var (
|
||||||
|
EzBookKeepingTransactionDataCSVFileConverter = &ezBookKeepingTransactionDataCSVFileConverter{
|
||||||
|
ezBookKeepingTransactionDataPlainTextConverter{
|
||||||
|
columnSeparator: ",",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package _default
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ezBookKeepingTransactionDataPlainTextConverter defines the structure of ezbookkeeping plain text converter for transaction data
|
||||||
|
type ezBookKeepingTransactionDataPlainTextConverter struct {
|
||||||
|
columnSeparator string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ezbookkeepingLineSeparator = "\n"
|
||||||
|
const ezbookkeepingGeoLocationSeparator = " "
|
||||||
|
const ezbookkeepingTagSeparator = ";"
|
||||||
|
|
||||||
|
var ezbookkeepingDataColumnNameMapping = map[datatable.DataTableColumn]string{
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TIME: "Time",
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TIMEZONE: "Timezone",
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TYPE: "Type",
|
||||||
|
datatable.DATA_TABLE_CATEGORY: "Category",
|
||||||
|
datatable.DATA_TABLE_SUB_CATEGORY: "Sub Category",
|
||||||
|
datatable.DATA_TABLE_ACCOUNT_NAME: "Account",
|
||||||
|
datatable.DATA_TABLE_ACCOUNT_CURRENCY: "Account Currency",
|
||||||
|
datatable.DATA_TABLE_AMOUNT: "Amount",
|
||||||
|
datatable.DATA_TABLE_RELATED_ACCOUNT_NAME: "Account2",
|
||||||
|
datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY: "Account2 Currency",
|
||||||
|
datatable.DATA_TABLE_RELATED_AMOUNT: "Account2 Amount",
|
||||||
|
datatable.DATA_TABLE_GEOGRAPHIC_LOCATION: "Geographic Location",
|
||||||
|
datatable.DATA_TABLE_TAGS: "Tags",
|
||||||
|
datatable.DATA_TABLE_DESCRIPTION: "Description",
|
||||||
|
}
|
||||||
|
|
||||||
|
var ezbookkeepingTransactionTypeNameMapping = map[models.TransactionType]string{
|
||||||
|
models.TRANSACTION_TYPE_MODIFY_BALANCE: "Balance Modification",
|
||||||
|
models.TRANSACTION_TYPE_INCOME: "Income",
|
||||||
|
models.TRANSACTION_TYPE_EXPENSE: "Expense",
|
||||||
|
models.TRANSACTION_TYPE_TRANSFER: "Transfer",
|
||||||
|
}
|
||||||
|
|
||||||
|
var ezbookkeepingDataColumns = []datatable.DataTableColumn{
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TIME,
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TIMEZONE,
|
||||||
|
datatable.DATA_TABLE_TRANSACTION_TYPE,
|
||||||
|
datatable.DATA_TABLE_CATEGORY,
|
||||||
|
datatable.DATA_TABLE_SUB_CATEGORY,
|
||||||
|
datatable.DATA_TABLE_ACCOUNT_NAME,
|
||||||
|
datatable.DATA_TABLE_ACCOUNT_CURRENCY,
|
||||||
|
datatable.DATA_TABLE_AMOUNT,
|
||||||
|
datatable.DATA_TABLE_RELATED_ACCOUNT_NAME,
|
||||||
|
datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY,
|
||||||
|
datatable.DATA_TABLE_RELATED_AMOUNT,
|
||||||
|
datatable.DATA_TABLE_GEOGRAPHIC_LOCATION,
|
||||||
|
datatable.DATA_TABLE_TAGS,
|
||||||
|
datatable.DATA_TABLE_DESCRIPTION,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
dataTableBuilder := createNewezbookkeepingTransactionPlainTextDataTableBuilder(
|
||||||
|
len(transactions),
|
||||||
|
ezbookkeepingDataColumns,
|
||||||
|
ezbookkeepingDataColumnNameMapping,
|
||||||
|
c.columnSeparator,
|
||||||
|
ezbookkeepingLineSeparator,
|
||||||
|
)
|
||||||
|
|
||||||
|
dataTableExporter := datatable.CreateNewDataTableTransactionDataExporter(
|
||||||
|
ezbookkeepingDataColumnNameMapping,
|
||||||
|
ezbookkeepingTransactionTypeNameMapping,
|
||||||
|
ezbookkeepingGeoLocationSeparator,
|
||||||
|
ezbookkeepingTagSeparator,
|
||||||
|
)
|
||||||
|
|
||||||
|
err := dataTableExporter.BuildExportedContent(ctx, dataTableBuilder, uid, transactions, accountMap, categoryMap, tagMap, allTagIndexes)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(dataTableBuilder.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
dataTable, err := createNewezbookkeepingTransactionPlainTextDataTable(
|
||||||
|
string(data),
|
||||||
|
c.columnSeparator,
|
||||||
|
ezbookkeepingLineSeparator,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
dataTableImporter := datatable.CreateNewDataTableTransactionDataImporter(
|
||||||
|
ezbookkeepingDataColumnNameMapping,
|
||||||
|
ezbookkeepingTransactionTypeNameMapping,
|
||||||
|
ezbookkeepingGeoLocationSeparator,
|
||||||
|
ezbookkeepingTagSeparator,
|
||||||
|
)
|
||||||
|
|
||||||
|
return dataTableImporter.ParseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package _default
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
+8
-7
@@ -1,10 +1,11 @@
|
|||||||
package converters
|
package _default
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||||
)
|
)
|
||||||
@@ -32,8 +33,8 @@ type ezBookKeepingTransactionPlainTextDataRowIterator struct {
|
|||||||
type ezBookKeepingTransactionPlainTextDataTableBuilder struct {
|
type ezBookKeepingTransactionPlainTextDataTableBuilder struct {
|
||||||
columnSeparator string
|
columnSeparator string
|
||||||
lineSeparator string
|
lineSeparator string
|
||||||
columns []DataTableColumn
|
columns []datatable.DataTableColumn
|
||||||
dataColumnNameMapping map[DataTableColumn]string
|
dataColumnNameMapping map[datatable.DataTableColumn]string
|
||||||
dataLineFormat string
|
dataLineFormat string
|
||||||
builder *strings.Builder
|
builder *strings.Builder
|
||||||
}
|
}
|
||||||
@@ -53,7 +54,7 @@ func (t *ezBookKeepingTransactionPlainTextDataTable) HeaderLineColumnNames() []s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
func (t *ezBookKeepingTransactionPlainTextDataTable) DataRowIterator() ImportedDataRowIterator {
|
func (t *ezBookKeepingTransactionPlainTextDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
||||||
return &ezBookKeepingTransactionPlainTextDataRowIterator{
|
return &ezBookKeepingTransactionPlainTextDataRowIterator{
|
||||||
dataTable: t,
|
dataTable: t,
|
||||||
currentIndex: 0,
|
currentIndex: 0,
|
||||||
@@ -90,7 +91,7 @@ func (t *ezBookKeepingTransactionPlainTextDataRowIterator) HasNext() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next imported data row
|
||||||
func (t *ezBookKeepingTransactionPlainTextDataRowIterator) Next() ImportedDataRow {
|
func (t *ezBookKeepingTransactionPlainTextDataRowIterator) Next() datatable.ImportedDataRow {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ func (t *ezBookKeepingTransactionPlainTextDataRowIterator) Next() ImportedDataRo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AppendTransaction appends the specified transaction to data builder
|
// AppendTransaction appends the specified transaction to data builder
|
||||||
func (b *ezBookKeepingTransactionPlainTextDataTableBuilder) AppendTransaction(data map[DataTableColumn]string) {
|
func (b *ezBookKeepingTransactionPlainTextDataTableBuilder) AppendTransaction(data map[datatable.DataTableColumn]string) {
|
||||||
dataRowParams := make([]any, len(b.columns))
|
dataRowParams := make([]any, len(b.columns))
|
||||||
|
|
||||||
for i := 0; i < len(b.columns); i++ {
|
for i := 0; i < len(b.columns); i++ {
|
||||||
@@ -186,7 +187,7 @@ func createNewezbookkeepingTransactionPlainTextDataTable(content string, columnS
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createNewezbookkeepingTransactionPlainTextDataTableBuilder(transactionCount int, columns []DataTableColumn, dataColumnNameMapping map[DataTableColumn]string, columnSeparator string, lineSeparator string) *ezBookKeepingTransactionPlainTextDataTableBuilder {
|
func createNewezbookkeepingTransactionPlainTextDataTableBuilder(transactionCount int, columns []datatable.DataTableColumn, dataColumnNameMapping map[datatable.DataTableColumn]string, columnSeparator string, lineSeparator string) *ezBookKeepingTransactionPlainTextDataTableBuilder {
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
builder.Grow(transactionCount * 100)
|
builder.Grow(transactionCount * 100)
|
||||||
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package _default
|
||||||
|
|
||||||
|
// ezBookKeepingTransactionDataTSVFileConverter defines the structure of TSV file converter
|
||||||
|
type ezBookKeepingTransactionDataTSVFileConverter struct {
|
||||||
|
ezBookKeepingTransactionDataPlainTextConverter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize an ezbookkeeping transaction data tsv file converter singleton instance
|
||||||
|
var (
|
||||||
|
EzBookKeepingTransactionDataTSVFileConverter = &ezBookKeepingTransactionDataTSVFileConverter{
|
||||||
|
ezBookKeepingTransactionDataPlainTextConverter{
|
||||||
|
columnSeparator: "\t",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package converters
|
|
||||||
|
|
||||||
// ezBookKeepingTransactionDataCSVFileConverter defines the structure of CSV file converter
|
|
||||||
type ezBookKeepingTransactionDataCSVFileConverter struct {
|
|
||||||
ezBookKeepingTransactionDataPlainTextExporter
|
|
||||||
ezBookKeepingTransactionDataPlainTextImporter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize an ezbookkeeping transaction data csv file converter singleton instance
|
|
||||||
var (
|
|
||||||
EzBookKeepingTransactionDataCSVFileConverter = &ezBookKeepingTransactionDataCSVFileConverter{
|
|
||||||
ezBookKeepingTransactionDataPlainTextExporter{
|
|
||||||
DataTableTransactionDataExporter: DataTableTransactionDataExporter{
|
|
||||||
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
|
|
||||||
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
|
|
||||||
geoLocationSeparator: " ",
|
|
||||||
transactionTagSeparator: ";",
|
|
||||||
},
|
|
||||||
columns: ezbookkeepingDataColumns,
|
|
||||||
columnSeparator: ",",
|
|
||||||
lineSeparator: "\n",
|
|
||||||
},
|
|
||||||
ezBookKeepingTransactionDataPlainTextImporter{
|
|
||||||
DataTableTransactionDataImporter: DataTableTransactionDataImporter{
|
|
||||||
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
|
|
||||||
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
|
|
||||||
geoLocationSeparator: " ",
|
|
||||||
transactionTagSeparator: ";",
|
|
||||||
},
|
|
||||||
columnSeparator: ",",
|
|
||||||
lineSeparator: "\n",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
package converters
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ezBookKeepingTransactionDataPlainTextExporter defines the structure of ezbookkeeping plain text exporter for transaction data
|
|
||||||
type ezBookKeepingTransactionDataPlainTextExporter struct {
|
|
||||||
DataTableTransactionDataExporter
|
|
||||||
columns []DataTableColumn
|
|
||||||
columnSeparator string
|
|
||||||
lineSeparator string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ezBookKeepingTransactionDataPlainTextImporter defines the structure of ezbookkeeping plain text importer for transaction data
|
|
||||||
type ezBookKeepingTransactionDataPlainTextImporter struct {
|
|
||||||
DataTableTransactionDataImporter
|
|
||||||
columnSeparator string
|
|
||||||
lineSeparator string
|
|
||||||
}
|
|
||||||
|
|
||||||
var ezbookkeepingDataColumnNameMapping = map[DataTableColumn]string{
|
|
||||||
DATA_TABLE_TRANSACTION_TIME: "Time",
|
|
||||||
DATA_TABLE_TRANSACTION_TIMEZONE: "Timezone",
|
|
||||||
DATA_TABLE_TRANSACTION_TYPE: "Type",
|
|
||||||
DATA_TABLE_CATEGORY: "Category",
|
|
||||||
DATA_TABLE_SUB_CATEGORY: "Sub Category",
|
|
||||||
DATA_TABLE_ACCOUNT_NAME: "Account",
|
|
||||||
DATA_TABLE_ACCOUNT_CURRENCY: "Account Currency",
|
|
||||||
DATA_TABLE_AMOUNT: "Amount",
|
|
||||||
DATA_TABLE_RELATED_ACCOUNT_NAME: "Account2",
|
|
||||||
DATA_TABLE_RELATED_ACCOUNT_CURRENCY: "Account2 Currency",
|
|
||||||
DATA_TABLE_RELATED_AMOUNT: "Account2 Amount",
|
|
||||||
DATA_TABLE_GEOGRAPHIC_LOCATION: "Geographic Location",
|
|
||||||
DATA_TABLE_TAGS: "Tags",
|
|
||||||
DATA_TABLE_DESCRIPTION: "Description",
|
|
||||||
}
|
|
||||||
|
|
||||||
var ezbookkeepingTransactionTypeNameMapping = map[models.TransactionType]string{
|
|
||||||
models.TRANSACTION_TYPE_MODIFY_BALANCE: "Balance Modification",
|
|
||||||
models.TRANSACTION_TYPE_INCOME: "Income",
|
|
||||||
models.TRANSACTION_TYPE_EXPENSE: "Expense",
|
|
||||||
models.TRANSACTION_TYPE_TRANSFER: "Transfer",
|
|
||||||
}
|
|
||||||
|
|
||||||
var ezbookkeepingDataColumns = []DataTableColumn{
|
|
||||||
DATA_TABLE_TRANSACTION_TIME,
|
|
||||||
DATA_TABLE_TRANSACTION_TIMEZONE,
|
|
||||||
DATA_TABLE_TRANSACTION_TYPE,
|
|
||||||
DATA_TABLE_CATEGORY,
|
|
||||||
DATA_TABLE_SUB_CATEGORY,
|
|
||||||
DATA_TABLE_ACCOUNT_NAME,
|
|
||||||
DATA_TABLE_ACCOUNT_CURRENCY,
|
|
||||||
DATA_TABLE_AMOUNT,
|
|
||||||
DATA_TABLE_RELATED_ACCOUNT_NAME,
|
|
||||||
DATA_TABLE_RELATED_ACCOUNT_CURRENCY,
|
|
||||||
DATA_TABLE_RELATED_AMOUNT,
|
|
||||||
DATA_TABLE_GEOGRAPHIC_LOCATION,
|
|
||||||
DATA_TABLE_TAGS,
|
|
||||||
DATA_TABLE_DESCRIPTION,
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToExportedContent returns the exported transaction plain text data
|
|
||||||
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)
|
|
||||||
err := c.buildExportedContent(ctx, dataTableBuilder, uid, transactions, accountMap, categoryMap, tagMap, allTagIndexes)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte(dataTableBuilder.String()), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseImportedData returns the imported data by parsing the transaction plain text data
|
|
||||||
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)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.parseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package converters
|
|
||||||
|
|
||||||
// ezBookKeepingTransactionDataTSVFileConverter defines the structure of TSV file converter
|
|
||||||
type ezBookKeepingTransactionDataTSVFileConverter struct {
|
|
||||||
ezBookKeepingTransactionDataPlainTextExporter
|
|
||||||
ezBookKeepingTransactionDataPlainTextImporter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize an ezbookkeeping transaction data tsv file converter singleton instance
|
|
||||||
var (
|
|
||||||
EzBookKeepingTransactionDataTSVFileConverter = &ezBookKeepingTransactionDataTSVFileConverter{
|
|
||||||
ezBookKeepingTransactionDataPlainTextExporter{
|
|
||||||
DataTableTransactionDataExporter: DataTableTransactionDataExporter{
|
|
||||||
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
|
|
||||||
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
|
|
||||||
geoLocationSeparator: " ",
|
|
||||||
transactionTagSeparator: ";",
|
|
||||||
},
|
|
||||||
columns: ezbookkeepingDataColumns,
|
|
||||||
columnSeparator: "\t",
|
|
||||||
lineSeparator: "\n",
|
|
||||||
},
|
|
||||||
ezBookKeepingTransactionDataPlainTextImporter{
|
|
||||||
DataTableTransactionDataImporter: DataTableTransactionDataImporter{
|
|
||||||
dataColumnMapping: ezbookkeepingDataColumnNameMapping,
|
|
||||||
transactionTypeMapping: ezbookkeepingTransactionTypeNameMapping,
|
|
||||||
geoLocationSeparator: " ",
|
|
||||||
transactionTagSeparator: ";",
|
|
||||||
},
|
|
||||||
columnSeparator: "\t",
|
|
||||||
lineSeparator: "\n",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
+52
-60
@@ -1,10 +1,11 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||||
@@ -15,15 +16,11 @@ const feideeMymoneyTransactionDataCsvFileHeader = "随手记导出文件(headers
|
|||||||
const feideeMymoneyTransactionDataCsvFileHeaderWithUtf8Bom = "\xEF\xBB\xBF" + feideeMymoneyTransactionDataCsvFileHeader
|
const feideeMymoneyTransactionDataCsvFileHeaderWithUtf8Bom = "\xEF\xBB\xBF" + feideeMymoneyTransactionDataCsvFileHeader
|
||||||
|
|
||||||
// feideeMymoneyTransactionDataCsvImporter defines the structure of feidee mymoney csv importer for transaction data
|
// feideeMymoneyTransactionDataCsvImporter defines the structure of feidee mymoney csv importer for transaction data
|
||||||
type feideeMymoneyTransactionDataCsvImporter struct {
|
type feideeMymoneyTransactionDataCsvImporter struct{}
|
||||||
transactionTypeMapping map[models.TransactionType]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize a feidee mymoney transaction data csv file importer singleton instance
|
// Initialize a feidee mymoney transaction data csv file importer singleton instance
|
||||||
var (
|
var (
|
||||||
FeideeMymoneyTransactionDataCsvImporter = &feideeMymoneyTransactionDataCsvImporter{
|
FeideeMymoneyTransactionDataCsvImporter = &feideeMymoneyTransactionDataCsvImporter{}
|
||||||
transactionTypeMapping: feideeMymoneyTransactionTypeNameMapping,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseImportedData returns the imported data by parsing the feidee mymoney transaction csv data
|
// ParseImportedData returns the imported data by parsing the feidee mymoney transaction csv data
|
||||||
@@ -68,41 +65,36 @@ func (c *feideeMymoneyTransactionDataCsvImporter) ParseImportedData(ctx core.Con
|
|||||||
return nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
return nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
newColumns := make([]DataTableColumn, 0, 11)
|
newColumns := make([]datatable.DataTableColumn, 0, 11)
|
||||||
newColumns = append(newColumns, DATA_TABLE_TRANSACTION_TYPE)
|
newColumns = append(newColumns, datatable.DATA_TABLE_TRANSACTION_TYPE)
|
||||||
newColumns = append(newColumns, DATA_TABLE_TRANSACTION_TIME)
|
newColumns = append(newColumns, datatable.DATA_TABLE_TRANSACTION_TIME)
|
||||||
|
|
||||||
if categoryColumnExists {
|
if categoryColumnExists {
|
||||||
newColumns = append(newColumns, DATA_TABLE_CATEGORY)
|
newColumns = append(newColumns, datatable.DATA_TABLE_CATEGORY)
|
||||||
}
|
}
|
||||||
|
|
||||||
newColumns = append(newColumns, DATA_TABLE_SUB_CATEGORY)
|
newColumns = append(newColumns, datatable.DATA_TABLE_SUB_CATEGORY)
|
||||||
newColumns = append(newColumns, DATA_TABLE_ACCOUNT_NAME)
|
newColumns = append(newColumns, datatable.DATA_TABLE_ACCOUNT_NAME)
|
||||||
|
|
||||||
if accountCurrencyColumnExists {
|
if accountCurrencyColumnExists {
|
||||||
newColumns = append(newColumns, DATA_TABLE_ACCOUNT_CURRENCY)
|
newColumns = append(newColumns, datatable.DATA_TABLE_ACCOUNT_CURRENCY)
|
||||||
}
|
}
|
||||||
|
|
||||||
newColumns = append(newColumns, DATA_TABLE_AMOUNT)
|
newColumns = append(newColumns, datatable.DATA_TABLE_AMOUNT)
|
||||||
newColumns = append(newColumns, DATA_TABLE_RELATED_ACCOUNT_NAME)
|
newColumns = append(newColumns, datatable.DATA_TABLE_RELATED_ACCOUNT_NAME)
|
||||||
|
|
||||||
if accountCurrencyColumnExists {
|
if accountCurrencyColumnExists {
|
||||||
newColumns = append(newColumns, DATA_TABLE_RELATED_ACCOUNT_CURRENCY)
|
newColumns = append(newColumns, datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY)
|
||||||
}
|
}
|
||||||
|
|
||||||
newColumns = append(newColumns, DATA_TABLE_RELATED_AMOUNT)
|
newColumns = append(newColumns, datatable.DATA_TABLE_RELATED_AMOUNT)
|
||||||
|
|
||||||
if descriptionColumnExists {
|
if descriptionColumnExists {
|
||||||
newColumns = append(newColumns, DATA_TABLE_DESCRIPTION)
|
newColumns = append(newColumns, datatable.DATA_TABLE_DESCRIPTION)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTable, err := createNewWritableDataTable(newColumns)
|
dataTable := datatable.CreateNewWritableDataTable(newColumns)
|
||||||
|
transferTransactionsMap := make(map[string]map[datatable.DataTableColumn]string, 0)
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transferTransactionsMap := make(map[string]map[DataTableColumn]string, 0)
|
|
||||||
|
|
||||||
for i := 1; i < len(allLines); i++ {
|
for i := 1; i < len(allLines); i++ {
|
||||||
items := allLines[i]
|
items := allLines[i]
|
||||||
@@ -132,20 +124,20 @@ func (c *feideeMymoneyTransactionDataCsvImporter) ParseImportedData(ctx core.Con
|
|||||||
return nil, nil, nil, nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
return nil, nil, nil, nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionType := data[DATA_TABLE_TRANSACTION_TYPE]
|
transactionType := data[datatable.DATA_TABLE_TRANSACTION_TYPE]
|
||||||
|
|
||||||
if transactionType == "余额变更" || transactionType == "收入" || transactionType == "支出" {
|
if transactionType == "余额变更" || transactionType == "收入" || transactionType == "支出" {
|
||||||
if transactionType == "余额变更" {
|
if transactionType == "余额变更" {
|
||||||
data[DATA_TABLE_TRANSACTION_TYPE] = c.transactionTypeMapping[models.TRANSACTION_TYPE_MODIFY_BALANCE]
|
data[datatable.DATA_TABLE_TRANSACTION_TYPE] = feideeMymoneyTransactionTypeNameMapping[models.TRANSACTION_TYPE_MODIFY_BALANCE]
|
||||||
} else if transactionType == "收入" {
|
} else if transactionType == "收入" {
|
||||||
data[DATA_TABLE_TRANSACTION_TYPE] = c.transactionTypeMapping[models.TRANSACTION_TYPE_INCOME]
|
data[datatable.DATA_TABLE_TRANSACTION_TYPE] = feideeMymoneyTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME]
|
||||||
} else if transactionType == "支出" {
|
} else if transactionType == "支出" {
|
||||||
data[DATA_TABLE_TRANSACTION_TYPE] = c.transactionTypeMapping[models.TRANSACTION_TYPE_EXPENSE]
|
data[datatable.DATA_TABLE_TRANSACTION_TYPE] = feideeMymoneyTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE]
|
||||||
}
|
}
|
||||||
|
|
||||||
data[DATA_TABLE_RELATED_ACCOUNT_NAME] = ""
|
data[datatable.DATA_TABLE_RELATED_ACCOUNT_NAME] = ""
|
||||||
data[DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = ""
|
data[datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = ""
|
||||||
data[DATA_TABLE_RELATED_AMOUNT] = ""
|
data[datatable.DATA_TABLE_RELATED_AMOUNT] = ""
|
||||||
dataTable.Add(data)
|
dataTable.Add(data)
|
||||||
} else if transactionType == "转入" || transactionType == "转出" {
|
} else if transactionType == "转入" || transactionType == "转出" {
|
||||||
if relatedId == "" {
|
if relatedId == "" {
|
||||||
@@ -160,18 +152,18 @@ func (c *feideeMymoneyTransactionDataCsvImporter) ParseImportedData(ctx core.Con
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if transactionType == "转入" && relatedData[DATA_TABLE_TRANSACTION_TYPE] == "转出" {
|
if transactionType == "转入" && relatedData[datatable.DATA_TABLE_TRANSACTION_TYPE] == "转出" {
|
||||||
relatedData[DATA_TABLE_TRANSACTION_TYPE] = c.transactionTypeMapping[models.TRANSACTION_TYPE_TRANSFER]
|
relatedData[datatable.DATA_TABLE_TRANSACTION_TYPE] = feideeMymoneyTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER]
|
||||||
relatedData[DATA_TABLE_RELATED_ACCOUNT_NAME] = data[DATA_TABLE_ACCOUNT_NAME]
|
relatedData[datatable.DATA_TABLE_RELATED_ACCOUNT_NAME] = data[datatable.DATA_TABLE_ACCOUNT_NAME]
|
||||||
relatedData[DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = data[DATA_TABLE_ACCOUNT_CURRENCY]
|
relatedData[datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = data[datatable.DATA_TABLE_ACCOUNT_CURRENCY]
|
||||||
relatedData[DATA_TABLE_RELATED_AMOUNT] = data[DATA_TABLE_AMOUNT]
|
relatedData[datatable.DATA_TABLE_RELATED_AMOUNT] = data[datatable.DATA_TABLE_AMOUNT]
|
||||||
dataTable.Add(relatedData)
|
dataTable.Add(relatedData)
|
||||||
delete(transferTransactionsMap, relatedId)
|
delete(transferTransactionsMap, relatedId)
|
||||||
} else if transactionType == "转出" && relatedData[DATA_TABLE_TRANSACTION_TYPE] == "转入" {
|
} else if transactionType == "转出" && relatedData[datatable.DATA_TABLE_TRANSACTION_TYPE] == "转入" {
|
||||||
data[DATA_TABLE_TRANSACTION_TYPE] = c.transactionTypeMapping[models.TRANSACTION_TYPE_TRANSFER]
|
data[datatable.DATA_TABLE_TRANSACTION_TYPE] = feideeMymoneyTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER]
|
||||||
data[DATA_TABLE_RELATED_ACCOUNT_NAME] = relatedData[DATA_TABLE_ACCOUNT_NAME]
|
data[datatable.DATA_TABLE_RELATED_ACCOUNT_NAME] = relatedData[datatable.DATA_TABLE_ACCOUNT_NAME]
|
||||||
data[DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = relatedData[DATA_TABLE_ACCOUNT_CURRENCY]
|
data[datatable.DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = relatedData[datatable.DATA_TABLE_ACCOUNT_CURRENCY]
|
||||||
data[DATA_TABLE_RELATED_AMOUNT] = relatedData[DATA_TABLE_AMOUNT]
|
data[datatable.DATA_TABLE_RELATED_AMOUNT] = relatedData[datatable.DATA_TABLE_AMOUNT]
|
||||||
dataTable.Add(data)
|
dataTable.Add(data)
|
||||||
delete(transferTransactionsMap, relatedId)
|
delete(transferTransactionsMap, relatedId)
|
||||||
} else {
|
} else {
|
||||||
@@ -189,13 +181,13 @@ func (c *feideeMymoneyTransactionDataCsvImporter) ParseImportedData(ctx core.Con
|
|||||||
return nil, nil, nil, nil, errs.ErrFoundRecordNotHasRelatedRecord
|
return nil, nil, nil, nil, errs.ErrFoundRecordNotHasRelatedRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTableImporter := DataTableTransactionDataImporter{
|
dataTableImporter := datatable.CreateNewSimpleDataTableTransactionDataImporterWithPostProcessFunc(
|
||||||
dataColumnMapping: dataTable.GetDataColumnMapping(),
|
dataTable.GetDataColumnMapping(),
|
||||||
transactionTypeMapping: c.transactionTypeMapping,
|
feideeMymoneyTransactionTypeNameMapping,
|
||||||
postProcessFunc: feideeMymoneyTransactionDataImporterPostProcess,
|
feideeMymoneyTransactionDataImporterPostProcess,
|
||||||
}
|
)
|
||||||
|
|
||||||
return dataTableImporter.parseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *feideeMymoneyTransactionDataCsvImporter) parseAllLinesFromCsvData(ctx core.Context, content string) ([][]string, error) {
|
func (c *feideeMymoneyTransactionDataCsvImporter) parseAllLinesFromCsvData(ctx core.Context, content string) ([][]string, error) {
|
||||||
@@ -246,40 +238,40 @@ func (c *feideeMymoneyTransactionDataCsvImporter) parseTransactionData(
|
|||||||
descriptionColumnExists bool,
|
descriptionColumnExists bool,
|
||||||
relatedIdColumnIdx int,
|
relatedIdColumnIdx int,
|
||||||
relatedIdColumnExists bool,
|
relatedIdColumnExists bool,
|
||||||
) (map[DataTableColumn]string, string) {
|
) (map[datatable.DataTableColumn]string, string) {
|
||||||
data := make(map[DataTableColumn]string, 11)
|
data := make(map[datatable.DataTableColumn]string, 11)
|
||||||
relatedId := ""
|
relatedId := ""
|
||||||
|
|
||||||
if timeColumnExists && timeColumnIdx < len(items) {
|
if timeColumnExists && timeColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_TRANSACTION_TIME] = items[timeColumnIdx]
|
data[datatable.DATA_TABLE_TRANSACTION_TIME] = items[timeColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if typeColumnExists && typeColumnIdx < len(items) {
|
if typeColumnExists && typeColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_TRANSACTION_TYPE] = items[typeColumnIdx]
|
data[datatable.DATA_TABLE_TRANSACTION_TYPE] = items[typeColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if categoryColumnExists && categoryColumnIdx < len(items) {
|
if categoryColumnExists && categoryColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_CATEGORY] = items[categoryColumnIdx]
|
data[datatable.DATA_TABLE_CATEGORY] = items[categoryColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if subCategoryColumnExists && subCategoryColumnIdx < len(items) {
|
if subCategoryColumnExists && subCategoryColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_SUB_CATEGORY] = items[subCategoryColumnIdx]
|
data[datatable.DATA_TABLE_SUB_CATEGORY] = items[subCategoryColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountColumnExists && accountColumnIdx < len(items) {
|
if accountColumnExists && accountColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_ACCOUNT_NAME] = items[accountColumnIdx]
|
data[datatable.DATA_TABLE_ACCOUNT_NAME] = items[accountColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if accountCurrencyColumnExists && accountCurrencyColumnIdx < len(items) {
|
if accountCurrencyColumnExists && accountCurrencyColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_ACCOUNT_CURRENCY] = items[accountCurrencyColumnIdx]
|
data[datatable.DATA_TABLE_ACCOUNT_CURRENCY] = items[accountCurrencyColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if amountColumnExists && amountColumnIdx < len(items) {
|
if amountColumnExists && amountColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_AMOUNT] = items[amountColumnIdx]
|
data[datatable.DATA_TABLE_AMOUNT] = items[amountColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if descriptionColumnExists && descriptionColumnIdx < len(items) {
|
if descriptionColumnExists && descriptionColumnIdx < len(items) {
|
||||||
data[DATA_TABLE_DESCRIPTION] = items[descriptionColumnIdx]
|
data[datatable.DATA_TABLE_DESCRIPTION] = items[descriptionColumnIdx]
|
||||||
}
|
}
|
||||||
|
|
||||||
if relatedIdColumnExists && relatedIdColumnIdx < len(items) {
|
if relatedIdColumnExists && relatedIdColumnIdx < len(items) {
|
||||||
@@ -289,7 +281,7 @@ func (c *feideeMymoneyTransactionDataCsvImporter) parseTransactionData(
|
|||||||
return data, relatedId
|
return data, relatedId
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *feideeMymoneyTransactionDataCsvImporter) getRelatedIds(transferTransactionsMap map[string]map[DataTableColumn]string) string {
|
func (c *feideeMymoneyTransactionDataCsvImporter) getRelatedIds(transferTransactionsMap map[string]map[datatable.DataTableColumn]string) string {
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
|
|
||||||
for relatedId := range transferTransactionsMap {
|
for relatedId := range transferTransactionsMap {
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
+4
-3
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/shakinm/xlsReader/xls"
|
"github.com/shakinm/xlsReader/xls"
|
||||||
|
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||||
)
|
)
|
||||||
@@ -53,7 +54,7 @@ func (t *feideeMymoneyTransactionExcelFileDataTable) HeaderLineColumnNames() []s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
func (t *feideeMymoneyTransactionExcelFileDataTable) DataRowIterator() ImportedDataRowIterator {
|
func (t *feideeMymoneyTransactionExcelFileDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
||||||
return &feideeMymoneyTransactionExcelFileDataRowIterator{
|
return &feideeMymoneyTransactionExcelFileDataRowIterator{
|
||||||
dataTable: t,
|
dataTable: t,
|
||||||
currentTableIndex: 0,
|
currentTableIndex: 0,
|
||||||
@@ -141,7 +142,7 @@ func (t *feideeMymoneyTransactionExcelFileDataRowIterator) HasNext() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next imported data row
|
||||||
func (t *feideeMymoneyTransactionExcelFileDataRowIterator) Next() ImportedDataRow {
|
func (t *feideeMymoneyTransactionExcelFileDataRowIterator) Next() datatable.ImportedDataRow {
|
||||||
allSheets := t.dataTable.workbook.GetSheets()
|
allSheets := t.dataTable.workbook.GetSheets()
|
||||||
currentRowIndexInTable := t.currentRowIndexInTable
|
currentRowIndexInTable := t.currentRowIndexInTable
|
||||||
|
|
||||||
+11
-10
@@ -1,19 +1,20 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
var feideeMymoneyDataColumnNameMapping = map[DataTableColumn]string{
|
var feideeMymoneyDataColumnNameMapping = map[datatable.DataTableColumn]string{
|
||||||
DATA_TABLE_TRANSACTION_TIME: "日期",
|
datatable.DATA_TABLE_TRANSACTION_TIME: "日期",
|
||||||
DATA_TABLE_TRANSACTION_TYPE: "交易类型",
|
datatable.DATA_TABLE_TRANSACTION_TYPE: "交易类型",
|
||||||
DATA_TABLE_CATEGORY: "分类",
|
datatable.DATA_TABLE_CATEGORY: "分类",
|
||||||
DATA_TABLE_SUB_CATEGORY: "子分类",
|
datatable.DATA_TABLE_SUB_CATEGORY: "子分类",
|
||||||
DATA_TABLE_ACCOUNT_NAME: "账户1",
|
datatable.DATA_TABLE_ACCOUNT_NAME: "账户1",
|
||||||
DATA_TABLE_AMOUNT: "金额",
|
datatable.DATA_TABLE_AMOUNT: "金额",
|
||||||
DATA_TABLE_RELATED_ACCOUNT_NAME: "账户2",
|
datatable.DATA_TABLE_RELATED_ACCOUNT_NAME: "账户2",
|
||||||
DATA_TABLE_DESCRIPTION: "备注",
|
datatable.DATA_TABLE_DESCRIPTION: "备注",
|
||||||
}
|
}
|
||||||
|
|
||||||
var feideeMymoneyTransactionTypeNameMapping = map[models.TransactionType]string{
|
var feideeMymoneyTransactionTypeNameMapping = map[models.TransactionType]string{
|
||||||
+11
-10
@@ -1,24 +1,19 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// feideeMymoneyTransactionDataXlsImporter defines the structure of feidee mymoney xls importer for transaction data
|
// feideeMymoneyTransactionDataXlsImporter defines the structure of feidee mymoney xls importer for transaction data
|
||||||
type feideeMymoneyTransactionDataXlsImporter struct {
|
type feideeMymoneyTransactionDataXlsImporter struct {
|
||||||
DataTableTransactionDataImporter
|
datatable.DataTableTransactionDataImporter
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize a feidee mymoney transaction data xls file importer singleton instance
|
// Initialize a feidee mymoney transaction data xls file importer singleton instance
|
||||||
var (
|
var (
|
||||||
FeideeMymoneyTransactionDataXlsImporter = &feideeMymoneyTransactionDataXlsImporter{
|
FeideeMymoneyTransactionDataXlsImporter = &feideeMymoneyTransactionDataXlsImporter{}
|
||||||
DataTableTransactionDataImporter{
|
|
||||||
dataColumnMapping: feideeMymoneyDataColumnNameMapping,
|
|
||||||
transactionTypeMapping: feideeMymoneyTransactionTypeNameMapping,
|
|
||||||
postProcessFunc: feideeMymoneyTransactionDataImporterPostProcess,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParseImportedData returns the imported data by parsing the feidee mymoney transaction xls data
|
// ParseImportedData returns the imported data by parsing the feidee mymoney transaction xls data
|
||||||
@@ -29,5 +24,11 @@ func (c *feideeMymoneyTransactionDataXlsImporter) ParseImportedData(ctx core.Con
|
|||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.parseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
dataTableImporter := datatable.CreateNewSimpleDataTableTransactionDataImporterWithPostProcessFunc(
|
||||||
|
feideeMymoneyDataColumnNameMapping,
|
||||||
|
feideeMymoneyTransactionTypeNameMapping,
|
||||||
|
feideeMymoneyTransactionDataImporterPostProcess,
|
||||||
|
)
|
||||||
|
|
||||||
|
return dataTableImporter.ParseImportedData(ctx, user, dataTable, defaultTimezoneOffset, accountMap, categoryMap, tagMap)
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
package converters
|
package feidee
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
@@ -21,7 +21,7 @@ func TestFeideeMymoneyTransactionDataXlsImporterParseImportedData_MinimumValidDa
|
|||||||
DefaultCurrency: "CNY",
|
DefaultCurrency: "CNY",
|
||||||
}
|
}
|
||||||
|
|
||||||
testdata, err := os.ReadFile("../../testdata/feidee_mymoney_test_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/feidee_mymoney_test_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
allNewTransactions, allNewAccounts, allNewSubCategories, allNewTags, err := converter.ParseImportedData(context, user, testdata, 0, nil, nil, nil)
|
allNewTransactions, allNewAccounts, allNewSubCategories, allNewTags, err := converter.ParseImportedData(context, user, testdata, 0, nil, nil, nil)
|
||||||
@@ -1,28 +1,33 @@
|
|||||||
package converters
|
package converters
|
||||||
|
|
||||||
import "github.com/mayswind/ezbookkeeping/pkg/errs"
|
import (
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/base"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/default"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/feidee"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
|
)
|
||||||
|
|
||||||
// GetTransactionDataExporter returns the transaction data exporter according to the file type
|
// GetTransactionDataExporter returns the transaction data exporter according to the file type
|
||||||
func GetTransactionDataExporter(fileType string) TransactionDataExporter {
|
func GetTransactionDataExporter(fileType string) base.TransactionDataExporter {
|
||||||
if fileType == "csv" {
|
if fileType == "csv" {
|
||||||
return EzBookKeepingTransactionDataCSVFileConverter
|
return _default.EzBookKeepingTransactionDataCSVFileConverter
|
||||||
} else if fileType == "tsv" {
|
} else if fileType == "tsv" {
|
||||||
return EzBookKeepingTransactionDataTSVFileConverter
|
return _default.EzBookKeepingTransactionDataTSVFileConverter
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTransactionDataImporter returns the transaction data importer according to the file type
|
// GetTransactionDataImporter returns the transaction data importer according to the file type
|
||||||
func GetTransactionDataImporter(fileType string) (TransactionDataImporter, error) {
|
func GetTransactionDataImporter(fileType string) (base.TransactionDataImporter, error) {
|
||||||
if fileType == "ezbookkeeping_csv" {
|
if fileType == "ezbookkeeping_csv" {
|
||||||
return EzBookKeepingTransactionDataCSVFileConverter, nil
|
return _default.EzBookKeepingTransactionDataCSVFileConverter, nil
|
||||||
} else if fileType == "ezbookkeeping_tsv" {
|
} else if fileType == "ezbookkeeping_tsv" {
|
||||||
return EzBookKeepingTransactionDataTSVFileConverter, nil
|
return _default.EzBookKeepingTransactionDataTSVFileConverter, nil
|
||||||
} else if fileType == "feidee_mymoney_csv" {
|
} else if fileType == "feidee_mymoney_csv" {
|
||||||
return FeideeMymoneyTransactionDataCsvImporter, nil
|
return feidee.FeideeMymoneyTransactionDataCsvImporter, nil
|
||||||
} else if fileType == "feidee_mymoney_xls" {
|
} else if fileType == "feidee_mymoney_xls" {
|
||||||
return FeideeMymoneyTransactionDataXlsImporter, nil
|
return feidee.FeideeMymoneyTransactionDataXlsImporter, nil
|
||||||
} else {
|
} else {
|
||||||
return nil, errs.ErrImportFileTypeNotSupported
|
return nil, errs.ErrImportFileTypeNotSupported
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user