code refactor
This commit is contained in:
@@ -61,13 +61,13 @@ func (c *alipayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Contex
|
|||||||
enc := simplifiedchinese.GB18030
|
enc := simplifiedchinese.GB18030
|
||||||
reader := transform.NewReader(bytes.NewReader(data), enc.NewDecoder())
|
reader := transform.NewReader(bytes.NewReader(data), enc.NewDecoder())
|
||||||
|
|
||||||
dataTable, err := c.createNewAlipayImportedDataTable(ctx, reader, c.fileHeaderLine, c.dataHeaderStartContent, c.dataBottomEndLineRune)
|
dataTable, err := c.createNewAlipayBasicDataTable(ctx, reader, c.fileHeaderLine, c.dataHeaderStartContent, c.dataBottomEndLineRune)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commonDataTable := datatable.CreateNewImportedCommonDataTable(dataTable)
|
commonDataTable := datatable.CreateNewCommonDataTableFromBasicDataTable(dataTable)
|
||||||
|
|
||||||
if !commonDataTable.HasColumn(c.originalColumnNames.timeColumnName) ||
|
if !commonDataTable.HasColumn(c.originalColumnNames.timeColumnName) ||
|
||||||
!commonDataTable.HasColumn(c.originalColumnNames.amountColumnName) ||
|
!commonDataTable.HasColumn(c.originalColumnNames.amountColumnName) ||
|
||||||
@@ -77,14 +77,14 @@ func (c *alipayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Contex
|
|||||||
return nil, nil, nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
return nil, nil, nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionRowParser := createAlipayTransactionDataRowParser(c.originalColumnNames)
|
transactionRowParser := createAlipayTransactionDataRowParser(c.originalColumnNames, dataTable.HeaderColumnNames())
|
||||||
transactionDataTable := datatable.CreateNewCommonTransactionDataTable(commonDataTable, alipayTransactionSupportedColumns, transactionRowParser)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, alipayTransactionSupportedColumns, transactionRowParser)
|
||||||
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(alipayTransactionTypeNameMapping)
|
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(alipayTransactionTypeNameMapping)
|
||||||
|
|
||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *alipayTransactionDataCsvFileImporter) createNewAlipayImportedDataTable(ctx core.Context, reader io.Reader, fileHeaderLine string, dataHeaderStartContent string, dataBottomEndLineRune rune) (datatable.ImportedDataTable, error) {
|
func (c *alipayTransactionDataCsvFileImporter) createNewAlipayBasicDataTable(ctx core.Context, reader io.Reader, fileHeaderLine string, dataHeaderStartContent string, dataBottomEndLineRune rune) (datatable.BasicDataTable, error) {
|
||||||
csvReader := csv.NewReader(reader)
|
csvReader := csv.NewReader(reader)
|
||||||
csvReader.FieldsPerRecord = -1
|
csvReader.FieldsPerRecord = -1
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ func (c *alipayTransactionDataCsvFileImporter) createNewAlipayImportedDataTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "[alipay_transaction_csv_data_table.createNewAlipayImportedDataTable] cannot parse alipay csv data, because %s", err.Error())
|
log.Errorf(ctx, "[alipay_transaction_data_csv_file_importer.createNewAlipayBasicDataTable] cannot parse alipay csv data, because %s", err.Error())
|
||||||
return nil, errs.ErrInvalidCSVFile
|
return nil, errs.ErrInvalidCSVFile
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ func (c *alipayTransactionDataCsvFileImporter) createNewAlipayImportedDataTable(
|
|||||||
hasFileHeader = true
|
hasFileHeader = true
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
log.Warnf(ctx, "[alipay_transaction_csv_data_table.createNewAlipayImportedDataTable] read unexpected line before read file header, line content is %s", strings.Join(items, ","))
|
log.Warnf(ctx, "[alipay_transaction_data_csv_file_importer.createNewAlipayBasicDataTable] read unexpected line before read file header, line content is %s", strings.Join(items, ","))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ func (c *alipayTransactionDataCsvFileImporter) createNewAlipayImportedDataTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(allOriginalLines) > 0 && len(items) < len(allOriginalLines[0]) {
|
if len(allOriginalLines) > 0 && len(items) < len(allOriginalLines[0]) {
|
||||||
log.Errorf(ctx, "[alipay_transaction_csv_data_table.createNewAlipayImportedDataTable] cannot parse row \"index:%d\", because may missing some columns (column count %d in data row is less than header column count %d)", len(allOriginalLines), len(items), len(allOriginalLines[0]))
|
log.Errorf(ctx, "[alipay_transaction_data_csv_file_importer.createNewAlipayBasicDataTable] cannot parse row \"index:%d\", because may missing some columns (column count %d in data row is less than header column count %d)", len(allOriginalLines), len(items), len(allOriginalLines[0]))
|
||||||
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,11 +152,11 @@ func (c *alipayTransactionDataCsvFileImporter) createNewAlipayImportedDataTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(allOriginalLines) < 2 {
|
if len(allOriginalLines) < 2 {
|
||||||
log.Errorf(ctx, "[alipay_transaction_csv_data_table.createNewAlipayImportedDataTable] cannot parse import data, because data table row count is less 1")
|
log.Errorf(ctx, "[alipay_transaction_data_csv_file_importer.createNewAlipayBasicDataTable] cannot parse import data, because data table row count is less 1")
|
||||||
return nil, errs.ErrNotFoundTransactionDataInFile
|
return nil, errs.ErrNotFoundTransactionDataInFile
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTable := csvdatatable.CreateNewCustomCsvImportedDataTable(allOriginalLines)
|
dataTable := csvdatatable.CreateNewCustomCsvBasicDataTable(allOriginalLines)
|
||||||
|
|
||||||
return dataTable, nil
|
return dataTable, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ const alipayTransactionDataProductNameRepaymentText = "还款"
|
|||||||
|
|
||||||
// alipayTransactionDataRowParser defines the structure of alipay transaction data row parser
|
// alipayTransactionDataRowParser defines the structure of alipay transaction data row parser
|
||||||
type alipayTransactionDataRowParser struct {
|
type alipayTransactionDataRowParser struct {
|
||||||
columns alipayTransactionColumnNames
|
columns alipayTransactionColumnNames
|
||||||
|
existedOriginalDataColumns map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse returns the converted transaction data row
|
// Parse returns the converted transaction data row
|
||||||
func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.User, dataTable *datatable.CommonTransactionDataTable, dataRow datatable.CommonDataRow, rowId string) (rowData map[datatable.TransactionDataTableColumn]string, rowDataValid bool, err error) {
|
func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.User, dataRow datatable.CommonDataTableRow, rowId string) (rowData map[datatable.TransactionDataTableColumn]string, rowDataValid bool, err error) {
|
||||||
if dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] &&
|
if dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] &&
|
||||||
dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE] &&
|
dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE] &&
|
||||||
dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] {
|
dataRow.GetData(p.columns.typeColumnName) != alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] {
|
||||||
@@ -50,23 +51,23 @@ func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.Us
|
|||||||
|
|
||||||
data := make(map[datatable.TransactionDataTableColumn]string, len(alipayTransactionSupportedColumns))
|
data := make(map[datatable.TransactionDataTableColumn]string, len(alipayTransactionSupportedColumns))
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.timeColumnName) {
|
if p.hasOriginalColumn(p.columns.timeColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = dataRow.GetData(p.columns.timeColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = dataRow.GetData(p.columns.timeColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.categoryColumnName) {
|
if p.hasOriginalColumn(p.columns.categoryColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = dataRow.GetData(p.columns.categoryColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = dataRow.GetData(p.columns.categoryColumnName)
|
||||||
} else {
|
} else {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = ""
|
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.amountColumnName) {
|
if p.hasOriginalColumn(p.columns.amountColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = dataRow.GetData(p.columns.amountColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = dataRow.GetData(p.columns.amountColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.descriptionColumnName) && dataRow.GetData(p.columns.descriptionColumnName) != "" {
|
if p.hasOriginalColumn(p.columns.descriptionColumnName) && dataRow.GetData(p.columns.descriptionColumnName) != "" {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(p.columns.descriptionColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(p.columns.descriptionColumnName)
|
||||||
} else if dataTable.HasOriginalColumn(p.columns.productNameColumnName) && dataRow.GetData(p.columns.productNameColumnName) != "" {
|
} else if p.hasOriginalColumn(p.columns.productNameColumnName) && dataRow.GetData(p.columns.productNameColumnName) != "" {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(p.columns.productNameColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(p.columns.productNameColumnName)
|
||||||
} else {
|
} else {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = ""
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = ""
|
||||||
@@ -74,13 +75,13 @@ func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.Us
|
|||||||
|
|
||||||
relatedAccountName := ""
|
relatedAccountName := ""
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.relatedAccountColumnName) {
|
if p.hasOriginalColumn(p.columns.relatedAccountColumnName) {
|
||||||
relatedAccountName = dataRow.GetData(p.columns.relatedAccountColumnName)
|
relatedAccountName = dataRow.GetData(p.columns.relatedAccountColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
statusName := ""
|
statusName := ""
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.statusColumnName) {
|
if p.hasOriginalColumn(p.columns.statusColumnName) {
|
||||||
statusName = dataRow.GetData(p.columns.statusColumnName)
|
statusName = dataRow.GetData(p.columns.statusColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.Us
|
|||||||
|
|
||||||
localeTextItems := locales.GetLocaleTextItems(locale)
|
localeTextItems := locales.GetLocaleTextItems(locale)
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.typeColumnName) {
|
if p.hasOriginalColumn(p.columns.typeColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = dataRow.GetData(p.columns.typeColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = dataRow.GetData(p.columns.typeColumnName)
|
||||||
|
|
||||||
if dataRow.GetData(p.columns.typeColumnName) == alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] {
|
if dataRow.GetData(p.columns.typeColumnName) == alipayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] {
|
||||||
@@ -117,11 +118,11 @@ func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.Us
|
|||||||
targetName := ""
|
targetName := ""
|
||||||
productName := ""
|
productName := ""
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.targetNameColumnName) {
|
if p.hasOriginalColumn(p.columns.targetNameColumnName) {
|
||||||
targetName = dataRow.GetData(p.columns.targetNameColumnName)
|
targetName = dataRow.GetData(p.columns.targetNameColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(p.columns.productNameColumnName) {
|
if p.hasOriginalColumn(p.columns.productNameColumnName) {
|
||||||
productName = dataRow.GetData(p.columns.productNameColumnName)
|
productName = dataRow.GetData(p.columns.productNameColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,9 +171,21 @@ func (p *alipayTransactionDataRowParser) Parse(ctx core.Context, user *models.Us
|
|||||||
return data, true, nil
|
return data, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *alipayTransactionDataRowParser) hasOriginalColumn(columnName string) bool {
|
||||||
|
_, exists := p.existedOriginalDataColumns[columnName]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
// createAlipayTransactionDataRowParser returns alipay transaction data row parser
|
// createAlipayTransactionDataRowParser returns alipay transaction data row parser
|
||||||
func createAlipayTransactionDataRowParser(originalColumnNames alipayTransactionColumnNames) datatable.CommonTransactionDataRowParser {
|
func createAlipayTransactionDataRowParser(originalColumnNames alipayTransactionColumnNames, headerColumnNames []string) datatable.CommonTransactionDataRowParser {
|
||||||
|
existedOriginalDataColumns := make(map[string]bool, len(headerColumnNames))
|
||||||
|
|
||||||
|
for i := 0; i < len(headerColumnNames); i++ {
|
||||||
|
existedOriginalDataColumns[headerColumnNames[i]] = true
|
||||||
|
}
|
||||||
|
|
||||||
return &alipayTransactionDataRowParser{
|
return &alipayTransactionDataRowParser{
|
||||||
columns: originalColumnNames,
|
columns: originalColumnNames,
|
||||||
|
existedOriginalDataColumns: existedOriginalDataColumns,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ func (t *beancountTransactionDataRowIterator) HasNext() bool {
|
|||||||
return t.currentIndex+1 < len(t.dataTable.allData)
|
return t.currentIndex+1 < len(t.dataTable.allData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *beancountTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *beancountTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ func (t *camtStatementTransactionDataRowIterator) HasNext() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *camtStatementTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *camtStatementTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
allStatements := t.dataTable.allStatements
|
allStatements := t.dataTable.allStatements
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,138 @@
|
|||||||
|
package csv
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/csv"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CsvFileBasicDataTable defines the structure of csv data table
|
||||||
|
type CsvFileBasicDataTable struct {
|
||||||
|
allLines [][]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CsvFileBasicDataTableRow defines the structure of csv data table row
|
||||||
|
type CsvFileBasicDataTableRow struct {
|
||||||
|
dataTable *CsvFileBasicDataTable
|
||||||
|
allItems []string
|
||||||
|
}
|
||||||
|
|
||||||
|
// CsvFileBasicDataTableRowIterator defines the structure of csv data table row iterator
|
||||||
|
type CsvFileBasicDataTableRowIterator struct {
|
||||||
|
dataTable *CsvFileBasicDataTable
|
||||||
|
currentIndex int
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataRowCount returns the total count of data row
|
||||||
|
func (t *CsvFileBasicDataTable) DataRowCount() int {
|
||||||
|
if len(t.allLines) < 1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(t.allLines) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderColumnNames returns the header column name list
|
||||||
|
func (t *CsvFileBasicDataTable) HeaderColumnNames() []string {
|
||||||
|
if len(t.allLines) < 1 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return t.allLines[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataRowIterator returns the iterator of data row
|
||||||
|
func (t *CsvFileBasicDataTable) DataRowIterator() datatable.BasicDataTableRowIterator {
|
||||||
|
return &CsvFileBasicDataTableRowIterator{
|
||||||
|
dataTable: t,
|
||||||
|
currentIndex: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnCount returns the total count of column in this data row
|
||||||
|
func (r *CsvFileBasicDataTableRow) ColumnCount() int {
|
||||||
|
return len(r.allItems)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetData returns the data in the specified column index
|
||||||
|
func (r *CsvFileBasicDataTableRow) GetData(columnIndex int) string {
|
||||||
|
if columnIndex >= len(r.allItems) {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.allItems[columnIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNext returns whether the iterator does not reach the end
|
||||||
|
func (t *CsvFileBasicDataTableRowIterator) HasNext() bool {
|
||||||
|
return t.currentIndex+1 < len(t.dataTable.allLines)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentRowId returns current index
|
||||||
|
func (t *CsvFileBasicDataTableRowIterator) CurrentRowId() string {
|
||||||
|
return fmt.Sprintf("line#%d", t.currentIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next basic data row
|
||||||
|
func (t *CsvFileBasicDataTableRowIterator) Next() datatable.BasicDataTableRow {
|
||||||
|
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t.currentIndex++
|
||||||
|
|
||||||
|
rowItems := t.dataTable.allLines[t.currentIndex]
|
||||||
|
|
||||||
|
return &CsvFileBasicDataTableRow{
|
||||||
|
dataTable: t.dataTable,
|
||||||
|
allItems: rowItems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewCsvBasicDataTable returns comma separated values data table by io readers
|
||||||
|
func CreateNewCsvBasicDataTable(ctx core.Context, reader io.Reader) (datatable.BasicDataTable, error) {
|
||||||
|
return createNewCsvFileBasicDataTable(ctx, reader, ',')
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewCustomCsvBasicDataTable returns character separated values data table by io readers
|
||||||
|
func CreateNewCustomCsvBasicDataTable(allLines [][]string) datatable.BasicDataTable {
|
||||||
|
return &CsvFileBasicDataTable{
|
||||||
|
allLines: allLines,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createNewCsvFileBasicDataTable(ctx core.Context, reader io.Reader, separator rune) (*CsvFileBasicDataTable, error) {
|
||||||
|
csvReader := csv.NewReader(reader)
|
||||||
|
csvReader.Comma = separator
|
||||||
|
csvReader.FieldsPerRecord = -1
|
||||||
|
|
||||||
|
allLines := make([][]string, 0)
|
||||||
|
|
||||||
|
for {
|
||||||
|
items, err := csvReader.Read()
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf(ctx, "[csv_file_basic_data_table.createNewCsvFileDataTable] cannot parse csv data, because %s", err.Error())
|
||||||
|
return nil, errs.ErrInvalidCSVFile
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(items) == 1 && items[0] == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
allLines = append(allLines, items)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CsvFileBasicDataTable{
|
||||||
|
allLines: allLines,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
+22
-22
@@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCsvFileImportedDataTableDataRowCount(t *testing.T) {
|
func TestCsvFileBasicDataTableDataRowCount(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -19,22 +19,22 @@ func TestCsvFileImportedDataTableDataRowCount(t *testing.T) {
|
|||||||
assert.Equal(t, 2, datatable.DataRowCount())
|
assert.Equal(t, 2, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
func TestCsvFileBasicDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataTableDataRowCount_EmptyContent(t *testing.T) {
|
func TestCsvFileBasicDataTableDataRowCount_EmptyContent(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{})
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{})
|
||||||
|
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataTableHeaderColumnNames(t *testing.T) {
|
func TestCsvFileBasicDataTableHeaderColumnNames(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -43,14 +43,14 @@ func TestCsvFileImportedDataTableHeaderColumnNames(t *testing.T) {
|
|||||||
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
func TestCsvFileBasicDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{})
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{})
|
||||||
|
|
||||||
assert.Nil(t, datatable.HeaderColumnNames())
|
assert.Nil(t, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataRowIterator(t *testing.T) {
|
func TestCsvFileBasicDataTableRowIterator(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -76,8 +76,8 @@ func TestCsvFileImportedDataRowIterator(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataRowColumnCount(t *testing.T) {
|
func TestCsvFileBasicDataTableRowColumnCount(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -92,8 +92,8 @@ func TestCsvFileImportedDataRowColumnCount(t *testing.T) {
|
|||||||
assert.EqualValues(t, 3, row2.ColumnCount())
|
assert.EqualValues(t, 3, row2.ColumnCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataRowGetData(t *testing.T) {
|
func TestCsvFileBasicDataTableRowGetData(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -112,8 +112,8 @@ func TestCsvFileImportedDataRowGetData(t *testing.T) {
|
|||||||
assert.Equal(t, "C3", row2.GetData(2))
|
assert.Equal(t, "C3", row2.GetData(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCsvFileImportedDataRowGetData_GetNotExistedColumnData(t *testing.T) {
|
func TestCsvFileBasicDataTableRowGetData_GetNotExistedColumnData(t *testing.T) {
|
||||||
datatable := CreateNewCustomCsvImportedDataTable([][]string{
|
datatable := CreateNewCustomCsvBasicDataTable([][]string{
|
||||||
{"A1", "B1", "C1"},
|
{"A1", "B1", "C1"},
|
||||||
{"A2", "B2", "C2"},
|
{"A2", "B2", "C2"},
|
||||||
{"A3", "B3", "C3"},
|
{"A3", "B3", "C3"},
|
||||||
@@ -125,12 +125,12 @@ func TestCsvFileImportedDataRowGetData_GetNotExistedColumnData(t *testing.T) {
|
|||||||
assert.Equal(t, "", row1.GetData(3))
|
assert.Equal(t, "", row1.GetData(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateNewCsvImportedDataTable(t *testing.T) {
|
func TestCreateNewCsvBasicDataTable(t *testing.T) {
|
||||||
context := core.NewNullContext()
|
context := core.NewNullContext()
|
||||||
reader := bytes.NewReader([]byte("A1,B1,C1\n" +
|
reader := bytes.NewReader([]byte("A1,B1,C1\n" +
|
||||||
"A2,B2,C2\n" +
|
"A2,B2,C2\n" +
|
||||||
"A3,B3,C3\n"))
|
"A3,B3,C3\n"))
|
||||||
datatable, err := CreateNewCsvImportedDataTable(context, reader)
|
datatable, err := CreateNewCsvBasicDataTable(context, reader)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, 2, datatable.DataRowCount())
|
assert.Equal(t, 2, datatable.DataRowCount())
|
||||||
@@ -153,14 +153,14 @@ func TestCreateNewCsvImportedDataTable(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateNewCsvImportedDataTable_SkipBlankLine(t *testing.T) {
|
func TestCreateNewCsvBasicDataTable_SkipBlankLine(t *testing.T) {
|
||||||
context := core.NewNullContext()
|
context := core.NewNullContext()
|
||||||
reader := bytes.NewReader([]byte("\n" +
|
reader := bytes.NewReader([]byte("\n" +
|
||||||
"A1,B1,C1\n" +
|
"A1,B1,C1\n" +
|
||||||
"A2,B2,C2\n" +
|
"A2,B2,C2\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"A3,B3,C3\n"))
|
"A3,B3,C3\n"))
|
||||||
datatable, err := CreateNewCsvImportedDataTable(context, reader)
|
datatable, err := CreateNewCsvBasicDataTable(context, reader)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, 2, datatable.DataRowCount())
|
assert.Equal(t, 2, datatable.DataRowCount())
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
package csv
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/csv"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CsvFileImportedDataTable defines the structure of csv data table
|
|
||||||
type CsvFileImportedDataTable struct {
|
|
||||||
allLines [][]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// CsvFileImportedDataRow defines the structure of csv data table row
|
|
||||||
type CsvFileImportedDataRow struct {
|
|
||||||
dataTable *CsvFileImportedDataTable
|
|
||||||
allItems []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// CsvFileImportedDataRowIterator defines the structure of csv data table row iterator
|
|
||||||
type CsvFileImportedDataRowIterator struct {
|
|
||||||
dataTable *CsvFileImportedDataTable
|
|
||||||
currentIndex int
|
|
||||||
}
|
|
||||||
|
|
||||||
// DataRowCount returns the total count of data row
|
|
||||||
func (t *CsvFileImportedDataTable) DataRowCount() int {
|
|
||||||
if len(t.allLines) < 1 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(t.allLines) - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeaderColumnNames returns the header column name list
|
|
||||||
func (t *CsvFileImportedDataTable) HeaderColumnNames() []string {
|
|
||||||
if len(t.allLines) < 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return t.allLines[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
|
||||||
func (t *CsvFileImportedDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
|
||||||
return &CsvFileImportedDataRowIterator{
|
|
||||||
dataTable: t,
|
|
||||||
currentIndex: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ColumnCount returns the total count of column in this data row
|
|
||||||
func (r *CsvFileImportedDataRow) ColumnCount() int {
|
|
||||||
return len(r.allItems)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetData returns the data in the specified column index
|
|
||||||
func (r *CsvFileImportedDataRow) GetData(columnIndex int) string {
|
|
||||||
if columnIndex >= len(r.allItems) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.allItems[columnIndex]
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
|
||||||
func (t *CsvFileImportedDataRowIterator) HasNext() bool {
|
|
||||||
return t.currentIndex+1 < len(t.dataTable.allLines)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentRowId returns current index
|
|
||||||
func (t *CsvFileImportedDataRowIterator) CurrentRowId() string {
|
|
||||||
return fmt.Sprintf("line#%d", t.currentIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next imported data row
|
|
||||||
func (t *CsvFileImportedDataRowIterator) Next() datatable.ImportedDataRow {
|
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t.currentIndex++
|
|
||||||
|
|
||||||
rowItems := t.dataTable.allLines[t.currentIndex]
|
|
||||||
|
|
||||||
return &CsvFileImportedDataRow{
|
|
||||||
dataTable: t.dataTable,
|
|
||||||
allItems: rowItems,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewCsvImportedDataTable returns comma separated values data table by io readers
|
|
||||||
func CreateNewCsvImportedDataTable(ctx core.Context, reader io.Reader) (*CsvFileImportedDataTable, error) {
|
|
||||||
return createNewCsvFileDataTable(ctx, reader, ',')
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewCustomCsvImportedDataTable returns character separated values data table by io readers
|
|
||||||
func CreateNewCustomCsvImportedDataTable(allLines [][]string) *CsvFileImportedDataTable {
|
|
||||||
return &CsvFileImportedDataTable{
|
|
||||||
allLines: allLines,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func createNewCsvFileDataTable(ctx core.Context, reader io.Reader, separator rune) (*CsvFileImportedDataTable, error) {
|
|
||||||
csvReader := csv.NewReader(reader)
|
|
||||||
csvReader.Comma = separator
|
|
||||||
csvReader.FieldsPerRecord = -1
|
|
||||||
|
|
||||||
allLines := make([][]string, 0)
|
|
||||||
|
|
||||||
for {
|
|
||||||
items, err := csvReader.Read()
|
|
||||||
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf(ctx, "[csv_file_imported_data_table.createNewCsvFileDataTable] cannot parse csv data, because %s", err.Error())
|
|
||||||
return nil, errs.ErrInvalidCSVFile
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(items) == 1 && items[0] == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
allLines = append(allLines, items)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &CsvFileImportedDataTable{
|
|
||||||
allLines: allLines,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
+9
-9
@@ -1,7 +1,7 @@
|
|||||||
package datatable
|
package datatable
|
||||||
|
|
||||||
// ImportedDataTable defines the structure of imported data table
|
// BasicDataTable defines the structure of basic data table
|
||||||
type ImportedDataTable interface {
|
type BasicDataTable interface {
|
||||||
// DataRowCount returns the total count of data row
|
// DataRowCount returns the total count of data row
|
||||||
DataRowCount() int
|
DataRowCount() int
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@ type ImportedDataTable interface {
|
|||||||
HeaderColumnNames() []string
|
HeaderColumnNames() []string
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
DataRowIterator() ImportedDataRowIterator
|
DataRowIterator() BasicDataTableRowIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportedDataRow defines the structure of imported data row
|
// BasicDataTableRow defines the structure of basic data row
|
||||||
type ImportedDataRow interface {
|
type BasicDataTableRow interface {
|
||||||
// ColumnCount returns the total count of column in this data row
|
// ColumnCount returns the total count of column in this data row
|
||||||
ColumnCount() int
|
ColumnCount() int
|
||||||
|
|
||||||
@@ -21,14 +21,14 @@ type ImportedDataRow interface {
|
|||||||
GetData(columnIndex int) string
|
GetData(columnIndex int) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportedDataRowIterator defines the structure of imported data row iterator
|
// BasicDataTableRowIterator defines the structure of basic data row iterator
|
||||||
type ImportedDataRowIterator interface {
|
type BasicDataTableRowIterator interface {
|
||||||
// HasNext returns whether the iterator does not reach the end
|
// HasNext returns whether the iterator does not reach the end
|
||||||
HasNext() bool
|
HasNext() bool
|
||||||
|
|
||||||
// CurrentRowId returns current row id
|
// CurrentRowId returns current row id
|
||||||
CurrentRowId() string
|
CurrentRowId() string
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next basic data row
|
||||||
Next() ImportedDataRow
|
Next() BasicDataTableRow
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package datatable
|
||||||
|
|
||||||
|
// basicDataTableToCommonDataTableWrapper defines the structure of basic data table to common data table wrapper
|
||||||
|
type basicDataTableToCommonDataTableWrapper struct {
|
||||||
|
innerDataTable BasicDataTable
|
||||||
|
dataColumnIndexes map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// basicDataTableToCommonDataTableWrapperRow defines the data row structure of basic data table to common data table wrapper
|
||||||
|
type basicDataTableToCommonDataTableWrapperRow struct {
|
||||||
|
rowData map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// basicDataTableToCommonDataTableWrapperRowIterator defines the data row iterator structure of basic data table to common data table wrapper
|
||||||
|
type basicDataTableToCommonDataTableWrapperRowIterator struct {
|
||||||
|
commonDataTable *basicDataTableToCommonDataTableWrapper
|
||||||
|
innerIterator BasicDataTableRowIterator
|
||||||
|
}
|
||||||
|
|
||||||
|
// HeaderColumnCount returns the total count of column in header row
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapper) HeaderColumnCount() int {
|
||||||
|
return len(t.innerDataTable.HeaderColumnNames())
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasColumn returns whether the data table has specified column name
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapper) HasColumn(columnName string) bool {
|
||||||
|
index, exists := t.dataColumnIndexes[columnName]
|
||||||
|
return exists && index >= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataRowCount returns the total count of common data row
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapper) DataRowCount() int {
|
||||||
|
return t.innerDataTable.DataRowCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataRowIterator returns the iterator of common data row
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapper) DataRowIterator() CommonDataTableRowIterator {
|
||||||
|
return &basicDataTableToCommonDataTableWrapperRowIterator{
|
||||||
|
commonDataTable: t,
|
||||||
|
innerIterator: t.innerDataTable.DataRowIterator(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasData returns whether the common data row has specified column data
|
||||||
|
func (r *basicDataTableToCommonDataTableWrapperRow) HasData(columnName string) bool {
|
||||||
|
_, exists := r.rowData[columnName]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// ColumnCount returns the total count of column in this data row
|
||||||
|
func (r *basicDataTableToCommonDataTableWrapperRow) ColumnCount() int {
|
||||||
|
return len(r.rowData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetData returns the data in the specified column name
|
||||||
|
func (r *basicDataTableToCommonDataTableWrapperRow) GetData(columnName string) string {
|
||||||
|
return r.rowData[columnName]
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNext returns whether the iterator does not reach the end
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapperRowIterator) HasNext() bool {
|
||||||
|
return t.innerIterator.HasNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
// CurrentRowId returns current row id
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapperRowIterator) CurrentRowId() string {
|
||||||
|
return t.innerIterator.CurrentRowId()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next common data row
|
||||||
|
func (t *basicDataTableToCommonDataTableWrapperRowIterator) Next() CommonDataTableRow {
|
||||||
|
basicDataRow := t.innerIterator.Next()
|
||||||
|
|
||||||
|
if basicDataRow == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rowData := make(map[string]string, len(t.commonDataTable.dataColumnIndexes))
|
||||||
|
|
||||||
|
for column, columnIndex := range t.commonDataTable.dataColumnIndexes {
|
||||||
|
if columnIndex < 0 || columnIndex >= basicDataRow.ColumnCount() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
value := basicDataRow.GetData(columnIndex)
|
||||||
|
rowData[column] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
return &basicDataTableToCommonDataTableWrapperRow{
|
||||||
|
rowData: rowData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewCommonDataTableFromBasicDataTable returns common data table from basic data table
|
||||||
|
func CreateNewCommonDataTableFromBasicDataTable(dataTable BasicDataTable) CommonDataTable {
|
||||||
|
headerLineItems := dataTable.HeaderColumnNames()
|
||||||
|
dataColumnIndexes := make(map[string]int, len(headerLineItems))
|
||||||
|
|
||||||
|
for i := 0; i < len(headerLineItems); i++ {
|
||||||
|
dataColumnIndexes[headerLineItems[i]] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
return &basicDataTableToCommonDataTableWrapper{
|
||||||
|
innerDataTable: dataTable,
|
||||||
|
dataColumnIndexes: dataColumnIndexes,
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
-34
@@ -7,30 +7,30 @@ import (
|
|||||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ImportedTransactionDataTable defines the structure of imported transaction data table
|
// basicDataTableToTransactionDataTableWrapper defines the structure of basic data table to transaction data table wrapper
|
||||||
type ImportedTransactionDataTable struct {
|
type basicDataTableToTransactionDataTableWrapper struct {
|
||||||
innerDataTable ImportedDataTable
|
innerDataTable BasicDataTable
|
||||||
dataColumnMapping map[TransactionDataTableColumn]string
|
dataColumnMapping map[TransactionDataTableColumn]string
|
||||||
dataColumnIndexes map[TransactionDataTableColumn]int
|
dataColumnIndexes map[TransactionDataTableColumn]int
|
||||||
rowParser TransactionDataRowParser
|
rowParser TransactionDataRowParser
|
||||||
addedColumns map[TransactionDataTableColumn]bool
|
addedColumns map[TransactionDataTableColumn]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportedTransactionDataRow defines the structure of imported transaction data row
|
// basicDataTableToTransactionDataTableWrapperRow defines the data row structure of basic data table to transaction data table wrapper
|
||||||
type ImportedTransactionDataRow struct {
|
type basicDataTableToTransactionDataTableWrapperRow struct {
|
||||||
transactionDataTable *ImportedTransactionDataTable
|
transactionDataTable *basicDataTableToTransactionDataTableWrapper
|
||||||
rowData map[TransactionDataTableColumn]string
|
rowData map[TransactionDataTableColumn]string
|
||||||
rowDataValid bool
|
rowDataValid bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportedTransactionDataRowIterator defines the structure of imported transaction data row iterator
|
// basicDataTableToTransactionDataTableWrapperRowIterator defines the data row iterator structure of basic data table to transaction data table wrapper
|
||||||
type ImportedTransactionDataRowIterator struct {
|
type basicDataTableToTransactionDataTableWrapperRowIterator struct {
|
||||||
transactionDataTable *ImportedTransactionDataTable
|
transactionDataTable *basicDataTableToTransactionDataTableWrapper
|
||||||
innerIterator ImportedDataRowIterator
|
innerIterator BasicDataTableRowIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasColumn returns whether the data table has specified column
|
// HasColumn returns whether the data table has specified column
|
||||||
func (t *ImportedTransactionDataTable) HasColumn(column TransactionDataTableColumn) bool {
|
func (t *basicDataTableToTransactionDataTableWrapper) HasColumn(column TransactionDataTableColumn) bool {
|
||||||
index, exists := t.dataColumnIndexes[column]
|
index, exists := t.dataColumnIndexes[column]
|
||||||
|
|
||||||
if exists && index >= 0 {
|
if exists && index >= 0 {
|
||||||
@@ -49,25 +49,25 @@ func (t *ImportedTransactionDataTable) HasColumn(column TransactionDataTableColu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TransactionRowCount returns the total count of transaction data row
|
// TransactionRowCount returns the total count of transaction data row
|
||||||
func (t *ImportedTransactionDataTable) TransactionRowCount() int {
|
func (t *basicDataTableToTransactionDataTableWrapper) TransactionRowCount() int {
|
||||||
return t.innerDataTable.DataRowCount()
|
return t.innerDataTable.DataRowCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionRowIterator returns the iterator of transaction data row
|
// TransactionRowIterator returns the iterator of transaction data row
|
||||||
func (t *ImportedTransactionDataTable) TransactionRowIterator() TransactionDataRowIterator {
|
func (t *basicDataTableToTransactionDataTableWrapper) TransactionRowIterator() TransactionDataRowIterator {
|
||||||
return &ImportedTransactionDataRowIterator{
|
return &basicDataTableToTransactionDataTableWrapperRowIterator{
|
||||||
transactionDataTable: t,
|
transactionDataTable: t,
|
||||||
innerIterator: t.innerDataTable.DataRowIterator(),
|
innerIterator: t.innerDataTable.DataRowIterator(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValid returns whether this row is valid data for importing
|
// IsValid returns whether this row is valid data for importing
|
||||||
func (r *ImportedTransactionDataRow) IsValid() bool {
|
func (r *basicDataTableToTransactionDataTableWrapperRow) IsValid() bool {
|
||||||
return r.rowDataValid
|
return r.rowDataValid
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetData returns the data in the specified column type
|
// GetData returns the data in the specified column type
|
||||||
func (r *ImportedTransactionDataRow) GetData(column TransactionDataTableColumn) string {
|
func (r *basicDataTableToTransactionDataTableWrapperRow) GetData(column TransactionDataTableColumn) string {
|
||||||
if !r.rowDataValid {
|
if !r.rowDataValid {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -90,28 +90,28 @@ func (r *ImportedTransactionDataRow) GetData(column TransactionDataTableColumn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
// HasNext returns whether the iterator does not reach the end
|
||||||
func (t *ImportedTransactionDataRowIterator) HasNext() bool {
|
func (t *basicDataTableToTransactionDataTableWrapperRowIterator) HasNext() bool {
|
||||||
return t.innerIterator.HasNext()
|
return t.innerIterator.HasNext()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next transaction data row
|
// Next returns the next transaction data row
|
||||||
func (t *ImportedTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow TransactionDataRow, err error) {
|
func (t *basicDataTableToTransactionDataTableWrapperRowIterator) Next(ctx core.Context, user *models.User) (daraRow TransactionDataRow, err error) {
|
||||||
importedRow := t.innerIterator.Next()
|
basicDataRow := t.innerIterator.Next()
|
||||||
|
|
||||||
if importedRow == nil {
|
if basicDataRow == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if importedRow.ColumnCount() == 1 && importedRow.GetData(0) == "" {
|
if basicDataRow.ColumnCount() == 1 && basicDataRow.GetData(0) == "" {
|
||||||
return &ImportedTransactionDataRow{
|
return &basicDataTableToTransactionDataTableWrapperRow{
|
||||||
transactionDataTable: t.transactionDataTable,
|
transactionDataTable: t.transactionDataTable,
|
||||||
rowData: nil,
|
rowData: nil,
|
||||||
rowDataValid: false,
|
rowDataValid: false,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if importedRow.ColumnCount() < len(t.transactionDataTable.dataColumnIndexes) {
|
if basicDataRow.ColumnCount() < len(t.transactionDataTable.dataColumnIndexes) {
|
||||||
log.Errorf(ctx, "[imported_transaction_data_table.Next] cannot parse data row, because may missing some columns (column count %d in data row is less than header column count %d)", importedRow.ColumnCount(), len(t.transactionDataTable.dataColumnIndexes))
|
log.Errorf(ctx, "[basic_data_table_to_transaction_data_table_wrapper.Next] cannot parse data row, because may missing some columns (column count %d in data row is less than header column count %d)", basicDataRow.ColumnCount(), len(t.transactionDataTable.dataColumnIndexes))
|
||||||
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,11 +119,11 @@ func (t *ImportedTransactionDataRowIterator) Next(ctx core.Context, user *models
|
|||||||
rowDataValid := true
|
rowDataValid := true
|
||||||
|
|
||||||
for column, columnIndex := range t.transactionDataTable.dataColumnIndexes {
|
for column, columnIndex := range t.transactionDataTable.dataColumnIndexes {
|
||||||
if columnIndex < 0 || columnIndex >= importedRow.ColumnCount() {
|
if columnIndex < 0 || columnIndex >= basicDataRow.ColumnCount() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
value := importedRow.GetData(columnIndex)
|
value := basicDataRow.GetData(columnIndex)
|
||||||
rowData[column] = value
|
rowData[column] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,25 +131,25 @@ func (t *ImportedTransactionDataRowIterator) Next(ctx core.Context, user *models
|
|||||||
rowData, rowDataValid, err = t.transactionDataTable.rowParser.Parse(rowData)
|
rowData, rowDataValid, err = t.transactionDataTable.rowParser.Parse(rowData)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "[imported_transaction_data_table.Next] cannot parse data row, because %s", err.Error())
|
log.Errorf(ctx, "[basic_data_table_to_transaction_data_table_wrapper.Next] cannot parse data row, because %s", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ImportedTransactionDataRow{
|
return &basicDataTableToTransactionDataTableWrapperRow{
|
||||||
transactionDataTable: t.transactionDataTable,
|
transactionDataTable: t.transactionDataTable,
|
||||||
rowData: rowData,
|
rowData: rowData,
|
||||||
rowDataValid: rowDataValid,
|
rowDataValid: rowDataValid,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewImportedTransactionDataTable returns transaction data table from imported data table
|
// CreateNewTransactionDataTableFromBasicDataTable returns transaction data table from basic data table
|
||||||
func CreateNewImportedTransactionDataTable(dataTable ImportedDataTable, dataColumnMapping map[TransactionDataTableColumn]string) *ImportedTransactionDataTable {
|
func CreateNewTransactionDataTableFromBasicDataTable(dataTable BasicDataTable, dataColumnMapping map[TransactionDataTableColumn]string) TransactionDataTable {
|
||||||
return CreateNewImportedTransactionDataTableWithRowParser(dataTable, dataColumnMapping, nil)
|
return CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, dataColumnMapping, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewImportedTransactionDataTableWithRowParser returns transaction data table from imported data table
|
// CreateNewTransactionDataTableFromBasicDataTableWithRowParser returns transaction data table from basic data table
|
||||||
func CreateNewImportedTransactionDataTableWithRowParser(dataTable ImportedDataTable, dataColumnMapping map[TransactionDataTableColumn]string, rowParser TransactionDataRowParser) *ImportedTransactionDataTable {
|
func CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable BasicDataTable, dataColumnMapping map[TransactionDataTableColumn]string, rowParser TransactionDataRowParser) TransactionDataTable {
|
||||||
headerLineItems := dataTable.HeaderColumnNames()
|
headerLineItems := dataTable.HeaderColumnNames()
|
||||||
headerItemMap := make(map[string]int, len(headerLineItems))
|
headerItemMap := make(map[string]int, len(headerLineItems))
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ func CreateNewImportedTransactionDataTableWithRowParser(dataTable ImportedDataTa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ImportedTransactionDataTable{
|
return &basicDataTableToTransactionDataTableWrapper{
|
||||||
innerDataTable: dataTable,
|
innerDataTable: dataTable,
|
||||||
dataColumnMapping: dataColumnMapping,
|
dataColumnMapping: dataColumnMapping,
|
||||||
dataColumnIndexes: dataColumnIndexes,
|
dataColumnIndexes: dataColumnIndexes,
|
||||||
@@ -12,11 +12,11 @@ type CommonDataTable interface {
|
|||||||
DataRowCount() int
|
DataRowCount() int
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of common data row
|
// DataRowIterator returns the iterator of common data row
|
||||||
DataRowIterator() CommonDataRowIterator
|
DataRowIterator() CommonDataTableRowIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommonDataRow defines the structure of common data row
|
// CommonDataTableRow defines the structure of common data row
|
||||||
type CommonDataRow interface {
|
type CommonDataTableRow interface {
|
||||||
// ColumnCount returns the total count of column in this data row
|
// ColumnCount returns the total count of column in this data row
|
||||||
ColumnCount() int
|
ColumnCount() int
|
||||||
|
|
||||||
@@ -27,8 +27,8 @@ type CommonDataRow interface {
|
|||||||
GetData(columnName string) string
|
GetData(columnName string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommonDataRowIterator defines the structure of common data row iterator
|
// CommonDataTableRowIterator defines the structure of common data row iterator
|
||||||
type CommonDataRowIterator interface {
|
type CommonDataTableRowIterator interface {
|
||||||
// HasNext returns whether the iterator does not reach the end
|
// HasNext returns whether the iterator does not reach the end
|
||||||
HasNext() bool
|
HasNext() bool
|
||||||
|
|
||||||
@@ -36,5 +36,5 @@ type CommonDataRowIterator interface {
|
|||||||
CurrentRowId() string
|
CurrentRowId() string
|
||||||
|
|
||||||
// Next returns the next common data row
|
// Next returns the next common data row
|
||||||
Next() CommonDataRow
|
Next() CommonDataTableRow
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
package datatable
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
||||||
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommonTransactionDataRowParser defines the structure of common transaction data row parser
|
||||||
|
type CommonTransactionDataRowParser interface {
|
||||||
|
// Parse returns the converted transaction data row
|
||||||
|
Parse(ctx core.Context, user *models.User, dataRow CommonDataTableRow, rowId string) (rowData map[TransactionDataTableColumn]string, rowDataValid bool, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonDataTableToTransactionDataTableWrapper defines the structure of common data table to transaction data table wrapper
|
||||||
|
type commonDataTableToTransactionDataTableWrapper struct {
|
||||||
|
innerDataTable CommonDataTable
|
||||||
|
supportedDataColumns map[TransactionDataTableColumn]bool
|
||||||
|
rowParser CommonTransactionDataRowParser
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonDataTableToTransactionDataTableWrapperRow defines the data row structure of common data table to transaction data table wrapper
|
||||||
|
type commonDataTableToTransactionDataTableWrapperRow struct {
|
||||||
|
transactionDataTable *commonDataTableToTransactionDataTableWrapper
|
||||||
|
rowData map[TransactionDataTableColumn]string
|
||||||
|
rowDataValid bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonDataTableToTransactionDataTableWrapperRowIterator defines the data row iterator structure of common data table to transaction data table wrapper
|
||||||
|
type commonDataTableToTransactionDataTableWrapperRowIterator struct {
|
||||||
|
transactionDataTable *commonDataTableToTransactionDataTableWrapper
|
||||||
|
innerIterator CommonDataTableRowIterator
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasColumn returns whether the data table has specified column
|
||||||
|
func (t *commonDataTableToTransactionDataTableWrapper) HasColumn(column TransactionDataTableColumn) bool {
|
||||||
|
_, exists := t.supportedDataColumns[column]
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionRowCount returns the total count of transaction data row
|
||||||
|
func (t *commonDataTableToTransactionDataTableWrapper) TransactionRowCount() int {
|
||||||
|
return t.innerDataTable.DataRowCount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TransactionRowIterator returns the iterator of transaction data row
|
||||||
|
func (t *commonDataTableToTransactionDataTableWrapper) TransactionRowIterator() TransactionDataRowIterator {
|
||||||
|
return &commonDataTableToTransactionDataTableWrapperRowIterator{
|
||||||
|
transactionDataTable: t,
|
||||||
|
innerIterator: t.innerDataTable.DataRowIterator(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid returns whether this row is valid data for importing
|
||||||
|
func (r *commonDataTableToTransactionDataTableWrapperRow) IsValid() bool {
|
||||||
|
return r.rowDataValid
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetData returns the data in the specified column type
|
||||||
|
func (r *commonDataTableToTransactionDataTableWrapperRow) GetData(column TransactionDataTableColumn) string {
|
||||||
|
if !r.rowDataValid {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
_, exists := r.transactionDataTable.supportedDataColumns[column]
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.rowData[column]
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasNext returns whether the iterator does not reach the end
|
||||||
|
func (t *commonDataTableToTransactionDataTableWrapperRowIterator) HasNext() bool {
|
||||||
|
return t.innerIterator.HasNext()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next returns the next transaction data row
|
||||||
|
func (t *commonDataTableToTransactionDataTableWrapperRowIterator) Next(ctx core.Context, user *models.User) (daraRow TransactionDataRow, err error) {
|
||||||
|
commonDataRow := t.innerIterator.Next()
|
||||||
|
|
||||||
|
if commonDataRow == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
rowId := t.innerIterator.CurrentRowId()
|
||||||
|
rowData, rowDataValid, err := t.transactionDataTable.rowParser.Parse(ctx, user, commonDataRow, rowId)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf(ctx, "[common_data_table_to_transaction_data_table_wrapper.Next] cannot parse data row, because %s", err.Error())
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &commonDataTableToTransactionDataTableWrapperRow{
|
||||||
|
transactionDataTable: t.transactionDataTable,
|
||||||
|
rowData: rowData,
|
||||||
|
rowDataValid: rowDataValid,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateNewTransactionDataTableFromCommonDataTable returns transaction data table from Common data table
|
||||||
|
func CreateNewTransactionDataTableFromCommonDataTable(dataTable CommonDataTable, supportedDataColumns map[TransactionDataTableColumn]bool, rowParser CommonTransactionDataRowParser) TransactionDataTable {
|
||||||
|
return &commonDataTableToTransactionDataTableWrapper{
|
||||||
|
innerDataTable: dataTable,
|
||||||
|
supportedDataColumns: supportedDataColumns,
|
||||||
|
rowParser: rowParser,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package datatable
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/log"
|
|
||||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommonTransactionDataTable defines the structure of common transaction data table
|
|
||||||
type CommonTransactionDataTable struct {
|
|
||||||
innerDataTable CommonDataTable
|
|
||||||
supportedDataColumns map[TransactionDataTableColumn]bool
|
|
||||||
rowParser CommonTransactionDataRowParser
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommonTransactionDataRow defines the structure of common transaction data row
|
|
||||||
type CommonTransactionDataRow struct {
|
|
||||||
transactionDataTable *CommonTransactionDataTable
|
|
||||||
rowData map[TransactionDataTableColumn]string
|
|
||||||
rowDataValid bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommonTransactionDataRowIterator defines the structure of common transaction data row iterator
|
|
||||||
type CommonTransactionDataRowIterator struct {
|
|
||||||
transactionDataTable *CommonTransactionDataTable
|
|
||||||
innerIterator CommonDataRowIterator
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommonTransactionDataRowParser defines the structure of common transaction data row parser
|
|
||||||
type CommonTransactionDataRowParser interface {
|
|
||||||
// Parse returns the converted transaction data row
|
|
||||||
Parse(ctx core.Context, user *models.User, dataTable *CommonTransactionDataTable, dataRow CommonDataRow, rowId string) (rowData map[TransactionDataTableColumn]string, rowDataValid bool, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasColumn returns whether the data table has specified column
|
|
||||||
func (t *CommonTransactionDataTable) HasColumn(column TransactionDataTableColumn) bool {
|
|
||||||
_, exists := t.supportedDataColumns[column]
|
|
||||||
return exists
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasOriginalColumn returns whether the original data table has specified column name
|
|
||||||
func (t *CommonTransactionDataTable) HasOriginalColumn(columnName string) bool {
|
|
||||||
return columnName != "" && t.innerDataTable.HasColumn(columnName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransactionRowCount returns the total count of transaction data row
|
|
||||||
func (t *CommonTransactionDataTable) TransactionRowCount() int {
|
|
||||||
return t.innerDataTable.DataRowCount()
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransactionRowIterator returns the iterator of transaction data row
|
|
||||||
func (t *CommonTransactionDataTable) TransactionRowIterator() TransactionDataRowIterator {
|
|
||||||
return &CommonTransactionDataRowIterator{
|
|
||||||
transactionDataTable: t,
|
|
||||||
innerIterator: t.innerDataTable.DataRowIterator(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValid returns whether this row is valid data for importing
|
|
||||||
func (r *CommonTransactionDataRow) IsValid() bool {
|
|
||||||
return r.rowDataValid
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetData returns the data in the specified column type
|
|
||||||
func (r *CommonTransactionDataRow) GetData(column TransactionDataTableColumn) string {
|
|
||||||
if !r.rowDataValid {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
_, exists := r.transactionDataTable.supportedDataColumns[column]
|
|
||||||
|
|
||||||
if !exists {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.rowData[column]
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
|
||||||
func (t *CommonTransactionDataRowIterator) HasNext() bool {
|
|
||||||
return t.innerIterator.HasNext()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next transaction data row
|
|
||||||
func (t *CommonTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow TransactionDataRow, err error) {
|
|
||||||
commonRow := t.innerIterator.Next()
|
|
||||||
|
|
||||||
if commonRow == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rowId := t.innerIterator.CurrentRowId()
|
|
||||||
rowData, rowDataValid, err := t.transactionDataTable.rowParser.Parse(ctx, user, t.transactionDataTable, commonRow, rowId)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf(ctx, "[common_transaction_data_table.Next] cannot parse data row, because %s", err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &CommonTransactionDataRow{
|
|
||||||
transactionDataTable: t.transactionDataTable,
|
|
||||||
rowData: rowData,
|
|
||||||
rowDataValid: rowDataValid,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewCommonTransactionDataTable returns transaction data table from Common data table
|
|
||||||
func CreateNewCommonTransactionDataTable(dataTable CommonDataTable, supportedDataColumns map[TransactionDataTableColumn]bool, rowParser CommonTransactionDataRowParser) *CommonTransactionDataTable {
|
|
||||||
return &CommonTransactionDataTable{
|
|
||||||
innerDataTable: dataTable,
|
|
||||||
supportedDataColumns: supportedDataColumns,
|
|
||||||
rowParser: rowParser,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package datatable
|
|
||||||
|
|
||||||
// ImportedCommonDataTable defines the structure of imported common data table
|
|
||||||
type ImportedCommonDataTable struct {
|
|
||||||
innerDataTable ImportedDataTable
|
|
||||||
dataColumnIndexes map[string]int
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportedCommonDataRow defines the structure of imported common data row
|
|
||||||
type ImportedCommonDataRow struct {
|
|
||||||
rowData map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportedCommonDataRowIterator defines the structure of imported common data row iterator
|
|
||||||
type ImportedCommonDataRowIterator struct {
|
|
||||||
commonDataTable *ImportedCommonDataTable
|
|
||||||
innerIterator ImportedDataRowIterator
|
|
||||||
}
|
|
||||||
|
|
||||||
// HeaderColumnCount returns the total count of column in header row
|
|
||||||
func (t *ImportedCommonDataTable) HeaderColumnCount() int {
|
|
||||||
return len(t.innerDataTable.HeaderColumnNames())
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasColumn returns whether the data table has specified column name
|
|
||||||
func (t *ImportedCommonDataTable) HasColumn(columnName string) bool {
|
|
||||||
index, exists := t.dataColumnIndexes[columnName]
|
|
||||||
return exists && index >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// DataRowCount returns the total count of common data row
|
|
||||||
func (t *ImportedCommonDataTable) DataRowCount() int {
|
|
||||||
return t.innerDataTable.DataRowCount()
|
|
||||||
}
|
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of common data row
|
|
||||||
func (t *ImportedCommonDataTable) DataRowIterator() CommonDataRowIterator {
|
|
||||||
return &ImportedCommonDataRowIterator{
|
|
||||||
commonDataTable: t,
|
|
||||||
innerIterator: t.innerDataTable.DataRowIterator(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasData returns whether the common data row has specified column data
|
|
||||||
func (r *ImportedCommonDataRow) HasData(columnName string) bool {
|
|
||||||
_, exists := r.rowData[columnName]
|
|
||||||
return exists
|
|
||||||
}
|
|
||||||
|
|
||||||
// ColumnCount returns the total count of column in this data row
|
|
||||||
func (r *ImportedCommonDataRow) ColumnCount() int {
|
|
||||||
return len(r.rowData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetData returns the data in the specified column name
|
|
||||||
func (r *ImportedCommonDataRow) GetData(columnName string) string {
|
|
||||||
return r.rowData[columnName]
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
|
||||||
func (t *ImportedCommonDataRowIterator) HasNext() bool {
|
|
||||||
return t.innerIterator.HasNext()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CurrentRowId returns current row id
|
|
||||||
func (t *ImportedCommonDataRowIterator) CurrentRowId() string {
|
|
||||||
return t.innerIterator.CurrentRowId()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next returns the next common data row
|
|
||||||
func (t *ImportedCommonDataRowIterator) Next() CommonDataRow {
|
|
||||||
importedRow := t.innerIterator.Next()
|
|
||||||
|
|
||||||
if importedRow == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
rowData := make(map[string]string, len(t.commonDataTable.dataColumnIndexes))
|
|
||||||
|
|
||||||
for column, columnIndex := range t.commonDataTable.dataColumnIndexes {
|
|
||||||
if columnIndex < 0 || columnIndex >= importedRow.ColumnCount() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
value := importedRow.GetData(columnIndex)
|
|
||||||
rowData[column] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ImportedCommonDataRow{
|
|
||||||
rowData: rowData,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateNewImportedCommonDataTable returns common data table from imported data table
|
|
||||||
func CreateNewImportedCommonDataTable(dataTable ImportedDataTable) *ImportedCommonDataTable {
|
|
||||||
headerLineItems := dataTable.HeaderColumnNames()
|
|
||||||
dataColumnIndexes := make(map[string]int, len(headerLineItems))
|
|
||||||
|
|
||||||
for i := 0; i < len(headerLineItems); i++ {
|
|
||||||
dataColumnIndexes[headerLineItems[i]] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ImportedCommonDataTable{
|
|
||||||
innerDataTable: dataTable,
|
|
||||||
dataColumnIndexes: dataColumnIndexes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -95,7 +95,7 @@ func (c *defaultTransactionDataPlainTextConverter) ParseImportedData(ctx core.Co
|
|||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionDataTable := datatable.CreateNewImportedTransactionDataTable(dataTable, ezbookkeepingDataColumnNameMapping)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTable(dataTable, ezbookkeepingDataColumnNameMapping)
|
||||||
|
|
||||||
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(
|
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(
|
||||||
ezbookkeepingTransactionTypeNameMapping,
|
ezbookkeepingTransactionTypeNameMapping,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (t *defaultPlainTextDataTable) HeaderColumnNames() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
func (t *defaultPlainTextDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
func (t *defaultPlainTextDataTable) DataRowIterator() datatable.BasicDataTableRowIterator {
|
||||||
return &defaultPlainTextDataRowIterator{
|
return &defaultPlainTextDataRowIterator{
|
||||||
dataTable: t,
|
dataTable: t,
|
||||||
currentIndex: 0,
|
currentIndex: 0,
|
||||||
@@ -83,8 +83,8 @@ func (t *defaultPlainTextDataRowIterator) CurrentRowId() string {
|
|||||||
return fmt.Sprintf("line#%d", t.currentIndex)
|
return fmt.Sprintf("line#%d", t.currentIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next basic data row
|
||||||
func (t *defaultPlainTextDataRowIterator) Next() datatable.ImportedDataRow {
|
func (t *defaultPlainTextDataRowIterator) Next() datatable.BasicDataTableRow {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
if t.currentIndex+1 >= len(t.dataTable.allLines) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ func (c *customTransactionDataDsvFileImporter) ParseImportedData(ctx core.Contex
|
|||||||
allLines = append([][]string{{}}, allLines...)
|
allLines = append([][]string{{}}, allLines...)
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTable := csvconverter.CreateNewCustomCsvImportedDataTable(allLines)
|
dataTable := csvconverter.CreateNewCustomCsvBasicDataTable(allLines)
|
||||||
transactionDataTable := CreateNewCustomPlainTextDataTable(dataTable, c.columnIndexMapping, c.transactionTypeNameMapping, c.timeFormat, c.timezoneFormat, c.amountDecimalSeparator, c.amountDigitGroupingSymbol)
|
transactionDataTable := CreateNewCustomPlainTextDataTable(dataTable, c.columnIndexMapping, c.transactionTypeNameMapping, c.timeFormat, c.timezoneFormat, c.amountDecimalSeparator, c.amountDigitGroupingSymbol)
|
||||||
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(customTransactionTypeNameMapping, c.geoLocationSeparator, c.geoLocationOrder, c.transactionTagSeparator)
|
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(customTransactionTypeNameMapping, c.geoLocationSeparator, c.geoLocationOrder, c.transactionTagSeparator)
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
// customPlainTextDataTable defines the structure of custom plain text transaction data table
|
// customPlainTextDataTable defines the structure of custom plain text transaction data table
|
||||||
type customPlainTextDataTable struct {
|
type customPlainTextDataTable struct {
|
||||||
innerDataTable datatable.ImportedDataTable
|
innerDataTable datatable.BasicDataTable
|
||||||
columnIndexMapping map[datatable.TransactionDataTableColumn]int
|
columnIndexMapping map[datatable.TransactionDataTableColumn]int
|
||||||
transactionTypeNameMapping map[string]models.TransactionType
|
transactionTypeNameMapping map[string]models.TransactionType
|
||||||
timeFormat string
|
timeFormat string
|
||||||
@@ -34,7 +34,7 @@ type customPlainTextDataRow struct {
|
|||||||
// customPlainTextDataRowIterator defines the structure of custom plain text transaction data row iterator
|
// customPlainTextDataRowIterator defines the structure of custom plain text transaction data row iterator
|
||||||
type customPlainTextDataRowIterator struct {
|
type customPlainTextDataRowIterator struct {
|
||||||
transactionDataTable *customPlainTextDataTable
|
transactionDataTable *customPlainTextDataTable
|
||||||
innerIterator datatable.ImportedDataRowIterator
|
innerIterator datatable.BasicDataTableRowIterator
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasColumn returns whether the data table has specified column
|
// HasColumn returns whether the data table has specified column
|
||||||
@@ -105,7 +105,7 @@ func (t *customPlainTextDataRowIterator) Next(ctx core.Context, user *models.Use
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *customPlainTextDataRowIterator) parseTransaction(ctx core.Context, user *models.User, row datatable.ImportedDataRow) (map[datatable.TransactionDataTableColumn]string, bool, error) {
|
func (t *customPlainTextDataRowIterator) parseTransaction(ctx core.Context, user *models.User, row datatable.BasicDataTableRow) (map[datatable.TransactionDataTableColumn]string, bool, error) {
|
||||||
rowData := make(map[datatable.TransactionDataTableColumn]string, len(t.transactionDataTable.columnIndexMapping))
|
rowData := make(map[datatable.TransactionDataTableColumn]string, len(t.transactionDataTable.columnIndexMapping))
|
||||||
|
|
||||||
for column, columnIndex := range t.transactionDataTable.columnIndexMapping {
|
for column, columnIndex := range t.transactionDataTable.columnIndexMapping {
|
||||||
@@ -236,7 +236,7 @@ func (t *customPlainTextDataRowIterator) parseAmount(ctx core.Context, amountVal
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewCustomPlainTextDataTable returns transaction data table from imported data table
|
// CreateNewCustomPlainTextDataTable returns transaction data table from imported data table
|
||||||
func CreateNewCustomPlainTextDataTable(dataTable datatable.ImportedDataTable, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string) *customPlainTextDataTable {
|
func CreateNewCustomPlainTextDataTable(dataTable datatable.BasicDataTable, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string) *customPlainTextDataTable {
|
||||||
timeFormatIncludeTimezone := strings.Contains(timeFormat, "z") || strings.Contains(timeFormat, "Z")
|
timeFormatIncludeTimezone := strings.Contains(timeFormat, "z") || strings.Contains(timeFormat, "Z")
|
||||||
|
|
||||||
return &customPlainTextDataTable{
|
return &customPlainTextDataTable{
|
||||||
|
|||||||
+22
-22
@@ -10,27 +10,27 @@ import (
|
|||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExcelMSCFBFileImportedDataTable defines the structure of excel (microsoft compound file binary) file data table
|
// ExcelMSCFBFileBasicDataTable defines the structure of excel (microsoft compound file binary) file data table
|
||||||
type ExcelMSCFBFileImportedDataTable struct {
|
type ExcelMSCFBFileBasicDataTable struct {
|
||||||
workbook *xls.WorkBook
|
workbook *xls.WorkBook
|
||||||
headerLineColumnNames []string
|
headerLineColumnNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcelMSCFBFileDataRow defines the structure of excel (microsoft compound file binary) file data table row
|
// ExcelMSCFBFileBasicDataTableRow defines the structure of excel (microsoft compound file binary) file data table row
|
||||||
type ExcelMSCFBFileDataRow struct {
|
type ExcelMSCFBFileBasicDataTableRow struct {
|
||||||
sheet *xls.WorkSheet
|
sheet *xls.WorkSheet
|
||||||
rowIndex int
|
rowIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcelMSCFBFileDataRowIterator defines the structure of excel (microsoft compound file binary) file data table row iterator
|
// ExcelMSCFBFileBasicDataTableRowIterator defines the structure of excel (microsoft compound file binary) file data table row iterator
|
||||||
type ExcelMSCFBFileDataRowIterator struct {
|
type ExcelMSCFBFileBasicDataTableRowIterator struct {
|
||||||
dataTable *ExcelMSCFBFileImportedDataTable
|
dataTable *ExcelMSCFBFileBasicDataTable
|
||||||
currentSheetIndex int
|
currentSheetIndex int
|
||||||
currentRowIndexInSheet uint16
|
currentRowIndexInSheet uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataRowCount returns the total count of data row
|
// DataRowCount returns the total count of data row
|
||||||
func (t *ExcelMSCFBFileImportedDataTable) DataRowCount() int {
|
func (t *ExcelMSCFBFileBasicDataTable) DataRowCount() int {
|
||||||
totalDataRowCount := 0
|
totalDataRowCount := 0
|
||||||
|
|
||||||
for i := 0; i < t.workbook.NumSheets(); i++ {
|
for i := 0; i < t.workbook.NumSheets(); i++ {
|
||||||
@@ -47,13 +47,13 @@ func (t *ExcelMSCFBFileImportedDataTable) DataRowCount() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HeaderColumnNames returns the header column name list
|
// HeaderColumnNames returns the header column name list
|
||||||
func (t *ExcelMSCFBFileImportedDataTable) HeaderColumnNames() []string {
|
func (t *ExcelMSCFBFileBasicDataTable) HeaderColumnNames() []string {
|
||||||
return t.headerLineColumnNames
|
return t.headerLineColumnNames
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
func (t *ExcelMSCFBFileImportedDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
func (t *ExcelMSCFBFileBasicDataTable) DataRowIterator() datatable.BasicDataTableRowIterator {
|
||||||
return &ExcelMSCFBFileDataRowIterator{
|
return &ExcelMSCFBFileBasicDataTableRowIterator{
|
||||||
dataTable: t,
|
dataTable: t,
|
||||||
currentSheetIndex: 0,
|
currentSheetIndex: 0,
|
||||||
currentRowIndexInSheet: 0,
|
currentRowIndexInSheet: 0,
|
||||||
@@ -61,19 +61,19 @@ func (t *ExcelMSCFBFileImportedDataTable) DataRowIterator() datatable.ImportedDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ColumnCount returns the total count of column in this data row
|
// ColumnCount returns the total count of column in this data row
|
||||||
func (r *ExcelMSCFBFileDataRow) ColumnCount() int {
|
func (r *ExcelMSCFBFileBasicDataTableRow) ColumnCount() int {
|
||||||
row := r.sheet.Row(r.rowIndex)
|
row := r.sheet.Row(r.rowIndex)
|
||||||
return row.LastCol() + 1
|
return row.LastCol() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetData returns the data in the specified column index
|
// GetData returns the data in the specified column index
|
||||||
func (r *ExcelMSCFBFileDataRow) GetData(columnIndex int) string {
|
func (r *ExcelMSCFBFileBasicDataTableRow) GetData(columnIndex int) string {
|
||||||
row := r.sheet.Row(r.rowIndex)
|
row := r.sheet.Row(r.rowIndex)
|
||||||
return row.Col(columnIndex)
|
return row.Col(columnIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
// HasNext returns whether the iterator does not reach the end
|
||||||
func (t *ExcelMSCFBFileDataRowIterator) HasNext() bool {
|
func (t *ExcelMSCFBFileBasicDataTableRowIterator) HasNext() bool {
|
||||||
workbook := t.dataTable.workbook
|
workbook := t.dataTable.workbook
|
||||||
|
|
||||||
if t.currentSheetIndex >= workbook.NumSheets() {
|
if t.currentSheetIndex >= workbook.NumSheets() {
|
||||||
@@ -100,12 +100,12 @@ func (t *ExcelMSCFBFileDataRowIterator) HasNext() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CurrentRowId returns current index
|
// CurrentRowId returns current index
|
||||||
func (t *ExcelMSCFBFileDataRowIterator) CurrentRowId() string {
|
func (t *ExcelMSCFBFileBasicDataTableRowIterator) CurrentRowId() string {
|
||||||
return fmt.Sprintf("table#%d-row#%d", t.currentSheetIndex, t.currentRowIndexInSheet)
|
return fmt.Sprintf("sheet#%d-row#%d", t.currentSheetIndex, t.currentRowIndexInSheet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next basic data row
|
||||||
func (t *ExcelMSCFBFileDataRowIterator) Next() datatable.ImportedDataRow {
|
func (t *ExcelMSCFBFileBasicDataTableRowIterator) Next() datatable.BasicDataTableRow {
|
||||||
workbook := t.dataTable.workbook
|
workbook := t.dataTable.workbook
|
||||||
currentRowIndexInTable := t.currentRowIndexInSheet
|
currentRowIndexInTable := t.currentRowIndexInSheet
|
||||||
|
|
||||||
@@ -133,14 +133,14 @@ func (t *ExcelMSCFBFileDataRowIterator) Next() datatable.ImportedDataRow {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ExcelMSCFBFileDataRow{
|
return &ExcelMSCFBFileBasicDataTableRow{
|
||||||
sheet: currentSheet,
|
sheet: currentSheet,
|
||||||
rowIndex: int(t.currentRowIndexInSheet),
|
rowIndex: int(t.currentRowIndexInSheet),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewExcelMSCFBFileImportedDataTable returns excel (microsoft compound file binary) data table by file binary data
|
// CreateNewExcelMSCFBFileBasicDataTable returns excel (microsoft compound file binary) data table by file binary data
|
||||||
func CreateNewExcelMSCFBFileImportedDataTable(data []byte) (*ExcelMSCFBFileImportedDataTable, error) {
|
func CreateNewExcelMSCFBFileBasicDataTable(data []byte) (datatable.BasicDataTable, error) {
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
workbook, err := xls.OpenReader(reader, "")
|
workbook, err := xls.OpenReader(reader, "")
|
||||||
|
|
||||||
@@ -184,7 +184,7 @@ func CreateNewExcelMSCFBFileImportedDataTable(data []byte) (*ExcelMSCFBFileImpor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ExcelMSCFBFileImportedDataTable{
|
return &ExcelMSCFBFileBasicDataTable{
|
||||||
workbook: workbook,
|
workbook: workbook,
|
||||||
headerLineColumnNames: headerRowItems,
|
headerLineColumnNames: headerRowItems,
|
||||||
}, nil
|
}, nil
|
||||||
+30
-30
@@ -9,63 +9,63 @@ import (
|
|||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableDataRowCount(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableDataRowCount(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, datatable.DataRowCount())
|
assert.Equal(t, 2, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableDataRowCount_MultipleSheets(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableDataRowCount_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 5, datatable.DataRowCount())
|
assert.Equal(t, 5, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableDataRowCount_EmptyContent(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableDataRowCount_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableHeaderColumnNames(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableHeaderColumnNames(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileImportedDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, datatable.HeaderColumnNames())
|
assert.Nil(t, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowIterator(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowIterator(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.True(t, iterator.HasNext())
|
assert.True(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ func TestExcelMSCFBFileDataRowIterator(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowIterator_MultipleSheets(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowIterator_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.True(t, iterator.HasNext())
|
assert.True(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -123,11 +123,11 @@ func TestExcelMSCFBFileDataRowIterator_MultipleSheets(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowIterator_OnlyHeaderLine(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowIterator_OnlyHeaderLine(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -140,11 +140,11 @@ func TestExcelMSCFBFileDataRowIterator_OnlyHeaderLine(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowIterator_EmptyContent(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowIterator_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -157,11 +157,11 @@ func TestExcelMSCFBFileDataRowIterator_EmptyContent(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowColumnCount(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowColumnCount(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
@@ -171,11 +171,11 @@ func TestExcelMSCFBFileDataRowColumnCount(t *testing.T) {
|
|||||||
assert.EqualValues(t, 4, row2.ColumnCount())
|
assert.EqualValues(t, 4, row2.ColumnCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowGetData(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowGetData(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
@@ -189,22 +189,22 @@ func TestExcelMSCFBFileDataRowGetData(t *testing.T) {
|
|||||||
assert.Equal(t, "C3", row2.GetData(2))
|
assert.Equal(t, "C3", row2.GetData(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowGetData_GetNotExistedColumnData(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowGetData_GetNotExistedColumnData(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
assert.Equal(t, "", row1.GetData(3))
|
assert.Equal(t, "", row1.GetData(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelMSCFBFileDataRowGetData_MultipleSheets(t *testing.T) {
|
func TestExcelMSCFBFileBasicDataTableRowGetData_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
sheet1Row1 := iterator.Next()
|
sheet1Row1 := iterator.Next()
|
||||||
@@ -237,10 +237,10 @@ func TestExcelMSCFBFileDataRowGetData_MultipleSheets(t *testing.T) {
|
|||||||
assert.Equal(t, "5-C3", sheet5Row2.GetData(2))
|
assert.Equal(t, "5-C3", sheet5Row2.GetData(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateNewExcelMSCFBFileImportedDataTable_MultipleSheetsWithDifferentHeaders(t *testing.T) {
|
func TestCreateNewExcelMSCFBFileBasicDataTable_MultipleSheetsWithDifferentHeaders(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_with_different_header_row_excel_file.xls")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_with_different_header_row_excel_file.xls")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
_, err = CreateNewExcelMSCFBFileImportedDataTable(testdata)
|
_, err = CreateNewExcelMSCFBFileBasicDataTable(testdata)
|
||||||
assert.EqualError(t, err, errs.ErrFieldsInMultiTableAreDifferent.Message)
|
assert.EqualError(t, err, errs.ErrFieldsInMultiTableAreDifferent.Message)
|
||||||
}
|
}
|
||||||
+22
-22
@@ -16,28 +16,28 @@ type excelOOXMLSheet struct {
|
|||||||
allData [][]string
|
allData [][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcelOOXMLFileImportedDataTable defines the structure of excel (Office Open XML) file data table
|
// ExcelOOXMLFileBasicDataTable defines the structure of excel (Office Open XML) file data table
|
||||||
type ExcelOOXMLFileImportedDataTable struct {
|
type ExcelOOXMLFileBasicDataTable struct {
|
||||||
sheets []*excelOOXMLSheet
|
sheets []*excelOOXMLSheet
|
||||||
headerLineColumnNames []string
|
headerLineColumnNames []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcelOOXMLFileDataRow defines the structure of excel (Office Open XML) file data table row
|
// ExcelOOXMLFileBasicDataTableRow defines the structure of excel (Office Open XML) file data table row
|
||||||
type ExcelOOXMLFileDataRow struct {
|
type ExcelOOXMLFileBasicDataTableRow struct {
|
||||||
sheet *excelOOXMLSheet
|
sheet *excelOOXMLSheet
|
||||||
rowData []string
|
rowData []string
|
||||||
rowIndex int
|
rowIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExcelOOXMLFileDataRowIterator defines the structure of excel (Office Open XML) file data table row iterator
|
// ExcelOOXMLFileBasicDataTableRowIterator defines the structure of excel (Office Open XML) file data table row iterator
|
||||||
type ExcelOOXMLFileDataRowIterator struct {
|
type ExcelOOXMLFileBasicDataTableRowIterator struct {
|
||||||
dataTable *ExcelOOXMLFileImportedDataTable
|
dataTable *ExcelOOXMLFileBasicDataTable
|
||||||
currentSheetIndex int
|
currentSheetIndex int
|
||||||
currentRowIndexInSheet int
|
currentRowIndexInSheet int
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataRowCount returns the total count of data row
|
// DataRowCount returns the total count of data row
|
||||||
func (t *ExcelOOXMLFileImportedDataTable) DataRowCount() int {
|
func (t *ExcelOOXMLFileBasicDataTable) DataRowCount() int {
|
||||||
totalDataRowCount := 0
|
totalDataRowCount := 0
|
||||||
|
|
||||||
for i := 0; i < len(t.sheets); i++ {
|
for i := 0; i < len(t.sheets); i++ {
|
||||||
@@ -54,13 +54,13 @@ func (t *ExcelOOXMLFileImportedDataTable) DataRowCount() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HeaderColumnNames returns the header column name list
|
// HeaderColumnNames returns the header column name list
|
||||||
func (t *ExcelOOXMLFileImportedDataTable) HeaderColumnNames() []string {
|
func (t *ExcelOOXMLFileBasicDataTable) HeaderColumnNames() []string {
|
||||||
return t.headerLineColumnNames
|
return t.headerLineColumnNames
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataRowIterator returns the iterator of data row
|
// DataRowIterator returns the iterator of data row
|
||||||
func (t *ExcelOOXMLFileImportedDataTable) DataRowIterator() datatable.ImportedDataRowIterator {
|
func (t *ExcelOOXMLFileBasicDataTable) DataRowIterator() datatable.BasicDataTableRowIterator {
|
||||||
return &ExcelOOXMLFileDataRowIterator{
|
return &ExcelOOXMLFileBasicDataTableRowIterator{
|
||||||
dataTable: t,
|
dataTable: t,
|
||||||
currentSheetIndex: 0,
|
currentSheetIndex: 0,
|
||||||
currentRowIndexInSheet: 0,
|
currentRowIndexInSheet: 0,
|
||||||
@@ -68,12 +68,12 @@ func (t *ExcelOOXMLFileImportedDataTable) DataRowIterator() datatable.ImportedDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ColumnCount returns the total count of column in this data row
|
// ColumnCount returns the total count of column in this data row
|
||||||
func (r *ExcelOOXMLFileDataRow) ColumnCount() int {
|
func (r *ExcelOOXMLFileBasicDataTableRow) ColumnCount() int {
|
||||||
return len(r.rowData)
|
return len(r.rowData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetData returns the data in the specified column index
|
// GetData returns the data in the specified column index
|
||||||
func (r *ExcelOOXMLFileDataRow) GetData(columnIndex int) string {
|
func (r *ExcelOOXMLFileBasicDataTableRow) GetData(columnIndex int) string {
|
||||||
if columnIndex < 0 || columnIndex >= len(r.rowData) {
|
if columnIndex < 0 || columnIndex >= len(r.rowData) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,7 @@ func (r *ExcelOOXMLFileDataRow) GetData(columnIndex int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasNext returns whether the iterator does not reach the end
|
// HasNext returns whether the iterator does not reach the end
|
||||||
func (t *ExcelOOXMLFileDataRowIterator) HasNext() bool {
|
func (t *ExcelOOXMLFileBasicDataTableRowIterator) HasNext() bool {
|
||||||
sheets := t.dataTable.sheets
|
sheets := t.dataTable.sheets
|
||||||
|
|
||||||
if t.currentSheetIndex >= len(sheets) {
|
if t.currentSheetIndex >= len(sheets) {
|
||||||
@@ -109,12 +109,12 @@ func (t *ExcelOOXMLFileDataRowIterator) HasNext() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CurrentRowId returns current index
|
// CurrentRowId returns current index
|
||||||
func (t *ExcelOOXMLFileDataRowIterator) CurrentRowId() string {
|
func (t *ExcelOOXMLFileBasicDataTableRowIterator) CurrentRowId() string {
|
||||||
return fmt.Sprintf("table#%d-row#%d", t.currentSheetIndex, t.currentRowIndexInSheet)
|
return fmt.Sprintf("sheet#%d-row#%d", t.currentSheetIndex, t.currentRowIndexInSheet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next basic data row
|
||||||
func (t *ExcelOOXMLFileDataRowIterator) Next() datatable.ImportedDataRow {
|
func (t *ExcelOOXMLFileBasicDataTableRowIterator) Next() datatable.BasicDataTableRow {
|
||||||
sheets := t.dataTable.sheets
|
sheets := t.dataTable.sheets
|
||||||
currentRowIndexInTable := t.currentRowIndexInSheet
|
currentRowIndexInTable := t.currentRowIndexInSheet
|
||||||
|
|
||||||
@@ -142,15 +142,15 @@ func (t *ExcelOOXMLFileDataRowIterator) Next() datatable.ImportedDataRow {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ExcelOOXMLFileDataRow{
|
return &ExcelOOXMLFileBasicDataTableRow{
|
||||||
sheet: currentSheet,
|
sheet: currentSheet,
|
||||||
rowData: currentSheet.allData[t.currentRowIndexInSheet],
|
rowData: currentSheet.allData[t.currentRowIndexInSheet],
|
||||||
rowIndex: t.currentRowIndexInSheet,
|
rowIndex: t.currentRowIndexInSheet,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateNewExcelOOXMLFileImportedDataTable returns excel (Office Open XML) data table by file binary data
|
// CreateNewExcelOOXMLFileBasicDataTable returns excel (Office Open XML) data table by file binary data
|
||||||
func CreateNewExcelOOXMLFileImportedDataTable(data []byte) (*ExcelOOXMLFileImportedDataTable, error) {
|
func CreateNewExcelOOXMLFileBasicDataTable(data []byte) (datatable.BasicDataTable, error) {
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
file, err := excelize.OpenReader(reader)
|
file, err := excelize.OpenReader(reader)
|
||||||
|
|
||||||
@@ -204,7 +204,7 @@ func CreateNewExcelOOXMLFileImportedDataTable(data []byte) (*ExcelOOXMLFileImpor
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ExcelOOXMLFileImportedDataTable{
|
return &ExcelOOXMLFileBasicDataTable{
|
||||||
sheets: sheets,
|
sheets: sheets,
|
||||||
headerLineColumnNames: headerRowItems,
|
headerLineColumnNames: headerRowItems,
|
||||||
}, nil
|
}, nil
|
||||||
+30
-30
@@ -9,63 +9,63 @@ import (
|
|||||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableDataRowCount(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableDataRowCount(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, datatable.DataRowCount())
|
assert.Equal(t, 2, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableDataRowCount_MultipleSheets(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableDataRowCount_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 5, datatable.DataRowCount())
|
assert.Equal(t, 5, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableDataRowCount_OnlyHeaderLine(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableDataRowCount_EmptyContent(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableDataRowCount_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, datatable.DataRowCount())
|
assert.Equal(t, 0, datatable.DataRowCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableHeaderColumnNames(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableHeaderColumnNames(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
assert.EqualValues(t, []string{"A1", "B1", "C1"}, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileImportedDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataTableHeaderColumnNames_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.Nil(t, datatable.HeaderColumnNames())
|
assert.Nil(t, datatable.HeaderColumnNames())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowIterator(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowIterator(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.True(t, iterator.HasNext())
|
assert.True(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ func TestExcelOOXMLFileDataRowIterator(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowIterator_MultipleSheets(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowIterator_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.True(t, iterator.HasNext())
|
assert.True(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -123,11 +123,11 @@ func TestExcelOOXMLFileDataRowIterator_MultipleSheets(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowIterator_OnlyHeaderLine(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowIterator_OnlyHeaderLine(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/only_one_row_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -140,11 +140,11 @@ func TestExcelOOXMLFileDataRowIterator_OnlyHeaderLine(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowIterator_EmptyContent(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowIterator_EmptyContent(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/empty_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
|
|
||||||
@@ -157,11 +157,11 @@ func TestExcelOOXMLFileDataRowIterator_EmptyContent(t *testing.T) {
|
|||||||
assert.False(t, iterator.HasNext())
|
assert.False(t, iterator.HasNext())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowColumnCount(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowColumnCount(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
@@ -171,11 +171,11 @@ func TestExcelOOXMLFileDataRowColumnCount(t *testing.T) {
|
|||||||
assert.EqualValues(t, 3, row2.ColumnCount())
|
assert.EqualValues(t, 3, row2.ColumnCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowGetData(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowGetData(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
@@ -189,22 +189,22 @@ func TestExcelOOXMLFileDataRowGetData(t *testing.T) {
|
|||||||
assert.Equal(t, "C3", row2.GetData(2))
|
assert.Equal(t, "C3", row2.GetData(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowGetData_GetNotExistedColumnData(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowGetData_GetNotExistedColumnData(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/simple_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
row1 := iterator.Next()
|
row1 := iterator.Next()
|
||||||
assert.Equal(t, "", row1.GetData(3))
|
assert.Equal(t, "", row1.GetData(3))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExcelOOXMLFileDataRowGetData_MultipleSheets(t *testing.T) {
|
func TestExcelOOXMLFileBasicDataRowGetData_MultipleSheets(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
datatable, err := CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
datatable, err := CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
iterator := datatable.DataRowIterator()
|
iterator := datatable.DataRowIterator()
|
||||||
|
|
||||||
sheet1Row1 := iterator.Next()
|
sheet1Row1 := iterator.Next()
|
||||||
@@ -237,10 +237,10 @@ func TestExcelOOXMLFileDataRowGetData_MultipleSheets(t *testing.T) {
|
|||||||
assert.Equal(t, "5-C3", sheet5Row2.GetData(2))
|
assert.Equal(t, "5-C3", sheet5Row2.GetData(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateNewExcelOOXMLFileImportedDataTable_MultipleSheetsWithDifferentHeaders(t *testing.T) {
|
func TestCreateNewExcelOOXMLFileBasicDataTable_MultipleSheetsWithDifferentHeaders(t *testing.T) {
|
||||||
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_with_different_header_row_excel_file.xlsx")
|
testdata, err := os.ReadFile("../../../testdata/multiple_sheets_with_different_header_row_excel_file.xlsx")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
_, err = CreateNewExcelOOXMLFileImportedDataTable(testdata)
|
_, err = CreateNewExcelOOXMLFileBasicDataTable(testdata)
|
||||||
assert.EqualError(t, err, errs.ErrFieldsInMultiTableAreDifferent.Message)
|
assert.EqualError(t, err, errs.ErrFieldsInMultiTableAreDifferent.Message)
|
||||||
}
|
}
|
||||||
@@ -60,13 +60,13 @@ func (c *feideeMymoneyAppTransactionDataCsvFileImporter) ParseImportedData(ctx c
|
|||||||
fallback := unicode.UTF8.NewDecoder()
|
fallback := unicode.UTF8.NewDecoder()
|
||||||
reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback))
|
reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback))
|
||||||
|
|
||||||
dataTable, err := c.createNewFeideeMymoneyAppImportedDataTable(ctx, reader)
|
dataTable, err := c.createNewFeideeMymoneyAppBasicDataTable(ctx, reader)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commonDataTable := datatable.CreateNewImportedCommonDataTable(dataTable)
|
commonDataTable := datatable.CreateNewCommonDataTableFromBasicDataTable(dataTable)
|
||||||
|
|
||||||
if !commonDataTable.HasColumn(feideeMymoneyAppTransactionTimeColumnName) ||
|
if !commonDataTable.HasColumn(feideeMymoneyAppTransactionTimeColumnName) ||
|
||||||
!commonDataTable.HasColumn(feideeMymoneyAppTransactionTypeColumnName) ||
|
!commonDataTable.HasColumn(feideeMymoneyAppTransactionTypeColumnName) ||
|
||||||
@@ -89,7 +89,7 @@ func (c *feideeMymoneyAppTransactionDataCsvFileImporter) ParseImportedData(ctx c
|
|||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *feideeMymoneyAppTransactionDataCsvFileImporter) createNewFeideeMymoneyAppImportedDataTable(ctx core.Context, reader io.Reader) (datatable.ImportedDataTable, error) {
|
func (c *feideeMymoneyAppTransactionDataCsvFileImporter) createNewFeideeMymoneyAppBasicDataTable(ctx core.Context, reader io.Reader) (datatable.BasicDataTable, error) {
|
||||||
csvReader := csv.NewReader(reader)
|
csvReader := csv.NewReader(reader)
|
||||||
csvReader.FieldsPerRecord = -1
|
csvReader.FieldsPerRecord = -1
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ func (c *feideeMymoneyAppTransactionDataCsvFileImporter) createNewFeideeMymoneyA
|
|||||||
return nil, errs.ErrNotFoundTransactionDataInFile
|
return nil, errs.ErrNotFoundTransactionDataInFile
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTable := csvdatatable.CreateNewCustomCsvImportedDataTable(allOriginalLines)
|
dataTable := csvdatatable.CreateNewCustomCsvBasicDataTable(allOriginalLines)
|
||||||
|
|
||||||
return dataTable, nil
|
return dataTable, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -32,14 +32,14 @@ var (
|
|||||||
|
|
||||||
// ParseImportedData returns the imported data by parsing the feidee mymoney (elecloud) transaction xlsx data
|
// ParseImportedData returns the imported data by parsing the feidee mymoney (elecloud) transaction xlsx data
|
||||||
func (c *feideeMymoneyElecloudTransactionDataXlsxFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
func (c *feideeMymoneyElecloudTransactionDataXlsxFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
||||||
dataTable, err := excel.CreateNewExcelOOXMLFileImportedDataTable(data)
|
dataTable, err := excel.CreateNewExcelOOXMLFileBasicDataTable(data)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionRowParser := createFeideeMymoneyElecloudTransactionDataRowParser()
|
transactionRowParser := createFeideeMymoneyElecloudTransactionDataRowParser()
|
||||||
transactionDataTable := datatable.CreateNewImportedTransactionDataTableWithRowParser(dataTable, feideeMymoneyElecloudDataColumnNameMapping, transactionRowParser)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, feideeMymoneyElecloudDataColumnNameMapping, transactionRowParser)
|
||||||
dataTableImporter := converter.CreateNewSimpleImporter(feideeMymoneyElecloudTransactionTypeNameMapping)
|
dataTableImporter := converter.CreateNewSimpleImporter(feideeMymoneyElecloudTransactionTypeNameMapping)
|
||||||
|
|
||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
|
|||||||
@@ -31,14 +31,14 @@ var (
|
|||||||
|
|
||||||
// ParseImportedData returns the imported data by parsing the feidee mymoney (web) transaction xls data
|
// ParseImportedData returns the imported data by parsing the feidee mymoney (web) transaction xls data
|
||||||
func (c *feideeMymoneyWebTransactionDataXlsFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
func (c *feideeMymoneyWebTransactionDataXlsFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
||||||
dataTable, err := excel.CreateNewExcelMSCFBFileImportedDataTable(data)
|
dataTable, err := excel.CreateNewExcelMSCFBFileBasicDataTable(data)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionRowParser := createFeideeMymoneyTransactionDataRowParser()
|
transactionRowParser := createFeideeMymoneyTransactionDataRowParser()
|
||||||
transactionDataTable := datatable.CreateNewImportedTransactionDataTableWithRowParser(dataTable, feideeMymoneyWebDataColumnNameMapping, transactionRowParser)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, feideeMymoneyWebDataColumnNameMapping, transactionRowParser)
|
||||||
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(feideeMymoneyTransactionTypeNameMapping)
|
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(feideeMymoneyTransactionTypeNameMapping)
|
||||||
|
|
||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ var (
|
|||||||
// ParseImportedData returns the imported data by parsing the firefly III transaction csv data
|
// ParseImportedData returns the imported data by parsing the firefly III transaction csv data
|
||||||
func (c *fireflyIIITransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
func (c *fireflyIIITransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]map[string]*models.TransactionCategory, incomeCategoryMap map[string]map[string]*models.TransactionCategory, transferCategoryMap map[string]map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
|
||||||
reader := bytes.NewReader(data)
|
reader := bytes.NewReader(data)
|
||||||
dataTable, err := csv.CreateNewCsvImportedDataTable(ctx, reader)
|
dataTable, err := csv.CreateNewCsvBasicDataTable(ctx, reader)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionRowParser := createFireflyIIITransactionDataRowParser()
|
transactionRowParser := createFireflyIIITransactionDataRowParser()
|
||||||
transactionDataTable := datatable.CreateNewImportedTransactionDataTableWithRowParser(dataTable, fireflyIIITransactionDataColumnNameMapping, transactionRowParser)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, fireflyIIITransactionDataColumnNameMapping, transactionRowParser)
|
||||||
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(fireflyIIITransactionTypeNameMapping, "", "", ",")
|
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(fireflyIIITransactionTypeNameMapping, "", "", ",")
|
||||||
|
|
||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ func (t *gnucashTransactionDataRowIterator) HasNext() bool {
|
|||||||
return t.currentIndex+1 < len(t.dataTable.allData)
|
return t.currentIndex+1 < len(t.dataTable.allData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *gnucashTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *gnucashTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func (t *iifTransactionDataRowIterator) HasNext() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *iifTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *iifTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
allDatasets := t.dataTable.transactionDatasets
|
allDatasets := t.dataTable.transactionDatasets
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func (t *ofxTransactionDataRowIterator) HasNext() bool {
|
|||||||
return t.currentIndex+1 < len(t.dataTable.allData)
|
return t.currentIndex+1 < len(t.dataTable.allData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *ofxTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *ofxTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func (t *qifTransactionDataRowIterator) HasNext() bool {
|
|||||||
return t.currentIndex+1 < len(t.dataTable.allData)
|
return t.currentIndex+1 < len(t.dataTable.allData)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next returns the next imported data row
|
// Next returns the next transaction data row
|
||||||
func (t *qifTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
func (t *qifTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow datatable.TransactionDataRow, err error) {
|
||||||
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
if t.currentIndex+1 >= len(t.dataTable.allData) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
|||||||
@@ -49,13 +49,13 @@ func (c *wechatPayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Con
|
|||||||
fallback := unicode.UTF8.NewDecoder()
|
fallback := unicode.UTF8.NewDecoder()
|
||||||
reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback))
|
reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback))
|
||||||
|
|
||||||
dataTable, err := c.createNewWeChatPayImportedDataTable(ctx, reader)
|
dataTable, err := c.createNewWeChatPayBasicDataTable(ctx, reader)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, nil, nil, err
|
return nil, nil, nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
commonDataTable := datatable.CreateNewImportedCommonDataTable(dataTable)
|
commonDataTable := datatable.CreateNewCommonDataTableFromBasicDataTable(dataTable)
|
||||||
|
|
||||||
if !commonDataTable.HasColumn(wechatPayTransactionTimeColumnName) ||
|
if !commonDataTable.HasColumn(wechatPayTransactionTimeColumnName) ||
|
||||||
!commonDataTable.HasColumn(wechatPayTransactionCategoryColumnName) ||
|
!commonDataTable.HasColumn(wechatPayTransactionCategoryColumnName) ||
|
||||||
@@ -66,14 +66,14 @@ func (c *wechatPayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Con
|
|||||||
return nil, nil, nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
return nil, nil, nil, nil, nil, nil, errs.ErrMissingRequiredFieldInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionRowParser := createWeChatPayTransactionDataRowParser()
|
transactionRowParser := createWeChatPayTransactionDataRowParser(dataTable.HeaderColumnNames())
|
||||||
transactionDataTable := datatable.CreateNewCommonTransactionDataTable(commonDataTable, wechatPayTransactionSupportedColumns, transactionRowParser)
|
transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, wechatPayTransactionSupportedColumns, transactionRowParser)
|
||||||
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(wechatPayTransactionTypeNameMapping)
|
dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(wechatPayTransactionTypeNameMapping)
|
||||||
|
|
||||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayImportedDataTable(ctx core.Context, reader io.Reader) (datatable.ImportedDataTable, error) {
|
func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayBasicDataTable(ctx core.Context, reader io.Reader) (datatable.BasicDataTable, error) {
|
||||||
csvReader := csv.NewReader(reader)
|
csvReader := csv.NewReader(reader)
|
||||||
csvReader.FieldsPerRecord = -1
|
csvReader.FieldsPerRecord = -1
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayImportedData
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayImportedDataTable] cannot parse wechat pay csv data, because %s", err.Error())
|
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayBasicDataTable] cannot parse wechat pay csv data, because %s", err.Error())
|
||||||
return nil, errs.ErrInvalidCSVFile
|
return nil, errs.ErrInvalidCSVFile
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayImportedData
|
|||||||
hasFileHeader = true
|
hasFileHeader = true
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
log.Warnf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayImportedDataTable] read unexpected line before read file header, line content is %s", strings.Join(items, ","))
|
log.Warnf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayBasicDataTable] read unexpected line before read file header, line content is %s", strings.Join(items, ","))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayImportedData
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(allOriginalLines) > 0 && len(items) < len(allOriginalLines[0]) {
|
if len(allOriginalLines) > 0 && len(items) < len(allOriginalLines[0]) {
|
||||||
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayImportedDataTable] cannot parse row \"index:%d\", because may missing some columns (column count %d in data row is less than header column count %d)", len(allOriginalLines), len(items), len(allOriginalLines[0]))
|
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayBasicDataTable] cannot parse row \"index:%d\", because may missing some columns (column count %d in data row is less than header column count %d)", len(allOriginalLines), len(items), len(allOriginalLines[0]))
|
||||||
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,11 +139,11 @@ func (c *wechatPayTransactionDataCsvFileImporter) createNewWeChatPayImportedData
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(allOriginalLines) < 2 {
|
if len(allOriginalLines) < 2 {
|
||||||
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayImportedDataTable] cannot parse import data, because data table row count is less 1")
|
log.Errorf(ctx, "[wechat_pay_transaction_data_csv_file_importer.createNewWeChatPayBasicDataTable] cannot parse import data, because data table row count is less 1")
|
||||||
return nil, errs.ErrNotFoundTransactionDataInFile
|
return nil, errs.ErrNotFoundTransactionDataInFile
|
||||||
}
|
}
|
||||||
|
|
||||||
dataTable := csvdatatable.CreateNewCustomCsvImportedDataTable(allOriginalLines)
|
dataTable := csvdatatable.CreateNewCustomCsvBasicDataTable(allOriginalLines)
|
||||||
|
|
||||||
return dataTable, nil
|
return dataTable, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ const wechatPayTransactionDataStatusRefundName = "退款"
|
|||||||
|
|
||||||
// weChatPayTransactionDataRowParser defines the structure of wechat pay transaction data row parser
|
// weChatPayTransactionDataRowParser defines the structure of wechat pay transaction data row parser
|
||||||
type weChatPayTransactionDataRowParser struct {
|
type weChatPayTransactionDataRowParser struct {
|
||||||
|
existedOriginalDataColumns map[string]bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse returns the converted transaction data row
|
// Parse returns the converted transaction data row
|
||||||
func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models.User, dataTable *datatable.CommonTransactionDataTable, dataRow datatable.CommonDataRow, rowId string) (rowData map[datatable.TransactionDataTableColumn]string, rowDataValid bool, err error) {
|
func (p *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models.User, dataRow datatable.CommonDataTableRow, rowId string) (rowData map[datatable.TransactionDataTableColumn]string, rowDataValid bool, err error) {
|
||||||
if dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] &&
|
if dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] &&
|
||||||
dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE] &&
|
dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE] &&
|
||||||
dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] {
|
dataRow.GetData(wechatPayTransactionTypeColumnName) != wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] {
|
||||||
@@ -44,15 +45,15 @@ func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models
|
|||||||
|
|
||||||
data := make(map[datatable.TransactionDataTableColumn]string, len(wechatPayTransactionSupportedColumns))
|
data := make(map[datatable.TransactionDataTableColumn]string, len(wechatPayTransactionSupportedColumns))
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionTimeColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionTimeColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = dataRow.GetData(wechatPayTransactionTimeColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = dataRow.GetData(wechatPayTransactionTimeColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionCategoryColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionCategoryColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = dataRow.GetData(wechatPayTransactionCategoryColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = dataRow.GetData(wechatPayTransactionCategoryColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionAmountColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionAmountColumnName) {
|
||||||
amount, success := utils.ParseFirstConsecutiveNumber(dataRow.GetData(wechatPayTransactionAmountColumnName))
|
amount, success := utils.ParseFirstConsecutiveNumber(dataRow.GetData(wechatPayTransactionAmountColumnName))
|
||||||
|
|
||||||
if !success {
|
if !success {
|
||||||
@@ -63,9 +64,9 @@ func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models
|
|||||||
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = amount
|
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = amount
|
||||||
}
|
}
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionDescriptionColumnName) && dataRow.GetData(wechatPayTransactionDescriptionColumnName) != "" && dataRow.GetData(wechatPayTransactionDescriptionColumnName) != "/" {
|
if p.hasOriginalColumn(wechatPayTransactionDescriptionColumnName) && dataRow.GetData(wechatPayTransactionDescriptionColumnName) != "" && dataRow.GetData(wechatPayTransactionDescriptionColumnName) != "/" {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(wechatPayTransactionDescriptionColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(wechatPayTransactionDescriptionColumnName)
|
||||||
} else if dataTable.HasOriginalColumn(wechatPayTransactionProductNameColumnName) && dataRow.GetData(wechatPayTransactionProductNameColumnName) != "" && dataRow.GetData(wechatPayTransactionProductNameColumnName) != "/" {
|
} else if p.hasOriginalColumn(wechatPayTransactionProductNameColumnName) && dataRow.GetData(wechatPayTransactionProductNameColumnName) != "" && dataRow.GetData(wechatPayTransactionProductNameColumnName) != "/" {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(wechatPayTransactionProductNameColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = dataRow.GetData(wechatPayTransactionProductNameColumnName)
|
||||||
} else {
|
} else {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = ""
|
data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = ""
|
||||||
@@ -73,13 +74,13 @@ func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models
|
|||||||
|
|
||||||
relatedAccountName := ""
|
relatedAccountName := ""
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionRelatedAccountColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionRelatedAccountColumnName) {
|
||||||
relatedAccountName = dataRow.GetData(wechatPayTransactionRelatedAccountColumnName)
|
relatedAccountName = dataRow.GetData(wechatPayTransactionRelatedAccountColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
statusName := ""
|
statusName := ""
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionStatusColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionStatusColumnName) {
|
||||||
statusName = dataRow.GetData(wechatPayTransactionStatusColumnName)
|
statusName = dataRow.GetData(wechatPayTransactionStatusColumnName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models
|
|||||||
|
|
||||||
localeTextItems := locales.GetLocaleTextItems(locale)
|
localeTextItems := locales.GetLocaleTextItems(locale)
|
||||||
|
|
||||||
if dataTable.HasOriginalColumn(wechatPayTransactionTypeColumnName) {
|
if p.hasOriginalColumn(wechatPayTransactionTypeColumnName) {
|
||||||
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = dataRow.GetData(wechatPayTransactionTypeColumnName)
|
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = dataRow.GetData(wechatPayTransactionTypeColumnName)
|
||||||
|
|
||||||
if dataRow.GetData(wechatPayTransactionTypeColumnName) == wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] {
|
if dataRow.GetData(wechatPayTransactionTypeColumnName) == wechatPayTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] {
|
||||||
@@ -132,7 +133,20 @@ func (t *weChatPayTransactionDataRowParser) Parse(ctx core.Context, user *models
|
|||||||
return data, true, nil
|
return data, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createWeChatPayTransactionDataRowParser returns wechat pay transaction data row parser
|
func (p *weChatPayTransactionDataRowParser) hasOriginalColumn(columnName string) bool {
|
||||||
func createWeChatPayTransactionDataRowParser() datatable.CommonTransactionDataRowParser {
|
_, exists := p.existedOriginalDataColumns[columnName]
|
||||||
return &weChatPayTransactionDataRowParser{}
|
return exists
|
||||||
|
}
|
||||||
|
|
||||||
|
// createWeChatPayTransactionDataRowParser returns wechat pay transaction data row parser
|
||||||
|
func createWeChatPayTransactionDataRowParser(headerColumnNames []string) datatable.CommonTransactionDataRowParser {
|
||||||
|
existedOriginalDataColumns := make(map[string]bool, len(headerColumnNames))
|
||||||
|
|
||||||
|
for i := 0; i < len(headerColumnNames); i++ {
|
||||||
|
existedOriginalDataColumns[headerColumnNames[i]] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return &weChatPayTransactionDataRowParser{
|
||||||
|
existedOriginalDataColumns: existedOriginalDataColumns,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user