From e9c175d2af0e2498986cd5a42d6d26d0ac9bdedf Mon Sep 17 00:00:00 2001 From: MaysWind Date: Thu, 19 Jun 2025 22:40:32 +0800 Subject: [PATCH] code refactor --- pkg/converters/beancount/beancount_data.go | 50 +-- .../beancount/beancount_data_reader.go | 94 +++--- .../beancount/beancount_data_reader_test.go | 308 +++++++++--------- .../beancount/beancount_data_test.go | 20 +- .../beancount_transaction_data_table.go | 82 ++--- pkg/converters/iif/iif_data.go | 24 +- pkg/converters/iif/iif_data_reader.go | 18 +- .../iif/iif_transaction_data_table.go | 58 ++-- pkg/converters/qif/qif_data.go | 116 +++---- pkg/converters/qif/qif_data_reader.go | 132 ++++---- pkg/converters/qif/qif_data_reader_test.go | 274 ++++++++-------- .../qif/qif_transaction_data_table.go | 46 +-- 12 files changed, 611 insertions(+), 611 deletions(-) diff --git a/pkg/converters/beancount/beancount_data.go b/pkg/converters/beancount/beancount_data.go index da03c5e6..292dccac 100644 --- a/pkg/converters/beancount/beancount_data.go +++ b/pkg/converters/beancount/beancount_data.go @@ -41,49 +41,49 @@ const ( // beancountData defines the structure of beancount data type beancountData struct { - accounts map[string]*beancountAccount - transactions []*beancountTransactionEntry + Accounts map[string]*beancountAccount + Transactions []*beancountTransactionEntry } // beancountAccount defines the structure of beancount account type beancountAccount struct { - name string - accountType beancountAccountType - openDate string - closeDate string + Name string + AccountType beancountAccountType + OpenDate string + CloseDate string } // beancountTransactionEntry defines the structure of beancount transaction entry type beancountTransactionEntry struct { - date string - directive beancountDirective - payee string - narration string - postings []*beancountPosting - tags []string - links []string - metadata map[string]string + Date string + Directive beancountDirective + Payee string + Narration string + Postings []*beancountPosting + Tags []string + Links []string + Metadata map[string]string } // beancountPosting defines the structure of beancount transaction posting type beancountPosting struct { - account string - amount string - originalAmount string - commodity string - totalCost string - totalCostCommodity string - price string - priceCommodity string - metadata map[string]string + Account string + Amount string + OriginalAmount string + Commodity string + TotalCost string + TotalCostCommodity string + Price string + PriceCommodity string + Metadata map[string]string } func (a *beancountAccount) isOpeningBalanceEquityAccount() bool { - if a.accountType != beancountEquityAccountType { + if a.AccountType != beancountEquityAccountType { return false } - nameItems := strings.Split(a.name, string(beancountMetadataKeySuffix)) + nameItems := strings.Split(a.Name, string(beancountMetadataKeySuffix)) if len(nameItems) != 2 { return false diff --git a/pkg/converters/beancount/beancount_data_reader.go b/pkg/converters/beancount/beancount_data_reader.go index 105c51eb..26645bd6 100644 --- a/pkg/converters/beancount/beancount_data_reader.go +++ b/pkg/converters/beancount/beancount_data_reader.go @@ -49,8 +49,8 @@ func (r *beancountDataReader) read(ctx core.Context) (*beancountData, error) { } data := &beancountData{ - accounts: make(map[string]*beancountAccount), - transactions: make([]*beancountTransactionEntry, 0), + Accounts: make(map[string]*beancountAccount), + Transactions: make([]*beancountTransactionEntry, 0), } var err error @@ -100,7 +100,7 @@ func (r *beancountDataReader) read(ctx core.Context) (*beancountData, error) { if ('A' <= actualFirstItem[0] && actualFirstItem[0] <= 'Z') || actualFirstItem[0] == '!' { // transaction posting if currentTransactionEntry != nil && currentTransactionPosting != nil { - currentTransactionEntry.postings = append(currentTransactionEntry.postings, currentTransactionPosting) + currentTransactionEntry.Postings = append(currentTransactionEntry.Postings, currentTransactionPosting) currentTransactionPosting = nil } @@ -120,12 +120,12 @@ func (r *beancountDataReader) read(ctx core.Context) (*beancountData, error) { metadataValue := metadata[1] if currentTransactionPosting != nil { - if _, exists := currentTransactionPosting.metadata[metadataKey]; !exists { - currentTransactionPosting.metadata[metadataKey] = metadataValue + if _, exists := currentTransactionPosting.Metadata[metadataKey]; !exists { + currentTransactionPosting.Metadata[metadataKey] = metadataValue } } else if currentTransactionEntry != nil { - if _, exists := currentTransactionEntry.metadata[metadataKey]; !exists { - currentTransactionEntry.metadata[metadataKey] = metadataValue + if _, exists := currentTransactionEntry.Metadata[metadataKey]; !exists { + currentTransactionEntry.Metadata[metadataKey] = metadataValue } } } else { @@ -172,11 +172,11 @@ func (r *beancountDataReader) read(ctx core.Context) (*beancountData, error) { if currentTransactionEntry != nil { if currentTransactionPosting != nil { - currentTransactionEntry.postings = append(currentTransactionEntry.postings, currentTransactionPosting) + currentTransactionEntry.Postings = append(currentTransactionEntry.Postings, currentTransactionPosting) currentTransactionPosting = nil } - data.transactions = append(data.transactions, currentTransactionEntry) + data.Transactions = append(data.Transactions, currentTransactionEntry) currentTransactionEntry = nil } @@ -186,11 +186,11 @@ func (r *beancountDataReader) read(ctx core.Context) (*beancountData, error) { func (r *beancountDataReader) updateCurrentState(data *beancountData, currentTransactionEntry *beancountTransactionEntry, currentTransactionPosting *beancountPosting) (*beancountTransactionEntry, *beancountPosting) { if currentTransactionEntry != nil { if currentTransactionPosting != nil { - currentTransactionEntry.postings = append(currentTransactionEntry.postings, currentTransactionPosting) + currentTransactionEntry.Postings = append(currentTransactionEntry.Postings, currentTransactionPosting) currentTransactionPosting = nil } - data.transactions = append(data.transactions, currentTransactionEntry) + data.Transactions = append(data.Transactions, currentTransactionEntry) currentTransactionEntry = nil currentTransactionPosting = nil } @@ -277,7 +277,7 @@ func (r *beancountDataReader) readAccountLine(ctx core.Context, lineIndex int, i var err error accountName := r.getNotEmptyItemByIndex(items, 2) - account, exists := data.accounts[accountName] + account, exists := data.Accounts[accountName] if !exists { account, err = r.createAccount(ctx, data, accountName) @@ -288,10 +288,10 @@ func (r *beancountDataReader) readAccountLine(ctx core.Context, lineIndex int, i } if directive == beancountDirectiveOpen { - account.openDate = date + account.OpenDate = date return account, nil } else if directive == beancountDirectiveClose { - account.closeDate = date + account.CloseDate = date return account, nil } else { log.Warnf(ctx, "[beancount_data_reader.parseAccount] cannot parse account line#%d \"%s\", because directive is invalid", lineIndex, strings.Join(items, " ")) @@ -301,8 +301,8 @@ func (r *beancountDataReader) readAccountLine(ctx core.Context, lineIndex int, i func (r *beancountDataReader) createAccount(ctx core.Context, data *beancountData, accountName string) (*beancountAccount, error) { account := &beancountAccount{ - name: accountName, - accountType: beancountUnknownAccountType, + Name: accountName, + AccountType: beancountUnknownAccountType, } accountNameItems := strings.Split(accountName, beancountAccountNameItemsSeparator) @@ -311,31 +311,31 @@ func (r *beancountDataReader) createAccount(ctx core.Context, data *beancountDat accountType, exists := r.accountTypeNameMap[accountNameItems[0]] if exists { - account.accountType = accountType + account.AccountType = accountType } else { log.Warnf(ctx, "[beancount_data_reader.createAccount] cannot parse account \"%s\", because account type \"%s\" is invalid", accountName, accountNameItems[0]) return nil, errs.ErrInvalidBeancountFile } } - data.accounts[accountName] = account + data.Accounts[accountName] = account return account, nil } func (r *beancountDataReader) readTransactionLine(ctx core.Context, lineIndex int, items []string, date string, directive beancountDirective, tags []string) *beancountTransactionEntry { transactionEntry := &beancountTransactionEntry{ - date: date, - directive: directive, - tags: make([]string, 0), - links: make([]string, 0), - metadata: make(map[string]string), + Date: date, + Directive: directive, + Tags: make([]string, 0), + Links: make([]string, 0), + Metadata: make(map[string]string), } - transactionEntry.tags = append(transactionEntry.tags, tags...) + transactionEntry.Tags = append(transactionEntry.Tags, tags...) - allTags := make(map[string]bool, len(transactionEntry.tags)) + allTags := make(map[string]bool, len(transactionEntry.Tags)) - for _, tag := range transactionEntry.tags { + for _, tag := range transactionEntry.Tags { allTags[tag] = true } @@ -363,7 +363,7 @@ func (r *beancountDataReader) readTransactionLine(ctx core.Context, lineIndex in tagName := item[1:] if _, exists := allTags[tagName]; !exists { - transactionEntry.tags = append(transactionEntry.tags, tagName) + transactionEntry.Tags = append(transactionEntry.Tags, tagName) allTags[tagName] = true } @@ -371,7 +371,7 @@ func (r *beancountDataReader) readTransactionLine(ctx core.Context, lineIndex in payeeNarrationLastIndex = i - 1 } } else if item[0] == beancountLinkPrefix { // [ˆlink] - transactionEntry.links = append(transactionEntry.links, item[1:]) + transactionEntry.Links = append(transactionEntry.Links, item[1:]) if i-1 < payeeNarrationLastIndex { payeeNarrationLastIndex = i - 1 @@ -380,10 +380,10 @@ func (r *beancountDataReader) readTransactionLine(ctx core.Context, lineIndex in } if payeeNarrationLastIndex-payeeNarrationFirstIndex >= 1 { - transactionEntry.payee = items[payeeNarrationFirstIndex] - transactionEntry.narration = items[payeeNarrationFirstIndex+1] + transactionEntry.Payee = items[payeeNarrationFirstIndex] + transactionEntry.Narration = items[payeeNarrationFirstIndex+1] } else if payeeNarrationLastIndex-payeeNarrationFirstIndex >= 0 { - transactionEntry.narration = items[payeeNarrationFirstIndex] + transactionEntry.Narration = items[payeeNarrationFirstIndex] } return transactionEntry @@ -410,36 +410,36 @@ func (r *beancountDataReader) readTransactionPostingLine(ctx core.Context, lineI } transactionPositing := &beancountPosting{ - account: accountName, - metadata: make(map[string]string), + Account: accountName, + Metadata: make(map[string]string), } amountActualLastIndex := -1 - transactionPositing.originalAmount, amountActualLastIndex = r.getOriginalAmountAndLastIndexFromIndex(items, accountNameActualIndex+1) + transactionPositing.OriginalAmount, amountActualLastIndex = r.getOriginalAmountAndLastIndexFromIndex(items, accountNameActualIndex+1) - if transactionPositing.originalAmount == "" || amountActualLastIndex < 0 { + if transactionPositing.OriginalAmount == "" || amountActualLastIndex < 0 { log.Warnf(ctx, "[beancount_data_reader.readTransactionPostingLine] cannot parse transaction posting line#%d \"%s\", because missing amount", lineIndex, strings.Join(items, " ")) return nil, errs.ErrAmountInvalid } - finalAmount, err := evaluateBeancountAmountExpression(ctx, transactionPositing.originalAmount) + finalAmount, err := evaluateBeancountAmountExpression(ctx, transactionPositing.OriginalAmount) if err != nil { log.Warnf(ctx, "[beancount_data_reader.readTransactionPostingLine] cannot evaluate amount expression in line#%d \"%s\", because %s", lineIndex, strings.Join(items, " "), err.Error()) return nil, errs.ErrAmountInvalid } else { - transactionPositing.amount = finalAmount + transactionPositing.Amount = finalAmount } commodityActualIndex := -1 - transactionPositing.commodity, commodityActualIndex = r.getNotEmptyItemAndIndexFromIndex(items, amountActualLastIndex+1) + transactionPositing.Commodity, commodityActualIndex = r.getNotEmptyItemAndIndexFromIndex(items, amountActualLastIndex+1) - if transactionPositing.commodity == "" || commodityActualIndex < 0 { + if transactionPositing.Commodity == "" || commodityActualIndex < 0 { log.Warnf(ctx, "[beancount_data_reader.readTransactionPostingLine] cannot parse transaction posting line#%d \"%s\", because missing commodity", lineIndex, strings.Join(items, " ")) return nil, errs.ErrInvalidBeancountFile } - if strings.ToUpper(transactionPositing.commodity) != transactionPositing.commodity { // The syntax for a currency is a word all in capital letters + if strings.ToUpper(transactionPositing.Commodity) != transactionPositing.Commodity { // The syntax for a currency is a word all in capital letters log.Warnf(ctx, "[beancount_data_reader.readTransactionPostingLine] cannot parse transaction posting line#%d \"%s\", because commodity name is not capital letters", lineIndex, strings.Join(items, " ")) return nil, errs.ErrInvalidBeancountFile } @@ -461,13 +461,13 @@ func (r *beancountDataReader) readTransactionPostingLine(ctx core.Context, lineI totalCost, totalCostActualIndex := r.getNotEmptyItemAndIndexFromIndex(items, i+1) if totalCostActualIndex > 0 { - transactionPositing.totalCost = totalCost + transactionPositing.TotalCost = totalCost i = totalCostActualIndex totalCostCommodity, totalCostCommodityActualIndex := r.getNotEmptyItemAndIndexFromIndex(items, totalCostActualIndex+1) if totalCostCommodityActualIndex > 0 { - transactionPositing.totalCostCommodity = totalCostCommodity + transactionPositing.TotalCostCommodity = totalCostCommodity i = totalCostCommodityActualIndex } } @@ -475,13 +475,13 @@ func (r *beancountDataReader) readTransactionPostingLine(ctx core.Context, lineI price, priceActualIndex := r.getNotEmptyItemAndIndexFromIndex(items, i+1) if priceActualIndex > 0 { - transactionPositing.price = price + transactionPositing.Price = price i = priceActualIndex priceCommodity, priceCommodityActualIndex := r.getNotEmptyItemAndIndexFromIndex(items, priceActualIndex+1) if priceCommodityActualIndex > 0 { - transactionPositing.priceCommodity = priceCommodity + transactionPositing.PriceCommodity = priceCommodity i = priceCommodityActualIndex } } @@ -489,11 +489,11 @@ func (r *beancountDataReader) readTransactionPostingLine(ctx core.Context, lineI } } - if transactionPositing.account != "" { - _, exists := data.accounts[transactionPositing.account] + if transactionPositing.Account != "" { + _, exists := data.Accounts[transactionPositing.Account] if !exists { - _, err := r.createAccount(ctx, data, transactionPositing.account) + _, err := r.createAccount(ctx, data, transactionPositing.Account) if err != nil { return nil, err diff --git a/pkg/converters/beancount/beancount_data_reader_test.go b/pkg/converters/beancount/beancount_data_reader_test.go index e33222ed..f56df385 100644 --- a/pkg/converters/beancount/beancount_data_reader_test.go +++ b/pkg/converters/beancount/beancount_data_reader_test.go @@ -41,56 +41,56 @@ func TestBeancountDataReaderRead(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 5, len(actualData.accounts)) - assert.Equal(t, "AssetsAccount:TestAccount", actualData.accounts["AssetsAccount:TestAccount"].name) - assert.Equal(t, beancountAssetsAccountType, actualData.accounts["AssetsAccount:TestAccount"].accountType) - assert.Equal(t, "2024-01-01", actualData.accounts["AssetsAccount:TestAccount"].openDate) - assert.Equal(t, "2024-01-07", actualData.accounts["AssetsAccount:TestAccount"].closeDate) + assert.Equal(t, 5, len(actualData.Accounts)) + assert.Equal(t, "AssetsAccount:TestAccount", actualData.Accounts["AssetsAccount:TestAccount"].Name) + assert.Equal(t, beancountAssetsAccountType, actualData.Accounts["AssetsAccount:TestAccount"].AccountType) + assert.Equal(t, "2024-01-01", actualData.Accounts["AssetsAccount:TestAccount"].OpenDate) + assert.Equal(t, "2024-01-07", actualData.Accounts["AssetsAccount:TestAccount"].CloseDate) - assert.Equal(t, "LiabilitiesAccount:TestAccount2", actualData.accounts["LiabilitiesAccount:TestAccount2"].name) - assert.Equal(t, beancountLiabilitiesAccountType, actualData.accounts["LiabilitiesAccount:TestAccount2"].accountType) - assert.Equal(t, "2024-01-02", actualData.accounts["LiabilitiesAccount:TestAccount2"].openDate) + assert.Equal(t, "LiabilitiesAccount:TestAccount2", actualData.Accounts["LiabilitiesAccount:TestAccount2"].Name) + assert.Equal(t, beancountLiabilitiesAccountType, actualData.Accounts["LiabilitiesAccount:TestAccount2"].AccountType) + assert.Equal(t, "2024-01-02", actualData.Accounts["LiabilitiesAccount:TestAccount2"].OpenDate) - assert.Equal(t, 2, len(actualData.transactions)) + assert.Equal(t, 2, len(actualData.Transactions)) - assert.Equal(t, "2024-01-05", actualData.transactions[0].date) - assert.Equal(t, "Payee Name", actualData.transactions[0].payee) - assert.Equal(t, "Foo Bar", actualData.transactions[0].narration) - assert.Equal(t, 2, len(actualData.transactions[0].postings)) - assert.Equal(t, "IncomeAccount:TestCategory", actualData.transactions[0].postings[0].account) - assert.Equal(t, "-123.45", actualData.transactions[0].postings[0].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[0].commodity) - assert.Equal(t, "AssetsAccount:TestAccount", actualData.transactions[0].postings[1].account) - assert.Equal(t, "123.45", actualData.transactions[0].postings[1].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[1].commodity) + assert.Equal(t, "2024-01-05", actualData.Transactions[0].Date) + assert.Equal(t, "Payee Name", actualData.Transactions[0].Payee) + assert.Equal(t, "Foo Bar", actualData.Transactions[0].Narration) + assert.Equal(t, 2, len(actualData.Transactions[0].Postings)) + assert.Equal(t, "IncomeAccount:TestCategory", actualData.Transactions[0].Postings[0].Account) + assert.Equal(t, "-123.45", actualData.Transactions[0].Postings[0].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[0].Commodity) + assert.Equal(t, "AssetsAccount:TestAccount", actualData.Transactions[0].Postings[1].Account) + assert.Equal(t, "123.45", actualData.Transactions[0].Postings[1].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[1].Commodity) - assert.Equal(t, 4, len(actualData.transactions[0].tags)) - assert.Equal(t, actualData.transactions[0].tags[0], "tag1") - assert.Equal(t, actualData.transactions[0].tags[1], "tag2") - assert.Equal(t, actualData.transactions[0].tags[2], "tag3") - assert.Equal(t, actualData.transactions[0].tags[3], "tag4") + assert.Equal(t, 4, len(actualData.Transactions[0].Tags)) + assert.Equal(t, actualData.Transactions[0].Tags[0], "tag1") + assert.Equal(t, actualData.Transactions[0].Tags[1], "tag2") + assert.Equal(t, actualData.Transactions[0].Tags[2], "tag3") + assert.Equal(t, actualData.Transactions[0].Tags[3], "tag4") - assert.Equal(t, 1, len(actualData.transactions[0].links)) - assert.Equal(t, actualData.transactions[0].links[0], "test-link") + assert.Equal(t, 1, len(actualData.Transactions[0].Links)) + assert.Equal(t, actualData.Transactions[0].Links[0], "test-link") - assert.Equal(t, "2024-01-06", actualData.transactions[1].date) - assert.Equal(t, "", actualData.transactions[1].payee) - assert.Equal(t, "test\n#test2", actualData.transactions[1].narration) - assert.Equal(t, 2, len(actualData.transactions[1].postings)) - assert.Equal(t, "LiabilitiesAccount:TestAccount2", actualData.transactions[1].postings[0].account) - assert.Equal(t, "-0.12", actualData.transactions[1].postings[0].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[0].commodity) - assert.Equal(t, "ExpensesAccount:TestCategory2", actualData.transactions[1].postings[1].account) - assert.Equal(t, "0.12", actualData.transactions[1].postings[1].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[1].commodity) + assert.Equal(t, "2024-01-06", actualData.Transactions[1].Date) + assert.Equal(t, "", actualData.Transactions[1].Payee) + assert.Equal(t, "test\n#test2", actualData.Transactions[1].Narration) + assert.Equal(t, 2, len(actualData.Transactions[1].Postings)) + assert.Equal(t, "LiabilitiesAccount:TestAccount2", actualData.Transactions[1].Postings[0].Account) + assert.Equal(t, "-0.12", actualData.Transactions[1].Postings[0].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[0].Commodity) + assert.Equal(t, "ExpensesAccount:TestCategory2", actualData.Transactions[1].Postings[1].Account) + assert.Equal(t, "0.12", actualData.Transactions[1].Postings[1].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[1].Commodity) - assert.Equal(t, 3, len(actualData.transactions[1].tags)) - assert.Equal(t, actualData.transactions[1].tags[0], "tag2") - assert.Equal(t, actualData.transactions[1].tags[1], "tag5") - assert.Equal(t, actualData.transactions[1].tags[2], "tag6") + assert.Equal(t, 3, len(actualData.Transactions[1].Tags)) + assert.Equal(t, actualData.Transactions[1].Tags[0], "tag2") + assert.Equal(t, actualData.Transactions[1].Tags[1], "tag5") + assert.Equal(t, actualData.Transactions[1].Tags[2], "tag6") - assert.Equal(t, 1, len(actualData.transactions[1].links)) - assert.Equal(t, actualData.transactions[1].links[0], "test-link2") + assert.Equal(t, 1, len(actualData.Transactions[1].Links)) + assert.Equal(t, actualData.Transactions[1].Links[0], "test-link2") } func TestBeancountDataReaderRead_EmptyContent(t *testing.T) { @@ -147,17 +147,17 @@ func TestBeancountDataReaderReadAndSetOption_AccountTypeName(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 3, len(actualData.accounts)) + assert.Equal(t, 3, len(actualData.Accounts)) - assert.Equal(t, "A:TestAccount", actualData.accounts["A:TestAccount"].name) - assert.Equal(t, beancountAssetsAccountType, actualData.accounts["A:TestAccount"].accountType) + assert.Equal(t, "A:TestAccount", actualData.Accounts["A:TestAccount"].Name) + assert.Equal(t, beancountAssetsAccountType, actualData.Accounts["A:TestAccount"].AccountType) - assert.Equal(t, "L:TestAccount2", actualData.accounts["L:TestAccount2"].name) - assert.Equal(t, beancountLiabilitiesAccountType, actualData.accounts["L:TestAccount2"].accountType) + assert.Equal(t, "L:TestAccount2", actualData.Accounts["L:TestAccount2"].Name) + assert.Equal(t, beancountLiabilitiesAccountType, actualData.Accounts["L:TestAccount2"].AccountType) - assert.Equal(t, "E:Opening-Balances", actualData.accounts["E:Opening-Balances"].name) - assert.Equal(t, beancountEquityAccountType, actualData.accounts["E:Opening-Balances"].accountType) - assert.True(t, actualData.accounts["E:Opening-Balances"].isOpeningBalanceEquityAccount()) + assert.Equal(t, "E:Opening-Balances", actualData.Accounts["E:Opening-Balances"].Name) + assert.Equal(t, beancountEquityAccountType, actualData.Accounts["E:Opening-Balances"].AccountType) + assert.True(t, actualData.Accounts["E:Opening-Balances"].isOpeningBalanceEquityAccount()) } func TestBeancountDataReaderReadAndSetOption_InvalidLineOrUnsupportedOption(t *testing.T) { @@ -203,31 +203,31 @@ func TestBeancountDataReaderReadAndSetTags(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 5, len(actualData.transactions)) + assert.Equal(t, 5, len(actualData.Transactions)) - assert.Equal(t, 4, len(actualData.transactions[0].tags)) - assert.Equal(t, actualData.transactions[0].tags[0], "tag1") - assert.Equal(t, actualData.transactions[0].tags[1], "tag2") - assert.Equal(t, actualData.transactions[0].tags[2], "tag3") - assert.Equal(t, actualData.transactions[0].tags[3], "tag4") + assert.Equal(t, 4, len(actualData.Transactions[0].Tags)) + assert.Equal(t, actualData.Transactions[0].Tags[0], "tag1") + assert.Equal(t, actualData.Transactions[0].Tags[1], "tag2") + assert.Equal(t, actualData.Transactions[0].Tags[2], "tag3") + assert.Equal(t, actualData.Transactions[0].Tags[3], "tag4") - assert.Equal(t, 2, len(actualData.transactions[1].tags)) - assert.Equal(t, actualData.transactions[1].tags[0], "tag5") - assert.Equal(t, actualData.transactions[1].tags[1], "tag6") + assert.Equal(t, 2, len(actualData.Transactions[1].Tags)) + assert.Equal(t, actualData.Transactions[1].Tags[0], "tag5") + assert.Equal(t, actualData.Transactions[1].Tags[1], "tag6") - assert.Equal(t, 2, len(actualData.transactions[2].tags)) - assert.Equal(t, actualData.transactions[2].tags[0], "tag5") - assert.Equal(t, actualData.transactions[2].tags[1], "tag6") + assert.Equal(t, 2, len(actualData.Transactions[2].Tags)) + assert.Equal(t, actualData.Transactions[2].Tags[0], "tag5") + assert.Equal(t, actualData.Transactions[2].Tags[1], "tag6") - assert.Equal(t, 3, len(actualData.transactions[3].tags)) - assert.Equal(t, actualData.transactions[3].tags[0], "tag3") - assert.Equal(t, actualData.transactions[3].tags[1], "tag6") - assert.Equal(t, actualData.transactions[3].tags[2], "tag5") + assert.Equal(t, 3, len(actualData.Transactions[3].Tags)) + assert.Equal(t, actualData.Transactions[3].Tags[0], "tag3") + assert.Equal(t, actualData.Transactions[3].Tags[1], "tag6") + assert.Equal(t, actualData.Transactions[3].Tags[2], "tag5") - assert.Equal(t, 3, len(actualData.transactions[4].tags)) - assert.Equal(t, actualData.transactions[4].tags[0], "tag3") - assert.Equal(t, actualData.transactions[4].tags[1], "tag6") - assert.Equal(t, actualData.transactions[4].tags[2], "tag5") + assert.Equal(t, 3, len(actualData.Transactions[4].Tags)) + assert.Equal(t, actualData.Transactions[4].Tags[0], "tag3") + assert.Equal(t, actualData.Transactions[4].Tags[1], "tag6") + assert.Equal(t, actualData.Transactions[4].Tags[2], "tag5") } func TestBeancountDataReaderReadAccountLine_InvalidLine(t *testing.T) { @@ -238,7 +238,7 @@ func TestBeancountDataReaderReadAccountLine_InvalidLine(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 0, len(actualData.accounts)) + assert.Equal(t, 0, len(actualData.Accounts)) } func TestBeancountDataReaderReadAccountLine_InvalidAccountType(t *testing.T) { @@ -274,44 +274,44 @@ func TestBeancountDataReaderReadTransactionLine(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 6, len(actualData.transactions)) + assert.Equal(t, 6, len(actualData.Transactions)) - assert.Equal(t, "2024-01-01", actualData.transactions[0].date) - assert.Equal(t, beancountDirectiveCompletedTransaction, actualData.transactions[0].directive) - assert.Equal(t, "", actualData.transactions[0].payee) - assert.Equal(t, "", actualData.transactions[0].narration) + assert.Equal(t, "2024-01-01", actualData.Transactions[0].Date) + assert.Equal(t, beancountDirectiveCompletedTransaction, actualData.Transactions[0].Directive) + assert.Equal(t, "", actualData.Transactions[0].Payee) + assert.Equal(t, "", actualData.Transactions[0].Narration) - assert.Equal(t, "2024-01-02", actualData.transactions[1].date) - assert.Equal(t, beancountDirectiveCompletedTransaction, actualData.transactions[1].directive) - assert.Equal(t, "", actualData.transactions[1].payee) - assert.Equal(t, "test\ttest2\ntest3", actualData.transactions[1].narration) + assert.Equal(t, "2024-01-02", actualData.Transactions[1].Date) + assert.Equal(t, beancountDirectiveCompletedTransaction, actualData.Transactions[1].Directive) + assert.Equal(t, "", actualData.Transactions[1].Payee) + assert.Equal(t, "test\ttest2\ntest3", actualData.Transactions[1].Narration) - assert.Equal(t, "2024-01-03", actualData.transactions[2].date) - assert.Equal(t, beancountDirectiveInCompleteTransaction, actualData.transactions[2].directive) - assert.Equal(t, "test", actualData.transactions[2].payee) - assert.Equal(t, "test2", actualData.transactions[2].narration) + assert.Equal(t, "2024-01-03", actualData.Transactions[2].Date) + assert.Equal(t, beancountDirectiveInCompleteTransaction, actualData.Transactions[2].Directive) + assert.Equal(t, "test", actualData.Transactions[2].Payee) + assert.Equal(t, "test2", actualData.Transactions[2].Narration) - assert.Equal(t, "2024-01-04", actualData.transactions[3].date) - assert.Equal(t, beancountDirectivePaddingTransaction, actualData.transactions[3].directive) - assert.Equal(t, "", actualData.transactions[3].payee) - assert.Equal(t, "test", actualData.transactions[3].narration) + assert.Equal(t, "2024-01-04", actualData.Transactions[3].Date) + assert.Equal(t, beancountDirectivePaddingTransaction, actualData.Transactions[3].Directive) + assert.Equal(t, "", actualData.Transactions[3].Payee) + assert.Equal(t, "test", actualData.Transactions[3].Narration) - assert.Equal(t, 2, len(actualData.transactions[3].tags)) - assert.Equal(t, actualData.transactions[3].tags[0], "tag") - assert.Equal(t, actualData.transactions[3].tags[1], "tag2") + assert.Equal(t, 2, len(actualData.Transactions[3].Tags)) + assert.Equal(t, actualData.Transactions[3].Tags[0], "tag") + assert.Equal(t, actualData.Transactions[3].Tags[1], "tag2") - assert.Equal(t, "2024-01-05", actualData.transactions[4].date) - assert.Equal(t, beancountDirectiveTransaction, actualData.transactions[4].directive) - assert.Equal(t, "", actualData.transactions[4].payee) - assert.Equal(t, "test", actualData.transactions[4].narration) + assert.Equal(t, "2024-01-05", actualData.Transactions[4].Date) + assert.Equal(t, beancountDirectiveTransaction, actualData.Transactions[4].Directive) + assert.Equal(t, "", actualData.Transactions[4].Payee) + assert.Equal(t, "test", actualData.Transactions[4].Narration) - assert.Equal(t, 1, len(actualData.transactions[4].links)) - assert.Equal(t, actualData.transactions[4].links[0], "scheme://path/to/test/link") + assert.Equal(t, 1, len(actualData.Transactions[4].Links)) + assert.Equal(t, actualData.Transactions[4].Links[0], "scheme://path/to/test/link") - assert.Equal(t, "2024-01-06", actualData.transactions[5].date) - assert.Equal(t, beancountDirectiveTransaction, actualData.transactions[5].directive) - assert.Equal(t, "", actualData.transactions[5].payee) - assert.Equal(t, "", actualData.transactions[5].narration) + assert.Equal(t, "2024-01-06", actualData.Transactions[5].Date) + assert.Equal(t, beancountDirectiveTransaction, actualData.Transactions[5].Directive) + assert.Equal(t, "", actualData.Transactions[5].Payee) + assert.Equal(t, "", actualData.Transactions[5].Narration) } func TestBeancountDataReaderReadTransactionPostingLine(t *testing.T) { @@ -331,39 +331,39 @@ func TestBeancountDataReaderReadTransactionPostingLine(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 2, len(actualData.transactions)) + assert.Equal(t, 2, len(actualData.Transactions)) - assert.Equal(t, "2024-01-01", actualData.transactions[0].date) - assert.Equal(t, 2, len(actualData.transactions[0].postings)) - assert.Equal(t, "Income:TestCategory", actualData.transactions[0].postings[0].account) - assert.Equal(t, "-123.45", actualData.transactions[0].postings[0].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[0].commodity) + assert.Equal(t, "2024-01-01", actualData.Transactions[0].Date) + assert.Equal(t, 2, len(actualData.Transactions[0].Postings)) + assert.Equal(t, "Income:TestCategory", actualData.Transactions[0].Postings[0].Account) + assert.Equal(t, "-123.45", actualData.Transactions[0].Postings[0].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[0].Commodity) - assert.Equal(t, "Assets:TestAccount", actualData.transactions[0].postings[1].account) - assert.Equal(t, "123.45", actualData.transactions[0].postings[1].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[1].commodity) + assert.Equal(t, "Assets:TestAccount", actualData.Transactions[0].Postings[1].Account) + assert.Equal(t, "123.45", actualData.Transactions[0].Postings[1].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[1].Commodity) - assert.Equal(t, "2024-01-02", actualData.transactions[1].date) - assert.Equal(t, 4, len(actualData.transactions[1].postings)) + assert.Equal(t, "2024-01-02", actualData.Transactions[1].Date) + assert.Equal(t, 4, len(actualData.Transactions[1].Postings)) - assert.Equal(t, "Liabilities:TestAccount2", actualData.transactions[1].postings[0].account) - assert.Equal(t, "-0.23", actualData.transactions[1].postings[0].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[0].commodity) - assert.Equal(t, "Expenses:TestCategory2", actualData.transactions[1].postings[1].account) + assert.Equal(t, "Liabilities:TestAccount2", actualData.Transactions[1].Postings[0].Account) + assert.Equal(t, "-0.23", actualData.Transactions[1].Postings[0].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[0].Commodity) + assert.Equal(t, "Expenses:TestCategory2", actualData.Transactions[1].Postings[1].Account) - assert.Equal(t, "0.12", actualData.transactions[1].postings[1].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[1].commodity) - assert.Equal(t, "0.84", actualData.transactions[1].postings[1].totalCost) - assert.Equal(t, "CNY", actualData.transactions[1].postings[1].totalCostCommodity) - assert.Equal(t, "Expenses:TestCategory3", actualData.transactions[1].postings[2].account) + assert.Equal(t, "0.12", actualData.Transactions[1].Postings[1].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[1].Commodity) + assert.Equal(t, "0.84", actualData.Transactions[1].Postings[1].TotalCost) + assert.Equal(t, "CNY", actualData.Transactions[1].Postings[1].TotalCostCommodity) + assert.Equal(t, "Expenses:TestCategory3", actualData.Transactions[1].Postings[2].Account) - assert.Equal(t, "0.11", actualData.transactions[1].postings[2].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[2].commodity) - assert.Equal(t, "7.12", actualData.transactions[1].postings[2].price) - assert.Equal(t, "CNY", actualData.transactions[1].postings[2].priceCommodity) + assert.Equal(t, "0.11", actualData.Transactions[1].Postings[2].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[2].Commodity) + assert.Equal(t, "7.12", actualData.Transactions[1].Postings[2].Price) + assert.Equal(t, "CNY", actualData.Transactions[1].Postings[2].PriceCommodity) - assert.Equal(t, "0.00", actualData.transactions[1].postings[3].amount) - assert.Equal(t, "USD", actualData.transactions[1].postings[3].commodity) + assert.Equal(t, "0.00", actualData.Transactions[1].Postings[3].Amount) + assert.Equal(t, "USD", actualData.Transactions[1].Postings[3].Commodity) } func TestBeancountDataReaderReadTransactionPostingLine_AmountExpression(t *testing.T) { @@ -377,19 +377,19 @@ func TestBeancountDataReaderReadTransactionPostingLine_AmountExpression(t *testi actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 1, len(actualData.transactions)) + assert.Equal(t, 1, len(actualData.Transactions)) - assert.Equal(t, "2024-01-01", actualData.transactions[0].date) - assert.Equal(t, 2, len(actualData.transactions[0].postings)) - assert.Equal(t, "Income:TestCategory", actualData.transactions[0].postings[0].account) - assert.Equal(t, "(1.2-3.4) * 5.6 / 7.8", actualData.transactions[0].postings[0].originalAmount) - assert.Equal(t, "-1.58", actualData.transactions[0].postings[0].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[0].commodity) + assert.Equal(t, "2024-01-01", actualData.Transactions[0].Date) + assert.Equal(t, 2, len(actualData.Transactions[0].Postings)) + assert.Equal(t, "Income:TestCategory", actualData.Transactions[0].Postings[0].Account) + assert.Equal(t, "(1.2-3.4) * 5.6 / 7.8", actualData.Transactions[0].Postings[0].OriginalAmount) + assert.Equal(t, "-1.58", actualData.Transactions[0].Postings[0].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[0].Commodity) - assert.Equal(t, "Assets:TestAccount", actualData.transactions[0].postings[1].account) - assert.Equal(t, "1.2 * 3.4/-5.6 - 7.8", actualData.transactions[0].postings[1].originalAmount) - assert.Equal(t, "-8.53", actualData.transactions[0].postings[1].amount) - assert.Equal(t, "CNY", actualData.transactions[0].postings[1].commodity) + assert.Equal(t, "Assets:TestAccount", actualData.Transactions[0].Postings[1].Account) + assert.Equal(t, "1.2 * 3.4/-5.6 - 7.8", actualData.Transactions[0].Postings[1].OriginalAmount) + assert.Equal(t, "-8.53", actualData.Transactions[0].Postings[1].Amount) + assert.Equal(t, "CNY", actualData.Transactions[0].Postings[1].Commodity) } func TestBeancountDataReaderReadTransactionPostingLine_InvalidAmountExpression(t *testing.T) { @@ -444,8 +444,8 @@ func TestBeancountDataReaderReadTransactionPostingLine_MissingAmount(t *testing. actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 1, len(actualData.transactions)) - assert.Equal(t, 0, len(actualData.transactions[0].postings)) + assert.Equal(t, 1, len(actualData.Transactions)) + assert.Equal(t, 0, len(actualData.Transactions[0].Postings)) reader, err = createNewBeancountDataReader(context, []byte(""+ "2024-01-01 *\n"+ @@ -454,8 +454,8 @@ func TestBeancountDataReaderReadTransactionPostingLine_MissingAmount(t *testing. actualData, err = reader.read(context) assert.Nil(t, err) - assert.Equal(t, 1, len(actualData.transactions)) - assert.Equal(t, 0, len(actualData.transactions[0].postings)) + assert.Equal(t, 1, len(actualData.Transactions)) + assert.Equal(t, 0, len(actualData.Transactions[0].Postings)) } func TestBeancountDataReaderReadTransactionPostingLine_MissingCommodity(t *testing.T) { @@ -503,18 +503,18 @@ func TestBeancountDataReaderReadTransactionMetadataLine(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 2, len(actualData.transactions)) + assert.Equal(t, 2, len(actualData.Transactions)) - assert.Equal(t, "2024-01-01", actualData.transactions[0].date) - assert.Equal(t, 2, len(actualData.transactions[0].postings)) - assert.Equal(t, 2, len(actualData.transactions[0].metadata)) - assert.Equal(t, "value", actualData.transactions[0].metadata["key"]) - assert.Equal(t, "value 2", actualData.transactions[0].metadata["key2"]) + assert.Equal(t, "2024-01-01", actualData.Transactions[0].Date) + assert.Equal(t, 2, len(actualData.Transactions[0].Postings)) + assert.Equal(t, 2, len(actualData.Transactions[0].Metadata)) + assert.Equal(t, "value", actualData.Transactions[0].Metadata["key"]) + assert.Equal(t, "value 2", actualData.Transactions[0].Metadata["key2"]) - assert.Equal(t, "2024-01-02", actualData.transactions[1].date) - assert.Equal(t, 2, len(actualData.transactions[1].postings)) - assert.Equal(t, 2, len(actualData.transactions[1].postings[0].metadata)) - assert.Equal(t, "value6", actualData.transactions[1].postings[0].metadata["key6"]) - assert.Equal(t, "value 7", actualData.transactions[1].postings[0].metadata["key7"]) - assert.Equal(t, 0, len(actualData.transactions[1].postings[1].metadata)) + assert.Equal(t, "2024-01-02", actualData.Transactions[1].Date) + assert.Equal(t, 2, len(actualData.Transactions[1].Postings)) + assert.Equal(t, 2, len(actualData.Transactions[1].Postings[0].Metadata)) + assert.Equal(t, "value6", actualData.Transactions[1].Postings[0].Metadata["key6"]) + assert.Equal(t, "value 7", actualData.Transactions[1].Postings[0].Metadata["key7"]) + assert.Equal(t, 0, len(actualData.Transactions[1].Postings[1].Metadata)) } diff --git a/pkg/converters/beancount/beancount_data_test.go b/pkg/converters/beancount/beancount_data_test.go index 7d251cc1..2dd2cd54 100644 --- a/pkg/converters/beancount/beancount_data_test.go +++ b/pkg/converters/beancount/beancount_data_test.go @@ -8,34 +8,34 @@ import ( func TestBeancountAccount_IsOpeningBalanceEquityAccount_True(t *testing.T) { account := beancountAccount{ - accountType: beancountEquityAccountType, - name: "Equity:Opening-Balances", + AccountType: beancountEquityAccountType, + Name: "Equity:Opening-Balances", } assert.True(t, account.isOpeningBalanceEquityAccount()) account = beancountAccount{ - accountType: beancountEquityAccountType, - name: "E:Opening-Balances", + AccountType: beancountEquityAccountType, + Name: "E:Opening-Balances", } assert.True(t, account.isOpeningBalanceEquityAccount()) } func TestBeancountAccount_IsOpeningBalanceEquityAccount_False(t *testing.T) { account := beancountAccount{ - accountType: beancountAssetsAccountType, - name: "Equity:Opening-Balances", + AccountType: beancountAssetsAccountType, + Name: "Equity:Opening-Balances", } assert.False(t, account.isOpeningBalanceEquityAccount()) account = beancountAccount{ - accountType: beancountEquityAccountType, - name: "Opening-Balances", + AccountType: beancountEquityAccountType, + Name: "Opening-Balances", } assert.False(t, account.isOpeningBalanceEquityAccount()) account = beancountAccount{ - accountType: beancountEquityAccountType, - name: "Equity:Other", + AccountType: beancountEquityAccountType, + Name: "Equity:Other", } assert.False(t, account.isOpeningBalanceEquityAccount()) } diff --git a/pkg/converters/beancount/beancount_transaction_data_table.go b/pkg/converters/beancount/beancount_transaction_data_table.go index 4ff5c6f4..afc20ad9 100644 --- a/pkg/converters/beancount/beancount_transaction_data_table.go +++ b/pkg/converters/beancount/beancount_transaction_data_table.go @@ -110,49 +110,49 @@ func (t *beancountTransactionDataRowIterator) Next(ctx core.Context, user *model func (t *beancountTransactionDataRowIterator) parseTransaction(ctx core.Context, user *models.User, beancountEntry *beancountTransactionEntry) (map[datatable.TransactionDataTableColumn]string, error) { data := make(map[datatable.TransactionDataTableColumn]string, len(beancountTransactionSupportedColumns)) - if beancountEntry.date == "" { + if beancountEntry.Date == "" { return nil, errs.ErrMissingTransactionTime } // Beancount supports the international ISO 8601 standard format for dates, with dashes or the same ordering with slashes - data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = strings.ReplaceAll(beancountEntry.date, "/", "-") + " 00:00:00" + data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = strings.ReplaceAll(beancountEntry.Date, "/", "-") + " 00:00:00" - if len(beancountEntry.postings) == 2 { - splitData1 := beancountEntry.postings[0] - splitData2 := beancountEntry.postings[1] + if len(beancountEntry.Postings) == 2 { + splitData1 := beancountEntry.Postings[0] + splitData2 := beancountEntry.Postings[1] - account1 := t.dataTable.accountMap[splitData1.account] - account2 := t.dataTable.accountMap[splitData2.account] + account1 := t.dataTable.accountMap[splitData1.Account] + account2 := t.dataTable.accountMap[splitData2.Account] if account1 == nil || account2 == nil { return nil, errs.ErrMissingAccountData } - amount1, err := utils.ParseAmount(splitData1.amount) + amount1, err := utils.ParseAmount(splitData1.Amount) if err != nil { - log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse amount \"%s\", because %s", splitData1.amount, err.Error()) + log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse amount \"%s\", because %s", splitData1.Amount, err.Error()) return nil, errs.ErrAmountInvalid } - amount2, err := utils.ParseAmount(splitData2.amount) + amount2, err := utils.ParseAmount(splitData2.Amount) if err != nil { - log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse amount \"%s\", because %s", splitData2.amount, err.Error()) + log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse amount \"%s\", because %s", splitData2.Amount, err.Error()) return nil, errs.ErrAmountInvalid } - if ((account1.accountType == beancountEquityAccountType || account1.accountType == beancountIncomeAccountType) && (account2.accountType == beancountAssetsAccountType || account2.accountType == beancountLiabilitiesAccountType)) || - ((account2.accountType == beancountEquityAccountType || account2.accountType == beancountIncomeAccountType) && (account1.accountType == beancountAssetsAccountType || account1.accountType == beancountLiabilitiesAccountType)) { // income + if ((account1.AccountType == beancountEquityAccountType || account1.AccountType == beancountIncomeAccountType) && (account2.AccountType == beancountAssetsAccountType || account2.AccountType == beancountLiabilitiesAccountType)) || + ((account2.AccountType == beancountEquityAccountType || account2.AccountType == beancountIncomeAccountType) && (account1.AccountType == beancountAssetsAccountType || account1.AccountType == beancountLiabilitiesAccountType)) { // income fromAccount := account1 toAccount := account2 - toCurrency := splitData2.commodity + toCurrency := splitData2.Commodity toAmount := amount2 - if (account2.accountType == beancountEquityAccountType || account2.accountType == beancountIncomeAccountType) && (account1.accountType == beancountAssetsAccountType || account1.accountType == beancountLiabilitiesAccountType) { + if (account2.AccountType == beancountEquityAccountType || account2.AccountType == beancountIncomeAccountType) && (account1.AccountType == beancountAssetsAccountType || account1.AccountType == beancountLiabilitiesAccountType) { fromAccount = account2 toAccount = account1 - toCurrency = splitData1.commodity + toCurrency = splitData1.Commodity toAmount = amount1 } @@ -162,48 +162,48 @@ func (t *beancountTransactionDataRowIterator) parseTransaction(ctx core.Context, data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = utils.IntToString(int(models.TRANSACTION_TYPE_INCOME)) } - data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = fromAccount.name - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = toAccount.name + data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = fromAccount.Name + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = toAccount.Name data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] = toCurrency data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(toAmount) - } else if account1.accountType == beancountExpensesAccountType && (account2.accountType == beancountAssetsAccountType || account2.accountType == beancountLiabilitiesAccountType) || - (account2.accountType == beancountExpensesAccountType && (account1.accountType == beancountAssetsAccountType || account1.accountType == beancountLiabilitiesAccountType)) { // expense + } else if account1.AccountType == beancountExpensesAccountType && (account2.AccountType == beancountAssetsAccountType || account2.AccountType == beancountLiabilitiesAccountType) || + (account2.AccountType == beancountExpensesAccountType && (account1.AccountType == beancountAssetsAccountType || account1.AccountType == beancountLiabilitiesAccountType)) { // expense fromAccount := account1 - fromCurrency := splitData1.commodity + fromCurrency := splitData1.Commodity fromAmount := amount1 toAccount := account2 - if account1.accountType == beancountExpensesAccountType && (account2.accountType == beancountAssetsAccountType || account2.accountType == beancountLiabilitiesAccountType) { + if account1.AccountType == beancountExpensesAccountType && (account2.AccountType == beancountAssetsAccountType || account2.AccountType == beancountLiabilitiesAccountType) { fromAccount = account2 - fromCurrency = splitData2.commodity + fromCurrency = splitData2.Commodity fromAmount = amount2 toAccount = account1 } data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = utils.IntToString(int(models.TRANSACTION_TYPE_EXPENSE)) - data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = toAccount.name - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = fromAccount.name + data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = toAccount.Name + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = fromAccount.Name data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] = fromCurrency data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-fromAmount) - } else if (account1.accountType == beancountAssetsAccountType || account1.accountType == beancountLiabilitiesAccountType) && - (account2.accountType == beancountAssetsAccountType || account2.accountType == beancountLiabilitiesAccountType) { + } else if (account1.AccountType == beancountAssetsAccountType || account1.AccountType == beancountLiabilitiesAccountType) && + (account2.AccountType == beancountAssetsAccountType || account2.AccountType == beancountLiabilitiesAccountType) { var fromAccount, toAccount *beancountAccount var fromAmount, toAmount int64 var fromCurrency, toCurrency string if amount1 < 0 { fromAccount = account1 - fromCurrency = splitData1.commodity + fromCurrency = splitData1.Commodity fromAmount = -amount1 toAccount = account2 - toCurrency = splitData2.commodity + toCurrency = splitData2.Commodity toAmount = amount2 } else if amount2 < 0 { fromAccount = account2 - fromCurrency = splitData2.commodity + fromCurrency = splitData2.Commodity fromAmount = -amount2 toAccount = account1 - toCurrency = splitData1.commodity + toCurrency = splitData1.Commodity toAmount = amount1 } else { log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse transfer transaction, because unexcepted account amounts \"%d\" and \"%d\"", amount1, amount2) @@ -212,26 +212,26 @@ func (t *beancountTransactionDataRowIterator) parseTransaction(ctx core.Context, data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = utils.IntToString(int(models.TRANSACTION_TYPE_TRANSFER)) data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = "" - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = fromAccount.name + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = fromAccount.Name data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] = fromCurrency data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(fromAmount) - data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = toAccount.name + data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = toAccount.Name data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = toCurrency data[datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT] = utils.FormatAmount(toAmount) } else { - log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse transaction, because unexcepted account types \"%d\" and \"%d\"", account1.accountType, account2.accountType) + log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse transaction, because unexcepted account types \"%d\" and \"%d\"", account1.AccountType, account2.AccountType) return nil, errs.ErrThereAreNotSupportedTransactionType } - } else if len(beancountEntry.postings) <= 1 { - log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse transaction, because postings count is %d", len(beancountEntry.postings)) + } else if len(beancountEntry.Postings) <= 1 { + log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse transaction, because postings count is %d", len(beancountEntry.Postings)) return nil, errs.ErrInvalidBeancountFile } else { - log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse split transaction, because postings count is %d", len(beancountEntry.postings)) + log.Errorf(ctx, "[beancount_transaction_data_table.parseTransaction] cannot parse split transaction, because postings count is %d", len(beancountEntry.Postings)) return nil, errs.ErrNotSupportedSplitTransactions } - data[datatable.TRANSACTION_DATA_TABLE_TAGS] = strings.Join(beancountEntry.tags, BEANCOUNT_TRANSACTION_TAG_SEPARATOR) - data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = beancountEntry.narration + data[datatable.TRANSACTION_DATA_TABLE_TAGS] = strings.Join(beancountEntry.Tags, BEANCOUNT_TRANSACTION_TAG_SEPARATOR) + data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = beancountEntry.Narration return data, nil } @@ -242,7 +242,7 @@ func createNewBeancountTransactionDataTable(beancountData *beancountData) (*bean } return &beancountTransactionDataTable{ - allData: beancountData.transactions, - accountMap: beancountData.accounts, + allData: beancountData.Transactions, + accountMap: beancountData.Accounts, }, nil } diff --git a/pkg/converters/iif/iif_data.go b/pkg/converters/iif/iif_data.go index 10b7bfd7..be009015 100644 --- a/pkg/converters/iif/iif_data.go +++ b/pkg/converters/iif/iif_data.go @@ -13,20 +13,20 @@ type iifAccountData struct { // iifTransactionDataset defines the structure of intuit interchange format (iif) transaction dataset type iifTransactionDataset struct { - transactionDataColumnIndexes map[string]int - splitDataColumnIndexes map[string]int - transactions []*iifTransactionData + TransactionDataColumnIndexes map[string]int + SplitDataColumnIndexes map[string]int + Transactions []*iifTransactionData } // iifTransactionData defines the structure of intuit interchange format (iif) transaction data type iifTransactionData struct { - dataItems []string - splitData []*iifTransactionSplitData + DataItems []string + SplitData []*iifTransactionSplitData } // iifTransactionSplitData defines the structure of intuit interchange format (iif) transaction split data type iifTransactionSplitData struct { - dataItems []string + DataItems []string } func (s *iifTransactionDataset) getTransactionDataItemValue(transactionData *iifTransactionData, columnName string) (string, bool) { @@ -34,13 +34,13 @@ func (s *iifTransactionDataset) getTransactionDataItemValue(transactionData *iif return "", false } - index, exists := s.transactionDataColumnIndexes[columnName] + index, exists := s.TransactionDataColumnIndexes[columnName] - if !exists || index < 0 || index >= len(transactionData.dataItems) { + if !exists || index < 0 || index >= len(transactionData.DataItems) { return "", false } - return transactionData.dataItems[index], true + return transactionData.DataItems[index], true } func (s *iifTransactionDataset) getSplitDataItemValue(splitData *iifTransactionSplitData, columnName string) (string, bool) { @@ -48,11 +48,11 @@ func (s *iifTransactionDataset) getSplitDataItemValue(splitData *iifTransactionS return "", false } - index, exists := s.splitDataColumnIndexes[columnName] + index, exists := s.SplitDataColumnIndexes[columnName] - if !exists || index < 0 || index >= len(splitData.dataItems) { + if !exists || index < 0 || index >= len(splitData.DataItems) { return "", false } - return splitData.dataItems[index], true + return splitData.DataItems[index], true } diff --git a/pkg/converters/iif/iif_data_reader.go b/pkg/converters/iif/iif_data_reader.go index 054a2c4d..9a5573ef 100644 --- a/pkg/converters/iif/iif_data_reader.go +++ b/pkg/converters/iif/iif_data_reader.go @@ -119,8 +119,8 @@ func (r *iifDataReader) read(ctx core.Context) ([]*iifAccountDataset, []*iifTran if lastLineSign == "" { if items[0] == iifTransactionLineSignColumnName { currentTransactionData = &iifTransactionData{ - dataItems: items, - splitData: make([]*iifTransactionSplitData, 0), + DataItems: items, + SplitData: make([]*iifTransactionSplitData, 0), } lastLineSign = items[0] } else { @@ -134,8 +134,8 @@ func (r *iifDataReader) read(ctx core.Context) ([]*iifAccountDataset, []*iifTran return nil, nil, errs.ErrInvalidIIFFile } - currentTransactionData.splitData = append(currentTransactionData.splitData, &iifTransactionSplitData{ - dataItems: items, + currentTransactionData.SplitData = append(currentTransactionData.SplitData, &iifTransactionSplitData{ + DataItems: items, }) lastLineSign = items[0] } else if items[0] == iifTransactionEndLineSignColumnName { @@ -144,12 +144,12 @@ func (r *iifDataReader) read(ctx core.Context) ([]*iifAccountDataset, []*iifTran return nil, nil, errs.ErrInvalidIIFFile } - if len(currentTransactionData.splitData) < 1 { + if len(currentTransactionData.SplitData) < 1 { log.Errorf(ctx, "[iif_data_reader.read] expected reading transaction split line, but read \"%s\"", items[0]) return nil, nil, errs.ErrInvalidIIFFile } - currentTransactionDataset.transactions = append(currentTransactionDataset.transactions, currentTransactionData) + currentTransactionDataset.Transactions = append(currentTransactionDataset.Transactions, currentTransactionData) lastLineSign = "" } else { log.Errorf(ctx, "[iif_data_reader.read] iif line expected reading split sign or transaction end sign, but actual is \"%s\"", items[0]) @@ -234,9 +234,9 @@ func (r *iifDataReader) readTransactionSampleLines(ctx core.Context, items []str } return &iifTransactionDataset{ - transactionDataColumnIndexes: transactionDataColumnIndexes, - splitDataColumnIndexes: splitDataColumnIndexes, - transactions: make([]*iifTransactionData, 0), + TransactionDataColumnIndexes: transactionDataColumnIndexes, + SplitDataColumnIndexes: splitDataColumnIndexes, + Transactions: make([]*iifTransactionData, 0), }, nil } diff --git a/pkg/converters/iif/iif_transaction_data_table.go b/pkg/converters/iif/iif_transaction_data_table.go index e340710d..d113007e 100644 --- a/pkg/converters/iif/iif_transaction_data_table.go +++ b/pkg/converters/iif/iif_transaction_data_table.go @@ -74,11 +74,11 @@ func (t *iifTransactionDataTable) TransactionRowCount() int { for i := 0; i < len(t.transactionDatasets); i++ { datasets := t.transactionDatasets[i] - for j := 0; j < len(datasets.transactions); j++ { - transaction := datasets.transactions[j] + for j := 0; j < len(datasets.Transactions); j++ { + transaction := datasets.Transactions[j] - if transaction.splitData != nil { - totalDataRowCount += len(transaction.splitData) + if transaction.SplitData != nil { + totalDataRowCount += len(transaction.SplitData) } } } @@ -122,17 +122,17 @@ func (t *iifTransactionDataRowIterator) HasNext() bool { currentDataset := allDatasets[t.currentDatasetIndex] - if t.currentIndexInDataset+1 < len(currentDataset.transactions) { + if t.currentIndexInDataset+1 < len(currentDataset.Transactions) { return true - } else if t.currentIndexInDataset < len(currentDataset.transactions) && - t.currentSplitDataIndex+1 < len(currentDataset.transactions[t.currentIndexInDataset].splitData) { + } else if t.currentIndexInDataset < len(currentDataset.Transactions) && + t.currentSplitDataIndex+1 < len(currentDataset.Transactions[t.currentIndexInDataset].SplitData) { return true } for i := t.currentDatasetIndex + 1; i < len(allDatasets); i++ { dataset := allDatasets[i] - if len(dataset.transactions) < 1 { + if len(dataset.Transactions) < 1 { continue } @@ -150,8 +150,8 @@ func (t *iifTransactionDataRowIterator) Next(ctx core.Context, user *models.User foundNextRow := false dataset := allDatasets[i] - for j := t.currentIndexInDataset; j < len(dataset.transactions); j++ { - if t.currentSplitDataIndex+1 < len(dataset.transactions[j].splitData) { + for j := t.currentIndexInDataset; j < len(dataset.Transactions); j++ { + if t.currentSplitDataIndex+1 < len(dataset.Transactions[j].SplitData) { t.currentSplitDataIndex++ foundNextRow = true break @@ -176,22 +176,22 @@ func (t *iifTransactionDataRowIterator) Next(ctx core.Context, user *models.User currentDataset := allDatasets[t.currentDatasetIndex] - if t.currentIndexInDataset >= len(currentDataset.transactions) { + if t.currentIndexInDataset >= len(currentDataset.Transactions) { return nil, nil } - data := currentDataset.transactions[t.currentIndexInDataset] + data := currentDataset.Transactions[t.currentIndexInDataset] - if len(data.splitData) < 1 { + if len(data.SplitData) < 1 { log.Errorf(ctx, "[iif_transaction_data_table.Next] cannot parsing transaction in row#%d (dataset#%d), because split data is empty", t.currentIndexInDataset, t.currentDatasetIndex) return nil, errs.ErrInvalidIIFFile } - if t.currentSplitDataIndex >= len(data.splitData) { + if t.currentSplitDataIndex >= len(data.SplitData) { return nil, nil } - if len(data.splitData) > 1 { + if len(data.SplitData) > 1 { _, err := t.isSplitTransactionSupported(ctx, currentDataset, data) if err != nil { @@ -222,11 +222,11 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user return nil, err } - transactionType, _ := dataset.getSplitDataItemValue(transactionData.splitData[splitDataIndex], iifTransactionTypeColumnName) + transactionType, _ := dataset.getSplitDataItemValue(transactionData.SplitData[splitDataIndex], iifTransactionTypeColumnName) mainAccountName, _ := dataset.getTransactionDataItemValue(transactionData, iifTransactionAccountNameColumnName) - splitAccountName, _ := dataset.getSplitDataItemValue(transactionData.splitData[splitDataIndex], iifTransactionAccountNameColumnName) + splitAccountName, _ := dataset.getSplitDataItemValue(transactionData.SplitData[splitDataIndex], iifTransactionAccountNameColumnName) mainAmount, _ := dataset.getTransactionDataItemValue(transactionData, iifTransactionAmountColumnName) - splitAmount, _ := dataset.getSplitDataItemValue(transactionData.splitData[splitDataIndex], iifTransactionAmountColumnName) + splitAmount, _ := dataset.getSplitDataItemValue(transactionData.SplitData[splitDataIndex], iifTransactionAmountColumnName) mainAmountNum, err := parseAmount(mainAmount) if err != nil { @@ -254,7 +254,7 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user categoryName = mainAccountName accountName = splitAccountName - if len(transactionData.splitData) > 1 { + if len(transactionData.SplitData) > 1 { amountNum = splitAmountNum } else { amountNum = -mainAmountNum @@ -263,7 +263,7 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user categoryName = splitAccountName accountName = mainAccountName - if len(transactionData.splitData) > 1 { + if len(transactionData.SplitData) > 1 { amountNum = -splitAmountNum } else { amountNum = mainAmountNum @@ -295,7 +295,7 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user categoryName = mainAccountName accountName = splitAccountName - if len(transactionData.splitData) > 1 { + if len(transactionData.SplitData) > 1 { amountNum = -splitAmountNum } else { amountNum = mainAmountNum @@ -304,7 +304,7 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user categoryName = splitAccountName accountName = mainAccountName - if len(transactionData.splitData) > 1 { + if len(transactionData.SplitData) > 1 { amountNum = splitAmountNum } else { amountNum = -mainAmountNum @@ -332,7 +332,7 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user relatedAmountNum := int64(0) mainAccountTransferToSplitAccount := false - if len(transactionData.splitData) > 1 { + if len(transactionData.SplitData) > 1 { amountNum = splitAmountNum relatedAmountNum = splitAmountNum mainAccountTransferToSplitAccount = amountNum >= 0 @@ -369,11 +369,11 @@ func (t *iifTransactionDataRowIterator) parseTransaction(ctx core.Context, user } } - if splitMemo, _ := dataset.getSplitDataItemValue(transactionData.splitData[splitDataIndex], iifTransactionMemoColumnName); splitMemo != "" { + if splitMemo, _ := dataset.getSplitDataItemValue(transactionData.SplitData[splitDataIndex], iifTransactionMemoColumnName); splitMemo != "" { data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = splitMemo } else if memo, _ := dataset.getTransactionDataItemValue(transactionData, iifTransactionMemoColumnName); memo != "" { data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = memo - } else if splitName, _ := dataset.getSplitDataItemValue(transactionData.splitData[splitDataIndex], iifTransactionNameColumnName); splitName != "" { + } else if splitName, _ := dataset.getSplitDataItemValue(transactionData.SplitData[splitDataIndex], iifTransactionNameColumnName); splitName != "" { data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = splitName } else if name, _ := dataset.getTransactionDataItemValue(transactionData, iifTransactionNameColumnName); name != "" { data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = name @@ -402,8 +402,8 @@ func (t *iifTransactionDataRowIterator) isSplitTransactionSupported(ctx core.Con splitTotalAmount := int64(0) - for i := 0; i < len(transactionData.splitData); i++ { - splitAmountStr, _ := dataset.getSplitDataItemValue(transactionData.splitData[i], iifTransactionAmountColumnName) + for i := 0; i < len(transactionData.SplitData); i++ { + splitAmountStr, _ := dataset.getSplitDataItemValue(transactionData.SplitData[i], iifTransactionAmountColumnName) splitAmount, err := parseAmount(splitAmountStr) if err != nil { @@ -420,7 +420,7 @@ func (t *iifTransactionDataRowIterator) isSplitTransactionSupported(ctx core.Con } } - if len(transactionData.splitData) > 1 && !supportSplitTransactions { + if len(transactionData.SplitData) > 1 && !supportSplitTransactions { return false, errs.ErrNotSupportedSplitTransactions } @@ -463,7 +463,7 @@ func createNewIIfTransactionDataTable(ctx core.Context, accountDatasets []*iifAc iifTransactionAccountNameColumnName, iifTransactionAmountColumnName, } { - if _, exists := transactionDataset.transactionDataColumnIndexes[requiredColumnName]; !exists { + if _, exists := transactionDataset.TransactionDataColumnIndexes[requiredColumnName]; !exists { return nil, errs.ErrMissingRequiredFieldInHeaderRow } } diff --git a/pkg/converters/qif/qif_data.go b/pkg/converters/qif/qif_data.go index ad065358..77ce8b10 100644 --- a/pkg/converters/qif/qif_data.go +++ b/pkg/converters/qif/qif_data.go @@ -34,91 +34,91 @@ const ( // qifData defines the structure of quicken interchange format (qif) data type qifData struct { - bankAccountTransactions []*qifTransactionData - cashAccountTransactions []*qifTransactionData - creditCardAccountTransactions []*qifTransactionData - assetAccountTransactions []*qifTransactionData - liabilityAccountTransactions []*qifTransactionData - memorizedTransactions []*qifMemorizedTransactionData - investmentAccountTransactions []*qifInvestmentTransactionData - accounts []*qifAccountData - categories []*qifCategoryData - classes []*qifClassData + BankAccountTransactions []*qifTransactionData + CashAccountTransactions []*qifTransactionData + CreditCardAccountTransactions []*qifTransactionData + AssetAccountTransactions []*qifTransactionData + LiabilityAccountTransactions []*qifTransactionData + MemorizedTransactions []*qifMemorizedTransactionData + InvestmentAccountTransactions []*qifInvestmentTransactionData + Accounts []*qifAccountData + Categories []*qifCategoryData + Classes []*qifClassData } // qifTransactionData defines the structure of quicken interchange format (qif) transaction data type qifTransactionData struct { - date string - amount string - clearedStatus qifTransactionClearedStatus - num string - payee string - memo string - addresses []string - category string - subTransactionCategory []string - subTransactionMemo []string - subTransactionAmount []string - account *qifAccountData + Date string + Amount string + ClearedStatus qifTransactionClearedStatus + Num string + Payee string + Memo string + Addresses []string + Category string + SubTransactionCategory []string + SubTransactionMemo []string + SubTransactionAmount []string + Account *qifAccountData } // qifInvestmentTransactionData defines the structure of quicken interchange format (qif) investment transaction data type qifInvestmentTransactionData struct { - date string - action string - security string - price string - quantity string - amount string - clearedStatus qifTransactionClearedStatus - text string - memo string - commission string - accountForTransfer string - amountTransferred string - account *qifAccountData + Date string + Action string + Security string + Price string + Quantity string + Amount string + ClearedStatus qifTransactionClearedStatus + Text string + Memo string + Commission string + AccountForTransfer string + AmountTransferred string + Account *qifAccountData } // qifMemorizedTransactionData defines the structure of quicken interchange format (qif) memorized transaction data type qifMemorizedTransactionData struct { qifTransactionData - transactionType qifTransactionType - amortization qifMemorizedTransactionAmortizationData + TransactionType qifTransactionType + Amortization qifMemorizedTransactionAmortizationData } // qifMemorizedTransactionAmortizationData defines the structure of quicken interchange format (qif) memorized transaction amortization data type qifMemorizedTransactionAmortizationData struct { - firstPaymentDate string - totalYearsForLoan string - numberOfPayments string - numberOfPeriodsPerYear string - interestRate string - currentLoanBalance string - originalLoanAmount string + FirstPaymentDate string + TotalYearsForLoan string + NumberOfPayments string + NumberOfPeriodsPerYear string + InterestRate string + CurrentLoanBalance string + OriginalLoanAmount string } // qifAccountData defines the structure of quicken interchange format (qif) account data type qifAccountData struct { - name string - accountType string - description string - creditLimit string - statementBalanceDate string - statementBalanceAmount string + Name string + AccountType string + Description string + CreditLimit string + StatementBalanceDate string + StatementBalanceAmount string } // qifCategoryData defines the structure of quicken interchange format (qif) category data type qifCategoryData struct { - name string - description string - taxRelated bool - categoryType qifCategoryType - budgetAmount string - taxScheduleInformation string + Name string + Description string + TaxRelated bool + CategoryType qifCategoryType + BudgetAmount string + TaxScheduleInformation string } // qifClassData defines the structure of quicken interchange format (qif) class data type qifClassData struct { - name string - description string + Name string + Description string } diff --git a/pkg/converters/qif/qif_data_reader.go b/pkg/converters/qif/qif_data_reader.go index 47796527..36056054 100644 --- a/pkg/converters/qif/qif_data_reader.go +++ b/pkg/converters/qif/qif_data_reader.go @@ -98,18 +98,18 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { continue } - transactionData.account = currentAccount + transactionData.Account = currentAccount if currentEntryHeader == qifBankTransactionHeader { - data.bankAccountTransactions = append(data.bankAccountTransactions, transactionData) + data.BankAccountTransactions = append(data.BankAccountTransactions, transactionData) } else if currentEntryHeader == qifCashTransactionHeader { - data.cashAccountTransactions = append(data.cashAccountTransactions, transactionData) + data.CashAccountTransactions = append(data.CashAccountTransactions, transactionData) } else if currentEntryHeader == qifCreditCardTransactionHeader { - data.creditCardAccountTransactions = append(data.creditCardAccountTransactions, transactionData) + data.CreditCardAccountTransactions = append(data.CreditCardAccountTransactions, transactionData) } else if currentEntryHeader == qifAssetAccountTransactionHeader { - data.assetAccountTransactions = append(data.assetAccountTransactions, transactionData) + data.AssetAccountTransactions = append(data.AssetAccountTransactions, transactionData) } else if currentEntryHeader == qifLiabilityAccountTransactionHeader { - data.liabilityAccountTransactions = append(data.liabilityAccountTransactions, transactionData) + data.LiabilityAccountTransactions = append(data.LiabilityAccountTransactions, transactionData) } } else if currentEntryHeader == qifMemorizedTransactionHeader || currentEntryHeader == qifMemorisedTransactionHeader { transactionData, err := r.parseMemorizedTransaction(ctx, entryData) @@ -122,8 +122,8 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { continue } - transactionData.account = currentAccount - data.memorizedTransactions = append(data.memorizedTransactions, transactionData) + transactionData.Account = currentAccount + data.MemorizedTransactions = append(data.MemorizedTransactions, transactionData) } else if currentEntryHeader == qifInvestmentTransactionHeader { transactionData, err := r.parseInvestmentTransaction(ctx, entryData) @@ -135,8 +135,8 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { continue } - transactionData.account = currentAccount - data.investmentAccountTransactions = append(data.investmentAccountTransactions, transactionData) + transactionData.Account = currentAccount + data.InvestmentAccountTransactions = append(data.InvestmentAccountTransactions, transactionData) } else if currentEntryHeader == qifAccountHeader { accountData, err := r.parseAccount(ctx, entryData) @@ -149,7 +149,7 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { } currentAccount = accountData - data.accounts = append(data.accounts, accountData) + data.Accounts = append(data.Accounts, accountData) } else if currentEntryHeader == qifCategoryHeader { categoryData, err := r.parseCategory(ctx, entryData) @@ -161,7 +161,7 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { continue } - data.categories = append(data.categories, categoryData) + data.Categories = append(data.Categories, categoryData) } else if currentEntryHeader == qifClassHeader { classData, err := r.parseClass(ctx, entryData) @@ -173,7 +173,7 @@ func (r *qifDataReader) read(ctx core.Context) (*qifData, error) { continue } - data.classes = append(data.classes, classData) + data.Classes = append(data.Classes, classData) } else { log.Warnf(ctx, "[qif_data_reader.read] read unsupported entry header \"%s\" and skip this entry", currentEntryHeader) } @@ -202,27 +202,27 @@ func (r *qifDataReader) parseTransaction(ctx core.Context, data []string, ignore } if line[0] == 'D' { - transactionData.date = line[1:] + transactionData.Date = line[1:] } else if line[0] == 'T' { - transactionData.amount = line[1:] + transactionData.Amount = line[1:] } else if line[0] == 'C' { - transactionData.clearedStatus = r.parseClearedStatus(ctx, line[1:]) + transactionData.ClearedStatus = r.parseClearedStatus(ctx, line[1:]) } else if line[0] == 'N' { - transactionData.num = line[1:] + transactionData.Num = line[1:] } else if line[0] == 'P' { - transactionData.payee = line[1:] + transactionData.Payee = line[1:] } else if line[0] == 'M' { - transactionData.memo = line[1:] + transactionData.Memo = line[1:] } else if line[0] == 'A' { - transactionData.addresses = append(transactionData.addresses, line[1:]) + transactionData.Addresses = append(transactionData.Addresses, line[1:]) } else if line[0] == 'L' { - transactionData.category = line[1:] + transactionData.Category = line[1:] } else if line[0] == 'S' { - transactionData.subTransactionCategory = append(transactionData.subTransactionCategory, line[1:]) + transactionData.SubTransactionCategory = append(transactionData.SubTransactionCategory, line[1:]) } else if line[0] == 'E' { - transactionData.subTransactionMemo = append(transactionData.subTransactionMemo, line[1:]) + transactionData.SubTransactionMemo = append(transactionData.SubTransactionMemo, line[1:]) } else if line[0] == '$' { - transactionData.subTransactionAmount = append(transactionData.subTransactionAmount, line[1:]) + transactionData.SubTransactionAmount = append(transactionData.SubTransactionAmount, line[1:]) } else { if !ignoreUnknown { log.Warnf(ctx, "[qif_data_reader.parseTransaction] read unsupported line \"%s\" and skip this line", line) @@ -247,7 +247,7 @@ func (r *qifDataReader) parseMemorizedTransaction(ctx core.Context, data []strin transactionData := &qifMemorizedTransactionData{ qifTransactionData: *baseTransactionData, - amortization: qifMemorizedTransactionAmortizationData{}, + Amortization: qifMemorizedTransactionAmortizationData{}, } for i := 0; i < len(data); i++ { @@ -266,33 +266,33 @@ func (r *qifDataReader) parseMemorizedTransaction(ctx core.Context, data []strin if line[0] == 'K' { if line == string(qifCheckTransactionType) { - transactionData.transactionType = qifCheckTransactionType + transactionData.TransactionType = qifCheckTransactionType } else if line == string(qifDepositTransactionType) { - transactionData.transactionType = qifDepositTransactionType + transactionData.TransactionType = qifDepositTransactionType } else if line == string(qifPaymentTransactionType) { - transactionData.transactionType = qifPaymentTransactionType + transactionData.TransactionType = qifPaymentTransactionType } else if line == string(qifInvestmentTransactionType) { - transactionData.transactionType = qifInvestmentTransactionType + transactionData.TransactionType = qifInvestmentTransactionType } else if line == string(qifElectronicPayeeTransactionType) { - transactionData.transactionType = qifElectronicPayeeTransactionType + transactionData.TransactionType = qifElectronicPayeeTransactionType } else { log.Warnf(ctx, "[qif_data_reader.parseMemorizedTransaction] read unsupported transaction type \"%s\" and skip this line", line) continue } } else if line[0] == '1' { - transactionData.amortization.firstPaymentDate = line[1:] + transactionData.Amortization.FirstPaymentDate = line[1:] } else if line[0] == '2' { - transactionData.amortization.totalYearsForLoan = line[1:] + transactionData.Amortization.TotalYearsForLoan = line[1:] } else if line[0] == '3' { - transactionData.amortization.numberOfPayments = line[1:] + transactionData.Amortization.NumberOfPayments = line[1:] } else if line[0] == '4' { - transactionData.amortization.numberOfPeriodsPerYear = line[1:] + transactionData.Amortization.NumberOfPeriodsPerYear = line[1:] } else if line[0] == '5' { - transactionData.amortization.interestRate = line[1:] + transactionData.Amortization.InterestRate = line[1:] } else if line[0] == '6' { - transactionData.amortization.currentLoanBalance = line[1:] + transactionData.Amortization.CurrentLoanBalance = line[1:] } else if line[0] == '7' { - transactionData.amortization.originalLoanAmount = line[1:] + transactionData.Amortization.OriginalLoanAmount = line[1:] } else { log.Warnf(ctx, "[qif_data_reader.parseMemorizedTransaction] read unsupported line \"%s\" and skip this line", line) continue @@ -317,29 +317,29 @@ func (r *qifDataReader) parseInvestmentTransaction(ctx core.Context, data []stri } if line[0] == 'D' { - transactionData.date = line[1:] + transactionData.Date = line[1:] } else if line[0] == 'N' { - transactionData.action = line[1:] + transactionData.Action = line[1:] } else if line[0] == 'Y' { - transactionData.security = line[1:] + transactionData.Security = line[1:] } else if line[0] == 'I' { - transactionData.price = line[1:] + transactionData.Price = line[1:] } else if line[0] == 'Q' { - transactionData.quantity = line[1:] + transactionData.Quantity = line[1:] } else if line[0] == 'T' { - transactionData.amount = line[1:] + transactionData.Amount = line[1:] } else if line[0] == 'C' { - transactionData.clearedStatus = r.parseClearedStatus(ctx, line[1:]) + transactionData.ClearedStatus = r.parseClearedStatus(ctx, line[1:]) } else if line[0] == 'P' { - transactionData.text = line[1:] + transactionData.Text = line[1:] } else if line[0] == 'M' { - transactionData.memo = line[1:] + transactionData.Memo = line[1:] } else if line[0] == 'O' { - transactionData.commission = line[1:] + transactionData.Commission = line[1:] } else if line[0] == 'L' { - transactionData.accountForTransfer = line[1:] + transactionData.AccountForTransfer = line[1:] } else if line[0] == '$' { - transactionData.amountTransferred = line[1:] + transactionData.AmountTransferred = line[1:] } else { log.Warnf(ctx, "[qif_data_reader.parseInvestmentTransaction] read unsupported line \"%s\" and skip this line", line) continue @@ -364,17 +364,17 @@ func (r *qifDataReader) parseAccount(ctx core.Context, data []string) (*qifAccou } if line[0] == 'N' { - accountData.name = line[1:] + accountData.Name = line[1:] } else if line[0] == 'T' { - accountData.accountType = line[1:] + accountData.AccountType = line[1:] } else if line[0] == 'D' { - accountData.description = line[1:] + accountData.Description = line[1:] } else if line[0] == 'L' { - accountData.creditLimit = line[1:] + accountData.CreditLimit = line[1:] } else if line[0] == '/' { - accountData.statementBalanceDate = line[1:] + accountData.StatementBalanceDate = line[1:] } else if line[0] == '$' { - accountData.statementBalanceAmount = line[1:] + accountData.StatementBalanceAmount = line[1:] } else { log.Warnf(ctx, "[qif_data_reader.parseAccount] read unsupported line \"%s\" and skip this line", line) continue @@ -399,27 +399,27 @@ func (r *qifDataReader) parseCategory(ctx core.Context, data []string) (*qifCate } if line[0] == 'N' { - categoryData.name = line[1:] + categoryData.Name = line[1:] } else if line[0] == 'D' { - categoryData.description = line[1:] + categoryData.Description = line[1:] } else if line[0] == 'T' { - categoryData.taxRelated = true + categoryData.TaxRelated = true } else if line[0] == 'I' { - categoryData.categoryType = qifIncomeTransaction + categoryData.CategoryType = qifIncomeTransaction } else if line[0] == 'E' { - categoryData.categoryType = qifExpenseTransaction + categoryData.CategoryType = qifExpenseTransaction } else if line[0] == 'B' { - categoryData.budgetAmount = line[1:] + categoryData.BudgetAmount = line[1:] } else if line[0] == 'R' { - categoryData.taxScheduleInformation = line[1:] + categoryData.TaxScheduleInformation = line[1:] } else { log.Warnf(ctx, "[qif_data_reader.parseCategory] read unsupported line \"%s\" and skip this line", line) continue } } - if categoryData.categoryType == "" { - categoryData.categoryType = qifExpenseTransaction + if categoryData.CategoryType == "" { + categoryData.CategoryType = qifExpenseTransaction } return categoryData, nil @@ -440,9 +440,9 @@ func (r *qifDataReader) parseClass(ctx core.Context, data []string) (*qifClassDa } if line[0] == 'N' { - classData.name = line[1:] + classData.Name = line[1:] } else if line[0] == 'D' { - classData.description = line[1:] + classData.Description = line[1:] } else { log.Warnf(ctx, "[qif_data_reader.parseClass] read unsupported line \"%s\" and skip this line", line) continue diff --git a/pkg/converters/qif/qif_data_reader_test.go b/pkg/converters/qif/qif_data_reader_test.go index dd969105..daa40daf 100644 --- a/pkg/converters/qif/qif_data_reader_test.go +++ b/pkg/converters/qif/qif_data_reader_test.go @@ -64,48 +64,48 @@ func TestQifDataReaderParse(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 2, len(actualData.bankAccountTransactions)) - assert.Equal(t, "2024/10/9", actualData.bankAccountTransactions[0].date) - assert.Equal(t, "-123.45", actualData.bankAccountTransactions[0].amount) - assert.Equal(t, "2024/10/12", actualData.bankAccountTransactions[1].date) - assert.Equal(t, "+234.56", actualData.bankAccountTransactions[1].amount) + assert.Equal(t, 2, len(actualData.BankAccountTransactions)) + assert.Equal(t, "2024/10/9", actualData.BankAccountTransactions[0].Date) + assert.Equal(t, "-123.45", actualData.BankAccountTransactions[0].Amount) + assert.Equal(t, "2024/10/12", actualData.BankAccountTransactions[1].Date) + assert.Equal(t, "+234.56", actualData.BankAccountTransactions[1].Amount) - assert.Equal(t, 1, len(actualData.cashAccountTransactions)) - assert.Equal(t, "2024/9/1", actualData.cashAccountTransactions[0].date) - assert.Equal(t, "100.00", actualData.cashAccountTransactions[0].amount) - assert.Equal(t, "Opening Balance", actualData.cashAccountTransactions[0].payee) - assert.Equal(t, "[Wallet]", actualData.cashAccountTransactions[0].category) + assert.Equal(t, 1, len(actualData.CashAccountTransactions)) + assert.Equal(t, "2024/9/1", actualData.CashAccountTransactions[0].Date) + assert.Equal(t, "100.00", actualData.CashAccountTransactions[0].Amount) + assert.Equal(t, "Opening Balance", actualData.CashAccountTransactions[0].Payee) + assert.Equal(t, "[Wallet]", actualData.CashAccountTransactions[0].Category) - assert.Equal(t, 1, len(actualData.memorizedTransactions)) - assert.Equal(t, qifCheckTransactionType, actualData.memorizedTransactions[0].transactionType) - assert.Equal(t, "-123.45", actualData.memorizedTransactions[0].amount) - assert.Equal(t, "2024/10/13", actualData.memorizedTransactions[0].amortization.firstPaymentDate) - assert.Equal(t, "3", actualData.memorizedTransactions[0].amortization.totalYearsForLoan) - assert.Equal(t, "1", actualData.memorizedTransactions[0].amortization.numberOfPayments) - assert.Equal(t, "2", actualData.memorizedTransactions[0].amortization.numberOfPeriodsPerYear) - assert.Equal(t, "12.34", actualData.memorizedTransactions[0].amortization.interestRate) - assert.Equal(t, "100.45", actualData.memorizedTransactions[0].amortization.currentLoanBalance) - assert.Equal(t, "234.56", actualData.memorizedTransactions[0].amortization.originalLoanAmount) + assert.Equal(t, 1, len(actualData.MemorizedTransactions)) + assert.Equal(t, qifCheckTransactionType, actualData.MemorizedTransactions[0].TransactionType) + assert.Equal(t, "-123.45", actualData.MemorizedTransactions[0].Amount) + assert.Equal(t, "2024/10/13", actualData.MemorizedTransactions[0].Amortization.FirstPaymentDate) + assert.Equal(t, "3", actualData.MemorizedTransactions[0].Amortization.TotalYearsForLoan) + assert.Equal(t, "1", actualData.MemorizedTransactions[0].Amortization.NumberOfPayments) + assert.Equal(t, "2", actualData.MemorizedTransactions[0].Amortization.NumberOfPeriodsPerYear) + assert.Equal(t, "12.34", actualData.MemorizedTransactions[0].Amortization.InterestRate) + assert.Equal(t, "100.45", actualData.MemorizedTransactions[0].Amortization.CurrentLoanBalance) + assert.Equal(t, "234.56", actualData.MemorizedTransactions[0].Amortization.OriginalLoanAmount) - assert.Equal(t, 1, len(actualData.investmentAccountTransactions)) - assert.Equal(t, "2024/10/14", actualData.investmentAccountTransactions[0].date) - assert.Equal(t, "Buy", actualData.investmentAccountTransactions[0].action) - assert.Equal(t, "Test", actualData.investmentAccountTransactions[0].security) - assert.Equal(t, "12.34", actualData.investmentAccountTransactions[0].price) - assert.Equal(t, "10", actualData.investmentAccountTransactions[0].quantity) - assert.Equal(t, "-123.4", actualData.investmentAccountTransactions[0].amount) + assert.Equal(t, 1, len(actualData.InvestmentAccountTransactions)) + assert.Equal(t, "2024/10/14", actualData.InvestmentAccountTransactions[0].Date) + assert.Equal(t, "Buy", actualData.InvestmentAccountTransactions[0].Action) + assert.Equal(t, "Test", actualData.InvestmentAccountTransactions[0].Security) + assert.Equal(t, "12.34", actualData.InvestmentAccountTransactions[0].Price) + assert.Equal(t, "10", actualData.InvestmentAccountTransactions[0].Quantity) + assert.Equal(t, "-123.4", actualData.InvestmentAccountTransactions[0].Amount) - assert.Equal(t, 2, len(actualData.accounts)) - assert.Equal(t, "Test Account", actualData.accounts[0].name) - assert.Equal(t, "Wallet", actualData.accounts[1].name) + assert.Equal(t, 2, len(actualData.Accounts)) + assert.Equal(t, "Test Account", actualData.Accounts[0].Name) + assert.Equal(t, "Wallet", actualData.Accounts[1].Name) - assert.Equal(t, 1, len(actualData.categories)) - assert.Equal(t, "Test Category", actualData.categories[0].name) - assert.Equal(t, qifIncomeTransaction, actualData.categories[0].categoryType) + assert.Equal(t, 1, len(actualData.Categories)) + assert.Equal(t, "Test Category", actualData.Categories[0].Name) + assert.Equal(t, qifIncomeTransaction, actualData.Categories[0].CategoryType) - assert.Equal(t, 1, len(actualData.classes)) - assert.Equal(t, "Test Class", actualData.classes[0].name) - assert.Equal(t, "Foo Bar", actualData.classes[0].description) + assert.Equal(t, 1, len(actualData.Classes)) + assert.Equal(t, "Test Class", actualData.Classes[0].Name) + assert.Equal(t, "Foo Bar", actualData.Classes[0].Description) } func TestQifDataReaderParse_AccountEntryBeforeTransaction(t *testing.T) { @@ -137,21 +137,21 @@ func TestQifDataReaderParse_AccountEntryBeforeTransaction(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 2, len(actualData.bankAccountTransactions)) - assert.Equal(t, "2024/10/9", actualData.bankAccountTransactions[0].date) - assert.Equal(t, "-123.45", actualData.bankAccountTransactions[0].amount) - assert.Equal(t, "2024/10/12", actualData.bankAccountTransactions[1].date) - assert.Equal(t, "+234.56", actualData.bankAccountTransactions[1].amount) + assert.Equal(t, 2, len(actualData.BankAccountTransactions)) + assert.Equal(t, "2024/10/9", actualData.BankAccountTransactions[0].Date) + assert.Equal(t, "-123.45", actualData.BankAccountTransactions[0].Amount) + assert.Equal(t, "2024/10/12", actualData.BankAccountTransactions[1].Date) + assert.Equal(t, "+234.56", actualData.BankAccountTransactions[1].Amount) - assert.Equal(t, 1, len(actualData.cashAccountTransactions)) - assert.Equal(t, "2024/9/1", actualData.cashAccountTransactions[0].date) - assert.Equal(t, "100.00", actualData.cashAccountTransactions[0].amount) - assert.Equal(t, "Opening Balance", actualData.cashAccountTransactions[0].payee) - assert.Equal(t, "[Wallet]", actualData.cashAccountTransactions[0].category) + assert.Equal(t, 1, len(actualData.CashAccountTransactions)) + assert.Equal(t, "2024/9/1", actualData.CashAccountTransactions[0].Date) + assert.Equal(t, "100.00", actualData.CashAccountTransactions[0].Amount) + assert.Equal(t, "Opening Balance", actualData.CashAccountTransactions[0].Payee) + assert.Equal(t, "[Wallet]", actualData.CashAccountTransactions[0].Category) - assert.Equal(t, 2, len(actualData.accounts)) - assert.Equal(t, "Test Account", actualData.accounts[0].name) - assert.Equal(t, "Wallet", actualData.accounts[1].name) + assert.Equal(t, 2, len(actualData.Accounts)) + assert.Equal(t, "Test Account", actualData.Accounts[0].Name) + assert.Equal(t, "Wallet", actualData.Accounts[1].Name) } func TestQifDataReaderParse_EmptyContent(t *testing.T) { @@ -188,13 +188,13 @@ func TestQifDataReaderParse_EmptyEntry(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 0, len(actualData.bankAccountTransactions)) - assert.Equal(t, 0, len(actualData.cashAccountTransactions)) - assert.Equal(t, 0, len(actualData.memorizedTransactions)) - assert.Equal(t, 0, len(actualData.investmentAccountTransactions)) - assert.Equal(t, 0, len(actualData.accounts)) - assert.Equal(t, 0, len(actualData.categories)) - assert.Equal(t, 0, len(actualData.classes)) + assert.Equal(t, 0, len(actualData.BankAccountTransactions)) + assert.Equal(t, 0, len(actualData.CashAccountTransactions)) + assert.Equal(t, 0, len(actualData.MemorizedTransactions)) + assert.Equal(t, 0, len(actualData.InvestmentAccountTransactions)) + assert.Equal(t, 0, len(actualData.Accounts)) + assert.Equal(t, 0, len(actualData.Categories)) + assert.Equal(t, 0, len(actualData.Classes)) } func TestQifDataReaderParse_UnsupportedEntryHeader(t *testing.T) { @@ -215,9 +215,9 @@ func TestQifDataReaderParse_UnsupportedEntryHeader(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 1, len(actualData.bankAccountTransactions)) - assert.Equal(t, "2024/10/9", actualData.bankAccountTransactions[0].date) - assert.Equal(t, "-123.45", actualData.bankAccountTransactions[0].amount) + assert.Equal(t, 1, len(actualData.BankAccountTransactions)) + assert.Equal(t, "2024/10/9", actualData.BankAccountTransactions[0].Date) + assert.Equal(t, "-123.45", actualData.BankAccountTransactions[0].Amount) } func TestQifDataReaderParse_UnsupportedLine(t *testing.T) { @@ -238,11 +238,11 @@ func TestQifDataReaderParse_UnsupportedLine(t *testing.T) { actualData, err := reader.read(context) assert.Nil(t, err) - assert.Equal(t, 2, len(actualData.bankAccountTransactions)) - assert.Equal(t, "2024/10/9", actualData.bankAccountTransactions[0].date) - assert.Equal(t, "-123.45", actualData.bankAccountTransactions[0].amount) - assert.Equal(t, "2024/10/11", actualData.bankAccountTransactions[1].date) - assert.Equal(t, "100.00", actualData.bankAccountTransactions[1].amount) + assert.Equal(t, 2, len(actualData.BankAccountTransactions)) + assert.Equal(t, "2024/10/9", actualData.BankAccountTransactions[0].Date) + assert.Equal(t, "-123.45", actualData.BankAccountTransactions[0].Amount) + assert.Equal(t, "2024/10/11", actualData.BankAccountTransactions[1].Date) + assert.Equal(t, "100.00", actualData.BankAccountTransactions[1].Amount) } func TestQifDataReaderParse_NewEntryHeaderAfterUnclosedEntry(t *testing.T) { @@ -289,26 +289,26 @@ func TestQifDataReaderParseTransaction_SupportedFields(t *testing.T) { }, false) assert.Nil(t, err) - assert.Equal(t, "2024/10/12", actualData.date) - assert.Equal(t, "-123.45", actualData.amount) - assert.Equal(t, qifClearedStatusUnreconciled, actualData.clearedStatus) - assert.Equal(t, "100", actualData.num) - assert.Equal(t, "Foo", actualData.payee) - assert.Equal(t, "Bar", actualData.memo) - assert.Equal(t, 3, len(actualData.addresses)) - assert.Equal(t, "Address 1", actualData.addresses[0]) - assert.Equal(t, "Address 2", actualData.addresses[1]) - assert.Equal(t, "Address 3", actualData.addresses[2]) - assert.Equal(t, "Test Category", actualData.category) - assert.Equal(t, 2, len(actualData.subTransactionCategory)) - assert.Equal(t, "Part1 Category", actualData.subTransactionCategory[0]) - assert.Equal(t, "Part2 Category", actualData.subTransactionCategory[1]) - assert.Equal(t, 2, len(actualData.subTransactionMemo)) - assert.Equal(t, "Part1 Memo", actualData.subTransactionMemo[0]) - assert.Equal(t, "Part2 Memo", actualData.subTransactionMemo[1]) - assert.Equal(t, 2, len(actualData.subTransactionAmount)) - assert.Equal(t, "-100.00", actualData.subTransactionAmount[0]) - assert.Equal(t, "-23.45", actualData.subTransactionAmount[1]) + assert.Equal(t, "2024/10/12", actualData.Date) + assert.Equal(t, "-123.45", actualData.Amount) + assert.Equal(t, qifClearedStatusUnreconciled, actualData.ClearedStatus) + assert.Equal(t, "100", actualData.Num) + assert.Equal(t, "Foo", actualData.Payee) + assert.Equal(t, "Bar", actualData.Memo) + assert.Equal(t, 3, len(actualData.Addresses)) + assert.Equal(t, "Address 1", actualData.Addresses[0]) + assert.Equal(t, "Address 2", actualData.Addresses[1]) + assert.Equal(t, "Address 3", actualData.Addresses[2]) + assert.Equal(t, "Test Category", actualData.Category) + assert.Equal(t, 2, len(actualData.SubTransactionCategory)) + assert.Equal(t, "Part1 Category", actualData.SubTransactionCategory[0]) + assert.Equal(t, "Part2 Category", actualData.SubTransactionCategory[1]) + assert.Equal(t, 2, len(actualData.SubTransactionMemo)) + assert.Equal(t, "Part1 Memo", actualData.SubTransactionMemo[0]) + assert.Equal(t, "Part2 Memo", actualData.SubTransactionMemo[1]) + assert.Equal(t, 2, len(actualData.SubTransactionAmount)) + assert.Equal(t, "-100.00", actualData.SubTransactionAmount[0]) + assert.Equal(t, "-23.45", actualData.SubTransactionAmount[1]) } func TestQifDataReaderParseMemorizedTransaction_SupportedFields(t *testing.T) { @@ -333,36 +333,36 @@ func TestQifDataReaderParseMemorizedTransaction_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, qifCheckTransactionType, actualData.transactionType) - assert.Equal(t, "2024/10/12", actualData.date) - assert.Equal(t, "-123.45", actualData.amount) - assert.Equal(t, qifClearedStatusCleared, actualData.clearedStatus) - assert.Equal(t, "100", actualData.num) - assert.Equal(t, "Foo", actualData.payee) - assert.Equal(t, "Bar", actualData.memo) - assert.Equal(t, "2024/10/13", actualData.amortization.firstPaymentDate) - assert.Equal(t, "3", actualData.amortization.totalYearsForLoan) - assert.Equal(t, "1", actualData.amortization.numberOfPayments) - assert.Equal(t, "2", actualData.amortization.numberOfPeriodsPerYear) - assert.Equal(t, "12.34", actualData.amortization.interestRate) - assert.Equal(t, "100.45", actualData.amortization.currentLoanBalance) - assert.Equal(t, "234.56", actualData.amortization.originalLoanAmount) + assert.Equal(t, qifCheckTransactionType, actualData.TransactionType) + assert.Equal(t, "2024/10/12", actualData.Date) + assert.Equal(t, "-123.45", actualData.Amount) + assert.Equal(t, qifClearedStatusCleared, actualData.ClearedStatus) + assert.Equal(t, "100", actualData.Num) + assert.Equal(t, "Foo", actualData.Payee) + assert.Equal(t, "Bar", actualData.Memo) + assert.Equal(t, "2024/10/13", actualData.Amortization.FirstPaymentDate) + assert.Equal(t, "3", actualData.Amortization.TotalYearsForLoan) + assert.Equal(t, "1", actualData.Amortization.NumberOfPayments) + assert.Equal(t, "2", actualData.Amortization.NumberOfPeriodsPerYear) + assert.Equal(t, "12.34", actualData.Amortization.InterestRate) + assert.Equal(t, "100.45", actualData.Amortization.CurrentLoanBalance) + assert.Equal(t, "234.56", actualData.Amortization.OriginalLoanAmount) actualData, err = reader.parseMemorizedTransaction(context, []string{"KD"}) assert.Nil(t, err) - assert.Equal(t, qifDepositTransactionType, actualData.transactionType) + assert.Equal(t, qifDepositTransactionType, actualData.TransactionType) actualData, err = reader.parseMemorizedTransaction(context, []string{"KP"}) assert.Nil(t, err) - assert.Equal(t, qifPaymentTransactionType, actualData.transactionType) + assert.Equal(t, qifPaymentTransactionType, actualData.TransactionType) actualData, err = reader.parseMemorizedTransaction(context, []string{"KI"}) assert.Nil(t, err) - assert.Equal(t, qifInvestmentTransactionType, actualData.transactionType) + assert.Equal(t, qifInvestmentTransactionType, actualData.TransactionType) actualData, err = reader.parseMemorizedTransaction(context, []string{"KE"}) assert.Nil(t, err) - assert.Equal(t, qifElectronicPayeeTransactionType, actualData.transactionType) + assert.Equal(t, qifElectronicPayeeTransactionType, actualData.TransactionType) } func TestQifDataReaderParseInvestmentTransaction_SupportedFields(t *testing.T) { @@ -385,18 +385,18 @@ func TestQifDataReaderParseInvestmentTransaction_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "2024/10/12", actualData.date) - assert.Equal(t, "Buy", actualData.action) - assert.Equal(t, "Test", actualData.security) - assert.Equal(t, "12.34", actualData.price) - assert.Equal(t, "10", actualData.quantity) - assert.Equal(t, "-123.4", actualData.amount) - assert.Equal(t, qifClearedStatusReconciled, actualData.clearedStatus) - assert.Equal(t, "Foo", actualData.text) - assert.Equal(t, "Bar", actualData.memo) - assert.Equal(t, "Test2", actualData.commission) - assert.Equal(t, "Account Name", actualData.accountForTransfer) - assert.Equal(t, "100", actualData.amountTransferred) + assert.Equal(t, "2024/10/12", actualData.Date) + assert.Equal(t, "Buy", actualData.Action) + assert.Equal(t, "Test", actualData.Security) + assert.Equal(t, "12.34", actualData.Price) + assert.Equal(t, "10", actualData.Quantity) + assert.Equal(t, "-123.4", actualData.Amount) + assert.Equal(t, qifClearedStatusReconciled, actualData.ClearedStatus) + assert.Equal(t, "Foo", actualData.Text) + assert.Equal(t, "Bar", actualData.Memo) + assert.Equal(t, "Test2", actualData.Commission) + assert.Equal(t, "Account Name", actualData.AccountForTransfer) + assert.Equal(t, "100", actualData.AmountTransferred) } func TestQifDataReaderParseAccount_SupportedFields(t *testing.T) { @@ -413,12 +413,12 @@ func TestQifDataReaderParseAccount_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "Account Name", actualData.name) - assert.Equal(t, "Account Type", actualData.accountType) - assert.Equal(t, "Some Text", actualData.description) - assert.Equal(t, "1234.56", actualData.creditLimit) - assert.Equal(t, "2024/10/12", actualData.statementBalanceDate) - assert.Equal(t, "123.45", actualData.statementBalanceAmount) + assert.Equal(t, "Account Name", actualData.Name) + assert.Equal(t, "Account Type", actualData.AccountType) + assert.Equal(t, "Some Text", actualData.Description) + assert.Equal(t, "1234.56", actualData.CreditLimit) + assert.Equal(t, "2024/10/12", actualData.StatementBalanceDate) + assert.Equal(t, "123.45", actualData.StatementBalanceAmount) } func TestQifDataReaderParseCategory_SupportedFields(t *testing.T) { @@ -435,12 +435,12 @@ func TestQifDataReaderParseCategory_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "Category Name:Sub Category Name", actualData.name) - assert.Equal(t, "Some Text", actualData.description) - assert.Equal(t, true, actualData.taxRelated) - assert.Equal(t, qifIncomeTransaction, actualData.categoryType) - assert.Equal(t, "123.45", actualData.budgetAmount) - assert.Equal(t, "Test", actualData.taxScheduleInformation) + assert.Equal(t, "Category Name:Sub Category Name", actualData.Name) + assert.Equal(t, "Some Text", actualData.Description) + assert.Equal(t, true, actualData.TaxRelated) + assert.Equal(t, qifIncomeTransaction, actualData.CategoryType) + assert.Equal(t, "123.45", actualData.BudgetAmount) + assert.Equal(t, "Test", actualData.TaxScheduleInformation) actualData2, err := reader.parseCategory(context, []string{ "NCategory Name:Sub Category Name", @@ -449,10 +449,10 @@ func TestQifDataReaderParseCategory_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "Category Name:Sub Category Name", actualData2.name) - assert.Equal(t, "Some Text", actualData2.description) - assert.Equal(t, false, actualData2.taxRelated) - assert.Equal(t, qifExpenseTransaction, actualData2.categoryType) + assert.Equal(t, "Category Name:Sub Category Name", actualData2.Name) + assert.Equal(t, "Some Text", actualData2.Description) + assert.Equal(t, false, actualData2.TaxRelated) + assert.Equal(t, qifExpenseTransaction, actualData2.CategoryType) actualData3, err := reader.parseCategory(context, []string{ "NCategory Name:Sub Category Name", @@ -460,9 +460,9 @@ func TestQifDataReaderParseCategory_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "Category Name:Sub Category Name", actualData3.name) - assert.Equal(t, "Some Text", actualData3.description) - assert.Equal(t, qifExpenseTransaction, actualData3.categoryType) + assert.Equal(t, "Category Name:Sub Category Name", actualData3.Name) + assert.Equal(t, "Some Text", actualData3.Description) + assert.Equal(t, qifExpenseTransaction, actualData3.CategoryType) } func TestQifDataReaderParseClass_SupportedFields(t *testing.T) { @@ -475,8 +475,8 @@ func TestQifDataReaderParseClass_SupportedFields(t *testing.T) { }) assert.Nil(t, err) - assert.Equal(t, "Class Name", actualData.name) - assert.Equal(t, "Some Text", actualData.description) + assert.Equal(t, "Class Name", actualData.Name) + assert.Equal(t, "Some Text", actualData.Description) } func TestQifDataReaderParse_UnsupportedFieldsOrValues(t *testing.T) { @@ -489,7 +489,7 @@ func TestQifDataReaderParse_UnsupportedFieldsOrValues(t *testing.T) { "", }, false) assert.Nil(t, err) - assert.Equal(t, qifClearedStatusUnreconciled, actualTransactionData.clearedStatus) + assert.Equal(t, qifClearedStatusUnreconciled, actualTransactionData.ClearedStatus) actualMemorizedTransactionData, err := reader.parseMemorizedTransaction(context, []string{ "ZTest", @@ -497,7 +497,7 @@ func TestQifDataReaderParse_UnsupportedFieldsOrValues(t *testing.T) { "", }) assert.Nil(t, err) - assert.Equal(t, qifInvalidTransactionType, actualMemorizedTransactionData.transactionType) + assert.Equal(t, qifInvalidTransactionType, actualMemorizedTransactionData.TransactionType) _, err = reader.parseInvestmentTransaction(context, []string{ "ZTest", diff --git a/pkg/converters/qif/qif_transaction_data_table.go b/pkg/converters/qif/qif_transaction_data_table.go index 5f5667c3..73f7a271 100644 --- a/pkg/converters/qif/qif_transaction_data_table.go +++ b/pkg/converters/qif/qif_transaction_data_table.go @@ -119,11 +119,11 @@ func (t *qifTransactionDataRowIterator) Next(ctx core.Context, user *models.User func (t *qifTransactionDataRowIterator) parseTransaction(ctx core.Context, user *models.User, qifTransaction *qifTransactionData) (map[datatable.TransactionDataTableColumn]string, error) { data := make(map[datatable.TransactionDataTableColumn]string, len(qifTransactionSupportedColumns)) - if qifTransaction.date == "" { + if qifTransaction.Date == "" { return nil, errs.ErrMissingTransactionTime } - transactionTime, err := t.parseTransactionTime(ctx, qifTransaction.date) + transactionTime, err := t.parseTransactionTime(ctx, qifTransaction.Date) if err != nil { return nil, err @@ -131,37 +131,37 @@ func (t *qifTransactionDataRowIterator) parseTransaction(ctx core.Context, user data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = transactionTime - if qifTransaction.amount == "" { + if qifTransaction.Amount == "" { return nil, errs.ErrAmountInvalid } - amount, err := utils.ParseAmount(strings.ReplaceAll(qifTransaction.amount, ",", "")) // trim thousands separator + amount, err := utils.ParseAmount(strings.ReplaceAll(qifTransaction.Amount, ",", "")) // trim thousands separator if err != nil { return nil, errs.ErrAmountInvalid } - if qifTransaction.account != nil { - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.account.name + if qifTransaction.Account != nil { + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.Account.Name } else { data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = "" } - if len(qifTransaction.category) > 0 && qifTransaction.category[0] == '[' && qifTransaction.category[len(qifTransaction.category)-1] == ']' { - if qifTransaction.payee == qifOpeningBalancePayeeText { // balance modification + if len(qifTransaction.Category) > 0 && qifTransaction.Category[0] == '[' && qifTransaction.Category[len(qifTransaction.Category)-1] == ']' { + if qifTransaction.Payee == qifOpeningBalancePayeeText { // balance modification data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = qifTransactionTypeNameMapping[models.TRANSACTION_TYPE_MODIFY_BALANCE] data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount) - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.category[1 : len(qifTransaction.category)-1] + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.Category[1 : len(qifTransaction.Category)-1] } else { // transfer data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = qifTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] if amount >= 0 { // transfer from [account name] data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount) data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] - data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.category[1 : len(qifTransaction.category)-1] + data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = qifTransaction.Category[1 : len(qifTransaction.Category)-1] } else { // transfer to [account name] data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount) - data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = qifTransaction.category[1 : len(qifTransaction.category)-1] + data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = qifTransaction.Category[1 : len(qifTransaction.Category)-1] } } } else { // income/expense @@ -173,20 +173,20 @@ func (t *qifTransactionDataRowIterator) parseTransaction(ctx core.Context, user data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount) } - if strings.Index(qifTransaction.category, ":") > 0 { // category:subcategory - categories := strings.Split(qifTransaction.category, ":") + if strings.Index(qifTransaction.Category, ":") > 0 { // category:subcategory + categories := strings.Split(qifTransaction.Category, ":") data[datatable.TRANSACTION_DATA_TABLE_CATEGORY] = categories[0] data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = categories[len(categories)-1] } else { data[datatable.TRANSACTION_DATA_TABLE_CATEGORY] = "" - data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = qifTransaction.category + data[datatable.TRANSACTION_DATA_TABLE_SUB_CATEGORY] = qifTransaction.Category } } - 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.Memo != "" { + data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = qifTransaction.Memo + } else if qifTransaction.Payee != "" && qifTransaction.Payee != qifOpeningBalancePayeeText { + data[datatable.TRANSACTION_DATA_TABLE_DESCRIPTION] = qifTransaction.Payee } return data, nil @@ -240,11 +240,11 @@ func createNewQifTransactionDataTable(dateFormatType qifDateFormatType, qifData } allData := make([]*qifTransactionData, 0) - allData = append(allData, qifData.bankAccountTransactions...) - allData = append(allData, qifData.cashAccountTransactions...) - allData = append(allData, qifData.creditCardAccountTransactions...) - allData = append(allData, qifData.assetAccountTransactions...) - allData = append(allData, qifData.liabilityAccountTransactions...) + allData = append(allData, qifData.BankAccountTransactions...) + allData = append(allData, qifData.CashAccountTransactions...) + allData = append(allData, qifData.CreditCardAccountTransactions...) + allData = append(allData, qifData.AssetAccountTransactions...) + allData = append(allData, qifData.LiabilityAccountTransactions...) return &qifTransactionDataTable{ dateFormatType: dateFormatType,