support transfer in transaction

This commit is contained in:
MaysWind
2024-10-30 23:42:17 +08:00
parent 98c96b8217
commit ce8c020477
2 changed files with 63 additions and 43 deletions
@@ -42,9 +42,14 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T)
" </STMTTRN>"+ " </STMTTRN>"+
" <STMTTRN>"+ " <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+ " <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240901235959.000[+8:CST]</DTPOSTED>"+ " <DTPOSTED>20240901225959.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-1.00</TRNAMT>"+ " <TRNAMT>-1.00</TRNAMT>"+
" </STMTTRN>"+ " </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240901235959.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>2.00</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+ " </BANKTRANLIST>"+
" </STMTRS>"+ " </STMTRS>"+
" </STMTTRNRS>"+ " </STMTTRNRS>"+
@@ -75,7 +80,7 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 5, len(allNewTransactions)) assert.Equal(t, 6, len(allNewTransactions))
assert.Equal(t, 3, len(allNewAccounts)) assert.Equal(t, 3, len(allNewAccounts))
assert.Equal(t, 1, len(allNewSubExpenseCategories)) assert.Equal(t, 1, len(allNewSubExpenseCategories))
assert.Equal(t, 1, len(allNewSubIncomeCategories)) assert.Equal(t, 1, len(allNewSubIncomeCategories))
@@ -100,28 +105,36 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T)
assert.Equal(t, int64(1234567890), allNewTransactions[2].Uid) assert.Equal(t, int64(1234567890), allNewTransactions[2].Uid)
assert.Equal(t, models.TRANSACTION_DB_TYPE_TRANSFER_OUT, allNewTransactions[2].Type) assert.Equal(t, models.TRANSACTION_DB_TYPE_TRANSFER_OUT, allNewTransactions[2].Type)
assert.Equal(t, int64(1725206399), utils.GetUnixTimeFromTransactionTime(allNewTransactions[2].TransactionTime)) assert.Equal(t, int64(1725202799), utils.GetUnixTimeFromTransactionTime(allNewTransactions[2].TransactionTime))
assert.Equal(t, int64(100), allNewTransactions[2].Amount) assert.Equal(t, int64(100), allNewTransactions[2].Amount)
assert.Equal(t, "123", allNewTransactions[2].OriginalSourceAccountName) assert.Equal(t, "123", allNewTransactions[2].OriginalSourceAccountName)
assert.Equal(t, "", allNewTransactions[2].OriginalDestinationAccountName) assert.Equal(t, "", allNewTransactions[2].OriginalDestinationAccountName)
assert.Equal(t, "", allNewTransactions[2].OriginalCategoryName) assert.Equal(t, "", allNewTransactions[2].OriginalCategoryName)
assert.Equal(t, int64(1234567890), allNewTransactions[3].Uid) assert.Equal(t, int64(1234567890), allNewTransactions[3].Uid)
assert.Equal(t, models.TRANSACTION_DB_TYPE_INCOME, allNewTransactions[3].Type) assert.Equal(t, models.TRANSACTION_DB_TYPE_TRANSFER_OUT, allNewTransactions[3].Type)
assert.Equal(t, int64(1725211425), utils.GetUnixTimeFromTransactionTime(allNewTransactions[3].TransactionTime)) assert.Equal(t, int64(1725206399), utils.GetUnixTimeFromTransactionTime(allNewTransactions[3].TransactionTime))
assert.Equal(t, int64(123), allNewTransactions[3].Amount) assert.Equal(t, int64(200), allNewTransactions[3].Amount)
assert.Equal(t, "456", allNewTransactions[3].OriginalSourceAccountName) assert.Equal(t, "", allNewTransactions[3].OriginalSourceAccountName)
assert.Equal(t, "USD", allNewTransactions[3].OriginalSourceAccountCurrency) assert.Equal(t, "123", allNewTransactions[3].OriginalDestinationAccountName)
assert.Equal(t, "", allNewTransactions[3].OriginalCategoryName) assert.Equal(t, "", allNewTransactions[3].OriginalCategoryName)
assert.Equal(t, int64(1234567890), allNewTransactions[4].Uid) assert.Equal(t, int64(1234567890), allNewTransactions[4].Uid)
assert.Equal(t, models.TRANSACTION_DB_TYPE_EXPENSE, allNewTransactions[4].Type) assert.Equal(t, models.TRANSACTION_DB_TYPE_INCOME, allNewTransactions[4].Type)
assert.Equal(t, int64(1725251696), utils.GetUnixTimeFromTransactionTime(allNewTransactions[4].TransactionTime)) assert.Equal(t, int64(1725211425), utils.GetUnixTimeFromTransactionTime(allNewTransactions[4].TransactionTime))
assert.Equal(t, int64(1), allNewTransactions[4].Amount) assert.Equal(t, int64(123), allNewTransactions[4].Amount)
assert.Equal(t, "456", allNewTransactions[4].OriginalSourceAccountName) assert.Equal(t, "456", allNewTransactions[4].OriginalSourceAccountName)
assert.Equal(t, "USD", allNewTransactions[4].OriginalSourceAccountCurrency) assert.Equal(t, "USD", allNewTransactions[4].OriginalSourceAccountCurrency)
assert.Equal(t, "", allNewTransactions[4].OriginalCategoryName) assert.Equal(t, "", allNewTransactions[4].OriginalCategoryName)
assert.Equal(t, int64(1234567890), allNewTransactions[5].Uid)
assert.Equal(t, models.TRANSACTION_DB_TYPE_EXPENSE, allNewTransactions[5].Type)
assert.Equal(t, int64(1725251696), utils.GetUnixTimeFromTransactionTime(allNewTransactions[5].TransactionTime))
assert.Equal(t, int64(1), allNewTransactions[5].Amount)
assert.Equal(t, "456", allNewTransactions[5].OriginalSourceAccountName)
assert.Equal(t, "USD", allNewTransactions[5].OriginalSourceAccountCurrency)
assert.Equal(t, "", allNewTransactions[5].OriginalCategoryName)
assert.Equal(t, int64(1234567890), allNewAccounts[0].Uid) assert.Equal(t, int64(1234567890), allNewAccounts[0].Uid)
assert.Equal(t, "123", allNewAccounts[0].Name) assert.Equal(t, "123", allNewAccounts[0].Name)
assert.Equal(t, "CNY", allNewAccounts[0].Currency) assert.Equal(t, "CNY", allNewAccounts[0].Currency)
+39 -32
View File
@@ -130,38 +130,10 @@ func (t *ofxTransactionDataRowIterator) parseTransaction(ctx core.Context, user
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = datetime data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME] = datetime
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIMEZONE] = timezone data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIMEZONE] = timezone
if ofxTransaction.Amount == "" {
return nil, errs.ErrAmountInvalid
}
amount, err := utils.ParseAmount(strings.ReplaceAll(ofxTransaction.Amount, ",", ".")) // ofx supports decimal point or comma to indicate the start of the fractional amount
if err != nil {
return nil, errs.ErrAmountInvalid
}
if ofxTransaction.TransactionType == "" { if ofxTransaction.TransactionType == "" {
return nil, errs.ErrTransactionTypeInvalid return nil, errs.ErrTransactionTypeInvalid
} }
if transactionType, exists := ofxTransactionTypeMapping[ofxTransaction.TransactionType]; exists {
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = utils.IntToString(int(transactionType))
if data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] == ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] {
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount)
} else {
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount)
}
} else {
if amount >= 0 {
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME]
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount)
} else {
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE]
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount)
}
}
if ofxTransaction.FromAccountId == "" { if ofxTransaction.FromAccountId == "" {
return nil, errs.ErrMissingAccountData return nil, errs.ErrMissingAccountData
} }
@@ -174,10 +146,45 @@ func (t *ofxTransactionDataRowIterator) parseTransaction(ctx core.Context, user
data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] = ofxTransaction.DefaultCurrency data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] = ofxTransaction.DefaultCurrency
} }
if data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] == ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_TRANSFER] { if ofxTransaction.Amount == "" {
data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = ofxTransaction.ToAccountId return nil, errs.ErrAmountInvalid
data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY] }
data[datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT] = data[datatable.TRANSACTION_DATA_TABLE_AMOUNT]
amount, err := utils.ParseAmount(strings.ReplaceAll(ofxTransaction.Amount, ",", ".")) // ofx supports decimal point or comma to indicate the start of the fractional amount
if err != nil {
return nil, errs.ErrAmountInvalid
}
if transactionType, exists := ofxTransactionTypeMapping[ofxTransaction.TransactionType]; exists { // known transaction type
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = utils.IntToString(int(transactionType))
if data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] == ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME] { // income
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount)
} else if data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] == ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE] { // expense
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount)
} else { // transfer
if amount >= 0 { // transfer in
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_RELATED_ACCOUNT_CURRENCY] = data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY]
data[datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT] = data[datatable.TRANSACTION_DATA_TABLE_AMOUNT]
data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_NAME] = ""
} else { // transfer out
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount)
data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_NAME] = ofxTransaction.ToAccountId
data[datatable.TRANSACTION_DATA_TABLE_RELATED_ACCOUNT_CURRENCY] = data[datatable.TRANSACTION_DATA_TABLE_ACCOUNT_CURRENCY]
data[datatable.TRANSACTION_DATA_TABLE_RELATED_AMOUNT] = data[datatable.TRANSACTION_DATA_TABLE_AMOUNT]
}
}
} else { // transaction type depends on signage of amount
if amount >= 0 { // income
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_INCOME]
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(amount)
} else { // expense
data[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE] = ofxTransactionTypeNameMapping[models.TRANSACTION_TYPE_EXPENSE]
data[datatable.TRANSACTION_DATA_TABLE_AMOUNT] = utils.FormatAmount(-amount)
}
} }
if ofxTransaction.Memo != "" { if ofxTransaction.Memo != "" {