code refactor

This commit is contained in:
MaysWind
2025-06-19 22:40:32 +08:00
parent 5dc0e925c1
commit e9c175d2af
12 changed files with 611 additions and 611 deletions
+58 -58
View File
@@ -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
}
+66 -66
View File
@@ -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
+137 -137
View File
@@ -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",
@@ -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,