get function of writable transaction data table supports data row parser, column count and get data function of writable transaction data row supports filtering defined columns add related unit tests
This commit is contained in:
@@ -43,17 +43,28 @@ func (t *WritableTransactionDataTable) Add(data map[TransactionDataTableColumn]s
|
||||
}
|
||||
|
||||
// Get returns the record in the specified index
|
||||
func (t *WritableTransactionDataTable) Get(index int) *WritableTransactionDataRow {
|
||||
func (t *WritableTransactionDataTable) Get(index int) (*WritableTransactionDataRow, error) {
|
||||
if index >= len(t.allData) {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
rowData := t.allData[index]
|
||||
rowDataValid := true
|
||||
|
||||
if t.rowParser != nil {
|
||||
var err error
|
||||
rowData, rowDataValid, err = t.rowParser.Parse(rowData)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &WritableTransactionDataRow{
|
||||
dataTable: t,
|
||||
rowData: rowData,
|
||||
}
|
||||
rowDataValid: rowDataValid,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// HasColumn returns whether the data table has specified column
|
||||
@@ -90,7 +101,19 @@ func (t *WritableTransactionDataTable) TransactionRowIterator() TransactionDataR
|
||||
|
||||
// ColumnCount returns the total count of column in this data row
|
||||
func (r *WritableTransactionDataRow) ColumnCount() int {
|
||||
return len(r.rowData)
|
||||
if !r.rowDataValid {
|
||||
return 0
|
||||
}
|
||||
|
||||
columnCount := 0
|
||||
|
||||
for column := range r.rowData {
|
||||
if r.dataTable.supportedColumns[column] || r.dataTable.addedColumns[column] {
|
||||
columnCount++
|
||||
}
|
||||
}
|
||||
|
||||
return columnCount
|
||||
}
|
||||
|
||||
// IsValid returns whether this row is valid data for importing
|
||||
@@ -100,9 +123,27 @@ func (r *WritableTransactionDataRow) IsValid() bool {
|
||||
|
||||
// GetData returns the data in the specified column type
|
||||
func (r *WritableTransactionDataRow) GetData(column TransactionDataTableColumn) string {
|
||||
if !r.rowDataValid {
|
||||
return ""
|
||||
}
|
||||
|
||||
_, exists := r.dataTable.supportedColumns[column]
|
||||
|
||||
if exists {
|
||||
return r.rowData[column]
|
||||
}
|
||||
|
||||
if r.dataTable.addedColumns != nil {
|
||||
_, exists = r.dataTable.addedColumns[column]
|
||||
|
||||
if exists {
|
||||
return r.rowData[column]
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// HasNext returns whether the iterator does not reach the end
|
||||
func (t *WritableTransactionDataRowIterator) HasNext() bool {
|
||||
return t.nextIndex < len(t.dataTable.allData)
|
||||
|
||||
@@ -1,16 +1,67 @@
|
||||
package datatable
|
||||
|
||||
import (
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
// testDataRowParser defines the structure of test transaction data row parser
|
||||
type testDataRowParser struct {
|
||||
}
|
||||
|
||||
// GetAddedColumns returns the added columns after converting the data row
|
||||
func (p *testDataRowParser) GetAddedColumns() []TransactionDataTableColumn {
|
||||
return []TransactionDataTableColumn{
|
||||
TRANSACTION_DATA_TABLE_DESCRIPTION,
|
||||
}
|
||||
}
|
||||
|
||||
// Parse returns the converted transaction data row
|
||||
func (p *testDataRowParser) Parse(data map[TransactionDataTableColumn]string) (rowData map[TransactionDataTableColumn]string, rowDataValid bool, err error) {
|
||||
rowData = make(map[TransactionDataTableColumn]string, len(data))
|
||||
|
||||
for column, value := range data {
|
||||
rowData[column] = value
|
||||
}
|
||||
|
||||
if _, exists := rowData[TRANSACTION_DATA_TABLE_SUB_CATEGORY]; exists {
|
||||
rowData[TRANSACTION_DATA_TABLE_SUB_CATEGORY] = "foo"
|
||||
} else {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
rowData[TRANSACTION_DATA_TABLE_TAGS] = "test"
|
||||
rowData[TRANSACTION_DATA_TABLE_DESCRIPTION] = "bar"
|
||||
|
||||
return rowData, true, nil
|
||||
}
|
||||
|
||||
func TestWritableDataTableCreate(t *testing.T) {
|
||||
columns := make([]TransactionDataTableColumn, 5)
|
||||
columns[0] = TRANSACTION_DATA_TABLE_TRANSACTION_TIME
|
||||
columns[1] = TRANSACTION_DATA_TABLE_TRANSACTION_TYPE
|
||||
columns[2] = TRANSACTION_DATA_TABLE_SUB_CATEGORY
|
||||
columns[3] = TRANSACTION_DATA_TABLE_ACCOUNT_NAME
|
||||
columns[4] = TRANSACTION_DATA_TABLE_AMOUNT
|
||||
|
||||
writableDataTable := CreateNewWritableTransactionDataTable(columns)
|
||||
|
||||
assert.Equal(t, 0, writableDataTable.TransactionRowCount())
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_TRANSACTION_TIME))
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_TRANSACTION_TYPE))
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_SUB_CATEGORY))
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_ACCOUNT_NAME))
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_AMOUNT))
|
||||
assert.False(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_TRANSACTION_TIMEZONE))
|
||||
assert.False(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY))
|
||||
}
|
||||
|
||||
func TestWritableDataTableAdd(t *testing.T) {
|
||||
columns := make([]TransactionDataTableColumn, 5)
|
||||
columns[0] = TRANSACTION_DATA_TABLE_TRANSACTION_TIME
|
||||
@@ -38,7 +89,10 @@ func TestWritableDataTableAdd(t *testing.T) {
|
||||
})
|
||||
assert.Equal(t, 1, writableDataTable.TransactionRowCount())
|
||||
|
||||
dataRow := writableDataTable.Get(0)
|
||||
dataRow, err := writableDataTable.Get(0)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, dataRow.IsValid())
|
||||
|
||||
actualTransactionTime := dataRow.GetData(TRANSACTION_DATA_TABLE_TRANSACTION_TIME)
|
||||
assert.Equal(t, expectedTransactionTime, actualTransactionTime)
|
||||
@@ -72,7 +126,8 @@ func TestWritableDataTableAdd_NotExistsColumn(t *testing.T) {
|
||||
})
|
||||
assert.Equal(t, 1, writableDataTable.TransactionRowCount())
|
||||
|
||||
dataRow := writableDataTable.Get(0)
|
||||
dataRow, err := writableDataTable.Get(0)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, dataRow.ColumnCount())
|
||||
}
|
||||
|
||||
@@ -83,7 +138,8 @@ func TestWritableDataTableGet_NotExistsRow(t *testing.T) {
|
||||
writableDataTable := CreateNewWritableTransactionDataTable(columns)
|
||||
assert.Equal(t, 0, writableDataTable.TransactionRowCount())
|
||||
|
||||
dataRow := writableDataTable.Get(0)
|
||||
dataRow, err := writableDataTable.Get(0)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, dataRow)
|
||||
}
|
||||
|
||||
@@ -101,7 +157,8 @@ func TestWritableDataRowGetData_NotExistsColumn(t *testing.T) {
|
||||
})
|
||||
assert.Equal(t, 1, writableDataTable.TransactionRowCount())
|
||||
|
||||
dataRow := writableDataTable.Get(0)
|
||||
dataRow, err := writableDataTable.Get(0)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 1, dataRow.ColumnCount())
|
||||
assert.Equal(t, "", dataRow.GetData(TRANSACTION_DATA_TABLE_TRANSACTION_TYPE))
|
||||
}
|
||||
@@ -194,3 +251,130 @@ func TestWritableDataTableDataRowIterator(t *testing.T) {
|
||||
|
||||
assert.Equal(t, 3, index)
|
||||
}
|
||||
|
||||
func TestWritableDataTableWithRowParser(t *testing.T) {
|
||||
columns := make([]TransactionDataTableColumn, 5)
|
||||
columns[0] = TRANSACTION_DATA_TABLE_TRANSACTION_TIME
|
||||
columns[1] = TRANSACTION_DATA_TABLE_TRANSACTION_TYPE
|
||||
columns[2] = TRANSACTION_DATA_TABLE_SUB_CATEGORY
|
||||
columns[3] = TRANSACTION_DATA_TABLE_ACCOUNT_NAME
|
||||
columns[4] = TRANSACTION_DATA_TABLE_AMOUNT
|
||||
|
||||
writableDataTable := CreateNewWritableTransactionDataTableWithRowParser(columns, &testDataRowParser{})
|
||||
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_DESCRIPTION))
|
||||
assert.False(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_TAGS))
|
||||
assert.Equal(t, 0, writableDataTable.TransactionRowCount())
|
||||
|
||||
writableDataTable.Add(map[TransactionDataTableColumn]string{
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TIME: "2024-09-01 01:23:45",
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: "Expense",
|
||||
TRANSACTION_DATA_TABLE_SUB_CATEGORY: "Test Category",
|
||||
TRANSACTION_DATA_TABLE_ACCOUNT_NAME: "Test Account",
|
||||
TRANSACTION_DATA_TABLE_AMOUNT: "123.45",
|
||||
})
|
||||
assert.Equal(t, 1, writableDataTable.TransactionRowCount())
|
||||
|
||||
// first row
|
||||
dataRow, err := writableDataTable.Get(0)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, dataRow.IsValid())
|
||||
assert.Equal(t, 6, dataRow.ColumnCount())
|
||||
|
||||
actualSubCategory := dataRow.GetData(TRANSACTION_DATA_TABLE_SUB_CATEGORY)
|
||||
assert.Equal(t, "foo", actualSubCategory)
|
||||
|
||||
actualTags := dataRow.GetData(TRANSACTION_DATA_TABLE_TAGS)
|
||||
assert.Equal(t, "", actualTags)
|
||||
|
||||
actualDescription := dataRow.GetData(TRANSACTION_DATA_TABLE_DESCRIPTION)
|
||||
assert.Equal(t, "bar", actualDescription)
|
||||
|
||||
writableDataTable.Add(map[TransactionDataTableColumn]string{
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TIME: "2024-09-01 12:34:56",
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: "Income",
|
||||
TRANSACTION_DATA_TABLE_ACCOUNT_NAME: "Test Account2",
|
||||
TRANSACTION_DATA_TABLE_AMOUNT: "0.12",
|
||||
})
|
||||
assert.Equal(t, 2, writableDataTable.TransactionRowCount())
|
||||
|
||||
// second row
|
||||
dataRow, err = writableDataTable.Get(1)
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, dataRow.IsValid())
|
||||
assert.Equal(t, 0, dataRow.ColumnCount())
|
||||
|
||||
actualSubCategory = dataRow.GetData(TRANSACTION_DATA_TABLE_SUB_CATEGORY)
|
||||
assert.Equal(t, "", actualSubCategory)
|
||||
|
||||
actualTags = dataRow.GetData(TRANSACTION_DATA_TABLE_TAGS)
|
||||
assert.Equal(t, "", actualTags)
|
||||
|
||||
actualDescription = dataRow.GetData(TRANSACTION_DATA_TABLE_DESCRIPTION)
|
||||
assert.Equal(t, "", actualDescription)
|
||||
}
|
||||
|
||||
func TestWritableDataTableDataRowIteratorWithRowParser(t *testing.T) {
|
||||
columns := make([]TransactionDataTableColumn, 5)
|
||||
columns[0] = TRANSACTION_DATA_TABLE_TRANSACTION_TIME
|
||||
columns[1] = TRANSACTION_DATA_TABLE_TRANSACTION_TYPE
|
||||
columns[2] = TRANSACTION_DATA_TABLE_SUB_CATEGORY
|
||||
columns[3] = TRANSACTION_DATA_TABLE_ACCOUNT_NAME
|
||||
columns[4] = TRANSACTION_DATA_TABLE_AMOUNT
|
||||
|
||||
writableDataTable := CreateNewWritableTransactionDataTableWithRowParser(columns, &testDataRowParser{})
|
||||
|
||||
assert.True(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_DESCRIPTION))
|
||||
assert.False(t, writableDataTable.HasColumn(TRANSACTION_DATA_TABLE_TAGS))
|
||||
assert.Equal(t, 0, writableDataTable.TransactionRowCount())
|
||||
|
||||
writableDataTable.Add(map[TransactionDataTableColumn]string{
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TIME: "2024-09-01 01:23:45",
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: "Expense",
|
||||
TRANSACTION_DATA_TABLE_SUB_CATEGORY: "Test Category",
|
||||
TRANSACTION_DATA_TABLE_ACCOUNT_NAME: "Test Account",
|
||||
TRANSACTION_DATA_TABLE_AMOUNT: "123.45",
|
||||
})
|
||||
|
||||
writableDataTable.Add(map[TransactionDataTableColumn]string{
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TIME: "2024-09-01 12:34:56",
|
||||
TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: "Income",
|
||||
TRANSACTION_DATA_TABLE_ACCOUNT_NAME: "Test Account2",
|
||||
TRANSACTION_DATA_TABLE_AMOUNT: "0.12",
|
||||
})
|
||||
|
||||
iterator := writableDataTable.TransactionRowIterator()
|
||||
assert.True(t, iterator.HasNext())
|
||||
|
||||
// first row
|
||||
dataRow, err := iterator.Next(core.NewNullContext(), &models.User{})
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, dataRow.IsValid())
|
||||
|
||||
actualSubCategory := dataRow.GetData(TRANSACTION_DATA_TABLE_SUB_CATEGORY)
|
||||
assert.Equal(t, "foo", actualSubCategory)
|
||||
|
||||
actualTags := dataRow.GetData(TRANSACTION_DATA_TABLE_TAGS)
|
||||
assert.Equal(t, "", actualTags)
|
||||
|
||||
actualDescription := dataRow.GetData(TRANSACTION_DATA_TABLE_DESCRIPTION)
|
||||
assert.Equal(t, "bar", actualDescription)
|
||||
|
||||
assert.True(t, iterator.HasNext())
|
||||
|
||||
// second row
|
||||
dataRow, err = iterator.Next(core.NewNullContext(), &models.User{})
|
||||
assert.Nil(t, err)
|
||||
assert.False(t, dataRow.IsValid())
|
||||
|
||||
actualSubCategory = dataRow.GetData(TRANSACTION_DATA_TABLE_SUB_CATEGORY)
|
||||
assert.Equal(t, "", actualSubCategory)
|
||||
|
||||
actualTags = dataRow.GetData(TRANSACTION_DATA_TABLE_TAGS)
|
||||
assert.Equal(t, "", actualTags)
|
||||
|
||||
actualDescription = dataRow.GetData(TRANSACTION_DATA_TABLE_DESCRIPTION)
|
||||
assert.Equal(t, "", actualDescription)
|
||||
|
||||
assert.False(t, iterator.HasNext())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user