read and check ofx 2.x file header

This commit is contained in:
MaysWind
2024-11-01 00:11:26 +08:00
parent d174e99c80
commit ac29f0bf98
4 changed files with 651 additions and 465 deletions
+93 -15
View File
@@ -1,17 +1,25 @@
package ofx
import (
"bufio"
"bytes"
"encoding/xml"
"regexp"
"strings"
"golang.org/x/net/html/charset"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/log"
)
var ofx2HeaderPattern = regexp.MustCompile("<\\?OFX( +[A-Z]+=\"[^=]*\")* *\\?>")
var ofx2HeaderAttributePattern = regexp.MustCompile(" +([A-Z]+)=\"([^=]*)\"")
// ofxFileReader defines the structure of open financial exchange (ofx) file reader
type ofxFileReader struct {
fileHeader *ofxFileHeader
xmlDecoder *xml.Decoder
}
@@ -25,27 +33,97 @@ func (r *ofxFileReader) read(ctx core.Context) (*ofxFile, error) {
return nil, err
}
file.FileHeader = r.fileHeader
return file, nil
}
func createNewOFXFileReader(data []byte) (*ofxFileReader, error) {
if len(data) > 5 && data[0] == 0x3C && data[1] == 0x3F && data[2] == 0x78 && data[3] == 0x6D && data[4] == 0x6C { // ofx 2.x starts with <?xml
xmlDecoder := xml.NewDecoder(bytes.NewReader(data))
xmlDecoder.CharsetReader = charset.NewReaderLabel
return &ofxFileReader{
xmlDecoder: xmlDecoder,
}, nil
} else if len(data) > 13 && string(data[0:13]) == "OFXHEADER:100" { // ofx 1.x starts with OFXHEADER:100
func createNewOFXFileReader(ctx core.Context, data []byte) (*ofxFileReader, error) {
if len(data) > 5 && string(data[0:5]) == "<?xml" { // ofx 2.x starts with <?xml
return createNewOFX2FileReader(ctx, data, true)
} else if len(data) > 10 && string(data[0:10]) == "OFXHEADER:" { // ofx 1.x starts with OFXHEADER:
} else if len(data) > 5 && string(data[0:5]) == "<OFX>" { // no ofx header
xmlDecoder := xml.NewDecoder(bytes.NewReader(data))
xmlDecoder.CharsetReader = charset.NewReaderLabel
return &ofxFileReader{
xmlDecoder: xmlDecoder,
}, nil
return createNewOFX2FileReader(ctx, data, false)
}
return nil, errs.ErrInvalidOFXFile
}
func createNewOFX2FileReader(ctx core.Context, data []byte, withHeader bool) (*ofxFileReader, error) {
var fileHeader *ofxFileHeader = nil
var err error
if withHeader {
fileHeader, err = readOFX2FileHeader(ctx, data)
if err != nil {
return nil, err
}
if fileHeader.OFXDeclarationVersion != ofxVersion2 {
log.Errorf(ctx, "[ofx_data_reader.createNewOFX2FileReader] cannot parse ofx 2.x file header, because declaration version is \"%s\"", fileHeader.OFXDeclarationVersion)
return nil, errs.ErrInvalidOFXFile
}
}
xmlDecoder := xml.NewDecoder(bytes.NewReader(data))
xmlDecoder.CharsetReader = charset.NewReaderLabel
return &ofxFileReader{
fileHeader: fileHeader,
xmlDecoder: xmlDecoder,
}, nil
}
func readOFX2FileHeader(ctx core.Context, data []byte) (fileHeader *ofxFileHeader, err error) {
reader := bytes.NewReader(data)
scanner := bufio.NewScanner(reader)
fileHeader = &ofxFileHeader{}
headerLine := ""
for scanner.Scan() {
line := scanner.Text()
ofxHeaderStartIndex := strings.Index(line, "<?OFX ")
if ofxHeaderStartIndex >= 0 {
headerLine = ofx2HeaderPattern.FindString(line)
break
}
}
if headerLine == "" {
log.Errorf(ctx, "[ofx_data_reader.readOFX2FileHeader] cannot find ofx 2.x file header")
return nil, errs.ErrInvalidOFXFile
}
headerAttributes := ofx2HeaderAttributePattern.FindAllStringSubmatch(headerLine, -1)
for _, attributeItems := range headerAttributes {
if len(attributeItems) != 3 {
log.Warnf(ctx, "[ofx_data_reader.readOFX2FileHeader] cannot parse line in ofx 2.x file header, because item is \"%s\"", attributeItems)
continue
}
name := attributeItems[1]
value := attributeItems[2]
if name == "OFXHEADER" {
fileHeader.OFXDeclarationVersion = oFXDeclarationVersion(value)
} else if name == "VERSION" {
fileHeader.OFXDataVersion = value
} else if name == "SECURITY" {
fileHeader.Security = value
} else if name == "OLDFILEUID" {
fileHeader.OldFileUid = value
} else if name == "NEWFILEUID" {
fileHeader.NewFileUid = value
} else {
log.Warnf(ctx, "[ofx_data_reader.readOFX2FileHeader] cannot parse unknown header line in ofx 2.x file header, because item is \"%s\"", attributeItems)
continue
}
}
return fileHeader, nil
}
+148 -40
View File
@@ -6,31 +6,32 @@ import (
"github.com/stretchr/testify/assert"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
)
func TestCreateNewOFXFileReader_OFX2(t *testing.T) {
context := core.NewNullContext()
reader, err := createNewOFXFileReader([]byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>" +
"<?OFX OFXHEADER=\"200\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?>" +
"<OFX>" +
" <BANKMSGSRSV1>" +
" <STMTTRNRS>" +
" <STMTRS>" +
" <CURDEF>CNY</CURDEF>" +
" <BANKACCTFROM>" +
" <ACCTID>123</ACCTID>" +
" </BANKACCTFROM>" +
" <BANKTRANLIST>" +
" <STMTTRN>" +
" <TRNTYPE>DEP</TRNTYPE>" +
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>" +
" <TRNAMT>123.45</TRNAMT>" +
" </STMTTRN>" +
" </BANKTRANLIST>" +
" </STMTRS>" +
" </STMTTRNRS>" +
" </BANKMSGSRSV1>" +
reader, err := createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n"+
"<?OFX OFXHEADER=\"200\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?>\n"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"))
assert.Nil(t, err)
@@ -38,6 +39,14 @@ func TestCreateNewOFXFileReader_OFX2(t *testing.T) {
ofxFile, err := reader.read(context)
assert.Nil(t, err)
assert.NotNil(t, ofxFile)
assert.NotNil(t, ofxFile.FileHeader)
assert.Equal(t, ofxVersion2, ofxFile.FileHeader.OFXDeclarationVersion)
assert.Equal(t, "211", ofxFile.FileHeader.OFXDataVersion)
assert.Equal(t, "NONE", ofxFile.FileHeader.Security)
assert.Equal(t, "NONE", ofxFile.FileHeader.OldFileUid)
assert.Equal(t, "NONE", ofxFile.FileHeader.NewFileUid)
assert.NotNil(t, ofxFile.BankMessageResponseV1)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse)
@@ -53,27 +62,124 @@ func TestCreateNewOFXFileReader_OFX2(t *testing.T) {
assert.Equal(t, "123.45", ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.TransactionList.StatementTransactions[0].Amount)
}
func TestCreateNewOFXFileReader_OFX2WithoutBreakLine(t *testing.T) {
context := core.NewNullContext()
reader, err := createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<?OFX OFXHEADER=\"200\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?>"+
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"</OFX>"))
assert.Nil(t, err)
ofxFile, err := reader.read(context)
assert.Nil(t, err)
assert.NotNil(t, ofxFile)
assert.NotNil(t, ofxFile.FileHeader)
assert.Equal(t, ofxVersion2, ofxFile.FileHeader.OFXDeclarationVersion)
assert.Equal(t, "211", ofxFile.FileHeader.OFXDataVersion)
assert.Equal(t, "NONE", ofxFile.FileHeader.Security)
assert.Equal(t, "NONE", ofxFile.FileHeader.OldFileUid)
assert.Equal(t, "NONE", ofxFile.FileHeader.NewFileUid)
assert.NotNil(t, ofxFile.BankMessageResponseV1)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse)
assert.Equal(t, "CNY", ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.DefaultCurrency)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.AccountFrom)
assert.Equal(t, "123", ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.AccountFrom.AccountId)
assert.Equal(t, 1, len(ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.TransactionList.StatementTransactions))
assert.Equal(t, ofxDepositTransaction, ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.TransactionList.StatementTransactions[0].TransactionType)
assert.Equal(t, "20240901012345.000[+8:CST]", ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.TransactionList.StatementTransactions[0].PostedDate)
assert.Equal(t, "123.45", ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse.TransactionList.StatementTransactions[0].Amount)
}
func TestCreateNewOFXFileReader_OFX2WithoutOFXHeader(t *testing.T) {
context := core.NewNullContext()
_, err := createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<OFX>"+
"</OFX>"))
assert.EqualError(t, err, errs.ErrInvalidOFXFile.Message)
}
func TestCreateNewOFXFileReader_OFX2WithInvalidHeaderVersion(t *testing.T) {
context := core.NewNullContext()
_, err := createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<?OFX OFXHEADER=\"100\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?>"+
"<OFX>"+
"</OFX>"))
assert.EqualError(t, err, errs.ErrInvalidOFXFile.Message)
}
func TestCreateNewOFXFileReader_OFX2WithInvalidHeader(t *testing.T) {
context := core.NewNullContext()
_, err := createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<?OFX?>"+
"<OFX>"+
"</OFX>"))
_, err = createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<?OFX OFXHEADER=100?>"+
"<OFX>"+
"</OFX>"))
assert.EqualError(t, err, errs.ErrInvalidOFXFile.Message)
_, err = createNewOFXFileReader(context, []byte(
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?>"+
"<?OFX OFXHEADER=\"100\" VERSION=\"211\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\" test=\"\"?>"+
"<OFX>"+
"</OFX>"))
assert.EqualError(t, err, errs.ErrInvalidOFXFile.Message)
}
func TestCreateNewOFXFileReader_OFX2WithoutAnyHeader(t *testing.T) {
context := core.NewNullContext()
reader, err := createNewOFXFileReader([]byte(
"<OFX>" +
" <BANKMSGSRSV1>" +
" <STMTTRNRS>" +
" <STMTRS>" +
" <CURDEF>CNY</CURDEF>" +
" <BANKACCTFROM>" +
" <ACCTID>123</ACCTID>" +
" </BANKACCTFROM>" +
" <BANKTRANLIST>" +
" <STMTTRN>" +
" <TRNTYPE>DEP</TRNTYPE>" +
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>" +
" <TRNAMT>123.45</TRNAMT>" +
" </STMTTRN>" +
" </BANKTRANLIST>" +
" </STMTRS>" +
" </STMTTRNRS>" +
" </BANKMSGSRSV1>" +
reader, err := createNewOFXFileReader(context, []byte(
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"))
assert.Nil(t, err)
@@ -81,6 +187,8 @@ func TestCreateNewOFXFileReader_OFX2WithoutAnyHeader(t *testing.T) {
ofxFile, err := reader.read(context)
assert.Nil(t, err)
assert.NotNil(t, ofxFile)
assert.Nil(t, ofxFile.FileHeader)
assert.NotNil(t, ofxFile.BankMessageResponseV1)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse)
assert.NotNil(t, ofxFile.BankMessageResponseV1.StatementTransactionResponse.StatementResponse)
@@ -24,7 +24,7 @@ var (
// ParseImportedData returns the imported data by parsing the open financial exchange (ofx) file transaction data
func (c *ofxTransactionDataImporter) ParseImportedData(ctx core.Context, user *models.User, data []byte, defaultTimezoneOffset int16, accountMap map[string]*models.Account, expenseCategoryMap map[string]*models.TransactionCategory, incomeCategoryMap map[string]*models.TransactionCategory, transferCategoryMap map[string]*models.TransactionCategory, tagMap map[string]*models.TransactionTag) (models.ImportedTransactionSlice, []*models.Account, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionCategory, []*models.TransactionTag, error) {
ofxDataReader, err := createNewOFXFileReader(data)
ofxDataReader, err := createNewOFXFileReader(ctx, data)
if err != nil {
return nil, nil, nil, nil, nil, nil, err
@@ -21,61 +21,61 @@ func TestOFXTransactionDataFileParseImportedData_MinimumValidData(t *testing.T)
}
allNewTransactions, allNewAccounts, allNewSubExpenseCategories, allNewSubIncomeCategories, allNewSubTransferCategories, allNewTags, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>CHECK</TRNTYPE>"+
" <DTPOSTED>20240901123456.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-0.12</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240901225959.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-1.00</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240901235959.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>2.00</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
" <CREDITCARDMSGSRSV1>"+
" <CCSTMTTRNRS>"+
" <CCSTMTRS>"+
" <CURDEF>USD</CURDEF>"+
" <CCACCTFROM>"+
" <ACCTID>456</ACCTID>"+
" </CCACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>ATM</TRNTYPE>"+
" <DTPOSTED>20240902012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>1.23</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>POS</TRNTYPE>"+
" <DTPOSTED>20240902123456.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-0.01</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </CCSTMTRS>"+
" </CCSTMTTRNRS>"+
" </CREDITCARDMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>CHECK</TRNTYPE>\n"+
" <DTPOSTED>20240901123456.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>-0.12</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>XFER</TRNTYPE>\n"+
" <DTPOSTED>20240901225959.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>-1.00</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>XFER</TRNTYPE>\n"+
" <DTPOSTED>20240901235959.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>2.00</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
" <CREDITCARDMSGSRSV1>\n"+
" <CCSTMTTRNRS>\n"+
" <CCSTMTRS>\n"+
" <CURDEF>USD</CURDEF>\n"+
" <CCACCTFROM>\n"+
" <ACCTID>456</ACCTID>\n"+
" </CCACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>ATM</TRNTYPE>\n"+
" <DTPOSTED>20240902012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>1.23</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>POS</TRNTYPE>\n"+
" <DTPOSTED>20240902123456.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>-0.01</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </CCSTMTRS>\n"+
" </CCSTMTTRNRS>\n"+
" </CREDITCARDMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -167,47 +167,47 @@ func TestOFXTransactionDataFileParseImportedData_ParseAccountTo(t *testing.T) {
}
allNewTransactions, allNewAccounts, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-123.45</TRNAMT>"+
" <BANKACCTTO>"+
" <ACCTID>456</ACCTID>"+
" </BANKACCTTO>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
" <CREDITCARDMSGSRSV1>"+
" <CCSTMTTRNRS>"+
" <CCSTMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <CCACCTFROM>"+
" <ACCTID>456</ACCTID>"+
" </CCACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>XFER</TRNTYPE>"+
" <DTPOSTED>20240902012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>-1.23</TRNAMT>"+
" <CCACCTTO>"+
" <ACCTID>789</ACCTID>"+
" </CCACCTTO>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </CCSTMTRS>"+
" </CCSTMTTRNRS>"+
" </CREDITCARDMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>XFER</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>-123.45</TRNAMT>\n"+
" <BANKACCTTO>\n"+
" <ACCTID>456</ACCTID>\n"+
" </BANKACCTTO>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
" <CREDITCARDMSGSRSV1>\n"+
" <CCSTMTTRNRS>\n"+
" <CCSTMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <CCACCTFROM>\n"+
" <ACCTID>456</ACCTID>\n"+
" </CCACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>XFER</TRNTYPE>\n"+
" <DTPOSTED>20240902012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>-1.23</TRNAMT>\n"+
" <CCACCTTO>\n"+
" <ACCTID>789</ACCTID>\n"+
" </CCACCTTO>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </CCSTMTRS>\n"+
" </CCSTMTTRNRS>\n"+
" </CREDITCARDMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -250,49 +250,49 @@ func TestOFXTransactionDataFileParseImportedData_ParseValidTransactionTime(t *te
}
allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901123456</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901123456.789</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901125959.000[-3]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901122959.000[-3.5]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240902030405.000[0]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901123456</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901123456.789</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901125959.000[-3]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901122959.000[-3.5]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240902030405.000[0]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -317,90 +317,90 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidTransactionTime(t *
}
_, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>2024</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>2024</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message)
_, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>2024-09-01</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>2024-09-01</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message)
_, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>202491</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>202491</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message)
_, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901 12:34:56</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901 12:34:56</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrTransactionTimeInvalid.Message)
}
@@ -415,24 +415,24 @@ func TestOFXTransactionDataFileParseImportedData_ParseAmount_CommaAsDecimalPoint
}
allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123,45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123,45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -451,24 +451,24 @@ func TestOFXTransactionDataFileParseImportedData_ParseInvalidAmount(t *testing.T
}
_, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123 45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123 45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrAmountInvalid.Message)
}
@@ -483,25 +483,25 @@ func TestOFXTransactionDataFileParseImportedData_ParseTransactionCurrency(t *tes
}
allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" <CURRENCY>USD</CURRENCY>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" <CURRENCY>USD</CURRENCY>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -519,26 +519,26 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T)
}
allNewTransactions, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" <NAME>Test</NAME>"+
" <MEMO>foo bar\t#test</MEMO>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" <NAME>Test</NAME>\n"+
" <MEMO>foo bar\t#test</MEMO>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -546,25 +546,25 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T)
assert.Equal(t, "foo bar\t#test", allNewTransactions[0].Comment)
allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" <NAME>Test</NAME>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" <NAME>Test</NAME>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -572,27 +572,27 @@ func TestOFXTransactionDataFileParseImportedData_ParseDescription(t *testing.T)
assert.Equal(t, "Test", allNewTransactions[0].Comment)
allNewTransactions, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" <PAYEE>"+
" <NAME>Test</NAME>"+
" </PAYEE>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" <PAYEE>\n"+
" <NAME>Test</NAME>\n"+
" </PAYEE>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.Nil(t, err)
@@ -611,21 +611,21 @@ func TestOFXTransactionDataFileParseImportedData_MissingAccountFromNode(t *testi
// Missing Posted Date Node
_, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrMissingAccountData.Message)
}
@@ -641,23 +641,23 @@ func TestOFXTransactionDataFileParseImportedData_MissingCurrencyNode(t *testing.
// Missing Default Currency Node
_, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrAccountCurrencyInvalid.Message)
}
@@ -673,67 +673,67 @@ func TestOFXTransactionDataFileParseImportedData_MissingTransactionRequiredNode(
// Missing Posted Date Node
_, _, _, _, _, _, err := converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrMissingTransactionTime.Message)
// Missing Transaction Type Node
_, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" <TRNAMT>123.45</TRNAMT>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" <TRNAMT>123.45</TRNAMT>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrTransactionTypeInvalid.Message)
// Missing Amount Node
_, _, _, _, _, _, err = converter.ParseImportedData(context, user, []byte(
"<OFX>"+
" <BANKMSGSRSV1>"+
" <STMTTRNRS>"+
" <STMTRS>"+
" <CURDEF>CNY</CURDEF>"+
" <BANKACCTFROM>"+
" <ACCTID>123</ACCTID>"+
" </BANKACCTFROM>"+
" <BANKTRANLIST>"+
" <STMTTRN>"+
" <TRNTYPE>DEP</TRNTYPE>"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>"+
" </STMTTRN>"+
" </BANKTRANLIST>"+
" </STMTRS>"+
" </STMTTRNRS>"+
" </BANKMSGSRSV1>"+
"<OFX>\n"+
" <BANKMSGSRSV1>\n"+
" <STMTTRNRS>\n"+
" <STMTRS>\n"+
" <CURDEF>CNY</CURDEF>\n"+
" <BANKACCTFROM>\n"+
" <ACCTID>123</ACCTID>\n"+
" </BANKACCTFROM>\n"+
" <BANKTRANLIST>\n"+
" <STMTTRN>\n"+
" <TRNTYPE>DEP</TRNTYPE>\n"+
" <DTPOSTED>20240901012345.000[+8:CST]</DTPOSTED>\n"+
" </STMTTRN>\n"+
" </BANKTRANLIST>\n"+
" </STMTRS>\n"+
" </STMTTRNRS>\n"+
" </BANKMSGSRSV1>\n"+
"</OFX>"), 0, nil, nil, nil, nil, nil)
assert.EqualError(t, err, errs.ErrAmountInvalid.Message)
}