189 lines
6.0 KiB
Go
189 lines
6.0 KiB
Go
package datatable
|
|
|
|
import (
|
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
|
)
|
|
|
|
// ImportedTransactionDataTable defines the structure of imported transaction data table
|
|
type ImportedTransactionDataTable struct {
|
|
innerDataTable ImportedDataTable
|
|
dataColumnMapping map[TransactionDataTableColumn]string
|
|
dataColumnIndexes map[TransactionDataTableColumn]int
|
|
rowParser TransactionDataRowParser
|
|
addedColumns map[TransactionDataTableColumn]bool
|
|
}
|
|
|
|
// ImportedTransactionDataRow defines the structure of imported transaction data row
|
|
type ImportedTransactionDataRow struct {
|
|
transactionDataTable *ImportedTransactionDataTable
|
|
rowData map[TransactionDataTableColumn]string
|
|
rowDataValid bool
|
|
}
|
|
|
|
// ImportedTransactionDataRowIterator defines the structure of imported transaction data row iterator
|
|
type ImportedTransactionDataRowIterator struct {
|
|
transactionDataTable *ImportedTransactionDataTable
|
|
innerIterator ImportedDataRowIterator
|
|
}
|
|
|
|
// HasColumn returns whether the data table has specified column
|
|
func (t *ImportedTransactionDataTable) HasColumn(column TransactionDataTableColumn) bool {
|
|
index, exists := t.dataColumnIndexes[column]
|
|
|
|
if exists && index >= 0 {
|
|
return exists
|
|
}
|
|
|
|
if t.addedColumns != nil {
|
|
_, exists = t.addedColumns[column]
|
|
|
|
if exists {
|
|
return exists
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// TransactionRowCount returns the total count of transaction data row
|
|
func (t *ImportedTransactionDataTable) TransactionRowCount() int {
|
|
return t.innerDataTable.DataRowCount()
|
|
}
|
|
|
|
// TransactionRowIterator returns the iterator of transaction data row
|
|
func (t *ImportedTransactionDataTable) TransactionRowIterator() TransactionDataRowIterator {
|
|
return &ImportedTransactionDataRowIterator{
|
|
transactionDataTable: t,
|
|
innerIterator: t.innerDataTable.DataRowIterator(),
|
|
}
|
|
}
|
|
|
|
// IsValid returns whether this row is valid data for importing
|
|
func (r *ImportedTransactionDataRow) IsValid() bool {
|
|
return r.rowDataValid
|
|
}
|
|
|
|
// GetData returns the data in the specified column type
|
|
func (r *ImportedTransactionDataRow) GetData(column TransactionDataTableColumn) string {
|
|
if !r.rowDataValid {
|
|
return ""
|
|
}
|
|
|
|
_, exists := r.transactionDataTable.dataColumnIndexes[column]
|
|
|
|
if exists {
|
|
return r.rowData[column]
|
|
}
|
|
|
|
if r.transactionDataTable.addedColumns != nil {
|
|
_, exists = r.transactionDataTable.addedColumns[column]
|
|
|
|
if exists {
|
|
return r.rowData[column]
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// HasNext returns whether the iterator does not reach the end
|
|
func (t *ImportedTransactionDataRowIterator) HasNext() bool {
|
|
return t.innerIterator.HasNext()
|
|
}
|
|
|
|
// Next returns the next transaction data row
|
|
func (t *ImportedTransactionDataRowIterator) Next(ctx core.Context, user *models.User) (daraRow TransactionDataRow, err error) {
|
|
importedRow := t.innerIterator.Next()
|
|
|
|
if importedRow == nil {
|
|
return nil, nil
|
|
}
|
|
|
|
if importedRow.ColumnCount() == 1 && importedRow.GetData(0) == "" {
|
|
return &ImportedTransactionDataRow{
|
|
transactionDataTable: t.transactionDataTable,
|
|
rowData: nil,
|
|
rowDataValid: false,
|
|
}, nil
|
|
}
|
|
|
|
if importedRow.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))
|
|
return nil, errs.ErrFewerFieldsInDataRowThanInHeaderRow
|
|
}
|
|
|
|
rowData := make(map[TransactionDataTableColumn]string, len(t.transactionDataTable.dataColumnIndexes))
|
|
rowDataValid := true
|
|
|
|
for column, columnIndex := range t.transactionDataTable.dataColumnIndexes {
|
|
if columnIndex < 0 || columnIndex >= importedRow.ColumnCount() {
|
|
continue
|
|
}
|
|
|
|
value := importedRow.GetData(columnIndex)
|
|
rowData[column] = value
|
|
}
|
|
|
|
if t.transactionDataTable.rowParser != nil {
|
|
rowData, rowDataValid, err = t.transactionDataTable.rowParser.Parse(rowData)
|
|
|
|
if err != nil {
|
|
log.Errorf(ctx, "[imported_transaction_data_table.Next] cannot parse data row, because %s", err.Error())
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return &ImportedTransactionDataRow{
|
|
transactionDataTable: t.transactionDataTable,
|
|
rowData: rowData,
|
|
rowDataValid: rowDataValid,
|
|
}, nil
|
|
}
|
|
|
|
// CreateNewImportedTransactionDataTable returns transaction data table from imported data table
|
|
func CreateNewImportedTransactionDataTable(dataTable ImportedDataTable, dataColumnMapping map[TransactionDataTableColumn]string) *ImportedTransactionDataTable {
|
|
return CreateNewImportedTransactionDataTableWithRowParser(dataTable, dataColumnMapping, nil)
|
|
}
|
|
|
|
// CreateNewImportedTransactionDataTableWithRowParser returns transaction data table from imported data table
|
|
func CreateNewImportedTransactionDataTableWithRowParser(dataTable ImportedDataTable, dataColumnMapping map[TransactionDataTableColumn]string, rowParser TransactionDataRowParser) *ImportedTransactionDataTable {
|
|
headerLineItems := dataTable.HeaderColumnNames()
|
|
headerItemMap := make(map[string]int, len(headerLineItems))
|
|
|
|
for i := 0; i < len(headerLineItems); i++ {
|
|
headerItemMap[headerLineItems[i]] = i
|
|
}
|
|
|
|
dataColumnIndexes := make(map[TransactionDataTableColumn]int, len(headerLineItems))
|
|
|
|
for column, columnName := range dataColumnMapping {
|
|
columnIndex, exists := headerItemMap[columnName]
|
|
|
|
if exists {
|
|
dataColumnIndexes[column] = columnIndex
|
|
}
|
|
}
|
|
|
|
var addedColumns map[TransactionDataTableColumn]bool
|
|
|
|
if rowParser != nil {
|
|
addedColumnsByParser := rowParser.GetAddedColumns()
|
|
addedColumns = make(map[TransactionDataTableColumn]bool, len(addedColumnsByParser))
|
|
|
|
for i := 0; i < len(addedColumnsByParser); i++ {
|
|
addedColumns[addedColumnsByParser[i]] = true
|
|
}
|
|
}
|
|
|
|
return &ImportedTransactionDataTable{
|
|
innerDataTable: dataTable,
|
|
dataColumnMapping: dataColumnMapping,
|
|
dataColumnIndexes: dataColumnIndexes,
|
|
rowParser: rowParser,
|
|
addedColumns: addedColumns,
|
|
}
|
|
}
|