diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index e9477780..4aff8f4f 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -1405,6 +1405,15 @@ func (a *TransactionsApi) TransactionParseImportFileHandler(c *core.WebContext) fileType := fileTypes[0] + textualOptions := form.Value["options"] + textualOption := "" + + if len(textualOptions) > 0 { + textualOption = textualOptions[0] + } + + additionalOptions := converter.ParseImporterOptions(textualOption) + var dataImporter converter.TransactionDataImporter if converters.IsCustomDelimiterSeparatedValuesFileType(fileType) { @@ -1581,7 +1590,7 @@ func (a *TransactionsApi) TransactionParseImportFileHandler(c *core.WebContext) tagMap := a.transactionTags.GetVisibleTagNameMapByList(tags) - parsedTransactions, _, _, _, _, _, err := dataImporter.ParseImportedData(c, user, fileData, utcOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + parsedTransactions, _, _, _, _, _, err := dataImporter.ParseImportedData(c, user, fileData, utcOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) if err != nil { log.Errorf(c, "[transactions.TransactionParseImportFileHandler] failed to parse imported data for user \"uid:%d\", because %s", user.Uid, err.Error()) diff --git a/pkg/cli/user_data.go b/pkg/cli/user_data.go index cd580e4f..c53488cc 100644 --- a/pkg/cli/user_data.go +++ b/pkg/cli/user_data.go @@ -5,6 +5,7 @@ import ( "time" "github.com/mayswind/ezbookkeeping/pkg/converters" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/log" @@ -818,7 +819,7 @@ func (l *UserDataCli) ImportTransaction(c *core.CliContext, username string, fil return err } - parsedTransactions, newAccounts, newSubExpenseCategories, newSubIncomeCategories, newSubTransferCategories, newTags, err := dataImporter.ParseImportedData(c, user, data, utils.GetTimezoneOffsetMinutes(time.Local), accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + parsedTransactions, newAccounts, newSubExpenseCategories, newSubIncomeCategories, newSubTransferCategories, newTags, err := dataImporter.ParseImportedData(c, user, data, utils.GetTimezoneOffsetMinutes(time.Local), converter.DefaultImporterOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) if err != nil { log.CliErrorf(c, "[user_data.ImportTransaction] failed to parse imported data for \"%s\", because %s", username, err.Error()) diff --git a/pkg/converters/alipay/alipay_transaction_data_csv_file_importer.go b/pkg/converters/alipay/alipay_transaction_data_csv_file_importer.go index 1d1ab3f1..508e2ad0 100644 --- a/pkg/converters/alipay/alipay_transaction_data_csv_file_importer.go +++ b/pkg/converters/alipay/alipay_transaction_data_csv_file_importer.go @@ -53,7 +53,7 @@ type alipayTransactionDataCsvFileImporter struct { } // ParseImportedData returns the imported data by parsing the alipay transaction csv data -func (c *alipayTransactionDataCsvFileImporter) 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 *alipayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { enc := simplifiedchinese.GB18030 reader := transform.NewReader(bytes.NewReader(data), enc.NewDecoder()) @@ -83,5 +83,5 @@ func (c *alipayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Contex transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, alipayTransactionSupportedColumns, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(alipayTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/alipay/alipay_transaction_data_csv_file_importer_test.go b/pkg/converters/alipay/alipay_transaction_data_csv_file_importer_test.go index a9b0cb8f..65c6bd37 100644 --- a/pkg/converters/alipay/alipay_transaction_data_csv_file_importer_test.go +++ b/pkg/converters/alipay/alipay_transaction_data_csv_file_importer_test.go @@ -8,6 +8,7 @@ import ( "golang.org/x/text/encoding/simplifiedchinese" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -15,7 +16,7 @@ import ( ) func TestAlipayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -35,7 +36,7 @@ func TestAlipayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 4, len(allNewTransactions)) @@ -94,7 +95,7 @@ func TestAlipayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { } func TestAlipayCsvFileImporterParseImportedData_ParseRefundTransaction(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -112,7 +113,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseRefundTransaction(t *testin "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(1234567890), allNewTransactions[0].Uid) @@ -132,7 +133,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseRefundTransaction(t *testin "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(1234567890), allNewTransactions[0].Uid) @@ -144,7 +145,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseRefundTransaction(t *testin } func TestAlipayCsvFileImporterParseImportedData_ParseInvestmentRefundTransaction(t *testing.T) { - converter := AlipayAppTransactionDataCsvFileImporter + importer := AlipayAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -163,7 +164,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseInvestmentRefundTransaction "2024-09-01 01:00:00,Test Account2,xxx-买入,不计收支,0.01,Test Account,退款成功,\n" + "2024-09-01 02:00:00,Test Account2,xxx-买入退款,不计收支,0.01,Test Account,退款成功,\n") - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 2, len(allNewTransactions)) @@ -184,7 +185,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseInvestmentRefundTransaction } func TestAlipayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -201,7 +202,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) data2, err := simplifiedchinese.GB18030.NewEncoder().String("支付宝交易记录明细查询\n" + @@ -213,12 +214,12 @@ func TestAlipayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestAlipayCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -235,12 +236,12 @@ func TestAlipayCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -258,7 +259,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -274,7 +275,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -290,7 +291,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -307,7 +308,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -324,7 +325,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data5), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data5), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -341,7 +342,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data6), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data6), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -358,7 +359,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data7), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data7), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -367,7 +368,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { } func TestAlipayCsvFileImporterParseImportedData_ParseCategory(t *testing.T) { - converter := AlipayAppTransactionDataCsvFileImporter + importer := AlipayAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -388,7 +389,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseCategory(t *testing.T) { "2024-09-01 23:59:59,Test Category3,充值-普通充值,不计收支,0.05,交易成功,\n") assert.Nil(t, err) - allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 3, len(allNewTransactions)) @@ -407,7 +408,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseCategory(t *testing.T) { } func TestAlipayCsvFileImporterParseImportedData_ParseRelatedAccount(t *testing.T) { - converter := AlipayAppTransactionDataCsvFileImporter + importer := AlipayAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -434,7 +435,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseRelatedAccount(t *testing.T "2024-09-01 08:00:00,Test Account4,信用卡还款,不计收支,0.01,Test Account,还款成功,repayment,\n") assert.Nil(t, err) - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 9, len(allNewTransactions)) @@ -529,7 +530,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseRelatedAccount(t *testing.T } func TestAlipayCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -546,7 +547,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -561,7 +562,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -569,7 +570,7 @@ func TestAlipayCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { } func TestAlipayCsvFileImporterParseImportedData_SkipClosedIncomeOrTransferTransaction(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -586,12 +587,12 @@ func TestAlipayCsvFileImporterParseImportedData_SkipClosedIncomeOrTransferTransa "2024-09-01 23:59:59 ,充值-普通充值 ,0.05 ,不计收支 ,交易关闭 ,\n" + "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestAlipayCsvFileImporterParseImportedData_SkipUnknownProductTransferTransaction(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -607,12 +608,12 @@ func TestAlipayCsvFileImporterParseImportedData_SkipUnknownProductTransferTransa "2024-09-01 23:59:59 ,xxxx ,0.05 ,不计收支 ,交易成功 ,\n" + "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestAlipayCsvFileImporterParseImportedData_SkipUnknownStatusTransaction(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -628,12 +629,12 @@ func TestAlipayCsvFileImporterParseImportedData_SkipUnknownStatusTransaction(t * "2024-09-01 01:23:45 ,xxxx ,0.12 ,收入 ,xxxx ,\n" + "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestAlipayCsvFileImporterParseImportedData_MissingFileHeader(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -647,15 +648,15 @@ func TestAlipayCsvFileImporterParseImportedData_MissingFileHeader(t *testing.T) "------------------------------------------------------------------------------------\n") assert.Nil(t, err) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) } func TestAlipayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -671,7 +672,7 @@ func TestAlipayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing "金额(元),收/支 ,交易状态 ,\n" + "0.12 ,收入 ,交易成功 ,\n" + "------------------------------------------------------------------------------------\n") - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column @@ -682,7 +683,7 @@ func TestAlipayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing "交易创建时间 ,收/支 ,交易状态 ,\n" + "2024-09-01 12:34:56 ,收入 ,交易成功 ,\n" + "------------------------------------------------------------------------------------\n") - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Status Column @@ -693,7 +694,7 @@ func TestAlipayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing "交易创建时间 ,金额(元),收/支 ,\n" + "2024-09-01 12:34:56 ,0.12 ,收入 ,\n" + "------------------------------------------------------------------------------------\n") - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column @@ -704,12 +705,12 @@ func TestAlipayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing "交易创建时间 ,金额(元),交易状态 ,\n" + "2024-09-01 12:34:56 ,0.12 ,交易成功 ,\n" + "------------------------------------------------------------------------------------\n") - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } func TestAlipayCsvFileImporterParseImportedData_NoTransactionData(t *testing.T) { - converter := AlipayWebTransactionDataCsvFileImporter + importer := AlipayWebTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -723,6 +724,6 @@ func TestAlipayCsvFileImporterParseImportedData_NoTransactionData(t *testing.T) "---------------------------------交易记录明细列表------------------------------------\n" + "交易创建时间 ,金额(元),收/支 ,交易状态 ,\n" + "------------------------------------------------------------------------------------\n") - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } diff --git a/pkg/converters/beancount/beancount_transaction_data_file_importer.go b/pkg/converters/beancount/beancount_transaction_data_file_importer.go index 71e67149..5b7b7536 100644 --- a/pkg/converters/beancount/beancount_transaction_data_file_importer.go +++ b/pkg/converters/beancount/beancount_transaction_data_file_importer.go @@ -24,7 +24,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the Beancount transaction data -func (c *beancountTransactionDataImporter) 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 *beancountTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { beancountDataReader, err := createNewBeancountDataReader(ctx, data) if err != nil { @@ -45,5 +45,5 @@ func (c *beancountTransactionDataImporter) ParseImportedData(ctx core.Context, u dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(beancountTransactionTypeNameMapping, "", "", BEANCOUNT_TRANSACTION_TAG_SEPARATOR) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/beancount/beancount_transaction_data_file_importer_test.go b/pkg/converters/beancount/beancount_transaction_data_file_importer_test.go index d145347d..11e14579 100644 --- a/pkg/converters/beancount/beancount_transaction_data_file_importer_test.go +++ b/pkg/converters/beancount/beancount_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestBeancountTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData(t *testi DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 *\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ " Assets:TestAccount 123.45 CNY\n"+ @@ -32,7 +33,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData(t *testi " Expenses:TestCategory2 1.00 CNY\n"+ "2024-09-04 *\n"+ " Assets:TestAccount -0.05 CNY\n"+ - " Assets:TestAccount2 0.05 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount2 0.05 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -91,7 +92,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData(t *testi } func TestBeancountTransactionDataFileParseImportedData_MinimumValidData2(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -99,7 +100,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData2(t *test DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 *\n"+ " Assets:TestAccount 123.45 CNY\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ @@ -111,7 +112,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData2(t *test " Assets:TestAccount -1.00 CNY\n"+ "2024-09-04 *\n"+ " Assets:TestAccount2 0.05 CNY\n"+ - " Assets:TestAccount -0.05 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount -0.05 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -170,7 +171,7 @@ func TestBeancountTransactionDataFileParseImportedData_MinimumValidData2(t *test } func TestBeancountTransactionDataFileParseImportedData_ParseInvalidTime(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -178,15 +179,15 @@ func TestBeancountTransactionDataFileParseImportedData_ParseInvalidTime(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024/09/01 *\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ - " Assets:TestAccount 123.45 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount 123.45 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestBeancountTransactionDataFileParseImportedData_ParseValidCurrency(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -194,10 +195,10 @@ func TestBeancountTransactionDataFileParseImportedData_ParseValidCurrency(t *tes DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Assets:TestAccount -0.12 USD\n"+ - " Assets:TestAccount2 0.84 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount2 0.84 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -222,7 +223,7 @@ func TestBeancountTransactionDataFileParseImportedData_ParseValidCurrency(t *tes } func TestBeancountTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -230,21 +231,21 @@ func TestBeancountTransactionDataFileParseImportedData_ParseInvalidAmount(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 *\n"+ " Equity:Opening-Balances -abc CNY\n"+ - " Assets:TestAccount abc CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount abc CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 *\n"+ " Equity:Opening-Balances -1/0 CNY\n"+ - " Assets:TestAccount 1/0 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount 1/0 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestBeancountTransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -252,13 +253,13 @@ func TestBeancountTransactionDataFileParseImportedData_ParseDescription(t *testi DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 * \"foo bar\t#test\n\"\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ " Assets:TestAccount 123.45 CNY\n"+ "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Income:TestCategory -0.12 CNY\n"+ - " Assets:TestAccount 0.12 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount 0.12 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -269,7 +270,7 @@ func TestBeancountTransactionDataFileParseImportedData_ParseDescription(t *testi } func TestBeancountTransactionDataFileParseImportedData_InvalidTransaction(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -277,33 +278,33 @@ func TestBeancountTransactionDataFileParseImportedData_InvalidTransaction(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Assets:TestAccount 0.11 CNY\n"+ - " Assets:TestAccount2 0.11 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount2 0.11 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidBeancountFile.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Expenses:TestCategory -0.11 CNY\n"+ - " Expenses:TestCategory2 0.11 CNY\n"), 0, nil, nil, nil, nil, nil) + " Expenses:TestCategory2 0.11 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrThereAreNotSupportedTransactionType.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Income:TestCategory -0.11 CNY\n"+ - " Income:TestCategory2 0.11 CNY\n"), 0, nil, nil, nil, nil, nil) + " Income:TestCategory2 0.11 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrThereAreNotSupportedTransactionType.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Equity:TestCategory -0.11 CNY\n"+ - " Equity:TestCategory2 0.11 CNY\n"), 0, nil, nil, nil, nil, nil) + " Equity:TestCategory2 0.11 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrThereAreNotSupportedTransactionType.Message) } func TestBeancountTransactionDataFileParseImportedData_NotSupportedToParseSplitTransaction(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -311,16 +312,16 @@ func TestBeancountTransactionDataFileParseImportedData_NotSupportedToParseSplitT DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-02 * \"Payee Name\" \"Hello\nWorld\"\n"+ " Assets:TestAccount -0.23 CNY\n"+ " Assets:TestAccount2 0.11 CNY\n"+ - " Assets:TestAccount3 0.12 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount3 0.12 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotSupportedSplitTransactions.Message) } func TestBeancountTransactionDataFileParseImportedData_MissingTransactionRequiredData(t *testing.T) { - converter := BeancountTransactionDataImporter + importer := BeancountTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -329,30 +330,30 @@ func TestBeancountTransactionDataFileParseImportedData_MissingTransactionRequire } // Missing Transaction Time - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "* \"narration\"\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ - " Assets:TestAccount 123.45 CNY\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount 123.45 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) // Missing Account Name - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 * \"narration\"\n"+ " Equity:Opening-Balances -123.45 CNY\n"+ - " 123.45 CNY\n"), 0, nil, nil, nil, nil, nil) + " 123.45 CNY\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidBeancountFile.Message) // Missing Amount - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 * \"narration\"\n"+ " Equity:Opening-Balances\n"+ - " Assets:TestAccount\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidBeancountFile.Message) // Missing Commodity - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 * \"narration\"\n"+ " Equity:Opening-Balances -123.45\n"+ - " Assets:TestAccount 123.45\n"), 0, nil, nil, nil, nil, nil) + " Assets:TestAccount 123.45\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidBeancountFile.Message) } diff --git a/pkg/converters/camt/camt_transaction_data_file_importer.go b/pkg/converters/camt/camt_transaction_data_file_importer.go index ec4c1f27..4299c06b 100644 --- a/pkg/converters/camt/camt_transaction_data_file_importer.go +++ b/pkg/converters/camt/camt_transaction_data_file_importer.go @@ -23,7 +23,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the camt.053 file transaction data -func (c *camt053TransactionDataImporter) 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 *camt053TransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { camt053DataReader, err := createNewCamt053FileReader(data) if err != nil { @@ -44,5 +44,5 @@ func (c *camt053TransactionDataImporter) ParseImportedData(ctx core.Context, use dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(camtTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/camt/camt_transaction_data_file_importer_test.go b/pkg/converters/camt/camt_transaction_data_file_importer_test.go index 4ac38c77..78ee47ca 100644 --- a/pkg/converters/camt/camt_transaction_data_file_importer_test.go +++ b/pkg/converters/camt/camt_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestCamt053TransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestCamt053TransactionDataFileParseImportedData_MinimumValidData(t *testing DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( ` @@ -64,7 +65,7 @@ func TestCamt053TransactionDataFileParseImportedData_MinimumValidData(t *testing - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -115,7 +116,7 @@ func TestCamt053TransactionDataFileParseImportedData_MinimumValidData(t *testing } func TestCamt053TransactionDataFileParseImportedData_ParseValidTransactionTime(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -123,7 +124,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseValidTransactionTime(t DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -157,7 +158,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseValidTransactionTime(t - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 3, len(allNewTransactions)) @@ -168,7 +169,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseValidTransactionTime(t } func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -176,7 +177,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -196,10 +197,10 @@ func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -219,10 +220,10 @@ func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -242,10 +243,10 @@ func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -265,12 +266,12 @@ func TestCamt053TransactionDataFileParseImportedData_ParseInvalidTransactionTime - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmountAndCurrency(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -278,7 +279,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -314,7 +315,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 2, len(allNewTransactions)) @@ -323,7 +324,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount assert.Equal(t, "USD", allNewTransactions[1].OriginalSourceAccountCurrency) assert.Equal(t, int64(10023), allNewTransactions[1].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -365,7 +366,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 2, len(allNewTransactions)) @@ -374,7 +375,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount assert.Equal(t, "USD", allNewTransactions[1].OriginalSourceAccountCurrency) assert.Equal(t, int64(9999), allNewTransactions[1].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -403,14 +404,14 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "USD", allNewTransactions[0].OriginalSourceAccountCurrency) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -430,7 +431,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -439,7 +440,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionValidAmount } func TestCamt053TransactionDataFileParseImportedData_ParseTransactionInvalidAmountAndCurrency(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -447,7 +448,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionInvalidAmou DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -467,10 +468,10 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionInvalidAmou - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -498,10 +499,10 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionInvalidAmou - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -529,12 +530,12 @@ func TestCamt053TransactionDataFileParseImportedData_ParseTransactionInvalidAmou - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -542,7 +543,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -572,13 +573,13 @@ func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "Test Transaction", allNewTransactions[0].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -607,13 +608,13 @@ func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "Test Line 1\nTest Line 2", allNewTransactions[0].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -634,7 +635,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -642,7 +643,7 @@ func TestCamt053TransactionDataFileParseImportedData_ParseDescription(t *testing } func TestCamt053TransactionDataFileParseImportedData_MissingAccountNode(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -650,7 +651,7 @@ func TestCamt053TransactionDataFileParseImportedData_MissingAccountNode(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -664,12 +665,12 @@ func TestCamt053TransactionDataFileParseImportedData_MissingAccountNode(t *testi - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingAccountData.Message) } func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredNode(t *testing.T) { - converter := Camt053TransactionDataImporter + importer := Camt053TransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -677,7 +678,7 @@ func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredN DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( ` @@ -694,10 +695,10 @@ func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredN - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingTransactionTime.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -716,10 +717,10 @@ func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredN - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -738,10 +739,10 @@ func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredN - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( ` @@ -760,6 +761,6 @@ func TestCamt053TransactionDataFileParseImportedData_MissingTransactionRequiredN - `), 0, nil, nil, nil, nil, nil) + `), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } diff --git a/pkg/converters/converter/data_table_transaction_data_importer.go b/pkg/converters/converter/data_table_transaction_data_importer.go index 51182d50..82305dae 100644 --- a/pkg/converters/converter/data_table_transaction_data_importer.go +++ b/pkg/converters/converter/data_table_transaction_data_importer.go @@ -29,7 +29,7 @@ type DataTableTransactionDataImporter struct { } // ParseImportedData returns the imported transaction data -func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, dataTable datatable.TransactionDataTable, 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 *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, dataTable datatable.TransactionDataTable, defaultTimezoneOffset int16, additionalOptions TransactionDataImporterOptions, 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) { if dataTable.TransactionRowCount() < 1 { log.Errorf(ctx, "[data_table_transaction_data_importer.ParseImportedData] cannot parse import data for user \"uid:%d\", because data table row count is less 1", user.Uid) return nil, nil, nil, nil, nil, nil, errs.ErrNotFoundTransactionDataInFile @@ -303,6 +303,7 @@ func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, u var tagIds []string var tagNames []string + tagNamesMap := make(map[string]bool) if dataTable.HasColumn(datatable.TRANSACTION_DATA_TABLE_TAGS) { var tagNameItems []string @@ -316,7 +317,7 @@ func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, u for i := 0; i < len(tagNameItems); i++ { tagName := tagNameItems[i] - if tagName == "" { + if tagName == "" || tagNamesMap[tagName] { continue } @@ -333,6 +334,28 @@ func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, u } tagNames = append(tagNames, tagName) + tagNamesMap[tagName] = true + } + } + + if dataTable.HasColumn(datatable.TRANSACTION_DATA_TABLE_PAYEE) && additionalOptions.IsPayeeAsTag() { + payee := dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_PAYEE) + + if payee != "" && !tagNamesMap[payee] { + tag, exists := tagMap[payee] + + if !exists { + tag = c.createNewTransactionTagModel(user.Uid, payee) + allNewTags = append(allNewTags, tag) + tagMap[payee] = tag + } + + if tag != nil { + tagIds = append(tagIds, utils.Int64ToString(tag.TagId)) + } + + tagNames = append(tagNames, payee) + tagNamesMap[payee] = true } } @@ -342,6 +365,10 @@ func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, u description = dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_DESCRIPTION) } + if description == "" && additionalOptions.IsPayeeAsDescription() && dataTable.HasColumn(datatable.TRANSACTION_DATA_TABLE_PAYEE) { + description = dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_PAYEE) + } + transaction := &models.ImportTransaction{ Transaction: &models.Transaction{ Uid: user.Uid, diff --git a/pkg/converters/converter/transaction_data_converter.go b/pkg/converters/converter/transaction_data_converter.go index 867e0401..3bf8c24d 100644 --- a/pkg/converters/converter/transaction_data_converter.go +++ b/pkg/converters/converter/transaction_data_converter.go @@ -14,7 +14,7 @@ type TransactionDataExporter interface { // TransactionDataImporter defines the structure of transaction data importer type TransactionDataImporter interface { // ParseImportedData returns the imported data - 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) + ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions TransactionDataImporterOptions, 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) } // TransactionDataConverter defines the structure of transaction data converter diff --git a/pkg/converters/converter/transaction_data_importer_options.go b/pkg/converters/converter/transaction_data_importer_options.go new file mode 100644 index 00000000..f9025e29 --- /dev/null +++ b/pkg/converters/converter/transaction_data_importer_options.go @@ -0,0 +1,118 @@ +package converter + +import "strings" + +// TransactionDataImporterOptions defines the options for transaction data importer +type TransactionDataImporterOptions struct { + payeeAsTag bool + payeeAsDescription bool + memberAsTag bool + projectAsTag bool + merchantAsTag bool +} + +// DefaultImporterOptions provides the default options for transaction data importer +var DefaultImporterOptions = TransactionDataImporterOptions{ + payeeAsTag: false, + payeeAsDescription: false, + memberAsTag: false, + projectAsTag: false, + merchantAsTag: false, +} + +// IsPayeeAsTag returns whether to import payee as tag +func (o TransactionDataImporterOptions) IsPayeeAsTag() bool { + return o.payeeAsTag +} + +// IsPayeeAsDescription returns whether to import payee as description +func (o TransactionDataImporterOptions) IsPayeeAsDescription() bool { + return o.payeeAsDescription +} + +// IsMemberAsTag returns whether to import member as tag +func (o TransactionDataImporterOptions) IsMemberAsTag() bool { + return o.memberAsTag +} + +// IsProjectAsTag returns whether to import project as tag +func (o TransactionDataImporterOptions) IsProjectAsTag() bool { + return o.projectAsTag +} + +// IsMerchantAsTag returns whether to import merchant as tag +func (o TransactionDataImporterOptions) IsMerchantAsTag() bool { + return o.merchantAsTag +} + +// WithPayeeAsTag sets the option to import payee as tag +func (o TransactionDataImporterOptions) WithPayeeAsTag() TransactionDataImporterOptions { + cloned := o.Clone() + cloned.payeeAsTag = true + return cloned +} + +// WithPayeeAsDescription sets the option to import payee as description +func (o TransactionDataImporterOptions) WithPayeeAsDescription() TransactionDataImporterOptions { + cloned := o.Clone() + cloned.payeeAsDescription = true + return cloned +} + +// WithMemberAsTag sets the option to import member as tag +func (o TransactionDataImporterOptions) WithMemberAsTag() TransactionDataImporterOptions { + cloned := o.Clone() + cloned.memberAsTag = true + return cloned +} + +// WithProjectAsTag sets the option to import project as tag +func (o TransactionDataImporterOptions) WithProjectAsTag() TransactionDataImporterOptions { + cloned := o.Clone() + cloned.projectAsTag = true + return cloned +} + +// WithMerchantAsTag sets the option to import merchant as tag +func (o TransactionDataImporterOptions) WithMerchantAsTag() TransactionDataImporterOptions { + cloned := o.Clone() + cloned.merchantAsTag = true + return cloned +} + +// Clone creates a copy of the options instance +func (o TransactionDataImporterOptions) Clone() TransactionDataImporterOptions { + return TransactionDataImporterOptions{ + payeeAsTag: o.payeeAsTag, + payeeAsDescription: o.payeeAsDescription, + memberAsTag: o.memberAsTag, + projectAsTag: o.projectAsTag, + merchantAsTag: o.merchantAsTag, + } +} + +// ParseImporterOptions parses the textual options to the instance +func ParseImporterOptions(s string) TransactionDataImporterOptions { + options := TransactionDataImporterOptions{} + + if s == "" { + return options + } + + for _, option := range strings.Split(s, ",") { + switch option { + case "payeeAsTag": + options.payeeAsTag = true + case "payeeAsDescription": + options.payeeAsDescription = true + case "memberAsTag": + options.memberAsTag = true + case "projectAsTag": + options.projectAsTag = true + case "merchantAsTag": + options.merchantAsTag = true + } + } + + return options +} diff --git a/pkg/converters/converter/transaction_data_importer_options_test.go b/pkg/converters/converter/transaction_data_importer_options_test.go new file mode 100644 index 00000000..796a1395 --- /dev/null +++ b/pkg/converters/converter/transaction_data_importer_options_test.go @@ -0,0 +1,110 @@ +package converter + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseImporterOptions(t *testing.T) { + actualValue := ParseImporterOptions("payeeAsTag,memberAsTag") + expectedValue := TransactionDataImporterOptions{ + payeeAsTag: true, + memberAsTag: true, + projectAsTag: false, + merchantAsTag: false, + } + assert.Equal(t, expectedValue, actualValue) + assert.Equal(t, true, actualValue.IsPayeeAsTag()) + assert.Equal(t, true, actualValue.IsMemberAsTag()) + assert.Equal(t, false, actualValue.IsProjectAsTag()) + assert.Equal(t, false, actualValue.IsMerchantAsTag()) + + actualValue = ParseImporterOptions("") + expectedValue = TransactionDataImporterOptions{ + payeeAsTag: false, + memberAsTag: false, + projectAsTag: false, + merchantAsTag: false, + } + assert.Equal(t, expectedValue, actualValue) + assert.Equal(t, false, actualValue.IsPayeeAsTag()) + assert.Equal(t, false, actualValue.IsMemberAsTag()) + assert.Equal(t, false, actualValue.IsProjectAsTag()) + assert.Equal(t, false, actualValue.IsMerchantAsTag()) +} + +func TestParseImporterOptions_WithAllOptions(t *testing.T) { + actualValue := ParseImporterOptions("payeeAsTag,payeeAsDescription,memberAsTag,projectAsTag,merchantAsTag") + expectedValue := TransactionDataImporterOptions{ + payeeAsTag: true, + payeeAsDescription: true, + memberAsTag: true, + projectAsTag: true, + merchantAsTag: true, + } + assert.Equal(t, expectedValue, actualValue) + assert.Equal(t, true, actualValue.IsPayeeAsTag()) + assert.Equal(t, true, actualValue.IsPayeeAsDescription()) + assert.Equal(t, true, actualValue.IsMemberAsTag()) + assert.Equal(t, true, actualValue.IsProjectAsTag()) + assert.Equal(t, true, actualValue.IsMerchantAsTag()) +} + +func TestParseImporterOptions_WithInvalidOptions(t *testing.T) { + actualValue := ParseImporterOptions("invalidOption,payeeAsTag,memberAsTag") + expectedValue := TransactionDataImporterOptions{ + payeeAsTag: true, + memberAsTag: true, + projectAsTag: false, + merchantAsTag: false, + } + assert.Equal(t, expectedValue, actualValue) + assert.Equal(t, true, actualValue.IsPayeeAsTag()) + assert.Equal(t, true, actualValue.IsMemberAsTag()) + assert.Equal(t, false, actualValue.IsProjectAsTag()) + assert.Equal(t, false, actualValue.IsMerchantAsTag()) + + actualValue = ParseImporterOptions("invalidOption") + expectedValue = TransactionDataImporterOptions{ + payeeAsTag: false, + memberAsTag: false, + projectAsTag: false, + merchantAsTag: false, + } + assert.Equal(t, expectedValue, actualValue) + assert.Equal(t, false, actualValue.IsPayeeAsTag()) + assert.Equal(t, false, actualValue.IsMemberAsTag()) + assert.Equal(t, false, actualValue.IsProjectAsTag()) + assert.Equal(t, false, actualValue.IsMerchantAsTag()) +} + +func TestParseImporterOptions_Clone(t *testing.T) { + original := TransactionDataImporterOptions{ + payeeAsTag: true, + payeeAsDescription: false, + memberAsTag: false, + projectAsTag: true, + merchantAsTag: false, + } + + cloned := original.Clone() + assert.Equal(t, original, cloned) + + // Modify cloned options and verify original options are not affected + cloned.payeeAsTag = false + cloned.payeeAsDescription = true + cloned.memberAsTag = true + + assert.Equal(t, true, original.payeeAsTag) + assert.Equal(t, false, original.payeeAsDescription) + assert.Equal(t, false, original.memberAsTag) + assert.Equal(t, true, original.projectAsTag) + assert.Equal(t, false, original.merchantAsTag) + + assert.Equal(t, false, cloned.payeeAsTag) + assert.Equal(t, true, cloned.payeeAsDescription) + assert.Equal(t, true, cloned.memberAsTag) + assert.Equal(t, true, cloned.projectAsTag) + assert.Equal(t, false, cloned.merchantAsTag) +} diff --git a/pkg/converters/datatable/transaction_data_table.go b/pkg/converters/datatable/transaction_data_table.go index 1ae312f2..b3ecc14f 100644 --- a/pkg/converters/datatable/transaction_data_table.go +++ b/pkg/converters/datatable/transaction_data_table.go @@ -72,6 +72,10 @@ const ( TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION TransactionDataTableColumn = 12 TRANSACTION_DATA_TABLE_TAGS TransactionDataTableColumn = 13 TRANSACTION_DATA_TABLE_DESCRIPTION TransactionDataTableColumn = 14 + TRANSACTION_DATA_TABLE_PAYEE TransactionDataTableColumn = 101 + TRANSACTION_DATA_TABLE_MEMBER TransactionDataTableColumn = 102 + TRANSACTION_DATA_TABLE_PROJECT TransactionDataTableColumn = 103 + TRANSACTION_DATA_TABLE_MERCHANT TransactionDataTableColumn = 104 ) // TRANSACTION_DATA_TABLE_TIMEZONE_NOT_AVAILABLE represents the constant for timezone not available diff --git a/pkg/converters/default/default_transaction_data_json_file_importer.go b/pkg/converters/default/default_transaction_data_json_file_importer.go index aa986f29..9ffd0f1d 100644 --- a/pkg/converters/default/default_transaction_data_json_file_importer.go +++ b/pkg/converters/default/default_transaction_data_json_file_importer.go @@ -35,7 +35,7 @@ var ( ) // 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) { +func (c *defaultTransactionDataJsonImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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 { @@ -55,7 +55,7 @@ func (c *defaultTransactionDataJsonImporter) ParseImportedData(ctx core.Context, ezbookkeepingTagSeparator, ) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } func (c *defaultTransactionDataJsonImporter) createNewDefaultTransactionDataTable(importRequest models.ImportTransactionRequest) (datatable.TransactionDataTable, error) { diff --git a/pkg/converters/default/default_transaction_data_plain_text_converter.go b/pkg/converters/default/default_transaction_data_plain_text_converter.go index 698f0281..825d2c8d 100644 --- a/pkg/converters/default/default_transaction_data_plain_text_converter.go +++ b/pkg/converters/default/default_transaction_data_plain_text_converter.go @@ -84,7 +84,7 @@ func (c *defaultTransactionDataPlainTextConverter) ToExportedContent(ctx core.Co } // ParseImportedData returns the imported data by parsing the transaction plain text data -func (c *defaultTransactionDataPlainTextConverter) 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 *defaultTransactionDataPlainTextConverter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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 := createNewDefaultPlainTextDataTable( string(data), c.columnSeparator, @@ -104,5 +104,5 @@ func (c *defaultTransactionDataPlainTextConverter) ParseImportedData(ctx core.Co ezbookkeepingTagSeparator, ) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/default/default_transaction_data_plain_text_converter_test.go b/pkg/converters/default/default_transaction_data_plain_text_converter_test.go index 748991b3..31428c28 100644 --- a/pkg/converters/default/default_transaction_data_plain_text_converter_test.go +++ b/pkg/converters/default/default_transaction_data_plain_text_converter_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestDefaultTransactionDataCSVFileConverterToExportedContent(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + exporter := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() transactions := make([]*models.Transaction, 3) @@ -119,14 +120,14 @@ func TestDefaultTransactionDataCSVFileConverterToExportedContent(t *testing.T) { "2024-09-01 12:34:56,+08:00,Income,Test Category,Test Sub Category,Test Account,CNY,123.45,,,,123.450000 45.670000,Test Tag;Test Tag2,Hello World\n" + "2024-09-01 12:34:56,+00:00,Expense,Test Category2,Test Sub Category2,Test Account,CNY,-0.10,,,,,Test Tag,Foo#Bar\n" + "2024-09-01 12:34:56,-05:00,Transfer,Test Category3,Test Sub Category3,Test Account,CNY,123.45,Test Account2,USD,17.35,,Test Tag2,T\te s t test\n" - actualContent, err := converter.ToExportedContent(context, 123, transactions, accountMap, categoryMap, tagMap, allTagIndexes) + actualContent, err := exporter.ToExportedContent(context, 123, transactions, accountMap, categoryMap, tagMap, allTagIndexes) assert.Nil(t, err) assert.Equal(t, expectedContent, string(actualContent)) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_MinimumValidData(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -134,11 +135,11 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_MinimumValidDat DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ "2024-09-01 00:00:00,Balance Modification,,Test Account,123.45,,\n"+ "2024-09-01 01:23:45,Income,Test Category,Test Account,0.12,,\n"+ "2024-09-01 12:34:56,Expense,Test Category2,Test Account,1.00,,\n"+ - "2024-09-01 23:59:59,Transfer,Test Category3,Test Account,0.05,Test Account2,0.05"), 0, nil, nil, nil, nil, nil) + "2024-09-01 23:59:59,Transfer,Test Category3,Test Account,0.05,Test Account2,0.05"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -197,7 +198,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_MinimumValidDat } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -205,17 +206,17 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidTim DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01T12:34:56,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01T12:34:56,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "09/01/2024 12:34:56,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "09/01/2024 12:34:56,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidType(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -223,13 +224,13 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidTyp DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,Type,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,Type,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidTimezone(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -237,27 +238,27 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidTimez DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,-10:00,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,-10:00,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,+00:00,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,+00:00,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,+12:45,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,+12:45,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidTimezone(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -265,13 +266,13 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidTim DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,Asia/Shanghai,Expense,Test Category,Test Account,123.45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,Asia/Shanghai,Expense,Test Category,Test Account,123.45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeZoneInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidAccountCurrency(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -279,9 +280,9 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidAccou DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ "2024-09-01 01:23:45,Balance Modification,,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,Transfer,Test Category2,Test Account,USD,1.23,Test Account2,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,Transfer,Test Category2,Test Account,USD,1.23,Test Account2,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -298,7 +299,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidAccou } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidAccountCurrency(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -306,19 +307,19 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidAcc DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ "2024-09-01 01:23:45,Balance Modification,,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,Transfer,Test Category3,Test Account,CNY,1.23,Test Account2,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,Transfer,Test Category3,Test Account,CNY,1.23,Test Account2,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ "2024-09-01 01:23:45,Balance Modification,,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,Transfer,Test Category3,Test Account2,CNY,1.23,Test Account,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,Transfer,Test Category3,Test Account2,CNY,1.23,Test Account,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseNotSupportedCurrency(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -326,17 +327,17 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseNotSupport DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ - "2024-09-01 01:23:45,Balance Modification,,Test Account,XXX,123.45,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ + "2024-09-01 01:23:45,Balance Modification,,Test Account,XXX,123.45,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ - "2024-09-01 01:23:45,Transfer,Test Category,Test Account,USD,123.45,Test Account2,XXX,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount\n"+ + "2024-09-01 01:23:45,Transfer,Test Category,Test Account,USD,123.45,Test Account2,XXX,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -344,17 +345,17 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidAmo DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123 45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123 45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ - "2024-09-01 12:34:56,Transfer,Test Category,Test Account,123.45,Test Account2,123 45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount\n"+ + "2024-09-01 12:34:56,Transfer,Test Category,Test Account,123.45,Test Account2,123 45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseNoAmount2(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -362,15 +363,15 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseNoAmount2( DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) assert.Equal(t, int64(0), allNewTransactions[0].RelatedAccountAmount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2\n"+ - "2024-09-01 12:34:56,Transfer,Test Category,Test Account,123.45,Test Account2"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2\n"+ + "2024-09-01 12:34:56,Transfer,Test Category,Test Account,123.45,Test Account2"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) @@ -378,7 +379,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseNoAmount2( } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidGeographicLocation(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -386,8 +387,8 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidGeogr DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,123.45 45.56"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,123.45 45.56"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -396,7 +397,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseValidGeogr } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidGeographicLocation(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -404,24 +405,24 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseInvalidGeo DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,1"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,1"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, float64(0), allNewTransactions[0].GeoLongitude) assert.Equal(t, float64(0), allNewTransactions[0].GeoLatitude) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,a b"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,a b"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrGeographicLocationInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,1 "), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Geographic Location\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,1 "), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrGeographicLocationInvalid.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseTag(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -429,8 +430,8 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseTag(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, allNewTags, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Tags\n"+ - "2024-09-01 00:00:00,Balance Modification,,Test Account,123.45,,,foo;;bar.;#test;hello\tworld;;"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, allNewTags, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Tags\n"+ + "2024-09-01 00:00:00,Balance Modification,,Test Account,123.45,,,foo;;bar.;#test;hello\tworld;;"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -450,7 +451,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseTag(t *tes } func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseDescription(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -458,8 +459,8 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseDescriptio DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Description\n"+ - "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,foo bar\t#test"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Time,Type,Sub Category,Account,Amount,Account2,Account2 Amount,Description\n"+ + "2024-09-01 12:34:56,Expense,Test Category,Test Account,123.45,,,foo bar\t#test"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -467,7 +468,7 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_ParseDescriptio } func TestDefaultTransactionDataCSVFileConverterParseImportedData_MissingFileHeader(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -475,12 +476,12 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_MissingFileHead DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestDefaultTransactionDataCSVFileConverterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := DefaultTransactionDataCSVFileConverter + importer := DefaultTransactionDataCSVFileConverter context := core.NewNullContext() user := &models.User{ @@ -489,32 +490,32 @@ func TestDefaultTransactionDataCSVFileConverterParseImportedData_MissingRequired } // Missing Time Column - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("Timezone,Type,Category,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,123.45,,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("Timezone,Type,Category,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,123.45,,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Category,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "2024-09-01 00:00:00,+08:00,Test Category,Test Sub Category,Test Account,CNY,123.45,,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Category,Sub Category,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "2024-09-01 00:00:00,+08:00,Test Category,Test Sub Category,Test Account,CNY,123.45,,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Sub Category Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Type,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "2024-09-01 00:00:00,+08:00,Balance Modification,Test Account,CNY,123.45,,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Type,Account,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "2024-09-01 00:00:00,+08:00,Balance Modification,Test Account,CNY,123.45,,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account Name Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,CNY,123.45,,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account Currency,Amount,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,CNY,123.45,,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account,Account Currency,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account,Account Currency,Account2,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account2 Name Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account,Account Currency,Amount,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ - "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,123.45,,,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("Time,Timezone,Type,Category,Sub Category,Account,Account Currency,Amount,Account2 Currency,Account2 Amount,Geographic Location,Tags,Description\n"+ + "2024-09-01 00:00:00,+08:00,Balance Modification,,Test Sub Category,Test Account,CNY,123.45,,,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } diff --git a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go index c5fd2657..2c709117 100644 --- a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go +++ b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go @@ -146,7 +146,7 @@ func (c *customTransactionDataDsvFileImporter) ParseDsvFileLines(ctx core.Contex } // ParseImportedData returns the imported data by parsing the custom transaction dsv data -func (c *customTransactionDataDsvFileImporter) 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 *customTransactionDataDsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { allLines, err := c.ParseDsvFileLines(ctx, data) if err != nil { @@ -157,7 +157,7 @@ func (c *customTransactionDataDsvFileImporter) ParseImportedData(ctx core.Contex 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) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } // IsDelimiterSeparatedValuesFileType returns whether the file type is the delimiter-separated values file type diff --git a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go index e2baeb70..208d4293 100644 --- a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go +++ b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "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" @@ -22,12 +23,12 @@ func TestIsDelimiterSeparatedValuesFileType(t *testing.T) { } func TestCustomTransactionDataDsvFileParser_ParseDsvFileLines(t *testing.T) { - converter, err := CreateNewCustomTransactionDataDsvFileParser("custom_csv", "utf-8") + importer, err := CreateNewCustomTransactionDataDsvFileParser("custom_csv", "utf-8") assert.Nil(t, err) context := core.NewNullContext() - allLines, err := converter.ParseDsvFileLines(context, []byte( + allLines, err := importer.ParseDsvFileLines(context, []byte( "2024-09-01 00:00:00,B,123.45\n"+ "2024-09-01 01:23:45,I,0.12\n")) assert.Nil(t, err) @@ -44,10 +45,10 @@ func TestCustomTransactionDataDsvFileParser_ParseDsvFileLines(t *testing.T) { assert.Equal(t, "I", allLines[1][1]) assert.Equal(t, "0.12", allLines[1][2]) - converter, err = CreateNewCustomTransactionDataDsvFileParser("custom_tsv", "utf-8") + importer, err = CreateNewCustomTransactionDataDsvFileParser("custom_tsv", "utf-8") assert.Nil(t, err) - allLines, err = converter.ParseDsvFileLines(context, []byte( + allLines, err = importer.ParseDsvFileLines(context, []byte( "2024-09-01 12:34:56\tE\t1.00\n"+ "2024-09-01 23:59:59\tT\t0.05")) assert.Nil(t, err) @@ -77,7 +78,7 @@ func TestCustomTransactionDataDsvFileImporter_MinimumValidData(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", ".", "", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", ".", "", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -87,11 +88,11 @@ func TestCustomTransactionDataDsvFileImporter_MinimumValidData(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 00:00:00,B,123.45\n"+ "2024-09-01 01:23:45,I,0.12\n"+ "2024-09-01 12:34:56,E,1.00\n"+ - "2024-09-01 23:59:59,T,0.05"), 0, nil, nil, nil, nil, nil) + "2024-09-01 23:59:59,T,0.05"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -168,7 +169,7 @@ func TestCustomTransactionDataDsvFileImporter_WithAllSupportedColumns(t *testing "Expense": models.TRANSACTION_TYPE_EXPENSE, "Transfer": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, true, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", ";") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, true, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", ";") assert.Nil(t, err) context := core.NewNullContext() @@ -178,12 +179,12 @@ func TestCustomTransactionDataDsvFileImporter_WithAllSupportedColumns(t *testing DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "\"Time\",\"Timezone\",\"Type\",\"Category\",\"Sub Category\",\"Account\",\"Account Currency\",\"Amount\",\"Account2\",\"Account2 Currency\",\"Account2 Amount\",\"Geographic Location\",\"Tags\",\"Description\"\n"+ "\"2024-09-01 00:00:00\",\"+08:00\",\"Balance Modification\",\"\",\"\",\"Test Account\",\"CNY\",\"123.45\",\"\",\"\",\"\",\"\",\"\",\"\"\n"+ "\"2024-09-01 01:23:45\",\"+08:00\",\"Income\",\"Test Category\",\"Test Sub Category\",\"Test Account\",\"CNY\",\"0.12\",\"\",\"\",\"\",\"123.450000 45.670000\",\"Test Tag;Test Tag2\",\"Hello World\"\n"+ "\"2024-09-01 12:34:56\",\"+00:00\",\"Expense\",\"Test Category2\",\"Test Sub Category2\",\"Test Account\",\"CNY\",\"1.00\",\"\",\"\",\"\",\"\",\"Test Tag\",\"Foo#Bar\"\n"+ - "\"2024-09-01 23:59:59\",\"-05:00\",\"Transfer\",\"Test Category3\",\"Test Sub Category3\",\"Test Account\",\"CNY\",\"0.05\",\"Test Account2\",\"USD\",\"0.35\",\"\",\"Test Tag2\",\"foo\tbar\""), 0, nil, nil, nil, nil, nil) + "\"2024-09-01 23:59:59\",\"-05:00\",\"Transfer\",\"Test Category3\",\"Test Sub Category3\",\"Test Account\",\"CNY\",\"0.05\",\"Test Account2\",\"USD\",\"0.35\",\"\",\"Test Tag2\",\"foo\tbar\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -261,7 +262,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTime(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -271,12 +272,12 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTime(t *testing.T) { DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01T12:34:56,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01T12:34:56,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "09/01/2024 12:34:56,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "09/01/2024 12:34:56,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } @@ -292,7 +293,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTransactionWithoutType(t *tes "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -302,8 +303,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseTransactionWithoutType(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,A,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,A,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } @@ -316,7 +317,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidType(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "B": 0, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -326,8 +327,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidType(t *testing.T) { DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,B,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,B,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) } @@ -340,7 +341,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone(t *testing.T transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZ", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZ", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -350,20 +351,20 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone(t *testing.T DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56-10:00,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56-10:00,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56+00:00,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56+00:00,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56+12:45,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56+12:45,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) @@ -378,7 +379,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone2(t *testing. transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZZ", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZZ", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -388,20 +389,20 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone2(t *testing. DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56-1000,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56-1000,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56+0000,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56+0000,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56+1245,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56+1245,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) @@ -417,7 +418,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -427,20 +428,20 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,-10:00,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,-10:00,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,+00:00,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,+00:00,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,+12:45,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,+12:45,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) @@ -456,7 +457,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone2(t *testing.T) transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -466,20 +467,20 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone2(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,-1000,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,-1000,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,+0000,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,+0000,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,+1245,E,123.45"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,+1245,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) @@ -495,7 +496,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezoneFormat(t *test transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "z", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "z", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -505,8 +506,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezoneFormat(t *test DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,CST,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,CST,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrImportFileTransactionTimezoneFormatInvalid.Message) } @@ -520,7 +521,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone(t *testing.T) transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -530,12 +531,12 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone(t *testing.T) DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,Asia/Shanghai,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,Asia/Shanghai,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeZoneInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,-0700,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,-0700,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeZoneInvalid.Message) } @@ -549,7 +550,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone2(t *testing.T transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -559,12 +560,12 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone2(t *testing.T DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,Asia/Shanghai,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,Asia/Shanghai,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeZoneInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,0700,E,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,0700,E,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeZoneInvalid.Message) } @@ -577,7 +578,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseAmountWithCustomFormat(t *tes transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", ".", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", ".", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -587,8 +588,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseAmountWithCustomFormat(t *tes DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56\tE\t1.234,56"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56\tE\t1.234,56"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(123456), allNewTransactions[0].Amount) @@ -603,7 +604,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", ",", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", ",", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -613,8 +614,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56\tE\t1.234,56"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56\tE\t1.234,56"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } @@ -627,7 +628,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -637,8 +638,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56\tE\t1.234,56"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56\tE\t1.234,56"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } @@ -655,7 +656,7 @@ func TestCustomTransactionDataDsvFileImporter_ParsePrimaryCategory(t *testing.T) "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -665,11 +666,11 @@ func TestCustomTransactionDataDsvFileImporter_ParsePrimaryCategory(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 00:00:00,B,,123.45\n"+ "2024-09-01 01:23:45,I,Test Category,0.12\n"+ "2024-09-01 12:34:56,E,Test Category2,1.00\n"+ - "2024-09-01 23:59:59,T,Test Category3,0.05"), 0, nil, nil, nil, nil, nil) + "2024-09-01 23:59:59,T,Test Category3,0.05"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -724,7 +725,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAccountCurrency(t *testi "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -734,9 +735,9 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAccountCurrency(t *testi DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 01:23:45,B,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,T,Test Account,USD,1.23,Test Account2,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,T,Test Account,USD,1.23,Test Account2,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -767,7 +768,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAccountCurrency(t *tes "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -777,14 +778,14 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAccountCurrency(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 01:23:45,B,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,T,Test Account,CNY,1.23,Test Account2,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,T,Test Account,CNY,1.23,Test Account2,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "2024-09-01 01:23:45,B,Test Account,USD,123.45,,,\n"+ - "2024-09-01 12:34:56,T,Test Account2,CNY,1.23,Test Account,EUR,1.10"), 0, nil, nil, nil, nil, nil) + "2024-09-01 12:34:56,T,Test Account2,CNY,1.23,Test Account,EUR,1.10"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } @@ -803,7 +804,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseNotSupportedCurrency(t *testi "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -813,12 +814,12 @@ func TestCustomTransactionDataDsvFileImporter_ParseNotSupportedCurrency(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 01:23:45,B,Test Account,XXX,123.45,,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 01:23:45,B,Test Account,XXX,123.45,,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 01:23:45,T,Test Account,USD,123.45,Test Account2,XXX,123.45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 01:23:45,T,Test Account,USD,123.45,Test Account2,XXX,123.45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } @@ -835,7 +836,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAmount(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -845,11 +846,11 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAmount(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "2024-09-01 00:00:00,B,123.45000000,\n"+ "2024-09-01 01:23:45,I,0.12000000,\n"+ "2024-09-01 12:34:56,E,1.00000000,\n"+ - "2024-09-01 23:59:59,T,0.05000000,0.35000000"), 0, nil, nil, nil, nil, nil) + "2024-09-01 23:59:59,T,0.05000000,0.35000000"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -886,7 +887,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmount(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -896,12 +897,12 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmount(t *testing.T) { DefaultCurrency: "CNY", } - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,E,Test Account,123 45,,"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,E,Test Account,123 45,,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,T,Test Account,123.45,Test Account2,123 45"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,T,Test Account,123.45,Test Account2,123 45"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } @@ -917,7 +918,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseNoAmount2(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -927,15 +928,15 @@ func TestCustomTransactionDataDsvFileImporter_ParseNoAmount2(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,E,Test Account,123.45,"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,E,Test Account,123.45,"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) assert.Equal(t, int64(0), allNewTransactions[0].RelatedAccountAmount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,T,Test Account,123.45,Test Account2"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,T,Test Account,123.45,Test Account2"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) @@ -952,7 +953,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidGeographicLocation(t *te transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", ";", "lonlat", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", ";", "lonlat", "") assert.Nil(t, err) context := core.NewNullContext() @@ -962,8 +963,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidGeographicLocation(t *te DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,E,123.45,123.45;45.56"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,E,123.45,123.45;45.56"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -981,7 +982,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidGeographicLocation(t * transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", "") assert.Nil(t, err) context := core.NewNullContext() @@ -991,15 +992,15 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidGeographicLocation(t * DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,E,123.45,,,1"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,E,123.45,,,1"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, float64(0), allNewTransactions[0].GeoLongitude) assert.Equal(t, float64(0), allNewTransactions[0].GeoLatitude) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,E,123.45,a b"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,E,123.45,a b"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrGeographicLocationInvalid.Message) } @@ -1013,7 +1014,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTag(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", ";") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", ";") assert.Nil(t, err) context := core.NewNullContext() @@ -1023,8 +1024,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseTag(t *testing.T) { DefaultCurrency: "CNY", } - _, _, _, _, _, allNewTags, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 00:00:00,E,123.45,foo;;bar.;#test;hello\tworld;;"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, allNewTags, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 00:00:00,E,123.45,foo;;bar.;#test;hello\tworld;;"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -1053,7 +1054,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTagWithoutSeparator(t *testin transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -1063,8 +1064,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseTagWithoutSeparator(t *testin DefaultCurrency: "CNY", } - _, _, _, _, _, allNewTags, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 00:00:00,E,123.45,foo;;bar.;#test;hello\tworld;;"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, allNewTags, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 00:00:00,E,123.45,foo;;bar.;#test;hello\tworld;;"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -1084,7 +1085,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseDescription(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") + importer, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -1094,8 +1095,8 @@ func TestCustomTransactionDataDsvFileImporter_ParseDescription(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( - "2024-09-01 12:34:56,T,123.45,foo bar\t#test"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "2024-09-01 12:34:56,T,123.45,foo bar\t#test"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) diff --git a/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer.go b/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer.go index 6890a7fc..0e8891ae 100644 --- a/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer.go +++ b/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer.go @@ -55,7 +55,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the feidee mymoney app transaction csv data -func (c *feideeMymoneyAppTransactionDataCsvFileImporter) 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 *feideeMymoneyAppTransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { fallback := unicode.UTF8.NewDecoder() reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback)) @@ -91,7 +91,7 @@ func (c *feideeMymoneyAppTransactionDataCsvFileImporter) ParseImportedData(ctx c dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(feideeMymoneyTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } func (c *feideeMymoneyAppTransactionDataCsvFileImporter) createNewFeideeMymoneyAppTransactionDataTable(ctx core.Context, commonDataTable datatable.CommonDataTable) (datatable.TransactionDataTable, error) { diff --git a/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer_test.go b/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer_test.go index b4b80233..9be19d92 100644 --- a/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer_test.go +++ b/pkg/converters/feidee/feidee_mymoney_app_transaction_data_csv_file_importer_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -13,7 +14,7 @@ import ( ) func TestFeideeMymoneyCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -21,7 +22,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_MinimumValidData(t *testi DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"+ "\"余额变更\",\"2024-09-01 01:00:00\",\"\",\"Test Account2\",\"-0.12\",\"\",\"\"\n"+ @@ -30,7 +31,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_MinimumValidData(t *testi "\"转出\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ "\"转入\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account2\",\"0.05\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ "\"转入\",\"2024-09-02 23:59:59\",\"Test Category3\",\"Test Account\",\"0.5\",\"\",\"00000000-0000-0000-0000-000000000002\"\n"+ - "\"转出\",\"2024-09-02 23:59:59\",\"Test Category3\",\"Test Account2\",\"0.5\",\"\",\"00000000-0000-0000-0000-000000000002\""), 0, nil, nil, nil, nil, nil) + "\"转出\",\"2024-09-02 23:59:59\",\"Test Category3\",\"Test Account2\",\"0.5\",\"\",\"00000000-0000-0000-0000-000000000002\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -110,7 +111,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_MinimumValidData(t *testi } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseOutstandingBalanceModification(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -118,10 +119,10 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseOutstandingBalanceMo DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"负债变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"+ - "\"负债变更\",\"2024-09-01 01:00:00\",\"\",\"Test Account2\",\"-0.12\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"负债变更\",\"2024-09-01 01:00:00\",\"\",\"Test Account2\",\"-0.12\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -160,7 +161,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseOutstandingBalanceMo } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -168,19 +169,19 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidTime(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"收入\",\"2024-09-01T12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"收入\",\"2024-09-01T12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"收入\",\"09/01/2024 12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"收入\",\"09/01/2024 12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -188,14 +189,14 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidType(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"Type\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"Type\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"0.12\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseValidAccountCurrency(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -203,11 +204,11 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseValidAccountCurrency DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"USD\",\"123.45\",\"\",\"\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account\",\"USD\",\"1.23\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account2\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account2\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -224,7 +225,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseValidAccountCurrency } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidAccountCurrency(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -232,23 +233,23 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidAccountCurren DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"USD\",\"123.45\",\"\",\"\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account\",\"CNY\",\"1.23\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account2\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account2\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"USD\",\"123.45\",\"\",\"\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account2\",\"CNY\",\"1.23\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category3\",\"Test Account\",\"EUR\",\"1.10\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseNotSupportedCurrency(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -256,26 +257,26 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseNotSupportedCurrency DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"XXX\",\"123.45\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"XXX\",\"123.45\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"USD\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"XXX\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"XXX\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"账户币种\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"XXX\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"USD\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"USD\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -283,31 +284,31 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseInvalidAmount(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"123 45\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"123 45\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"负债变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"123 45\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"负债变更\",\"2024-09-01 01:23:45\",\"\",\"Test Account\",\"123 45\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"123 45\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"转出\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"123.45\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"123 45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account2\",\"123 45\",\"\",\"00000000-0000-0000-0000-000000000001\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -315,10 +316,10 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseDescription(t *testi DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"支出\",\"2024-09-01 12:34:56\",\"Test Category\",\"Test Account\",\"123.45\",\"Test\n"+ - "A new line break\",\"\""), 0, nil, nil, nil, nil, nil) + "A new line break\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -326,7 +327,7 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_ParseDescription(t *testi } func TestFeideeMymoneyCsvFileImporterParseImportedData_InvalidRelatedId(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -334,41 +335,41 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_InvalidRelatedId(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"转出\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"转出\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrRelatedIdCannotBeBlank.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"转入\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrRelatedIdCannotBeBlank.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ "\"转出\",\"2024-09-01 23:59:59\",\"Test Category3\",\"Test Account\",\"0.05\",\"\",\"00000000-0000-0000-0000-000000000001\"\n"+ - "\"转入\",\"2024-09-02 23:59:59\",\"Test Category3\",\"Test Account\",\"0.5\",\"\",\"00000000-0000-0000-0000-000000000002\""), 0, nil, nil, nil, nil, nil) + "\"转入\",\"2024-09-02 23:59:59\",\"Test Category3\",\"Test Account\",\"0.5\",\"\",\"00000000-0000-0000-0000-000000000002\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrFoundRecordNotHasRelatedRecord.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_MissingFileHeader(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ Uid: 1, DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ + "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) } func TestFeideeMymoneyCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := FeideeMymoneyAppTransactionDataCsvFileImporter + importer := FeideeMymoneyAppTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -377,38 +378,38 @@ func TestFeideeMymoneyCsvFileImporterParseImportedData_MissingRequiredColumn(t * } // Missing Time Column - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"2024-09-01 00:00:00\",\"Test Category\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"2024-09-01 00:00:00\",\"Test Category\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Sub Category Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"账户\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 00:00:00\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 00:00:00\",\"Test Account\",\"123.45\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account Name Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"金额\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"123.45\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"123.45\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"备注\",\"关联Id\"\n"+ - "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Related ID Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("随手记导出文件(headers:v5;xxxxx)\n"+ "\"交易类型\",\"日期\",\"子类别\",\"账户\",\"金额\",\"备注\"\n"+ - "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\"\n"), 0, nil, nil, nil, nil, nil) + "\"余额变更\",\"2024-09-01 00:00:00\",\"\",\"Test Account\",\"123.45\",\"\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } diff --git a/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer.go b/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer.go index b1fe391d..6f38dbf2 100644 --- a/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer.go +++ b/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer.go @@ -31,7 +31,7 @@ var ( ) // 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, additionalOptions converter.TransactionDataImporterOptions, 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.CreateNewExcelOOXMLFileBasicDataTable(data, true) if err != nil { @@ -42,5 +42,5 @@ func (c *feideeMymoneyElecloudTransactionDataXlsxFileImporter) ParseImportedData transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, feideeMymoneyElecloudDataColumnNameMapping, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporter(feideeMymoneyElecloudTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer_test.go b/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer_test.go index 034f432e..06e7cc08 100644 --- a/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer_test.go +++ b/pkg/converters/feidee/feidee_mymoney_elecloud_transaction_data_xlsx_file_importer_test.go @@ -7,13 +7,14 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/utils" ) func TestFeideeMymoneyElecloudTransactionDataXlsxImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := FeideeMymoneyElecloudTransactionDataXlsxFileImporter + importer := FeideeMymoneyElecloudTransactionDataXlsxFileImporter context := core.NewNullContext() user := &models.User{ @@ -24,7 +25,7 @@ func TestFeideeMymoneyElecloudTransactionDataXlsxImporterParseImportedData_Minim testdata, err := os.ReadFile("../../../testdata/feidee_mymoney_elecloud_test_file.xlsx") assert.Nil(t, err) - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, testdata, 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, testdata, 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 7, len(allNewTransactions)) diff --git a/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer.go b/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer.go index c6e8f3e5..fef43442 100644 --- a/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer.go +++ b/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer.go @@ -30,7 +30,7 @@ var ( ) // 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, additionalOptions converter.TransactionDataImporterOptions, 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.CreateNewExcelMSCFBFileBasicDataTable(data, true) if err != nil { @@ -41,5 +41,5 @@ func (c *feideeMymoneyWebTransactionDataXlsFileImporter) ParseImportedData(ctx c transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, feideeMymoneyWebDataColumnNameMapping, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(feideeMymoneyTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer_test.go b/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer_test.go index 316eccf6..84e6fc72 100644 --- a/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer_test.go +++ b/pkg/converters/feidee/feidee_mymoney_web_transaction_data_xls_file_importer_test.go @@ -7,13 +7,14 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/utils" ) func TestFeideeMymoneyTransactionDataXlsImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := FeideeMymoneyWebTransactionDataXlsFileImporter + importer := FeideeMymoneyWebTransactionDataXlsFileImporter context := core.NewNullContext() user := &models.User{ @@ -24,7 +25,7 @@ func TestFeideeMymoneyTransactionDataXlsImporterParseImportedData_MinimumValidDa testdata, err := os.ReadFile("../../../testdata/feidee_mymoney_test_file.xls") assert.Nil(t, err) - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, testdata, 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, testdata, 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 7, len(allNewTransactions)) diff --git a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go index 5860c443..4b91efe0 100644 --- a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go +++ b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go @@ -40,7 +40,7 @@ var ( ) // 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, additionalOptions converter.TransactionDataImporterOptions, 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) dataTable, err := csv.CreateNewCsvBasicDataTable(ctx, reader, true) @@ -52,5 +52,5 @@ func (c *fireflyIIITransactionDataCsvFileImporter) ParseImportedData(ctx core.Co transactionDataTable := datatable.CreateNewTransactionDataTableFromBasicDataTableWithRowParser(dataTable, fireflyIIITransactionDataColumnNameMapping, transactionRowParser) dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(fireflyIIITransactionTypeNameMapping, "", "", ",") - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer_test.go b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer_test.go index 1d5adacf..80978315 100644 --- a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer_test.go +++ b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer_test.go @@ -5,14 +5,15 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" "github.com/mayswind/ezbookkeeping/pkg/utils" ) -func TestFireFlyIIICsvFileConverterParseImportedData_MinimumValidData(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_MinimumValidData(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -20,11 +21,11 @@ func TestFireFlyIIICsvFileConverterParseImportedData_MinimumValidData(t *testing DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"+ "Deposit,0.12,2024-09-01T01:23:45+08:00,\"A revenue account\",\"Test Account\",\"Test Category\"\n"+ "Withdrawal,-1.00,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category2\"\n"+ - "Transfer,0.05,2024-09-01T23:59:59+08:00,\"Test Account\",\"Test Account2\",\"Test Category3\""), 0, nil, nil, nil, nil, nil) + "Transfer,0.05,2024-09-01T23:59:59+08:00,\"Test Account\",\"Test Account2\",\"Test Category3\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -82,8 +83,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_MinimumValidData(t *testing assert.Equal(t, "Test Category3", allNewSubTransferCategories[0].Name) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseInvalidTime(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -91,17 +92,17 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidTime(t *testing DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01T12:34:56,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01T12:34:56,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01 12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01 12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidType(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseInvalidType(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -109,13 +110,13 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidType(t *testing DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Type,123.45,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Type,123.45,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseAccountNameAsCategoryName(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseAccountNameAsCategoryName(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -123,23 +124,23 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseAccountNameAsCategoryN DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "A expense account", allNewTransactions[0].OriginalCategoryName) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Deposit,10.00,2024-09-01T12:34:56+08:00,\"A revenue account\",\"Test Account\",\"\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Deposit,10.00,2024-09-01T12:34:56+08:00,\"A revenue account\",\"Test Account\",\"\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "A revenue account", allNewTransactions[0].OriginalCategoryName) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidTimezone(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseValidTimezone(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -147,27 +148,27 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidTimezone(t *testi DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01T12:34:56-10:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01T12:34:56-10:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01T12:34:56+00:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01T12:34:56+00:00,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725194096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-1.00,2024-09-01T12:34:56+12:45,\"Test Account\",\"A expense account\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-1.00,2024-09-01T12:34:56+12:45,\"Test Account\",\"A expense account\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidAccountCurrency(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseValidAccountCurrency(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -175,9 +176,9 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidAccountCurrency(t DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ "\"Opening balance\",123.45,,2024-09-01T00:00:00+08:00,USD,,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"+ - "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, nil, nil, nil, nil, nil) + "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -193,8 +194,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidAccountCurrency(t assert.Equal(t, "EUR", allNewAccounts[1].Currency) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidForeignAmountAndCurrency(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseValidForeignAmountAndCurrency(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -202,8 +203,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidForeignAmountAndC DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ - "Transfer,10.00,15.00,2024-09-01T12:34:56+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + "Transfer,10.00,15.00,2024-09-01T12:34:56+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -213,8 +214,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidForeignAmountAndC assert.Equal(t, "USD", allNewTransactions[0].OriginalSourceAccountCurrency) assert.Equal(t, "EUR", allNewTransactions[0].OriginalDestinationAccountCurrency) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ - "Transfer,10.00,2024-09-01T12:34:56+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + "Transfer,10.00,2024-09-01T12:34:56+08:00,USD,EUR,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -223,8 +224,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidForeignAmountAndC assert.Equal(t, "USD", allNewTransactions[0].OriginalSourceAccountCurrency) assert.Equal(t, "EUR", allNewTransactions[0].OriginalDestinationAccountCurrency) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ - "Transfer,10.00,2024-09-01T12:34:56+08:00,USD,,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + "Transfer,10.00,2024-09-01T12:34:56+08:00,USD,,\"Test Account\",\"Test Account2\",\"Test Category\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -232,8 +233,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseValidForeignAmountAndC assert.Equal(t, "USD", allNewTransactions[0].OriginalDestinationAccountCurrency) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidAccountCurrency(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseInvalidAccountCurrency(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -241,19 +242,19 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidAccountCurrency DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ "\"Opening balance\",123.45,,2024-09-01T00:00:00+08:00,USD,,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"+ - "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,CNY,EUR,\"Test Account\",\"Test Account2\",\"Test Category3\""), 0, nil, nil, nil, nil, nil) + "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,CNY,EUR,\"Test Account\",\"Test Account2\",\"Test Category3\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ "\"Opening balance\",123.45,,2024-09-01T00:00:00+08:00,USD,,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"+ - "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,CNY,EUR,\"Test Account2\",\"Test Account\",\"Test Category3\""), 0, nil, nil, nil, nil, nil) + "Transfer,1.23,1.10,2024-09-01T23:59:59+08:00,CNY,EUR,\"Test Account2\",\"Test Account\",\"Test Category3\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseNotSupportedCurrency(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseNotSupportedCurrency(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -261,17 +262,17 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseNotSupportedCurrency(t DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ - "\"Opening balance\",123.45,,2024-09-01T00:00:00+08:00,XXX,,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + "\"Opening balance\",123.45,,2024-09-01T00:00:00+08:00,XXX,,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ - "Transfer,123.45,123.45,2024-09-01T23:59:59+08:00,USD,XXX,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,currency_code,foreign_currency_code,source_name,destination_name,category\n"+ + "Transfer,123.45,123.45,2024-09-01T23:59:59+08:00,USD,XXX,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseInvalidAmount(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -279,17 +280,17 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseInvalidAmount(t *testi DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ - "Withdrawal,-123 45,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name,category\n"+ + "Withdrawal,-123 45,2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,source_name,destination_name,category\n"+ - "Transfer,123.45,123 45,2024-09-01T23:59:59+08:00,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,foreign_amount,date,source_name,destination_name,category\n"+ + "Transfer,123.45,123 45,2024-09-01T23:59:59+08:00,\"Test Account\",\"Test Account2\",\"Test Category2\""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseDescription(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseDescription(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -297,16 +298,16 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseDescription(t *testing DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,description,date,source_name,destination_name,category\n"+ - "Withdrawal,-123.45,\"foo bar\t#test\",2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,description,date,source_name,destination_name,category\n"+ + "Withdrawal,-123.45,\"foo bar\t#test\",2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "foo bar\t#test", allNewTransactions[0].Comment) } -func TestFireFlyIIICsvFileConverterParseImportedData_ParseTags(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_ParseTags(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -314,8 +315,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseTags(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, allNewTags, err := converter.ParseImportedData(context, user, []byte("type,amount,tags,date,source_name,destination_name,category\n"+ - "Withdrawal,-123.45,\"tag1,tag2,tag3\",2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, allNewTags, err := importer.ParseImportedData(context, user, []byte("type,amount,tags,date,source_name,destination_name,category\n"+ + "Withdrawal,-123.45,\"tag1,tag2,tag3\",2024-09-01T12:34:56+08:00,\"Test Account\",\"A expense account\",\"Test Category\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -328,8 +329,8 @@ func TestFireFlyIIICsvFileConverterParseImportedData_ParseTags(t *testing.T) { assert.Equal(t, "tag3", allNewTags[2].Name) } -func TestFireFlyIIICsvFileConverterParseImportedData_MissingFileHeader(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_MissingFileHeader(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -337,12 +338,12 @@ func TestFireFlyIIICsvFileConverterParseImportedData_MissingFileHeader(t *testin DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } -func TestFireFlyIIICsvFileConverterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := FireflyIIITransactionDataCsvFileImporter +func TestFireFlyIIICsvFileimporterParseImportedData_MissingRequiredColumn(t *testing.T) { + importer := FireflyIIITransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -351,32 +352,32 @@ func TestFireFlyIIICsvFileConverterParseImportedData_MissingRequiredColumn(t *te } // Missing Time Column - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("type,amount,source_name,destination_name,category\n"+ - "\"Opening balance\",123.45,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("type,amount,source_name,destination_name,category\n"+ + "\"Opening balance\",123.45,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("amount,date,source_name,destination_name,category\n"+ - "123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("amount,date,source_name,destination_name,category\n"+ + "123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Sub Category Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name\n"+ - "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\"\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,destination_name\n"+ + "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\"\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account Name Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,destination_name,category\n"+ - "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Test Account\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,destination_name,category\n"+ + "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Test Account\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,date,source_name,destination_name,category\n"+ - "\"Opening balance\",2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,date,source_name,destination_name,category\n"+ + "\"Opening balance\",2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\"Test Account\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account2 Name Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte("type,amount,date,source_name,category\n"+ - "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\n"), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte("type,amount,date,source_name,category\n"+ + "\"Opening balance\",123.45,2024-09-01T00:00:00+08:00,\"Initial balance for \"\"Test Account\"\"\",\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } diff --git a/pkg/converters/gnucash/gnucash_transaction_data_file_importer.go b/pkg/converters/gnucash/gnucash_transaction_data_file_importer.go index 277465b1..adfd5d68 100644 --- a/pkg/converters/gnucash/gnucash_transaction_data_file_importer.go +++ b/pkg/converters/gnucash/gnucash_transaction_data_file_importer.go @@ -24,7 +24,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the gnucash transaction data -func (c *gnucashTransactionDataImporter) 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 *gnucashTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { gnucashDataReader, err := createNewGnuCashDatabaseReader(data) if err != nil { @@ -45,5 +45,5 @@ func (c *gnucashTransactionDataImporter) ParseImportedData(ctx core.Context, use dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(gnucashTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/gnucash/gnucash_transaction_data_file_importer_test.go b/pkg/converters/gnucash/gnucash_transaction_data_file_importer_test.go index 20331da3..65b28e38 100644 --- a/pkg/converters/gnucash/gnucash_transaction_data_file_importer_test.go +++ b/pkg/converters/gnucash/gnucash_transaction_data_file_importer_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -185,7 +186,7 @@ const gnucashCommonValidDataCaseFooter = "\n" + "\n" func TestGnuCashTransactionDatabaseFileParseImportedData_MinimumValidData(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -193,14 +194,14 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MinimumValidData(t *tes DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte(gnucashMinimumValidDataCase), 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte(gnucashMinimumValidDataCase), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) checkParsedMinimumValidData(t, allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags) } func TestGnuCashTransactionDatabaseFileParseImportedData_GzippedMinimumValidData(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -217,14 +218,14 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_GzippedMinimumValidData assert.Nil(t, err) gzippedData := buffer.Bytes() - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, gzippedData, 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, gzippedData, 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) checkParsedMinimumValidData(t, allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags) } func TestGnuCashTransactionDatabaseFileParseImportedData_MinimumValidDataWithReversedSplitOrder(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -232,7 +233,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MinimumValidDataWithRev DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte("\n"+ + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte("\n"+ "\n"+ "\n"+ "\n"+ - "\n"), 0, nil, nil, nil, nil, nil) + "\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) checkParsedMinimumValidData(t, allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags) } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidTime(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -371,7 +372,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidTime(t *tes DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -388,10 +389,10 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidTime(t *tes " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -408,12 +409,12 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidTime(t *tes " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidTimezone(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -421,7 +422,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidTimezone(t *t DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -438,12 +439,12 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidTimezone(t *t " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725230096), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -460,14 +461,14 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidTimezone(t *t " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1725148196), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAccountCurrency(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -475,7 +476,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAccountCurren DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte("\n"+ + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte("\n"+ "\n"+ "\n"+ "\n"+ - "\n"), 0, nil, nil, nil, nil, nil) + "\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -574,7 +575,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAccountCurren } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAmount(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -582,7 +583,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAmount(t *tes DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -599,13 +600,13 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAmount(t *tes " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, int64(1234500), allNewTransactions[0].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -622,7 +623,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAmount(t *tes " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -630,7 +631,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseValidAmount(t *tes } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -638,7 +639,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidAmount(t *t DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -655,10 +656,10 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidAmount(t *t " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -675,10 +676,10 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidAmount(t *t " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -695,12 +696,12 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseInvalidAmount(t *t " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestGnuCashTransactionDatabaseFileParseImportedData_ParseDescription(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -708,7 +709,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseDescription(t *tes DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -726,7 +727,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseDescription(t *tes " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -734,7 +735,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_ParseDescription(t *tes } func TestGnuCashTransactionDatabaseFileParseImportedData_SkipZeroAmountTransaction(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -742,7 +743,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_SkipZeroAmountTransacti DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -755,12 +756,12 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_SkipZeroAmountTransacti " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestGnuCashTransactionDatabaseFileParseImportedData_NotSupportedToParseSplitTransaction(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -768,7 +769,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_NotSupportedToParseSpli DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " Test Category2\n"+ @@ -805,12 +806,12 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_NotSupportedToParseSpli " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotSupportedSplitTransactions.Message) } func TestGnuCashTransactionDatabaseFileParseImportedData_MissingAccountRequiredNode(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -819,7 +820,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MissingAccountRequiredN } // Missing Account Currency Node - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ "\n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestGnuCashTransactionDatabaseFileParseImportedData_MissingTransactionRequiredNode(t *testing.T) { - converter := GnuCashTransactionDataImporter + importer := GnuCashTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -886,7 +887,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MissingTransactionRequi } // Missing Transaction Time Node - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -900,22 +901,22 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MissingTransactionRequi " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingTransactionTime.Message) // Missing Transaction Splits Node - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ " 2024-09-01 00:00:00 +0000\n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidGnuCashFile.Message) // Missing Transaction Split Quantity Node - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -930,11 +931,11 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MissingTransactionRequi " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) // Missing Transaction Split Account Node - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( gnucashCommonValidDataCaseHeader+ "\n"+ " \n"+ @@ -950,7 +951,7 @@ func TestGnuCashTransactionDatabaseFileParseImportedData_MissingTransactionRequi " \n"+ " \n"+ "\n"+ - gnucashCommonValidDataCaseFooter), 0, nil, nil, nil, nil, nil) + gnucashCommonValidDataCaseFooter), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingAccountData.Message) } diff --git a/pkg/converters/iif/iif_transaction_data_file_importer.go b/pkg/converters/iif/iif_transaction_data_file_importer.go index b12d5cfc..fca7ba98 100644 --- a/pkg/converters/iif/iif_transaction_data_file_importer.go +++ b/pkg/converters/iif/iif_transaction_data_file_importer.go @@ -23,7 +23,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the intuit interchange format (iif) data -func (c *iifTransactionDataFileImporter) 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 *iifTransactionDataFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { iifDataReader := createNewIifDataReader(data) accountDatasets, transactionDatasets, err := iifDataReader.read(ctx) @@ -39,5 +39,5 @@ func (c *iifTransactionDataFileImporter) ParseImportedData(ctx core.Context, use dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(iifTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/iif/iif_transaction_data_file_importer_test.go b/pkg/converters/iif/iif_transaction_data_file_importer_test.go index 177ad419..9281d630 100644 --- a/pkg/converters/iif/iif_transaction_data_file_importer_test.go +++ b/pkg/converters/iif/iif_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestIIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestIIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "!ACCNT\tNAME\tACCNTTYPE\n"+ "ACCNT\tTest Account\tBANK\n"+ "ACCNT\tTest Account2\tBANK\n"+ @@ -49,7 +50,7 @@ func TestIIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) "ENDTRNS\t\t\t\t\n"+ "TRNS\tCREDIT CARD\t09/07/2024\tTest Category2\t34.56\n"+ "SPL\tCREDIT CARD\t09/07/2024\tTest Account2\t-34.56\n"+ - "ENDTRNS\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -132,7 +133,7 @@ func TestIIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) } func TestIIFTransactionDataFileParseImportedData_MinimumValidDataWithoutAccountData(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -140,13 +141,13 @@ func TestIIFTransactionDataFileParseImportedData_MinimumValidDataWithoutAccountD DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Category\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -162,7 +163,7 @@ func TestIIFTransactionDataFileParseImportedData_MinimumValidDataWithoutAccountD } func TestIIFTransactionDataFileParseImportedData_MultipleDataset(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -170,7 +171,7 @@ func TestIIFTransactionDataFileParseImportedData_MultipleDataset(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!ACCNT\tNAME\tACCNTTYPE\n"+ "ACCNT\tTest Account3\tBANK\n"+ "ACCNT\tTest Account4\tBANK\n"+ @@ -202,7 +203,7 @@ func TestIIFTransactionDataFileParseImportedData_MultipleDataset(t *testing.T) { "ENDTRNS\t\t\t\t\n"+ "!ACCNT\tTEST\tNAME\tACCNTTYPE\n"+ "ACCNT\t\tTest Category\tINC\n"+ - "ACCNT\t\tTest Category2\tEXP\n"), 0, nil, nil, nil, nil, nil) + "ACCNT\t\tTest Category2\tEXP\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -247,7 +248,7 @@ func TestIIFTransactionDataFileParseImportedData_MultipleDataset(t *testing.T) { } func TestIIFTransactionDataFileParseImportedData_ParseCategoryAndSubCategory(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -255,7 +256,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseCategoryAndSubCategory(t * DefaultCurrency: "CNY", } - allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, allNewSubExpenseCategories, allNewSubIncomeCategories, _, _, err := importer.ParseImportedData(context, user, []byte( "!ACCNT\tNAME\tACCNTTYPE\n"+ "ACCNT\tTest Parent Category:Test Category\tINC\n"+ "ACCNT\tTest Parent Category2:Test Category2\tEXP\n"+ @@ -267,7 +268,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseCategoryAndSubCategory(t * "ENDTRNS\t\t\t\n"+ "TRNS\t09/02/2024\tTest Account2\t-123.45\n"+ "SPL\t09/02/2024\tTest Parent Category2:Test Category2\t123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -299,7 +300,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseCategoryAndSubCategory(t * } func TestIIFTransactionDataFileParseImportedData_ParseYearMonthDayFormatTime(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -307,7 +308,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseYearMonthDayFormatTime(t * DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ @@ -322,7 +323,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseYearMonthDayFormatTime(t * "ENDTRNS\t\t\t\n"+ "TRNS\t2024/9/4\tTest Account\t123.45\n"+ "SPL\t2024/9/4\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -334,7 +335,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseYearMonthDayFormatTime(t * } func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayYearFormatTime(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -342,7 +343,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayYearFormatTim DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ @@ -354,7 +355,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayYearFormatTim "ENDTRNS\t\t\t\n"+ "TRNS\t9/3/2024\tTest Account\t123.45\n"+ "SPL\t9/3/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -365,7 +366,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayYearFormatTim } func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayTwoDigitsYearFormatTime(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -373,7 +374,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayTwoDigitsYear DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ @@ -385,7 +386,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayTwoDigitsYear "ENDTRNS\t\t\t\n"+ "TRNS\t24/9/3\tTest Account\t123.45\n"+ "SPL\t24/9/3\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -396,7 +397,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseShortMonthDayTwoDigitsYear } func TestIIFTransactionDataFileParseImportedData_ParseInvalidTime(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -404,36 +405,36 @@ func TestIIFTransactionDataFileParseImportedData_ParseInvalidTime(t *testing.T) DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09-01-2024\tTest Account\t123.45\n"+ "SPL\t09-01-2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t2024-09-01\tTest Account\t123.45\n"+ "SPL\t2024-09-01\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t9/24\tTest Account\t123.45\n"+ "SPL\t9/24\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestIIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparator(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -441,13 +442,13 @@ func TestIIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparat DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t9/01/2024\tTest Account\t123,456.78\n"+ "SPL\t9/01/2024\tTest Account2\t-123,456.78\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -456,7 +457,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparat } func TestIIFTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -464,27 +465,27 @@ func TestIIFTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123 45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123 45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestIIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -492,25 +493,25 @@ func TestIIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!SPL\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!ENDTRNS\t\t\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t\"Test\"\t123.45\t\"foo bar\t#test\"\n"+ "SPL\t09/01/2024\tTest Account2\t\t-123.45\t\n"+ - "ENDTRNS\t\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "foo bar\t#test", allNewTransactions[0].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!SPL\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!ENDTRNS\t\t\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\tTest\t123.45\t\n"+ "SPL\t09/01/2024\tTest Account2\t\t-123.45\t\n"+ - "ENDTRNS\t\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -518,7 +519,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) } func TestIIFTransactionDataFileParseImportedData_ParseSplitTransaction(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -526,7 +527,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransaction(t *testin DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!ACCNT\tNAME\tACCNTTYPE\n"+ "ACCNT\tTest Category\tINC\n"+ "ACCNT\tTest Category2\tEXP\n"+ @@ -552,7 +553,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransaction(t *testin "TRNS\t09/05/2024\tTest Category2\t100.00\n"+ "SPL\t09/05/2024\tTest Account3\t-40.00\n"+ "SPL\t09/05/2024\tTest Account4\t-60.00\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -651,7 +652,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransaction(t *testin } func TestIIFTransactionDataFileParseImportedData_ParseSplitTransactionDescription(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -659,21 +660,21 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransactionDescriptio DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!SPL\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!ENDTRNS\t\t\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t\"Test\"\t123.45\t\"foo bar\t#test\"\n"+ "SPL\t09/01/2024\tTest Account2\t\t-100.00\t\"foo\ttest#bar\"\n"+ "SPL\t09/01/2024\tTest Account3\t\t-23.45\t\n"+ - "ENDTRNS\t\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 2, len(allNewTransactions)) assert.Equal(t, "foo\ttest#bar", allNewTransactions[0].Comment) assert.Equal(t, "foo bar\t#test", allNewTransactions[1].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!SPL\tDATE\tACCNT\tNAME\tAMOUNT\tMEMO\n"+ "!ENDTRNS\t\t\t\t\t\n"+ @@ -681,7 +682,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransactionDescriptio "SPL\t09/01/2024\tTest Account2\t\t-100.00\t\"test\"\n"+ "SPL\t09/01/2024\tTest Account3\tfoo\t-12.34\t\n"+ "SPL\t09/01/2024\tTest Account4\t\t-11.11\t\n"+ - "ENDTRNS\t\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 3, len(allNewTransactions)) @@ -691,7 +692,7 @@ func TestIIFTransactionDataFileParseImportedData_ParseSplitTransactionDescriptio } func TestIIFTransactionDataFileParseImportedData_NotSupportedSplitTransaction(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -700,52 +701,52 @@ func TestIIFTransactionDataFileParseImportedData_NotSupportedSplitTransaction(t } // Opening balance transaction - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tTRNSTYPE\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tTRNSTYPE\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\t\n"+ "TRNS\tBEGINBALCHECK\t09/01/2024\tTest Account\t123.45\n"+ "SPL\tBEGINBALCHECK\t09/01/2024\tTest Account2\t-100.00\n"+ "SPL\tBEGINBALCHECK\t09/01/2024\tTest Account3\t-23.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotSupportedSplitTransactions.Message) // Transaction with invalid amount - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123 45\n"+ "SPL\t09/01/2024\tTest Account2\t-100.00\n"+ "SPL\t09/01/2024\tTest Account3\t-23.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) // Transaction split data with invalid amount - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-100 00\n"+ "SPL\t09/01/2024\tTest Account3\t-23.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) // Transaction amount not equal to sum of split data amount - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.00\n"+ "SPL\t09/01/2024\tTest Account2\t-100.00\n"+ "SPL\t09/01/2024\tTest Account3\t-23.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotSupportedSplitTransactions.Message) } func TestIIFTransactionDataFileParseImportedData_InvalidDataLines(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -754,75 +755,75 @@ func TestIIFTransactionDataFileParseImportedData_InvalidDataLines(t *testing.T) } //Missing Transaction Line - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction And Split Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Split Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction End Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ - "SPL\t09/01/2024\tTest Account2\t-123.45\n"), 0, nil, nil, nil, nil, nil) + "SPL\t09/01/2024\tTest Account2\t-123.45\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction End Line (following is another header) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ "!ACCNT\tNAME\tACCNTTYPE\n"+ - "ACCNT\tTest Account\tBANK\n"), 0, nil, nil, nil, nil, nil) + "ACCNT\tTest Account\tBANK\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Invalid Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ "TEST\t\t\t\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Repeat Transaction Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Repeat Transaction End Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\t\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\t\n"+ "!ENDTRNS\t\t\t\n"+ @@ -830,12 +831,12 @@ func TestIIFTransactionDataFileParseImportedData_InvalidDataLines(t *testing.T) "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ "ENDTRNS\t\t\t\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) } func TestIIFTransactionDataFileParseImportedData_InvalidHeaderLines(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -844,49 +845,49 @@ func TestIIFTransactionDataFileParseImportedData_InvalidHeaderLines(t *testing.T } // Missing All Sample Lines - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction Sample Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!SPL\tDATE\tACCNT\tAMOUNT\n"+ - "!ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "!ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Split Sample Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ - "!ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "!ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction End Sample Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ - "!SPL\tDATE\tACCNT\tAMOUNT\n"), 0, nil, nil, nil, nil, nil) + "!SPL\tDATE\tACCNT\tAMOUNT\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Missing Transaction End Sample Line (following is data line) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!SPL\tDATE\tACCNT\tAMOUNT\n"+ "TRNS\t09/01/2024\tTest Account\t123.45\n"+ "SPL\t09/01/2024\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) // Invalid Sample Line - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\tAMOUNT\n"+ "!TEST\tDATE\tACCNT\tAMOUNT\n"+ - "!ENDTRNS\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "!ENDTRNS\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidIIFFile.Message) } func TestIIFTransactionDataFileParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := IifTransactionDataFileImporter + importer := IifTransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -895,32 +896,32 @@ func TestIIFTransactionDataFileParseImportedData_MissingRequiredColumn(t *testin } // Missing Date Column - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!TRNS\tACCNT\tAMOUNT\t\n"+ "!SPL\tACCNT\tAMOUNT\t\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\tTest Account\t123.45\n"+ "SPL\tTest Account2\t-123.45\n"+ - "ENDTRNS\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Account Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tAMOUNT\t\n"+ "!SPL\tDATE\tAMOUNT\t\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\t123.45\n"+ "SPL\t09/01/2024\t-123.45\n"+ - "ENDTRNS\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!TRNS\tDATE\tACCNT\t\n"+ "!SPL\tDATE\tACCNT\t\n"+ "!ENDTRNS\t\t\t\n"+ "TRNS\t09/01/2024\tTest Account\n"+ "SPL\t09/01/2024\tTest Account2\n"+ - "ENDTRNS\t\t\t\t\n"), 0, nil, nil, nil, nil, nil) + "ENDTRNS\t\t\t\t\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } diff --git a/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer.go b/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer.go index 272be036..9741dceb 100644 --- a/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer.go +++ b/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer.go @@ -27,7 +27,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the jd.com finance transaction csv data -func (c *jdComFinanceTransactionDataCsvFileImporter) 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 *jdComFinanceTransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { fallback := unicode.UTF8.NewDecoder() reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback)) @@ -60,5 +60,5 @@ func (c *jdComFinanceTransactionDataCsvFileImporter) ParseImportedData(ctx core. transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, jdComFinanceTransactionSupportedColumns, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(jdComFinanceTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer_test.go b/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer_test.go index 5e2c53d5..3f698115 100644 --- a/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer_test.go +++ b/pkg/converters/jdcom/jdcom_finance_transaction_data_csv_file_importer_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -13,7 +14,7 @@ import ( ) func TestJDComFinanceCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -30,7 +31,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MinimumValidData(t *testin "2025-09-01 12:34:56,xxx,xxx,123.45,银行卡,交易成功,支出,其他网购\n" + "2025-09-01 23:59:59,xxx,京东钱包余额充值,0.05,银行卡,交易成功,不计收支,余额\n" + "2025-09-02 23:59:59,xxx,京东余额提现,0.03,银行卡,交易成功,不计收支,余额\n" - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 4, len(allNewTransactions)) @@ -93,7 +94,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MinimumValidData(t *testin } func TestJDComFinanceCsvFileImporterParseImportedData_ParseRefundTransaction(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -110,7 +111,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseRefundTransaction(t * "2025-09-01 02:34:56,xxx,xxx,0.12(已全额退款),银行卡,交易成功,不计收支\n" + "2025-09-02 01:23:45,xxx,xxx,3.45,银行卡,退款成功,不计收支\n" + "2025-09-02 02:34:56,xxx,xxx,123.45(已退款3.45),银行卡,交易成功,支出\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(1234567890), allNewTransactions[0].Uid) @@ -139,7 +140,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseRefundTransaction(t * } func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -153,7 +154,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidTime(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01T01:23:45,xxx,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) data2 := "导出信息:\n" + @@ -162,12 +163,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidTime(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "09/01/2025 01:23:45,xxx,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -181,12 +182,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidType(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,交易成功,转账\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -200,12 +201,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseInvalidAmount(t *test "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,¥0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -220,7 +221,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支,交易分类\n" + "2025-09-01 01:23:45,xxx,京东钱包余额充值,0.05,银行卡,交易成功,不计收支,余额\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -235,7 +236,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支,交易分类\n" + "2025-09-01 01:23:45,xxx,京东余额提现,0.05,银行卡,交易成功,不计收支,余额\n" - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -252,7 +253,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "2025-09-01 01:23:45,xxx,京东小金库-转入,0.05,余额,交易成功,不计收支,小金库\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -269,7 +270,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "2025-09-01 01:23:45,xxx,京东小金库-转出,0.05,余额,交易成功,不计收支,小金库\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -286,7 +287,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "2025-09-01 01:23:45,xxx,价保退款,0.05,银行卡,交易成功,不计收支,其他\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data5), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data5), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -302,7 +303,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin "2025-09-01 01:23:45,xxx,白条主动还款,0.05,银行卡,交易成功,不计收支,白条\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data6), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data6), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -312,7 +313,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseAccountName(t *testin } func TestJDComFinanceCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -326,7 +327,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseDescription(t *testin "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,,0.12,银行卡,交易成功,支出\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -338,7 +339,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseDescription(t *testin "\n" + "交易时间,商户名称,交易说明,交易说明,金额,收/付款方式,交易状态,收/支,备注\n" + "2025-09-01 01:23:45,xxx,xxx,Test,0.12,银行卡,交易成功,支出,\"foo\"\"bar,\ntest\"\n" - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "foo\"bar,\ntest", allNewTransactions[0].Comment) @@ -348,13 +349,13 @@ func TestJDComFinanceCsvFileImporterParseImportedData_ParseDescription(t *testin "\n" + "交易时间,商户名称,交易说明,交易说明,金额,收/付款方式,交易状态,收/支,备注\n" + "2025-09-01 01:23:45,xxx,xxx,Test,0.12,银行卡,交易成功,支出,\n" - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "Test", allNewTransactions[0].Comment) } func TestJDComFinanceCsvFileImporterParseImportedData_SkipUnknownStatusTransaction(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -368,12 +369,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_SkipUnknownStatusTransacti "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,xxxx,支出\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_SkipUnknownMemoTransferTransaction(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -387,12 +388,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_SkipUnknownMemoTransferTra "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,交易成功,不计收支\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_MissingFileHeader(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -402,15 +403,15 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingFileHeader(t *testi data := "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -425,7 +426,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" + "xxx,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) // Missing Merchant Name Column @@ -435,7 +436,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,交易说明,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Transaction Memo Column @@ -445,7 +446,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,商户名称,金额,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,0.12,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column @@ -455,7 +456,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,商户名称,交易说明,收/付款方式,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,银行卡,交易成功,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Related Account Column @@ -465,7 +466,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,商户名称,交易说明,金额,交易状态,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,交易成功,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data5), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data5), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Status Column @@ -475,7 +476,7 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,收/支\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,支出\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data6), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data6), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column @@ -485,12 +486,12 @@ func TestJDComFinanceCsvFileImporterParseImportedData_MissingRequiredColumn(t *t "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态\n" + "2025-09-01 01:23:45,xxx,xxx,0.12,银行卡,交易成功\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data7), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data7), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } func TestJDComFinanceCsvFileImporterParseImportedData_NoTransactionData(t *testing.T) { - converter := JDComFinanceTransactionDataCsvFileImporter + importer := JDComFinanceTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -503,6 +504,6 @@ func TestJDComFinanceCsvFileImporterParseImportedData_NoTransactionData(t *testi "日期区间:2025-01-01 至 2025-09-01\n" + "\n" + "交易时间,商户名称,交易说明,金额,收/付款方式,交易状态,收/支\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } diff --git a/pkg/converters/mt/mt_transaction_data_file_importer.go b/pkg/converters/mt/mt_transaction_data_file_importer.go index ef53b727..435d749d 100644 --- a/pkg/converters/mt/mt_transaction_data_file_importer.go +++ b/pkg/converters/mt/mt_transaction_data_file_importer.go @@ -22,7 +22,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the mt940 file statement data -func (c *mt940TransactionDataFileImporter) 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 *mt940TransactionDataFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { mt940DataReader := createNewMT940FileReader(data) mt940Data, err := mt940DataReader.read(ctx) @@ -38,5 +38,5 @@ func (c *mt940TransactionDataFileImporter) ParseImportedData(ctx core.Context, u dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(mt940TransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/mt/mt_transaction_data_file_importer_test.go b/pkg/converters/mt/mt_transaction_data_file_importer_test.go index 390c3202..162eafa3 100644 --- a/pkg/converters/mt/mt_transaction_data_file_importer_test.go +++ b/pkg/converters/mt/mt_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestMT940TransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestMT940TransactionDataFileParseImportedData_MinimumValidData(t *testing.T DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -31,7 +32,7 @@ func TestMT940TransactionDataFileParseImportedData_MinimumValidData(t *testing.T :61:2506020603D234,56NTRFFOOBAR :86:Transaction 2 :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -70,7 +71,7 @@ func TestMT940TransactionDataFileParseImportedData_MinimumValidData(t *testing.T } func TestMT940TransactionDataFileParseImportedData_ParseTransactionValidAmountAndCurrency(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -78,7 +79,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionValidAmountAn DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -91,7 +92,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionValidAmountAn :61:250603C1,NTRFTEST :86:Transaction 3 :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 3, len(allNewTransactions)) @@ -101,7 +102,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionValidAmountAn } func TestMT940TransactionDataFileParseImportedData_ParseTransactionInvalidAmountAndCurrency(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -109,7 +110,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionInvalidAmount DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -117,10 +118,10 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionInvalidAmount :60F:C250601CNY123,45 :61:2506010602C123 45NTRFTEST :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidMT940File.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -128,12 +129,12 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionInvalidAmount :60F:C250601CNY123,45 :61:2506010602C12.45NTRFTEST :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidMT940File.Message) } func TestMT940TransactionDataFileParseImportedData_ParseTransactionType(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -141,7 +142,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionType(t *testi DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -156,7 +157,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionType(t *testi :61:250604RD123,45NTRFTEST :86:Transaction 4 :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 4, len(allNewTransactions)) @@ -167,7 +168,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseTransactionType(t *testi } func TestMT940TransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -175,7 +176,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseDescription(t *testing.T DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :25:12345678 @@ -186,7 +187,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseDescription(t *testing.T Part 2 Part 3 :62F:C250601CNY123,45 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -194,7 +195,7 @@ func TestMT940TransactionDataFileParseImportedData_ParseDescription(t *testing.T } func TestMT940TransactionDataFileParseImportedData_MissingRequiredField(t *testing.T) { - converter := MT940TransactionDataFileImporter + importer := MT940TransactionDataFileImporter context := core.NewNullContext() user := &models.User{ @@ -203,12 +204,12 @@ func TestMT940TransactionDataFileParseImportedData_MissingRequiredField(t *testi } // Missing opening balance and closing balance - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( `{1:F01TESTBANK123456789}{2:I940TESTBANK}{4: :20:123456789 :28C:123/1 :61:250601C123,45NTRFTEST :86:Transaction 1 - -}`), 0, nil, nil, nil, nil, nil) + -}`), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } diff --git a/pkg/converters/ofx/ofx_transaction_data_file_importer.go b/pkg/converters/ofx/ofx_transaction_data_file_importer.go index 2d409c86..3c1d0329 100644 --- a/pkg/converters/ofx/ofx_transaction_data_file_importer.go +++ b/pkg/converters/ofx/ofx_transaction_data_file_importer.go @@ -23,7 +23,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the open financial exchange (ofx) file transaction data -func (c *ofxTransactionDataImporter) 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 *ofxTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { ofxDataReader, err := createNewOFXFileReader(ctx, data) if err != nil { @@ -44,5 +44,5 @@ func (c *ofxTransactionDataImporter) ParseImportedData(ctx core.Context, user *m dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(ofxTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/ofx/ofx_transaction_data_file_importer_test.go b/pkg/converters/ofx/ofx_transaction_data_file_importer_test.go index 02a42505..fb7722f7 100644 --- a/pkg/converters/ofx/ofx_transaction_data_file_importer_test.go +++ b/pkg/converters/ofx/ofx_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -76,7 +77,7 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -160,7 +161,7 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) } func TestOFXTransactionDataFileParseImportedData_ParseAccountTo(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -168,7 +169,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAccountTo(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -210,7 +211,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAccountTo(t *testing.T) { " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -243,7 +244,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAccountTo(t *testing.T) { } func TestOFXTransactionDataFileParseImportedData_ParseValidTransactionTime(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -251,7 +252,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseValidTransactionTime(t *te DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -295,7 +296,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseValidTransactionTime(t *te " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -310,7 +311,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseValidTransactionTime(t *te } func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -318,7 +319,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t * DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -337,10 +338,10 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t * " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -359,10 +360,10 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t * " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -381,10 +382,10 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t * " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -403,12 +404,12 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t * " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestOFXTransactionDataFileParseImportedData_ParseAmount_CommaAsDecimalPoint(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -416,7 +417,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAmount_CommaAsDecimalPoint DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -435,7 +436,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAmount_CommaAsDecimalPoint " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -444,7 +445,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseAmount_CommaAsDecimalPoint } func TestOFXTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -452,7 +453,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -471,12 +472,12 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestOFXTransactionDataFileParseImportedData_ParseTransactionCurrency(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -484,7 +485,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseTransactionCurrency(t *tes DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -504,7 +505,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseTransactionCurrency(t *tes " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -512,7 +513,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseTransactionCurrency(t *tes } func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -520,7 +521,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -541,13 +542,13 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "foo bar\t#test", allNewTransactions[0].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -567,13 +568,13 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "Test", allNewTransactions[0].Comment) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -595,7 +596,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -603,7 +604,7 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T) } func TestOFXTransactionDataFileParseImportedData_MissingAccountFromNode(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -612,7 +613,7 @@ func TestOFXTransactionDataFileParseImportedData_MissingAccountFromNode(t *testi } // Missing Posted Date Node - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -628,12 +629,12 @@ func TestOFXTransactionDataFileParseImportedData_MissingAccountFromNode(t *testi " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingAccountData.Message) } func TestOFXTransactionDataFileParseImportedData_MissingCurrencyNode(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -642,7 +643,7 @@ func TestOFXTransactionDataFileParseImportedData_MissingCurrencyNode(t *testing. } // Missing Default Currency Node - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -660,12 +661,12 @@ func TestOFXTransactionDataFileParseImportedData_MissingCurrencyNode(t *testing. " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message) } func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode(t *testing.T) { - converter := OFXTransactionDataImporter + importer := OFXTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -674,7 +675,7 @@ func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode( } // Missing Posted Date Node - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -692,11 +693,11 @@ func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode( " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingTransactionTime.Message) // Missing Transaction Type Node - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -714,11 +715,11 @@ func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode( " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message) // Missing Amount Node - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "\n"+ " \n"+ " \n"+ @@ -736,6 +737,6 @@ func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode( " \n"+ " \n"+ " \n"+ - ""), 0, nil, nil, nil, nil, nil) + ""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } diff --git a/pkg/converters/qif/qif_transaction_data_file_importer.go b/pkg/converters/qif/qif_transaction_data_file_importer.go index 38799cc6..ff04e57b 100644 --- a/pkg/converters/qif/qif_transaction_data_file_importer.go +++ b/pkg/converters/qif/qif_transaction_data_file_importer.go @@ -35,7 +35,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the quicken interchange format (qif) transaction data -func (c *qifTransactionDataImporter) 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 *qifTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { qifDataReader := createNewQifDataReader(data) qifData, err := qifDataReader.read(ctx) @@ -51,5 +51,5 @@ func (c *qifTransactionDataImporter) ParseImportedData(ctx core.Context, user *m dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(qifTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/qif/qif_transaction_data_file_importer_test.go b/pkg/converters/qif/qif_transaction_data_file_importer_test.go index bbec9fd4..6c199ea6 100644 --- a/pkg/converters/qif/qif_transaction_data_file_importer_test.go +++ b/pkg/converters/qif/qif_transaction_data_file_importer_test.go @@ -5,6 +5,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -12,7 +13,7 @@ import ( ) func TestQIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -20,7 +21,7 @@ func TestQIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T123.45\n"+ @@ -42,7 +43,7 @@ func TestQIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) "D2024-09-05\n"+ "T0.06\n"+ "L[Test Account2]\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -113,7 +114,7 @@ func TestQIFTransactionDataFileParseImportedData_MinimumValidData(t *testing.T) } func TestQIFTransactionDataFileParseImportedData_ParseYearMonthDayDateFormatTime(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -121,7 +122,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseYearMonthDayDateFormatTime DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123.45\n"+ @@ -137,7 +138,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseYearMonthDayDateFormatTime "^\n"+ "D2024'9.5\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -151,7 +152,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseYearMonthDayDateFormatTime } func TestQIFTransactionDataFileParseImportedData_ParseMonthDayYearDateFormatTime(t *testing.T) { - converter := QifMonthDayYearTransactionDataImporter + importer := QifMonthDayYearTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -159,7 +160,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseMonthDayYearDateFormatTime DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D09-01-2024\n"+ "T-123.45\n"+ @@ -175,7 +176,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseMonthDayYearDateFormatTime "^\n"+ "D9.5'2024\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -189,7 +190,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseMonthDayYearDateFormatTime } func TestQIFTransactionDataFileParseImportedData_ParseDayYearMonthDateFormatTime(t *testing.T) { - converter := QifDayMonthYearTransactionDataImporter + importer := QifDayMonthYearTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -197,7 +198,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseDayYearMonthDateFormatTime DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D01-09-2024\n"+ "T-123.45\n"+ @@ -213,7 +214,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseDayYearMonthDateFormatTime "^\n"+ "D5'9.2024\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -227,7 +228,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseDayYearMonthDateFormatTime } func TestQIFTransactionDataFileParseImportedData_ParseShortYearMonthDayDateFormatTime(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -235,7 +236,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseShortYearMonthDayDateForma DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D24-09-01\n"+ "T-123.45\n"+ @@ -251,7 +252,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseShortYearMonthDayDateForma "^\n"+ "D24'9.5\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -265,7 +266,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseShortYearMonthDayDateForma } func TestQIFTransactionDataFileParseImportedData_ParseInvalidTime(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -273,16 +274,16 @@ func TestQIFTransactionDataFileParseImportedData_ParseInvalidTime(t *testing.T) DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024 09 01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestQIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparator(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -290,11 +291,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparat DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123,456.78\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) @@ -304,7 +305,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseAmountWithThousandsSeparat } func TestQIFTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -312,16 +313,16 @@ func TestQIFTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T DefaultCurrency: "CNY", } - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123 45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -329,11 +330,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Cash\n"+ "D2024-09-01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -342,11 +343,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) assert.Equal(t, int64(1725148800), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!Type:CCard\n"+ "D2024-09-01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -355,11 +356,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) assert.Equal(t, int64(1725148800), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!Type:Oth A\n"+ "D2024-09-01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -368,11 +369,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) assert.Equal(t, int64(1725148800), utils.GetUnixTimeFromTransactionTime(allNewTransactions[0].TransactionTime)) assert.Equal(t, int64(12345), allNewTransactions[0].Amount) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!Type:Oth L\n"+ "D2024-09-01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -383,7 +384,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccountType(t *testing.T) } func TestQIFTransactionDataFileParseImportedData_ParseAccount(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -391,14 +392,14 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccount(t *testing.T) { DefaultCurrency: "CNY", } - allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, allNewAccounts, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Account\n"+ "NTest Account\n"+ "^\n"+ "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -412,7 +413,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseAccount(t *testing.T) { } func TestQIFTransactionDataFileParseImportedData_ParseAmountWithLeadingPlusSign(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -420,11 +421,11 @@ func TestQIFTransactionDataFileParseImportedData_ParseAmountWithLeadingPlusSign( DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T+123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -432,7 +433,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseAmountWithLeadingPlusSign( } func TestQIFTransactionDataFileParseImportedData_ParseSubCategory(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -440,12 +441,12 @@ func TestQIFTransactionDataFileParseImportedData_ParseSubCategory(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, allNewSubExpenseCategories, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, allNewSubExpenseCategories, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123.45\n"+ "LTest Category:Sub Category\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -458,7 +459,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseSubCategory(t *testing.T) } func TestQIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -466,7 +467,7 @@ func TestQIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) DefaultCurrency: "CNY", } - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ "T-123.45\n"+ @@ -476,7 +477,24 @@ func TestQIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) "D2024-09-02\n"+ "T-234.56\n"+ "PTest2\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) + + assert.Nil(t, err) + assert.Equal(t, 2, len(allNewTransactions)) + assert.Equal(t, "foo bar\t#test", allNewTransactions[0].Comment) + assert.Equal(t, "", allNewTransactions[1].Comment) + + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "!Type:Bank\n"+ + "D2024-09-01\n"+ + "T-123.45\n"+ + "PTest\n"+ + "Mfoo bar\t#test\n"+ + "^\n"+ + "D2024-09-02\n"+ + "T-234.56\n"+ + "PTest2\n"+ + "^\n"), 0, converter.DefaultImporterOptions.WithPayeeAsDescription(), nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 2, len(allNewTransactions)) @@ -484,8 +502,41 @@ func TestQIFTransactionDataFileParseImportedData_ParseDescription(t *testing.T) assert.Equal(t, "Test2", allNewTransactions[1].Comment) } +func TestQIFTransactionDataFileParseImportedData_WithAdditionalOptions(t *testing.T) { + importer := QifYearMonthDayTransactionDataImporter + context := core.NewNullContext() + + user := &models.User{ + Uid: 1234567890, + DefaultCurrency: "CNY", + } + + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( + "!Type:Bank\n"+ + "D2024-09-01\n"+ + "T-123.45\n"+ + "PTest2\n"+ + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) + + assert.Nil(t, err) + assert.Equal(t, 1, len(allNewTransactions)) + assert.Equal(t, 0, len(allNewTransactions[0].OriginalTagNames)) + + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( + "!Type:Bank\n"+ + "D2024-09-01\n"+ + "T-123.45\n"+ + "PTest2\n"+ + "^\n"), 0, converter.DefaultImporterOptions.WithPayeeAsTag(), nil, nil, nil, nil, nil) + + assert.Nil(t, err) + assert.Equal(t, 1, len(allNewTransactions)) + assert.Equal(t, 1, len(allNewTransactions[0].OriginalTagNames)) + assert.Equal(t, "Test2", allNewTransactions[0].OriginalTagNames[0]) +} + func TestQIFTransactionDataFileParseImportedData_MissingRequiredFields(t *testing.T) { - converter := QifYearMonthDayTransactionDataImporter + importer := QifYearMonthDayTransactionDataImporter context := core.NewNullContext() user := &models.User{ @@ -494,16 +545,16 @@ func TestQIFTransactionDataFileParseImportedData_MissingRequiredFields(t *testin } // Missing Time Field - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "T-123.45\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingTransactionTime.Message) // Missing Amount Field - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte( + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte( "!Type:Bank\n"+ "D2024-09-01\n"+ - "^\n"), 0, nil, nil, nil, nil, nil) + "^\n"), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } diff --git a/pkg/converters/qif/qif_transaction_data_table.go b/pkg/converters/qif/qif_transaction_data_table.go index 500a6d61..8cb4ab41 100644 --- a/pkg/converters/qif/qif_transaction_data_table.go +++ b/pkg/converters/qif/qif_transaction_data_table.go @@ -22,6 +22,7 @@ var qifTransactionSupportedColumns = map[datatable.TransactionDataTableColumn]bo datatable.TRANSACTION_DATA_TABLE_AMOUNT: true, datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME: true, datatable.TRANSACTION_DATA_TABLE_DESCRIPTION: true, + datatable.TRANSACTION_DATA_TABLE_PAYEE: true, } // qifDateFormatType represents the quicken interchange format (qif) date format type @@ -184,8 +185,10 @@ func (t *qifTransactionDataRowIterator) parseTransaction(ctx core.Context, user if qifTransaction.Memo != "" { data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = qifTransaction.Memo - } else if qifTransaction.Payee != "" && qifTransaction.Payee != qifOpeningBalancePayeeText { - data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = qifTransaction.Payee + } + + if qifTransaction.Payee != "" && qifTransaction.Payee != qifOpeningBalancePayeeText { + data[datatable.TRANSACTION_DATA_TABLE_PAYEE] = qifTransaction.Payee } return data, nil diff --git a/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer.go b/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer.go index a9fa537d..0c7eeec7 100644 --- a/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer.go +++ b/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer.go @@ -27,7 +27,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the wechat pay transaction csv data -func (c *wechatPayTransactionDataCsvFileImporter) 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 *wechatPayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { fallback := unicode.UTF8.NewDecoder() reader := transform.NewReader(bytes.NewReader(data), unicode.BOMOverride(fallback)) @@ -58,5 +58,5 @@ func (c *wechatPayTransactionDataCsvFileImporter) ParseImportedData(ctx core.Con transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, wechatPayTransactionSupportedColumns, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(wechatPayTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer_test.go b/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer_test.go index 9aa48e9c..5c46eb6c 100644 --- a/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer_test.go +++ b/pkg/converters/wechat/wechat_pay_transaction_data_csv_file_importer_test.go @@ -6,6 +6,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/mayswind/ezbookkeeping/pkg/converters/converter" "github.com/mayswind/ezbookkeeping/pkg/core" "github.com/mayswind/ezbookkeeping/pkg/errs" "github.com/mayswind/ezbookkeeping/pkg/models" @@ -13,7 +14,7 @@ import ( ) func TestWeChatPayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -31,7 +32,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T "2024-09-01 12:34:56,商户消费,支出,¥123.45,支付成功\n" + "2024-09-01 23:59:59,零钱充值,/,¥0.05,充值完成\n" + "2024-09-02 23:59:59,零钱提现,/,¥0.03,提现已到账\n" - allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 4, len(allNewTransactions)) @@ -93,7 +94,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MinimumValidData(t *testing.T } func TestWeChatPayCsvFileImporterParseImportedData_ParseRefundTransaction(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -108,7 +109,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseRefundTransaction(t *tes "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01 01:23:45,xxx-退款,收入,¥0.12,已全额退款\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, int64(1234567890), allNewTransactions[0].Uid) @@ -120,7 +121,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseRefundTransaction(t *tes } func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -135,7 +136,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01T01:23:45,二维码收款,收入,¥0.12,已收钱\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) data2 := "微信支付账单明细,,,,\n" + @@ -145,12 +146,12 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidTime(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "09/01/2024 12:34:56,二维码收款,收入,¥0.12,已收钱\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message) } func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -165,12 +166,12 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidType(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01T01:23:45,xxx,,¥0.12,支付成功\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidAmount(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -185,12 +186,12 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseInvalidAmount(t *testing "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01 01:23:45,二维码收款,收入,¥,已收钱\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrAmountInvalid.Message) } func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -206,7 +207,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),支付方式,当前状态\n" + "2024-09-01 01:23:45,二维码收款,收入,¥0.12,/,已收钱\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -222,7 +223,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T "2024-09-01 01:23:45,xxx-退款,收入,¥0.12,test,已全额退款\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -238,7 +239,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T "2024-09-01 23:59:59,零钱充值,/,¥0.05,test,充值完成\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -255,7 +256,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T "2024-09-02 23:59:59,零钱提现,/,¥0.03,test,提现已到账\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -272,7 +273,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T "2024-09-03 23:59:59,信用卡还款,/,¥0.01,零钱,支付成功\n" assert.Nil(t, err) - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data5), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data5), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -281,7 +282,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseAccountName(t *testing.T } func TestWeChatPayCsvFileImporterParseImportedData_ParseDescription(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -296,7 +297,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseDescription(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态,备注\n" + "2024-09-01 01:23:45,二维码收款,收入,¥0.12,已收钱,\"/\"\n" - allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Nil(t, err) assert.Equal(t, 1, len(allNewTransactions)) @@ -309,7 +310,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseDescription(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,商品,收/支,金额(元),当前状态,备注\n" + "2024-09-01 01:23:45,二维码收款,Test,收入,¥0.12,已收钱,\"foo\"\"bar,\ntest\"\n" - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "foo\"bar,\ntest", allNewTransactions[0].Comment) @@ -320,13 +321,13 @@ func TestWeChatPayCsvFileImporterParseImportedData_ParseDescription(t *testing.T "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,商品,收/支,金额(元),当前状态,备注\n" + "2024-09-01 01:23:45,二维码收款,Test,收入,¥0.12,已收钱,\"\"\n" - allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + allNewTransactions, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.Equal(t, 1, len(allNewTransactions)) assert.Equal(t, "Test", allNewTransactions[0].Comment) } func TestWeChatPayCsvFileImporterParseImportedData_SkipUnknownTransferTransaction(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -341,12 +342,12 @@ func TestWeChatPayCsvFileImporterParseImportedData_SkipUnknownTransferTransactio "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01 23:59:59,/,/,¥0.05,充值完成\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } func TestWeChatPayCsvFileImporterParseImportedData_MissingFileHeader(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -356,15 +357,15 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingFileHeader(t *testing. data := "交易时间,交易类型,收/支,金额(元),当前状态\n" + "2024-09-01 01:23:45,二维码收款,收入,¥0.12,已收钱\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(""), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(""), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrInvalidFileHeader.Message) } func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -380,7 +381,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *test "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易类型,收/支,金额(元),当前状态\n" + "二维码收款,收入,¥0.12,已收钱\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data1), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data1), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Category Column @@ -391,7 +392,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *test "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,收/支,金额(元),当前状态\n" + "2024-09-01 01:23:45,收入,¥0.12,已收钱\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data2), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data2), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column @@ -402,7 +403,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *test "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,金额(元),当前状态\n" + "2024-09-01 01:23:45,二维码收款,¥0.12,已收钱\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data3), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data3), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column @@ -413,7 +414,7 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *test "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,当前状态\n" + "2024-09-01 01:23:45,二维码收款,收入,已收钱\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data4), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data4), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Status Column @@ -424,12 +425,12 @@ func TestWeChatPayCsvFileImporterParseImportedData_MissingRequiredColumn(t *test "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元)\n" + "2024-09-01 01:23:45,二维码收款,收入,¥0.12\n" - _, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(data5), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err = importer.ParseImportedData(context, user, []byte(data5), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } func TestWeChatPayCsvFileImporterParseImportedData_NoTransactionData(t *testing.T) { - converter := WeChatPayTransactionDataCsvFileImporter + importer := WeChatPayTransactionDataCsvFileImporter context := core.NewNullContext() user := &models.User{ @@ -443,6 +444,6 @@ func TestWeChatPayCsvFileImporterParseImportedData_NoTransactionData(t *testing. ",,,,\n" + "----------------------微信支付账单明细列表--------------------,,,,\n" + "交易时间,交易类型,收/支,金额(元),当前状态\n" - _, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(data), 0, nil, nil, nil, nil, nil) + _, _, _, _, _, _, err := importer.ParseImportedData(context, user, []byte(data), 0, converter.DefaultImporterOptions, nil, nil, nil, nil, nil) assert.EqualError(t, err, errs.ErrNotFoundTransactionDataInFile.Message) } diff --git a/pkg/converters/wechat/wechat_pay_transaction_data_xlsx_file_importer.go b/pkg/converters/wechat/wechat_pay_transaction_data_xlsx_file_importer.go index dc7c2448..51f281cc 100644 --- a/pkg/converters/wechat/wechat_pay_transaction_data_xlsx_file_importer.go +++ b/pkg/converters/wechat/wechat_pay_transaction_data_xlsx_file_importer.go @@ -21,7 +21,7 @@ var ( ) // ParseImportedData returns the imported data by parsing the wechat pay transaction csv data -func (c *wechatPayTransactionDataXlsxFileImporter) 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 *wechatPayTransactionDataXlsxFileImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, additionalOptions converter.TransactionDataImporterOptions, 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) { xlsxDataTable, err := excel.CreateNewExcelOOXMLFileBasicDataTable(data, false) if err != nil { @@ -49,5 +49,5 @@ func (c *wechatPayTransactionDataXlsxFileImporter) ParseImportedData(ctx core.Co transactionDataTable := datatable.CreateNewTransactionDataTableFromCommonDataTable(commonDataTable, wechatPayTransactionSupportedColumns, transactionRowParser) dataTableImporter := converter.CreateNewSimpleImporterWithTypeNameMapping(wechatPayTransactionTypeNameMapping) - return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) + return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, additionalOptions, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/src/consts/file.ts b/src/consts/file.ts index 55953715..8c0773ae 100644 --- a/src/consts/file.ts +++ b/src/consts/file.ts @@ -168,7 +168,11 @@ export const SUPPORTED_IMPORT_FILE_CATEGORY_AND_TYPES: ImportFileCategoryAndType type: 'qif_dmy', name: 'Day-month-year format', } - ] + ], + supportedAdditionalOptions: { + payeeAsTag: false, + payeeAsDescription: true + } }, { type: 'iif', diff --git a/src/core/base.ts b/src/core/base.ts index 3605a8a0..aaa4dfac 100644 --- a/src/core/base.ts +++ b/src/core/base.ts @@ -75,6 +75,11 @@ export interface NameNumeralValue { readonly value: number; } +export interface KeyAndName { + readonly key: string; + readonly name: string; +} + export interface TypeAndName { readonly type: number; readonly name: string; diff --git a/src/core/file.ts b/src/core/file.ts index cd7fc546..51401e67 100644 --- a/src/core/file.ts +++ b/src/core/file.ts @@ -68,6 +68,14 @@ export interface ImportFileCategoryAndTypes { readonly fileTypes: ImportFileType[]; } +export interface ImportFileTypeSupportedAdditionalOptions extends Record { + readonly payeeAsTag?: boolean; + readonly payeeAsDescription?: boolean; + readonly memberAsTag?: boolean; + readonly projectAsTag?: boolean; + readonly merchantAsTag?: boolean; +} + export interface ImportFileType extends ImportFileTypeAndExtensions { readonly type: string; readonly name: string; @@ -75,6 +83,7 @@ export interface ImportFileType extends ImportFileTypeAndExtensions { readonly subTypes?: ImportFileTypeSubType[]; readonly supportedEncodings?: string[]; readonly dataFromTextbox?: boolean; + readonly supportedAdditionalOptions?: ImportFileTypeSupportedAdditionalOptions; readonly document?: { readonly supportMultiLanguages: boolean | string; readonly anchor: string; @@ -99,6 +108,7 @@ export interface LocalizedImportFileType extends ImportFileTypeAndExtensions { readonly subTypes?: LocalizedImportFileTypeSubType[]; readonly supportedEncodings?: LocalizedImportFileTypeSupportedEncodings[]; readonly dataFromTextbox?: boolean; + readonly supportedAdditionalOptions?: ImportFileTypeSupportedAdditionalOptions; readonly document?: LocalizedImportFileDocument; } diff --git a/src/lib/services.ts b/src/lib/services.ts index d377e690..fc668a28 100644 --- a/src/lib/services.ts +++ b/src/lib/services.ts @@ -8,6 +8,9 @@ import type { import type { VersionInfo } from '@/core/version.ts'; +import type { + ImportFileTypeSupportedAdditionalOptions +} from '@/core/file.ts'; import { TransactionType } from '@/core/transaction.ts'; @@ -160,7 +163,8 @@ import { import { isDefined, - isBoolean + isBoolean, + objectFieldWithValueToArrayItem } from './common.ts'; import { getGoogleMapAPIKey, @@ -588,11 +592,16 @@ export default { timeout: DEFAULT_UPLOAD_API_TIMEOUT } as ApiRequestConfig); }, - parseImportTransaction: ({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): ApiResponsePromise => { + parseImportTransaction: ({ fileType, additionalOptions, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, additionalOptions?: ImportFileTypeSupportedAdditionalOptions, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): ApiResponsePromise => { + let textualAdditionalOptions: string | undefined = undefined; let textualColumnMapping: string | undefined = undefined; let textualTransactionTypeMapping: string | undefined = undefined; let textualHasHeaderLine: string | undefined = undefined; + if (additionalOptions) { + textualAdditionalOptions = objectFieldWithValueToArrayItem(additionalOptions, true).join(','); + } + if (columnMapping) { textualColumnMapping = JSON.stringify(columnMapping); } @@ -607,6 +616,7 @@ export default { return axios.postForm>('v1/transactions/parse_import.json', { fileType: fileType, + options: textualAdditionalOptions, fileEncoding: fileEncoding, file: importFile, columnMapping: textualColumnMapping, diff --git a/src/locales/de.json b/src/locales/de.json index 07e56c4d..91044946 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Datendatei", "Data to import": "Data to import", "Please select a file to import": "Bitte wählen Sie eine Datei zum Importieren aus", diff --git a/src/locales/en.json b/src/locales/en.json index ff98f4be..9e05cf6c 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Data File", "Data to import": "Data to import", "Please select a file to import": "Please select a file to import", diff --git a/src/locales/es.json b/src/locales/es.json index cc4067a8..59491c2d 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Archivo de datos", "Data to import": "Data to import", "Please select a file to import": "Please select a file to import", diff --git a/src/locales/fr.json b/src/locales/fr.json index 2b74217a..41a27906 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1885,6 +1885,9 @@ "Custom Script": "Script personnalisé", "Execute Custom Script": "Exécuter le script personnalisé", "Execute Custom Script to Parse Data": "Exécuter le script personnalisé pour analyser les données", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Fichier de données", "Data to import": "Données à importer", "Please select a file to import": "Veuillez sélectionner un fichier à importer", diff --git a/src/locales/helpers.ts b/src/locales/helpers.ts index ec8db763..a5d52e5b 100644 --- a/src/locales/helpers.ts +++ b/src/locales/helpers.ts @@ -1525,6 +1525,7 @@ export function useI18n() { subTypes: subTypes.length ? subTypes : undefined, supportedEncodings: supportedEncodings.length ? supportedEncodings : undefined, dataFromTextbox: fileType.dataFromTextbox, + supportedAdditionalOptions: fileType.supportedAdditionalOptions, document: document }; diff --git a/src/locales/it.json b/src/locales/it.json index a0b1822c..9b3a668f 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "File dati", "Data to import": "Dati da importare", "Please select a file to import": "Seleziona un file da importare", diff --git a/src/locales/ja.json b/src/locales/ja.json index e63232bd..993ef698 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "データファイル", "Data to import": "インポートするデータ", "Please select a file to import": "インポートするファイルを選択してください", diff --git a/src/locales/ko.json b/src/locales/ko.json index 6aad73b2..77bc0c7c 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1885,6 +1885,9 @@ "Custom Script": "사용자 정의 스크립트", "Execute Custom Script": "사용자 정의 스크립트 실행", "Execute Custom Script to Parse Data": "데이터 구문 분석을 위한 사용자 정의 스크립트 실행", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "데이터 파일", "Data to import": "가져올 데이터", "Please select a file to import": "가져올 파일을 선택하십시오", diff --git a/src/locales/nl.json b/src/locales/nl.json index 864bb9a3..25fab015 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Gegevensbestand", "Data to import": "Te importeren gegevens", "Please select a file to import": "Selecteer een bestand om te importeren", diff --git a/src/locales/pt_BR.json b/src/locales/pt_BR.json index a0afd707..c70ce4f5 100644 --- a/src/locales/pt_BR.json +++ b/src/locales/pt_BR.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Arquivo de Dados", "Data to import": "Dados para importar", "Please select a file to import": "Por favor, selecione um arquivo para importar", diff --git a/src/locales/ru.json b/src/locales/ru.json index 3438cbf3..c34544a5 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Файл данных", "Data to import": "Data to import", "Please select a file to import": "Please select a file to import", diff --git a/src/locales/th.json b/src/locales/th.json index 57217f0a..cd059f53 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -1885,6 +1885,9 @@ "Custom Script": "สคริปต์กำหนดเอง", "Execute Custom Script": "เรียกใช้สคริปต์กำหนดเอง", "Execute Custom Script to Parse Data": "เรียกใช้สคริปต์กำหนดเองเพื่อแยกข้อมูล", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "ไฟล์ข้อมูล", "Data to import": "ข้อมูลที่จะนำเข้า", "Please select a file to import": "กรุณาเลือกไฟล์เพื่อนำเข้า", diff --git a/src/locales/uk.json b/src/locales/uk.json index 3f113ee5..6cb3ebce 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Файл даних", "Data to import": "Дані для імпорту", "Please select a file to import": "Будь ласка, виберіть файл для імпорту", diff --git a/src/locales/vi.json b/src/locales/vi.json index 35440f88..0871fde9 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1885,6 +1885,9 @@ "Custom Script": "Custom Script", "Execute Custom Script": "Execute Custom Script", "Execute Custom Script to Parse Data": "Execute Custom Script to Parse Data", + "Additional Options": "Additional Options", + "Parse Payee as Tag": "Parse Payee as Tag", + "Parse Payee as Description": "Parse Payee as Description", "Data File": "Tệp dữ liệu", "Data to import": "Data to import", "Please select a file to import": "Please select a file to import", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index edde0519..0a97e27d 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1885,6 +1885,9 @@ "Custom Script": "自定义脚本", "Execute Custom Script": "执行自定义脚本", "Execute Custom Script to Parse Data": "执行自定义脚本解析数据", + "Additional Options": "附加选项", + "Parse Payee as Tag": "将收款人解析为标签", + "Parse Payee as Description": "将收款人解析为描述", "Data File": "数据文件", "Data to import": "要导入的数据", "Please select a file to import": "请选择要导入的文件", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index 11856636..24711cc8 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1885,6 +1885,9 @@ "Custom Script": "自訂腳本", "Execute Custom Script": "執行自訂腳本", "Execute Custom Script to Parse Data": "執行自訂腳本來解析資料", + "Additional Options": "附加選項", + "Parse Payee as Tag": "將收款人解析為標籤", + "Parse Payee as Description": "將收款人解析為描述", "Data File": "資料檔案", "Data to import": "要匯入的資料", "Please select a file to import": "請選擇要匯入的檔案", diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index d42e74ca..d0145c60 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -12,6 +12,7 @@ import { useExchangeRatesStore } from './exchangeRates.ts'; import { type BeforeResolveFunction, itemAndIndex, entries, keys } from '@/core/base.ts'; import { type TextualYearMonth, DateRange } from '@/core/datetime.ts'; import { CategoryType } from '@/core/category.ts'; +import type { ImportFileTypeSupportedAdditionalOptions } from '@/core/file.ts'; import { TransactionType, TransactionTagFilterType } from '@/core/transaction.ts'; import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts'; import { @@ -1264,9 +1265,9 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } - function parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): Promise { + function parseImportTransaction({ fileType, additionalOptions, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, additionalOptions?: ImportFileTypeSupportedAdditionalOptions, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): Promise { return new Promise((resolve, reject) => { - services.parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }).then(response => { + services.parseImportTransaction({ fileType, additionalOptions, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }).then(response => { const data = response.data; if (!data || !data.success || !data.result) { diff --git a/src/views/desktop/transactions/import/ImportDialog.vue b/src/views/desktop/transactions/import/ImportDialog.vue index 921caa06..0b33a1c1 100644 --- a/src/views/desktop/transactions/import/ImportDialog.vue +++ b/src/views/desktop/transactions/import/ImportDialog.vue @@ -145,6 +145,31 @@ /> + + + + + + + + ('importTransactionCheckDataTab'); const fileInput = useTemplateRef('fileInput'); +const allSupportedAdditionalOptions: KeyAndName[] = [ + { + key: 'payeeAsTag', + name: 'Parse Payee as Tag' + }, + { + key: 'payeeAsDescription', + name: 'Parse Payee as Description' + } +]; + const showState = ref(false); +const additionalOptionsMenuState = ref(false); const clientSessionId = ref(''); const currentStep = ref('uploadFile'); const importProcess = ref(0); @@ -326,6 +369,7 @@ const fileEncoding = ref('utf-8'); const processDSVMethod = ref(ImportDSVProcessMethod.ColumnMapping); const importFile = ref(null); const importData = ref(''); +const importAdditionalOptions = ref({}); const parsedFileData = ref(undefined); const importTransactions = ref(undefined); @@ -342,6 +386,7 @@ const allSupportedImportFileCategoryAndTypes = computed(() => allSupportedImportFileTypesMap.value[fileType.value]?.subTypes); const allSupportedEncodings = computed(() => allSupportedImportFileTypesMap.value[fileType.value]?.supportedEncodings); const isImportDataFromTextbox = computed(() => allSupportedImportFileTypesMap.value[fileType.value]?.dataFromTextbox ?? false); +const supportedAdditionalOptions = computed(() => allSupportedImportFileTypesMap.value[fileType.value]?.supportedAdditionalOptions); const allSteps = computed(() => { const steps: StepBarItem[] = [ @@ -408,6 +453,26 @@ const supportedImportFileExtensions = computed(() => { return allSupportedImportFileTypesMap.value[fileType.value]?.extensions; }); +const displaySelectedAdditionalOptions = computed(() => { + if (!supportedAdditionalOptions.value) { + return tt('None'); + } + + const selectedOptions: string[] = []; + + for (const option of allSupportedAdditionalOptions) { + if (isDefined(supportedAdditionalOptions.value[option.key]) && importAdditionalOptions.value[option.key]) { + selectedOptions.push(tt(option.name)); + } + } + + if (selectedOptions.length < 1) { + return tt('None'); + } + + return joinMultiText(selectedOptions); +}); + const exportFileGuideDocumentUrl = computed(() => { const document = allSupportedImportFileTypesMap.value[fileType.value]?.document; @@ -437,6 +502,7 @@ function open(): Promise { importProcess.value = 0; importFile.value = null; importData.value = ''; + importAdditionalOptions.value = Object.assign({}, supportedAdditionalOptions.value ?? {}); parsedFileData.value = undefined; importTransactionDefineColumnTab.value?.reset(); importTransactionExecuteCustomScriptTab.value?.reset(); @@ -614,6 +680,7 @@ function parseData(): void { transactionsStore.parseImportTransaction({ fileType: type, + additionalOptions: importAdditionalOptions.value, fileEncoding: encoding, importFile: uploadFile, columnMapping: columnMapping, @@ -773,6 +840,7 @@ watch(fileType, () => { importFile.value = null; parsedFileData.value = undefined; + importAdditionalOptions.value = Object.assign({}, supportedAdditionalOptions.value ?? {}); importTransactions.value = undefined; });