mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-14 06:57:35 +08:00
support custom script to process delimiter-separated values (data) file / data
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
package _default
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/mayswind/ezbookkeeping/pkg/converters/converter"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/converters/datatable"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/core"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/models"
|
||||
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
||||
)
|
||||
|
||||
var allJsonDataSupportedColumns = []datatable.TransactionDataTableColumn{
|
||||
datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME,
|
||||
datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIMEZONE,
|
||||
datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE,
|
||||
datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY,
|
||||
datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME,
|
||||
datatable.TRANSACTION_DATA_TABLE_AMOUNT,
|
||||
datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME,
|
||||
datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT,
|
||||
datatable.TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION,
|
||||
datatable.TRANSACTION_DATA_TABLE_TAGS,
|
||||
datatable.TRANSACTION_DATA_TABLE_DESCRIPTION,
|
||||
}
|
||||
|
||||
// defaultTransactionDataJsonImporter defines the structure of ezbookkeeping default json importer for transaction data
|
||||
type defaultTransactionDataJsonImporter struct{}
|
||||
|
||||
// Initialize an ezbookkeeping default transaction data json file importer singleton instance
|
||||
var (
|
||||
DefaultTransactionDataJsonFileImporter = &defaultTransactionDataJsonImporter{}
|
||||
)
|
||||
|
||||
// ParseImportedData returns the imported data by parsing the transaction json data
|
||||
func (c *defaultTransactionDataJsonImporter) 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) {
|
||||
var importRequest models.ImportTransactionRequest
|
||||
|
||||
if err := json.Unmarshal(data, &importRequest); err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, errs.ErrInvalidJSONFile
|
||||
}
|
||||
|
||||
transactionDataTable, err := c.createNewDefaultTransactionDataTable(importRequest)
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(
|
||||
ezbookkeepingTransactionTypeNameMapping,
|
||||
ezbookkeepingGeoLocationSeparator,
|
||||
ezbookkeepingGeoLocationOrder,
|
||||
ezbookkeepingTagSeparator,
|
||||
)
|
||||
|
||||
return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap)
|
||||
}
|
||||
|
||||
func (c *defaultTransactionDataJsonImporter) createNewDefaultTransactionDataTable(importRequest models.ImportTransactionRequest) (datatable.TransactionDataTable, error) {
|
||||
transactionDataTable := datatable.CreateNewWritableTransactionDataTable(allJsonDataSupportedColumns)
|
||||
|
||||
if importRequest.Transactions == nil || len(importRequest.Transactions) < 1 {
|
||||
return nil, errs.ErrNotFoundTransactionDataInFile
|
||||
}
|
||||
|
||||
for i := 0; i < len(importRequest.Transactions); i++ {
|
||||
transaction := importRequest.Transactions[i]
|
||||
|
||||
utcOffset, err := utils.StringToInt(transaction.UtcOffset)
|
||||
|
||||
if err != nil {
|
||||
return nil, errs.ErrTransactionTimeZoneInvalid
|
||||
}
|
||||
|
||||
timezone := time.FixedZone("Transaction Timezone", utcOffset*60)
|
||||
|
||||
row := make(map[datatable.TransactionDataTableColumn]string, len(allJsonDataSupportedColumns))
|
||||
row[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = transaction.Time
|
||||
row[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIMEZONE] = utils.FormatTimezoneOffset(timezone)
|
||||
row[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = transaction.Type
|
||||
row[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = transaction.CategoryName
|
||||
row[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = transaction.SourceAccountName
|
||||
row[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = transaction.SourceAmount
|
||||
row[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = transaction.DestinationAccountName
|
||||
row[datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT] = transaction.DestinationAmount
|
||||
row[datatable.TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION] = transaction.GeoLocation
|
||||
row[datatable.TRANSACTION_DATA_TABLE_TAGS] = transaction.TagNames
|
||||
row[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = transaction.Comment
|
||||
|
||||
transactionDataTable.Add(row)
|
||||
}
|
||||
|
||||
return transactionDataTable, nil
|
||||
}
|
||||
@@ -38,6 +38,8 @@ func GetTransactionDataImporter(fileType string) (converter.TransactionDataImpor
|
||||
return _default.DefaultTransactionDataCSVFileConverter, nil
|
||||
} else if fileType == "ezbookkeeping_tsv" {
|
||||
return _default.DefaultTransactionDataTSVFileConverter, nil
|
||||
} else if fileType == "ezbookkeeping_json" {
|
||||
return _default.DefaultTransactionDataJsonFileImporter, nil
|
||||
} else if fileType == "ofx" {
|
||||
return ofx.OFXTransactionDataImporter, nil
|
||||
} else if fileType == "qfx" {
|
||||
|
||||
@@ -30,4 +30,5 @@ var (
|
||||
ErrInvalidAmountExpression = NewNormalError(NormalSubcategoryConverter, 23, http.StatusBadRequest, "invalid amount expression")
|
||||
ErrInvalidXmlFile = NewNormalError(NormalSubcategoryConverter, 24, http.StatusBadRequest, "invalid xml file")
|
||||
ErrInvalidMT940File = NewNormalError(NormalSubcategoryConverter, 25, http.StatusBadRequest, "invalid mt940 file")
|
||||
ErrInvalidJSONFile = NewNormalError(NormalSubcategoryConverter, 26, http.StatusBadRequest, "invalid json file")
|
||||
)
|
||||
|
||||
@@ -14,6 +14,26 @@ type ImportTransaction struct {
|
||||
OriginalTagNames []string
|
||||
}
|
||||
|
||||
// ImportTransactionRequest represents all parameters of the imported transaction data
|
||||
type ImportTransactionRequest struct {
|
||||
Transactions []*ImportTransactionRequestItem
|
||||
}
|
||||
|
||||
// ImportTransactionRequestItem represents a single item of the imported transaction data
|
||||
type ImportTransactionRequestItem struct {
|
||||
Time string `json:"time"`
|
||||
UtcOffset string `json:"utcOffset"`
|
||||
Type string `json:"type"`
|
||||
CategoryName string `json:"categoryName,omitempty"`
|
||||
SourceAccountName string `json:"sourceAccountName,omitempty"`
|
||||
DestinationAccountName string `json:"destinationAccountName,omitempty"`
|
||||
SourceAmount string `json:"sourceAmount"`
|
||||
DestinationAmount string `json:"destinationAmount,omitempty"`
|
||||
GeoLocation string `json:"geoLocation,omitempty"`
|
||||
TagNames string `json:"tagNames,omitempty"`
|
||||
Comment string `json:"comment,omitempty"`
|
||||
}
|
||||
|
||||
// ImportTransactionResponse represents a view-object of the imported transaction data
|
||||
type ImportTransactionResponse struct {
|
||||
Type TransactionType `json:"type"`
|
||||
|
||||
Reference in New Issue
Block a user