1
0
mirror of https://github.com/aclindsa/ofxgo.git synced 2025-07-04 04:48:38 -04:00

15 Commits

Author SHA1 Message Date
d31ac10d08 Add InvTransaction() method to InvTransaction interface. 2024-04-10 21:16:42 -04:00
4f2c5582d1 Pass by value in MarshalXML. 2024-04-10 09:12:15 -04:00
e302ce2e6b CI: Update go versions tested 2023-03-14 22:18:43 -04:00
e3c4afc0a3 Add SecurityInfo() and InvPosition() tests. 2023-03-14 22:10:19 -04:00
c2490e1c6a Add InvPosition() InvPosition to Position interface. 2023-03-14 22:10:19 -04:00
12aca9ab06 Add SecurityInfo() SecInfo to Security interface. 2023-03-14 22:10:19 -04:00
1f657a5d18 Add missing handling for -dryrun flag in command-line client
This flag was only handled for the `download-profile` command. Add
the same handling for all other commands (except `detect-settings`).
2023-02-05 19:52:02 -05:00
afd882f7d2 README: Add inline link to documentation 2021-10-17 21:57:26 -04:00
5ed0050aad Add tests for String/Boolean String() methods 2021-10-17 21:55:45 -04:00
09f161e13e Add tests for Payee/Balance Valid() methods 2021-10-17 21:55:45 -04:00
e1a72fcd54 Replace github.com/howeyc/gopass with golang.org/x/term
gopass is no longer maintained, and the suggested replacement for
getting passwords from terminals is x/term.
2021-10-17 21:20:04 -04:00
a4a166aa74 Update dependencies 2021-10-17 21:04:05 -04:00
3ee400d1ec Test against latest golang: 1.17 2021-10-17 20:50:10 -04:00
67fa945cc8 cmd/ofx: check for nil Currency fields in transactions 2021-10-17 15:49:08 -04:00
cb48d30deb Added Accept http header as Citi now requires it
Without this header set Citi returns http 403 for every request.
2021-09-01 09:35:45 -04:00
22 changed files with 997 additions and 118 deletions

View File

@ -6,7 +6,7 @@ jobs:
test: test:
strategy: strategy:
matrix: matrix:
go-version: [1.13.x, 1.15.x, 1.16.x] go-version: [1.13.x, 1.18.x, 1.20.x]
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:

View File

@ -26,7 +26,8 @@ created a sample command-line client which uses the library to do simple tasks
(currently it does little more than list accounts and query for balances and (currently it does little more than list accounts and query for balances and
transactions). My hope is that by studying its code, new users will be able to transactions). My hope is that by studying its code, new users will be able to
figure out how to use the library much faster than staring at the OFX figure out how to use the library much faster than staring at the OFX
specification (or this library's API documentation). The command-line client specification (or this library's [API
documentation](https://pkg.go.dev/github.com/aclindsa/ofxgo)). The command-line client
also serves as an easy way for me to test/debug the library with actual also serves as an easy way for me to test/debug the library with actual
financial institutions, which frequently have 'quirks' in their implementations. financial institutions, which frequently have 'quirks' in their implementations.
The command-line client can be found in the [cmd/ofx The command-line client can be found in the [cmd/ofx

View File

@ -284,3 +284,100 @@ func TestUnmarshalBankStatementResponse(t *testing.T) {
checkResponsesEqual(t, &expected, response) checkResponsesEqual(t, &expected, response)
checkResponseRoundTrip(t, response) checkResponseRoundTrip(t, response)
} }
func TestPayeeValid(t *testing.T) {
p := Payee{
Name: "Jane",
Addr1: "Sesame Street",
City: "Mytown",
State: "AA",
PostalCode: "12345",
Phone: "12345678901",
}
valid, err := p.Valid()
if !valid {
t.Fatalf("Unexpected error from calling Valid: %s\n", err)
}
// Ensure some empty fields trigger invalid response
badp := p
badp.Name = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty name\n")
}
badp = p
badp.Addr1 = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty address\n")
}
badp = p
badp.City = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty city\n")
}
badp = p
badp.State = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty state\n")
}
badp = p
badp.PostalCode = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty postal code\n")
}
badp = p
badp.Phone = ""
valid, err = badp.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty phone\n")
}
}
func TestBalanceValid(t *testing.T) {
var a Amount
a.SetFrac64(8, 1)
b := Balance{
Name: "Checking",
Desc: "Jane's Personal Checking",
BalType: BalTypeDollar,
Value: a,
}
valid, err := b.Valid()
if !valid {
t.Fatalf("Unexpected error from calling Valid: %s\n", err)
}
badb := b
badb.Name = ""
valid, err = badb.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty name\n")
}
badb = b
badb.Desc = ""
valid, err = badb.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with empty description\n")
}
badb = Balance{
Name: "Checking",
Desc: "Jane's Personal Checking",
Value: a,
}
valid, err = badb.Valid()
if valid || err == nil {
t.Fatalf("Expected error from calling Valid with unspecified balance type\n")
}
}

View File

@ -75,6 +75,7 @@ func (c *BasicClient) RawRequest(URL string, r io.Reader) (*http.Response, error
return nil, err return nil, err
} }
request.Header.Set("Content-Type", "application/x-ofx") request.Header.Set("Content-Type", "application/x-ofx")
request.Header.Add("Accept", "*/*, application/x-ofx")
if c.UserAgent != "" { if c.UserAgent != "" {
request.Header.Set("User-Agent", c.UserAgent) request.Header.Set("User-Agent", c.UserAgent)
} }

View File

@ -64,6 +64,11 @@ func download() {
query.Bank = append(query.Bank, &statementRequest) query.Bank = append(query.Bank, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.RequestNoParse(query) response, err := client.RequestNoParse(query)
if err != nil { if err != nil {
fmt.Println("Error requesting account statement:", err) fmt.Println("Error requesting account statement:", err)

View File

@ -49,6 +49,11 @@ func bankTransactions() {
query.Bank = append(query.Bank, &statementRequest) query.Bank = append(query.Bank, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.Request(query) response, err := client.Request(query)
if err != nil { if err != nil {
fmt.Println("Error requesting account statement:", err) fmt.Println("Error requesting account statement:", err)
@ -77,7 +82,7 @@ func bankTransactions() {
func printTransaction(defCurrency ofxgo.CurrSymbol, tran *ofxgo.Transaction) { func printTransaction(defCurrency ofxgo.CurrSymbol, tran *ofxgo.Transaction) {
currency := defCurrency currency := defCurrency
if ok, _ := tran.Currency.Valid(); ok { if tran.Currency != nil {
currency = tran.Currency.CurSym currency = tran.Currency.CurSym
} }

View File

@ -51,6 +51,11 @@ func ccDownload() {
} }
query.CreditCard = append(query.CreditCard, &statementRequest) query.CreditCard = append(query.CreditCard, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.RequestNoParse(query) response, err := client.RequestNoParse(query)
if err != nil { if err != nil {

View File

@ -38,6 +38,11 @@ func ccTransactions() {
} }
query.CreditCard = append(query.CreditCard, &statementRequest) query.CreditCard = append(query.CreditCard, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.Request(query) response, err := client.Request(query)
if err != nil { if err != nil {
fmt.Println("Error requesting account statement:", err) fmt.Println("Error requesting account statement:", err)
@ -60,7 +65,7 @@ func ccTransactions() {
fmt.Println("Transactions:") fmt.Println("Transactions:")
for _, tran := range stmt.BankTranList.Transactions { for _, tran := range stmt.BankTranList.Transactions {
currency := stmt.CurDef currency := stmt.CurDef
if ok, _ := tran.Currency.Valid(); ok { if tran.Currency != nil {
currency = tran.Currency.CurSym currency = tran.Currency.CurSym
} }

View File

@ -3,7 +3,8 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"github.com/howeyc/gopass" "golang.org/x/term"
"os"
) )
type command struct { type command struct {
@ -55,7 +56,7 @@ func checkServerFlags() bool {
if ret && len(password) == 0 { if ret && len(password) == 0 {
fmt.Printf("Password for %s: ", username) fmt.Printf("Password for %s: ", username)
pass, err := gopass.GetPasswd() pass, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil { if err != nil {
fmt.Printf("Error reading password: %s\n", err) fmt.Printf("Error reading password: %s\n", err)
ret = false ret = false

View File

@ -35,6 +35,11 @@ func getAccounts() {
} }
query.Signup = append(query.Signup, &acctInfo) query.Signup = append(query.Signup, &acctInfo)
if dryrun {
printRequest(client, query)
return
}
response, err := client.Request(query) response, err := client.Request(query)
if err != nil { if err != nil {
fmt.Println("Error requesting account information:", err) fmt.Println("Error requesting account information:", err)

View File

@ -60,6 +60,11 @@ func invDownload() {
} }
query.InvStmt = append(query.InvStmt, &statementRequest) query.InvStmt = append(query.InvStmt, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.RequestNoParse(query) response, err := client.RequestNoParse(query)
if err != nil { if err != nil {

View File

@ -45,6 +45,11 @@ func invTransactions() {
} }
query.InvStmt = append(query.InvStmt, &statementRequest) query.InvStmt = append(query.InvStmt, &statementRequest)
if dryrun {
printRequest(client, query)
return
}
response, err := client.Request(query) response, err := client.Request(query)
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)

View File

@ -69,11 +69,11 @@ func (e *ofxVersion) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *ofxVersion) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e ofxVersion) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(ofxVersions[*e-1], start) enc.EncodeElement(ofxVersions[e-1], start)
return nil return nil
} }
@ -137,11 +137,11 @@ func (e *acctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *acctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e acctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(acctTypes[*e-1], start) enc.EncodeElement(acctTypes[e-1], start)
return nil return nil
} }
@ -218,11 +218,11 @@ func (e *trnType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *trnType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e trnType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(trnTypes[*e-1], start) enc.EncodeElement(trnTypes[e-1], start)
return nil return nil
} }
@ -284,11 +284,11 @@ func (e *imageType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *imageType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e imageType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(imageTypes[*e-1], start) enc.EncodeElement(imageTypes[e-1], start)
return nil return nil
} }
@ -350,11 +350,11 @@ func (e *imageRefType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
return e.FromString(value) return e.FromString(value)
} }
func (e *imageRefType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e imageRefType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(imageRefTypes[*e-1], start) enc.EncodeElement(imageRefTypes[e-1], start)
return nil return nil
} }
@ -416,11 +416,11 @@ func (e *checkSup) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *checkSup) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e checkSup) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(checkSups[*e-1], start) enc.EncodeElement(checkSups[e-1], start)
return nil return nil
} }
@ -481,11 +481,11 @@ func (e *correctAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
return e.FromString(value) return e.FromString(value)
} }
func (e *correctAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e correctAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(correctActions[*e-1], start) enc.EncodeElement(correctActions[e-1], start)
return nil return nil
} }
@ -547,11 +547,11 @@ func (e *balType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *balType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e balType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(balTypes[*e-1], start) enc.EncodeElement(balTypes[e-1], start)
return nil return nil
} }
@ -617,11 +617,11 @@ func (e *inv401kSource) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
return e.FromString(value) return e.FromString(value)
} }
func (e *inv401kSource) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e inv401kSource) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(inv401kSources[*e-1], start) enc.EncodeElement(inv401kSources[e-1], start)
return nil return nil
} }
@ -684,11 +684,11 @@ func (e *subAcctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *subAcctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e subAcctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(subAcctTypes[*e-1], start) enc.EncodeElement(subAcctTypes[e-1], start)
return nil return nil
} }
@ -749,11 +749,11 @@ func (e *buyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *buyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e buyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(buyTypes[*e-1], start) enc.EncodeElement(buyTypes[e-1], start)
return nil return nil
} }
@ -815,11 +815,11 @@ func (e *optAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *optAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e optAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(optActions[*e-1], start) enc.EncodeElement(optActions[e-1], start)
return nil return nil
} }
@ -880,11 +880,11 @@ func (e *tferAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *tferAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e tferAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(tferActions[*e-1], start) enc.EncodeElement(tferActions[e-1], start)
return nil return nil
} }
@ -945,11 +945,11 @@ func (e *posType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *posType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e posType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(posTypes[*e-1], start) enc.EncodeElement(posTypes[e-1], start)
return nil return nil
} }
@ -1010,11 +1010,11 @@ func (e *secured) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *secured) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e secured) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(secureds[*e-1], start) enc.EncodeElement(secureds[e-1], start)
return nil return nil
} }
@ -1076,11 +1076,11 @@ func (e *duration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *duration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e duration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(durations[*e-1], start) enc.EncodeElement(durations[e-1], start)
return nil return nil
} }
@ -1142,11 +1142,11 @@ func (e *restriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *restriction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e restriction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(restrictions[*e-1], start) enc.EncodeElement(restrictions[e-1], start)
return nil return nil
} }
@ -1207,11 +1207,11 @@ func (e *unitType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *unitType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e unitType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(unitTypes[*e-1], start) enc.EncodeElement(unitTypes[e-1], start)
return nil return nil
} }
@ -1272,11 +1272,11 @@ func (e *optBuyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *optBuyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e optBuyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(optBuyTypes[*e-1], start) enc.EncodeElement(optBuyTypes[e-1], start)
return nil return nil
} }
@ -1337,11 +1337,11 @@ func (e *sellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *sellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e sellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(sellTypes[*e-1], start) enc.EncodeElement(sellTypes[e-1], start)
return nil return nil
} }
@ -1410,11 +1410,11 @@ func (e *loanPmtFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *loanPmtFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e loanPmtFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(loanPmtFreqs[*e-1], start) enc.EncodeElement(loanPmtFreqs[e-1], start)
return nil return nil
} }
@ -1478,11 +1478,11 @@ func (e *incomeType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *incomeType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e incomeType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(incomeTypes[*e-1], start) enc.EncodeElement(incomeTypes[e-1], start)
return nil return nil
} }
@ -1544,11 +1544,11 @@ func (e *sellReason) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *sellReason) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e sellReason) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(sellReasons[*e-1], start) enc.EncodeElement(sellReasons[e-1], start)
return nil return nil
} }
@ -1609,11 +1609,11 @@ func (e *optSellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *optSellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e optSellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(optSellTypes[*e-1], start) enc.EncodeElement(optSellTypes[e-1], start)
return nil return nil
} }
@ -1676,11 +1676,11 @@ func (e *relType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *relType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e relType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(relTypes[*e-1], start) enc.EncodeElement(relTypes[e-1], start)
return nil return nil
} }
@ -1743,11 +1743,11 @@ func (e *charType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *charType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e charType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(charTypes[*e-1], start) enc.EncodeElement(charTypes[e-1], start)
return nil return nil
} }
@ -1808,11 +1808,11 @@ func (e *syncMode) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *syncMode) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e syncMode) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(syncModes[*e-1], start) enc.EncodeElement(syncModes[e-1], start)
return nil return nil
} }
@ -1873,11 +1873,11 @@ func (e *ofxSec) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *ofxSec) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e ofxSec) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(ofxSecs[*e-1], start) enc.EncodeElement(ofxSecs[e-1], start)
return nil return nil
} }
@ -1938,11 +1938,11 @@ func (e *debtType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *debtType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e debtType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(debtTypes[*e-1], start) enc.EncodeElement(debtTypes[e-1], start)
return nil return nil
} }
@ -2005,11 +2005,11 @@ func (e *debtClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *debtClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e debtClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(debtClasss[*e-1], start) enc.EncodeElement(debtClasss[e-1], start)
return nil return nil
} }
@ -2073,11 +2073,11 @@ func (e *couponFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *couponFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e couponFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(couponFreqs[*e-1], start) enc.EncodeElement(couponFreqs[e-1], start)
return nil return nil
} }
@ -2140,11 +2140,11 @@ func (e *callType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *callType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e callType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(callTypes[*e-1], start) enc.EncodeElement(callTypes[e-1], start)
return nil return nil
} }
@ -2210,11 +2210,11 @@ func (e *assetClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *assetClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e assetClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(assetClasss[*e-1], start) enc.EncodeElement(assetClasss[e-1], start)
return nil return nil
} }
@ -2276,11 +2276,11 @@ func (e *mfType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *mfType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e mfType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(mfTypes[*e-1], start) enc.EncodeElement(mfTypes[e-1], start)
return nil return nil
} }
@ -2341,11 +2341,11 @@ func (e *optType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *optType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e optType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(optTypes[*e-1], start) enc.EncodeElement(optTypes[e-1], start)
return nil return nil
} }
@ -2408,11 +2408,11 @@ func (e *stockType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *stockType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e stockType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(stockTypes[*e-1], start) enc.EncodeElement(stockTypes[e-1], start)
return nil return nil
} }
@ -2476,11 +2476,11 @@ func (e *holderType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
} }
func (e *holderType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e holderType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(holderTypes[*e-1], start) enc.EncodeElement(holderTypes[e-1], start)
return nil return nil
} }
@ -2543,11 +2543,11 @@ func (e *acctClassification) UnmarshalXML(d *xml.Decoder, start xml.StartElement
return e.FromString(value) return e.FromString(value)
} }
func (e *acctClassification) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e acctClassification) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(acctClassifications[*e-1], start) enc.EncodeElement(acctClassifications[e-1], start)
return nil return nil
} }
@ -2609,11 +2609,11 @@ func (e *svcStatus) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return e.FromString(value) return e.FromString(value)
} }
func (e *svcStatus) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e svcStatus) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(svcStatuss[*e-1], start) enc.EncodeElement(svcStatuss[e-1], start)
return nil return nil
} }
@ -2683,11 +2683,11 @@ func (e *usProductType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
return e.FromString(value) return e.FromString(value)
} }
func (e *usProductType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { func (e usProductType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
if !e.Valid() { if !e.Valid() {
return nil return nil
} }
enc.EncodeElement(usProductTypes[*e-1], start) enc.EncodeElement(usProductTypes[e-1], start)
return nil return nil
} }

View File

@ -56,6 +56,18 @@ func TestOfxVersion(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E ofxVersion
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OfxVersion): %s\n", err)
}
if string(b) != "<SC><E>220</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>220</E></SC>", string(b))
}
} }
func TestAcctType(t *testing.T) { func TestAcctType(t *testing.T) {
@ -101,6 +113,18 @@ func TestAcctType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E acctType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct AcctType): %s\n", err)
}
if string(b) != "<SC><E>CD</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>CD</E></SC>", string(b))
}
} }
func TestTrnType(t *testing.T) { func TestTrnType(t *testing.T) {
@ -146,6 +170,18 @@ func TestTrnType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E trnType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct TrnType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestImageType(t *testing.T) { func TestImageType(t *testing.T) {
@ -191,6 +227,18 @@ func TestImageType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E imageType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct ImageType): %s\n", err)
}
if string(b) != "<SC><E>TAX</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>TAX</E></SC>", string(b))
}
} }
func TestImageRefType(t *testing.T) { func TestImageRefType(t *testing.T) {
@ -236,6 +284,18 @@ func TestImageRefType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E imageRefType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct ImageRefType): %s\n", err)
}
if string(b) != "<SC><E>FORMURL</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>FORMURL</E></SC>", string(b))
}
} }
func TestCheckSup(t *testing.T) { func TestCheckSup(t *testing.T) {
@ -281,6 +341,18 @@ func TestCheckSup(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E checkSup
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct CheckSup): %s\n", err)
}
if string(b) != "<SC><E>FRONTANDBACK</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>FRONTANDBACK</E></SC>", string(b))
}
} }
func TestCorrectAction(t *testing.T) { func TestCorrectAction(t *testing.T) {
@ -326,6 +398,18 @@ func TestCorrectAction(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E correctAction
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct CorrectAction): %s\n", err)
}
if string(b) != "<SC><E>REPLACE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>REPLACE</E></SC>", string(b))
}
} }
func TestBalType(t *testing.T) { func TestBalType(t *testing.T) {
@ -371,6 +455,18 @@ func TestBalType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E balType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct BalType): %s\n", err)
}
if string(b) != "<SC><E>NUMBER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>NUMBER</E></SC>", string(b))
}
} }
func TestInv401kSource(t *testing.T) { func TestInv401kSource(t *testing.T) {
@ -416,6 +512,18 @@ func TestInv401kSource(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E inv401kSource
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct Inv401kSource): %s\n", err)
}
if string(b) != "<SC><E>OTHERNONVEST</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHERNONVEST</E></SC>", string(b))
}
} }
func TestSubAcctType(t *testing.T) { func TestSubAcctType(t *testing.T) {
@ -461,6 +569,18 @@ func TestSubAcctType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E subAcctType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct SubAcctType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestBuyType(t *testing.T) { func TestBuyType(t *testing.T) {
@ -506,6 +626,18 @@ func TestBuyType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E buyType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct BuyType): %s\n", err)
}
if string(b) != "<SC><E>BUYTOCOVER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>BUYTOCOVER</E></SC>", string(b))
}
} }
func TestOptAction(t *testing.T) { func TestOptAction(t *testing.T) {
@ -551,6 +683,18 @@ func TestOptAction(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E optAction
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OptAction): %s\n", err)
}
if string(b) != "<SC><E>EXPIRE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>EXPIRE</E></SC>", string(b))
}
} }
func TestTferAction(t *testing.T) { func TestTferAction(t *testing.T) {
@ -596,6 +740,18 @@ func TestTferAction(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E tferAction
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct TferAction): %s\n", err)
}
if string(b) != "<SC><E>OUT</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OUT</E></SC>", string(b))
}
} }
func TestPosType(t *testing.T) { func TestPosType(t *testing.T) {
@ -641,6 +797,18 @@ func TestPosType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E posType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct PosType): %s\n", err)
}
if string(b) != "<SC><E>SHORT</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>SHORT</E></SC>", string(b))
}
} }
func TestSecured(t *testing.T) { func TestSecured(t *testing.T) {
@ -686,6 +854,18 @@ func TestSecured(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E secured
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct Secured): %s\n", err)
}
if string(b) != "<SC><E>COVERED</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>COVERED</E></SC>", string(b))
}
} }
func TestDuration(t *testing.T) { func TestDuration(t *testing.T) {
@ -731,6 +911,18 @@ func TestDuration(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E duration
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct Duration): %s\n", err)
}
if string(b) != "<SC><E>IMMEDIATE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>IMMEDIATE</E></SC>", string(b))
}
} }
func TestRestriction(t *testing.T) { func TestRestriction(t *testing.T) {
@ -776,6 +968,18 @@ func TestRestriction(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E restriction
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct Restriction): %s\n", err)
}
if string(b) != "<SC><E>NONE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>NONE</E></SC>", string(b))
}
} }
func TestUnitType(t *testing.T) { func TestUnitType(t *testing.T) {
@ -821,6 +1025,18 @@ func TestUnitType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E unitType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct UnitType): %s\n", err)
}
if string(b) != "<SC><E>CURRENCY</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>CURRENCY</E></SC>", string(b))
}
} }
func TestOptBuyType(t *testing.T) { func TestOptBuyType(t *testing.T) {
@ -866,6 +1082,18 @@ func TestOptBuyType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E optBuyType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OptBuyType): %s\n", err)
}
if string(b) != "<SC><E>BUYTOCLOSE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>BUYTOCLOSE</E></SC>", string(b))
}
} }
func TestSellType(t *testing.T) { func TestSellType(t *testing.T) {
@ -911,6 +1139,18 @@ func TestSellType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E sellType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct SellType): %s\n", err)
}
if string(b) != "<SC><E>SELLSHORT</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>SELLSHORT</E></SC>", string(b))
}
} }
func TestLoanPmtFreq(t *testing.T) { func TestLoanPmtFreq(t *testing.T) {
@ -956,6 +1196,18 @@ func TestLoanPmtFreq(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E loanPmtFreq
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct LoanPmtFreq): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestIncomeType(t *testing.T) { func TestIncomeType(t *testing.T) {
@ -1001,6 +1253,18 @@ func TestIncomeType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E incomeType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct IncomeType): %s\n", err)
}
if string(b) != "<SC><E>MISC</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>MISC</E></SC>", string(b))
}
} }
func TestSellReason(t *testing.T) { func TestSellReason(t *testing.T) {
@ -1046,6 +1310,18 @@ func TestSellReason(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E sellReason
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct SellReason): %s\n", err)
}
if string(b) != "<SC><E>MATURITY</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>MATURITY</E></SC>", string(b))
}
} }
func TestOptSellType(t *testing.T) { func TestOptSellType(t *testing.T) {
@ -1091,6 +1367,18 @@ func TestOptSellType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E optSellType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OptSellType): %s\n", err)
}
if string(b) != "<SC><E>SELLTOOPEN</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>SELLTOOPEN</E></SC>", string(b))
}
} }
func TestRelType(t *testing.T) { func TestRelType(t *testing.T) {
@ -1136,6 +1424,18 @@ func TestRelType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E relType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct RelType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestCharType(t *testing.T) { func TestCharType(t *testing.T) {
@ -1181,6 +1481,18 @@ func TestCharType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E charType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct CharType): %s\n", err)
}
if string(b) != "<SC><E>ALPHAANDNUMERIC</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>ALPHAANDNUMERIC</E></SC>", string(b))
}
} }
func TestSyncMode(t *testing.T) { func TestSyncMode(t *testing.T) {
@ -1226,6 +1538,18 @@ func TestSyncMode(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E syncMode
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct SyncMode): %s\n", err)
}
if string(b) != "<SC><E>LITE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>LITE</E></SC>", string(b))
}
} }
func TestOfxSec(t *testing.T) { func TestOfxSec(t *testing.T) {
@ -1271,6 +1595,18 @@ func TestOfxSec(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E ofxSec
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OfxSec): %s\n", err)
}
if string(b) != "<SC><E>TYPE 1</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>TYPE 1</E></SC>", string(b))
}
} }
func TestDebtType(t *testing.T) { func TestDebtType(t *testing.T) {
@ -1316,6 +1652,18 @@ func TestDebtType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E debtType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct DebtType): %s\n", err)
}
if string(b) != "<SC><E>ZERO</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>ZERO</E></SC>", string(b))
}
} }
func TestDebtClass(t *testing.T) { func TestDebtClass(t *testing.T) {
@ -1361,6 +1709,18 @@ func TestDebtClass(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E debtClass
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct DebtClass): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestCouponFreq(t *testing.T) { func TestCouponFreq(t *testing.T) {
@ -1406,6 +1766,18 @@ func TestCouponFreq(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E couponFreq
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct CouponFreq): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestCallType(t *testing.T) { func TestCallType(t *testing.T) {
@ -1451,6 +1823,18 @@ func TestCallType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E callType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct CallType): %s\n", err)
}
if string(b) != "<SC><E>MATURITY</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>MATURITY</E></SC>", string(b))
}
} }
func TestAssetClass(t *testing.T) { func TestAssetClass(t *testing.T) {
@ -1496,6 +1880,18 @@ func TestAssetClass(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E assetClass
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct AssetClass): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestMfType(t *testing.T) { func TestMfType(t *testing.T) {
@ -1541,6 +1937,18 @@ func TestMfType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E mfType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct MfType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestOptType(t *testing.T) { func TestOptType(t *testing.T) {
@ -1586,6 +1994,18 @@ func TestOptType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E optType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct OptType): %s\n", err)
}
if string(b) != "<SC><E>CALL</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>CALL</E></SC>", string(b))
}
} }
func TestStockType(t *testing.T) { func TestStockType(t *testing.T) {
@ -1631,6 +2051,18 @@ func TestStockType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E stockType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct StockType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestHolderType(t *testing.T) { func TestHolderType(t *testing.T) {
@ -1676,6 +2108,18 @@ func TestHolderType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E holderType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct HolderType): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestAcctClassification(t *testing.T) { func TestAcctClassification(t *testing.T) {
@ -1721,6 +2165,18 @@ func TestAcctClassification(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E acctClassification
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct AcctClassification): %s\n", err)
}
if string(b) != "<SC><E>OTHER</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>OTHER</E></SC>", string(b))
}
} }
func TestSvcStatus(t *testing.T) { func TestSvcStatus(t *testing.T) {
@ -1766,6 +2222,18 @@ func TestSvcStatus(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E svcStatus
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct SvcStatus): %s\n", err)
}
if string(b) != "<SC><E>ACTIVE</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>ACTIVE</E></SC>", string(b))
}
} }
func TestUsProductType(t *testing.T) { func TestUsProductType(t *testing.T) {
@ -1811,4 +2279,16 @@ func TestUsProductType(t *testing.T) {
if err == nil { if err == nil {
t.Fatalf("Expected error unmarshalling garbage value\n") t.Fatalf("Expected error unmarshalling garbage value\n")
} }
type SC struct {
E usProductType
}
sc := SC{E: e}
b, err = xml.Marshal(sc)
if err != nil {
t.Fatalf("Unexpected error on xml.Marshal(struct UsProductType): %s\n", err)
}
if string(b) != "<SC><E>UGMA</E></SC>" {
t.Fatalf("Expected '%s', got '%s'\n", "<SC><E>UGMA</E></SC>", string(b))
}
} }

View File

@ -116,11 +116,11 @@ func (e *{enumLower}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return e.FromString(value) return e.FromString(value)
}} }}
func (e *{enumLower}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {{ func (e {enumLower}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {{
if !e.Valid() {{ if !e.Valid() {{
return nil return nil
}} }}
enc.EncodeElement({enumLower}s[*e-1], start) enc.EncodeElement({enumLower}s[e-1], start)
return nil return nil
}} }}
@ -225,6 +225,18 @@ func Test{enum}(t *testing.T) {{
if err == nil {{ if err == nil {{
t.Fatalf("Expected error unmarshalling garbage value\\n") t.Fatalf("Expected error unmarshalling garbage value\\n")
}} }}
type SC struct {{
E {enumLower}
}}
sc := SC{{E: e}}
b, err = xml.Marshal(sc)
if err != nil {{
t.Fatalf("Unexpected error on xml.Marshal(struct {enum}): %s\\n", err)
}}
if string(b) != "<SC><E>{lastValueUpper}</E></SC>" {{
t.Fatalf("Expected '%s', got '%s'\\n", "<SC><E>{lastValueUpper}</E></SC>", string(b))
}}
}} }}
""" """
@ -232,8 +244,10 @@ with open("constants_test.go", 'w') as f:
f.write(test_header) f.write(test_header)
for enum in enums: for enum in enums:
enumLower = enum[:1].lower() + enum[1:].replace(" ", "")
firstValueUpper = enums[enum][0][0].upper() firstValueUpper = enums[enum][0][0].upper()
lastValueUpper = enums[enum][0][-1].upper() lastValueUpper = enums[enum][0][-1].upper()
f.write(test_template.format(enum=enum, f.write(test_template.format(enum=enum,
enumLower=enumLower,
firstValueUpper=firstValueUpper, firstValueUpper=firstValueUpper,
lastValueUpper=lastValueUpper)) lastValueUpper=lastValueUpper))

8
go.mod
View File

@ -1,11 +1,9 @@
module github.com/aclindsa/ofxgo module github.com/aclindsa/ofxgo
require ( require (
github.com/aclindsa/xml v0.0.0-20190701095008-453d2c6090c2 github.com/aclindsa/xml v0.0.0-20201125035057-bbd5c9ec99ac
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect golang.org/x/text v0.3.7
golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf // indirect
golang.org/x/text v0.3.3
) )
go 1.9 go 1.9

23
go.sum
View File

@ -1,16 +1,9 @@
github.com/aclindsa/xml v0.0.0-20190701095008-453d2c6090c2 h1:ICeGSGrc6fd81VtQ3nZ2h7GEOKxWYwRxjW0v0d/mgu4= github.com/aclindsa/xml v0.0.0-20201125035057-bbd5c9ec99ac h1:xCNSfPWpcx3Sdz/+aB/Re4L8oA6Y4kRRRuTh1CHCDEw=
github.com/aclindsa/xml v0.0.0-20190701095008-453d2c6090c2/go.mod h1:GjqOUT8xlg5+T19lFv6yAGNrtMKkZ839Gt4e16mBXlY= github.com/aclindsa/xml v0.0.0-20201125035057-bbd5c9ec99ac/go.mod h1:GjqOUT8xlg5+T19lFv6yAGNrtMKkZ839Gt4e16mBXlY=
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf h1:Bg47KQy0JhTHuf4sLiQwTMKwUMfSDwgSGatrxGR7nLM=
golang.org/x/sys v0.0.0-20201006155630-ac719f4daadf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -131,6 +131,10 @@ func (t BuyDebt) TransactionType() string {
return "BUYDEBT" return "BUYDEBT"
} }
func (t BuyDebt) InvTransaction() InvTran {
return t.InvBuy.InvTran
}
// BuyMF represents a transaction purchasing a mutual fund // BuyMF represents a transaction purchasing a mutual fund
type BuyMF struct { type BuyMF struct {
XMLName xml.Name `xml:"BUYMF"` XMLName xml.Name `xml:"BUYMF"`
@ -144,6 +148,10 @@ func (t BuyMF) TransactionType() string {
return "BUYMF" return "BUYMF"
} }
func (t BuyMF) InvTransaction() InvTran {
return t.InvBuy.InvTran
}
// BuyOpt represents a transaction purchasing an option // BuyOpt represents a transaction purchasing an option
type BuyOpt struct { type BuyOpt struct {
XMLName xml.Name `xml:"BUYOPT"` XMLName xml.Name `xml:"BUYOPT"`
@ -157,6 +165,10 @@ func (t BuyOpt) TransactionType() string {
return "BUYOPT" return "BUYOPT"
} }
func (t BuyOpt) InvTransaction() InvTran {
return t.InvBuy.InvTran
}
// BuyOther represents a transaction purchasing a type of security not covered // BuyOther represents a transaction purchasing a type of security not covered
// by the other Buy* structs // by the other Buy* structs
type BuyOther struct { type BuyOther struct {
@ -169,6 +181,10 @@ func (t BuyOther) TransactionType() string {
return "BUYOTHER" return "BUYOTHER"
} }
func (t BuyOther) InvTransaction() InvTran {
return t.InvBuy.InvTran
}
// BuyStock represents a transaction purchasing stock // BuyStock represents a transaction purchasing stock
type BuyStock struct { type BuyStock struct {
XMLName xml.Name `xml:"BUYSTOCK"` XMLName xml.Name `xml:"BUYSTOCK"`
@ -181,6 +197,10 @@ func (t BuyStock) TransactionType() string {
return "BUYSTOCK" return "BUYSTOCK"
} }
func (t BuyStock) InvTransaction() InvTran {
return t.InvBuy.InvTran
}
// ClosureOpt represents a transaction closing a position for an option // ClosureOpt represents a transaction closing a position for an option
type ClosureOpt struct { type ClosureOpt struct {
XMLName xml.Name `xml:"CLOSUREOPT"` XMLName xml.Name `xml:"CLOSUREOPT"`
@ -199,6 +219,10 @@ func (t ClosureOpt) TransactionType() string {
return "CLOSUREOPT" return "CLOSUREOPT"
} }
func (t ClosureOpt) InvTransaction() InvTran {
return t.InvTran
}
// Income represents a transaction where investment income is being realized as // Income represents a transaction where investment income is being realized as
// cash into the investment account // cash into the investment account
type Income struct { type Income struct {
@ -221,6 +245,10 @@ func (t Income) TransactionType() string {
return "INCOME" return "INCOME"
} }
func (t Income) InvTransaction() InvTran {
return t.InvTran
}
// InvExpense represents a transaction realizing an expense associated with an // InvExpense represents a transaction realizing an expense associated with an
// investment // investment
type InvExpense struct { type InvExpense struct {
@ -240,6 +268,10 @@ func (t InvExpense) TransactionType() string {
return "INVEXPENSE" return "INVEXPENSE"
} }
func (t InvExpense) InvTransaction() InvTran {
return t.InvTran
}
// JrnlFund represents a transaction journaling cash holdings between // JrnlFund represents a transaction journaling cash holdings between
// sub-accounts within the same investment account // sub-accounts within the same investment account
type JrnlFund struct { type JrnlFund struct {
@ -255,6 +287,10 @@ func (t JrnlFund) TransactionType() string {
return "JRNLFUND" return "JRNLFUND"
} }
func (t JrnlFund) InvTransaction() InvTran {
return t.InvTran
}
// JrnlSec represents a transaction journaling security holdings between // JrnlSec represents a transaction journaling security holdings between
// sub-accounts within the same investment account // sub-accounts within the same investment account
type JrnlSec struct { type JrnlSec struct {
@ -271,6 +307,10 @@ func (t JrnlSec) TransactionType() string {
return "JRNLSEC" return "JRNLSEC"
} }
func (t JrnlSec) InvTransaction() InvTran {
return t.InvTran
}
// MarginInterest represents a transaction realizing a margin interest expense // MarginInterest represents a transaction realizing a margin interest expense
type MarginInterest struct { type MarginInterest struct {
XMLName xml.Name `xml:"MARGININTEREST"` XMLName xml.Name `xml:"MARGININTEREST"`
@ -286,6 +326,10 @@ func (t MarginInterest) TransactionType() string {
return "MARGININTEREST" return "MARGININTEREST"
} }
func (t MarginInterest) InvTransaction() InvTran {
return t.InvTran
}
// Reinvest is a single transaction that contains both income and an investment // Reinvest is a single transaction that contains both income and an investment
// transaction. If servers cant track this as a single transaction they should // transaction. If servers cant track this as a single transaction they should
// return an Income transaction and an InvTran. // return an Income transaction and an InvTran.
@ -313,6 +357,10 @@ func (t Reinvest) TransactionType() string {
return "REINVEST" return "REINVEST"
} }
func (t Reinvest) InvTransaction() InvTran {
return t.InvTran
}
// RetOfCap represents a transaction where capital is being returned to the // RetOfCap represents a transaction where capital is being returned to the
// account holder // account holder
type RetOfCap struct { type RetOfCap struct {
@ -332,6 +380,10 @@ func (t RetOfCap) TransactionType() string {
return "RETOFCAP" return "RETOFCAP"
} }
func (t RetOfCap) InvTransaction() InvTran {
return t.InvTran
}
// SellDebt represents the sale of a debt security. Used when debt is sold, // SellDebt represents the sale of a debt security. Used when debt is sold,
// called, or reaches maturity. // called, or reaches maturity.
type SellDebt struct { type SellDebt struct {
@ -346,6 +398,10 @@ func (t SellDebt) TransactionType() string {
return "SELLDEBT" return "SELLDEBT"
} }
func (t SellDebt) InvTransaction() InvTran {
return t.InvSell.InvTran
}
// SellMF represents a transaction selling a mutual fund // SellMF represents a transaction selling a mutual fund
type SellMF struct { type SellMF struct {
XMLName xml.Name `xml:"SELLMF"` XMLName xml.Name `xml:"SELLMF"`
@ -360,6 +416,10 @@ func (t SellMF) TransactionType() string {
return "SELLMF" return "SELLMF"
} }
func (t SellMF) InvTransaction() InvTran {
return t.InvSell.InvTran
}
// SellOpt represents a transaction selling an option. Depending on the value // SellOpt represents a transaction selling an option. Depending on the value
// of OptSellType, can be used to sell a previously bought option or write a // of OptSellType, can be used to sell a previously bought option or write a
// new option. // new option.
@ -378,6 +438,10 @@ func (t SellOpt) TransactionType() string {
return "SELLOPT" return "SELLOPT"
} }
func (t SellOpt) InvTransaction() InvTran {
return t.InvSell.InvTran
}
// SellOther represents a transaction selling a security type not covered by // SellOther represents a transaction selling a security type not covered by
// the other Sell* structs // the other Sell* structs
type SellOther struct { type SellOther struct {
@ -390,6 +454,10 @@ func (t SellOther) TransactionType() string {
return "SELLOTHER" return "SELLOTHER"
} }
func (t SellOther) InvTransaction() InvTran {
return t.InvSell.InvTran
}
// SellStock represents a transaction selling stock // SellStock represents a transaction selling stock
type SellStock struct { type SellStock struct {
XMLName xml.Name `xml:"SELLSTOCK"` XMLName xml.Name `xml:"SELLSTOCK"`
@ -402,6 +470,10 @@ func (t SellStock) TransactionType() string {
return "SELLSTOCK" return "SELLSTOCK"
} }
func (t SellStock) InvTransaction() InvTran {
return t.InvSell.InvTran
}
// Split represents a stock or mutual fund split // Split represents a stock or mutual fund split
type Split struct { type Split struct {
XMLName xml.Name `xml:"SPLIT"` XMLName xml.Name `xml:"SPLIT"`
@ -424,6 +496,10 @@ func (t Split) TransactionType() string {
return "SPLIT" return "SPLIT"
} }
func (t Split) InvTransaction() InvTran {
return t.InvTran
}
// Transfer represents the transfer of securities into or out of an account // Transfer represents the transfer of securities into or out of an account
type Transfer struct { type Transfer struct {
XMLName xml.Name `xml:"TRANSFER"` XMLName xml.Name `xml:"TRANSFER"`
@ -445,10 +521,15 @@ func (t Transfer) TransactionType() string {
return "TRANSFER" return "TRANSFER"
} }
func (t Transfer) InvTransaction() InvTran {
return t.InvTran
}
// InvTransaction is a generic interface met by all investment transactions // InvTransaction is a generic interface met by all investment transactions
// (Buy*, Sell*, & co.) // (Buy*, Sell*, & co.)
type InvTransaction interface { type InvTransaction interface {
TransactionType() string TransactionType() string
InvTransaction() InvTran
} }
// InvBankTransaction is a banking transaction performed in an investment // InvBankTransaction is a banking transaction performed in an investment
@ -764,6 +845,7 @@ type InvPosition struct {
// Position is an interface satisfied by all the other *Position types // Position is an interface satisfied by all the other *Position types
type Position interface { type Position interface {
PositionType() string PositionType() string
InvPosition() InvPosition
} }
// DebtPosition represents a position held in a debt security // DebtPosition represents a position held in a debt security
@ -777,6 +859,11 @@ func (p DebtPosition) PositionType() string {
return "POSDEBT" return "POSDEBT"
} }
// InvPosition returns InvPos
func (p DebtPosition) InvPosition() InvPosition {
return p.InvPos
}
// MFPosition represents a position held in a mutual fund // MFPosition represents a position held in a mutual fund
type MFPosition struct { type MFPosition struct {
XMLName xml.Name `xml:"POSMF"` XMLName xml.Name `xml:"POSMF"`
@ -792,6 +879,11 @@ func (p MFPosition) PositionType() string {
return "POSMF" return "POSMF"
} }
// InvPosition returns InvPos
func (p MFPosition) InvPosition() InvPosition {
return p.InvPos
}
// OptPosition represents a position held in an option // OptPosition represents a position held in an option
type OptPosition struct { type OptPosition struct {
XMLName xml.Name `xml:"POSOPT"` XMLName xml.Name `xml:"POSOPT"`
@ -804,6 +896,11 @@ func (p OptPosition) PositionType() string {
return "POSOPT" return "POSOPT"
} }
// InvPosition returns InvPos
func (p OptPosition) InvPosition() InvPosition {
return p.InvPos
}
// OtherPosition represents a position held in a security type not covered by // OtherPosition represents a position held in a security type not covered by
// the other *Position elements // the other *Position elements
type OtherPosition struct { type OtherPosition struct {
@ -816,6 +913,11 @@ func (p OtherPosition) PositionType() string {
return "POSOTHER" return "POSOTHER"
} }
// InvPosition returns InvPos
func (p OtherPosition) InvPosition() InvPosition {
return p.InvPos
}
// StockPosition represents a position held in a stock // StockPosition represents a position held in a stock
type StockPosition struct { type StockPosition struct {
XMLName xml.Name `xml:"POSSTOCK"` XMLName xml.Name `xml:"POSSTOCK"`
@ -830,6 +932,11 @@ func (p StockPosition) PositionType() string {
return "POSSTOCK" return "POSSTOCK"
} }
// InvPosition returns InvPos
func (p StockPosition) InvPosition() InvPosition {
return p.InvPos
}
// PositionList represents a list of positions held in securities in an // PositionList represents a list of positions held in securities in an
// investment account // investment account
type PositionList []Position type PositionList []Position
@ -885,12 +992,12 @@ func (p *PositionList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
} }
// MarshalXML handles marshalling a PositionList to an XML string // MarshalXML handles marshalling a PositionList to an XML string
func (p *PositionList) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (p PositionList) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
invPosListElement := xml.StartElement{Name: xml.Name{Local: "INVPOSLIST"}} invPosListElement := xml.StartElement{Name: xml.Name{Local: "INVPOSLIST"}}
if err := e.EncodeToken(invPosListElement); err != nil { if err := e.EncodeToken(invPosListElement); err != nil {
return err return err
} }
for _, position := range *p { for _, position := range p {
start := xml.StartElement{Name: xml.Name{Local: position.PositionType()}} start := xml.StartElement{Name: xml.Name{Local: position.PositionType()}}
switch pos := position.(type) { switch pos := position.(type) {
case DebtPosition: case DebtPosition:
@ -1190,12 +1297,12 @@ func (o *OOList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
} }
// MarshalXML handles marshalling an OOList to an XML string // MarshalXML handles marshalling an OOList to an XML string
func (o *OOList) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (o OOList) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
ooListElement := xml.StartElement{Name: xml.Name{Local: "INVOOLIST"}} ooListElement := xml.StartElement{Name: xml.Name{Local: "INVOOLIST"}}
if err := e.EncodeToken(ooListElement); err != nil { if err := e.EncodeToken(ooListElement); err != nil {
return err return err
} }
for _, openorder := range *o { for _, openorder := range o {
start := xml.StartElement{Name: xml.Name{Local: openorder.OrderType()}} start := xml.StartElement{Name: xml.Name{Local: openorder.OrderType()}}
switch oo := openorder.(type) { switch oo := openorder.(type) {
case OOBuyDebt: case OOBuyDebt:

View File

@ -1,11 +1,12 @@
package ofxgo package ofxgo
import ( import (
"github.com/aclindsa/xml"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"time" "time"
"github.com/aclindsa/xml"
) )
func TestMarshalInvStatementRequest(t *testing.T) { func TestMarshalInvStatementRequest(t *testing.T) {
@ -1866,3 +1867,84 @@ func TestUnmarshalOOList(t *testing.T) {
} }
checkEqual(t, "OOList", reflect.ValueOf(&expected), reflect.ValueOf(&actual)) checkEqual(t, "OOList", reflect.ValueOf(&expected), reflect.ValueOf(&actual))
} }
func TestSecurityInfo(t *testing.T) {
secInfo := SecInfo{
Ticker: "ABC",
}
tests := []Security{
DebtInfo{SecInfo: secInfo},
MFInfo{SecInfo: secInfo},
OptInfo{SecInfo: secInfo},
OtherInfo{SecInfo: secInfo},
StockInfo{SecInfo: secInfo},
}
for _, tc := range tests {
t.Run(tc.SecurityType(), func(t *testing.T) {
info := tc.SecurityInfo()
if info.Ticker != secInfo.Ticker {
t.Errorf("got %v, want %v", info, secInfo)
}
})
}
}
func TestInvPosition(t *testing.T) {
invPos := InvPosition{
Memo: "stuff",
}
tests := []Position{
DebtPosition{InvPos: invPos},
MFPosition{InvPos: invPos},
OptPosition{InvPos: invPos},
OtherPosition{InvPos: invPos},
StockPosition{InvPos: invPos},
}
for _, tc := range tests {
t.Run(tc.PositionType(), func(t *testing.T) {
pos := tc.InvPosition()
if pos.Memo != invPos.Memo {
t.Errorf("got %v, want %v", pos, invPos)
}
})
}
}
func TestInvTransaction(t *testing.T) {
invTran := InvTran{
Memo: "stuff",
}
tests := []InvTransaction{
BuyDebt{InvBuy: InvBuy{InvTran: invTran}},
BuyMF{InvBuy: InvBuy{InvTran: invTran}},
BuyOpt{InvBuy: InvBuy{InvTran: invTran}},
BuyOther{InvBuy: InvBuy{InvTran: invTran}},
BuyStock{InvBuy: InvBuy{InvTran: invTran}},
ClosureOpt{InvTran: invTran},
Income{InvTran: invTran},
InvExpense{InvTran: invTran},
JrnlFund{InvTran: invTran},
JrnlSec{InvTran: invTran},
MarginInterest{InvTran: invTran},
Reinvest{InvTran: invTran},
RetOfCap{InvTran: invTran},
SellDebt{InvSell: InvSell{InvTran: invTran}},
SellMF{InvSell: InvSell{InvTran: invTran}},
SellOpt{InvSell: InvSell{InvTran: invTran}},
SellOther{InvSell: InvSell{InvTran: invTran}},
SellStock{InvSell: InvSell{InvTran: invTran}},
Split{InvTran: invTran},
Transfer{InvTran: invTran},
}
for _, tc := range tests {
t.Run(tc.TransactionType(), func(t *testing.T) {
tran := tc.InvTransaction()
if tran.Memo != invTran.Memo {
t.Errorf("got %v, want %v", tran, invTran)
}
})
}
}

View File

@ -94,6 +94,7 @@ func (r *SecListResponse) Type() messageType {
// securities for SecurityList // securities for SecurityList
type Security interface { type Security interface {
SecurityType() string SecurityType() string
SecurityInfo() SecInfo
} }
// SecInfo represents the generic information about a security. It is included // SecInfo represents the generic information about a security. It is included
@ -136,6 +137,11 @@ func (i DebtInfo) SecurityType() string {
return "DEBTINFO" return "DEBTINFO"
} }
// SecurityInfo returns SecInfo
func (i DebtInfo) SecurityInfo() SecInfo {
return i.SecInfo
}
// AssetPortion represents the percentage of a mutual fund with the given asset // AssetPortion represents the percentage of a mutual fund with the given asset
// classification // classification
type AssetPortion struct { type AssetPortion struct {
@ -169,6 +175,11 @@ func (i MFInfo) SecurityType() string {
return "MFINFO" return "MFINFO"
} }
// SecurityInfo returns SecInfo
func (i MFInfo) SecurityInfo() SecInfo {
return i.SecInfo
}
// OptInfo provides information about an option // OptInfo provides information about an option
type OptInfo struct { type OptInfo struct {
XMLName xml.Name `xml:"OPTINFO"` XMLName xml.Name `xml:"OPTINFO"`
@ -187,6 +198,11 @@ func (i OptInfo) SecurityType() string {
return "OPTINFO" return "OPTINFO"
} }
// SecurityInfo returns SecInfo
func (i OptInfo) SecurityInfo() SecInfo {
return i.SecInfo
}
// OtherInfo provides information about a security type not covered by the // OtherInfo provides information about a security type not covered by the
// other *Info elements // other *Info elements
type OtherInfo struct { type OtherInfo struct {
@ -202,6 +218,11 @@ func (i OtherInfo) SecurityType() string {
return "OTHERINFO" return "OTHERINFO"
} }
// SecurityInfo returns SecInfo
func (i OtherInfo) SecurityInfo() SecInfo {
return i.SecInfo
}
// StockInfo provides information about a security type // StockInfo provides information about a security type
type StockInfo struct { type StockInfo struct {
XMLName xml.Name `xml:"STOCKINFO"` XMLName xml.Name `xml:"STOCKINFO"`
@ -218,6 +239,11 @@ func (i StockInfo) SecurityType() string {
return "STOCKINFO" return "STOCKINFO"
} }
// SecurityInfo returns SecInfo
func (i StockInfo) SecurityInfo() SecInfo {
return i.SecInfo
}
// SecurityList is a container for Security objects containaing information // SecurityList is a container for Security objects containaing information
// about securities // about securities
type SecurityList struct { type SecurityList struct {

View File

@ -76,7 +76,7 @@ func (a Amount) String() string {
} }
// MarshalXML marshals an Amount to SGML/XML // MarshalXML marshals an Amount to SGML/XML
func (a *Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (a Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return e.EncodeElement(a.String(), start) return e.EncodeElement(a.String(), start)
} }
@ -188,7 +188,7 @@ func (od Date) String() string {
} }
// MarshalXML marshals a Date to XML // MarshalXML marshals a Date to XML
func (od *Date) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (od Date) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return e.EncodeElement(od.String(), start) return e.EncodeElement(od.String(), start)
} }
@ -260,8 +260,8 @@ func (ob *Boolean) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
} }
// MarshalXML marshals a Boolean to XML // MarshalXML marshals a Boolean to XML
func (ob *Boolean) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (ob Boolean) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
if *ob { if ob {
return e.EncodeElement("Y", start) return e.EncodeElement("Y", start)
} }
return e.EncodeElement("N", start) return e.EncodeElement("N", start)
@ -358,7 +358,7 @@ func (c *CurrSymbol) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
} }
// MarshalXML marshals a CurrSymbol to SGML/XML // MarshalXML marshals a CurrSymbol to SGML/XML
func (c *CurrSymbol) MarshalXML(e *xml.Encoder, start xml.StartElement) error { func (c CurrSymbol) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
return e.EncodeElement(c.String(), start) return e.EncodeElement(c.String(), start)
} }

View File

@ -91,6 +91,13 @@ func TestMarshalAmount(t *testing.T) {
marshalHelper(t, "-768276587425", &a) marshalHelper(t, "-768276587425", &a)
a.SetFrac64(1, 12) a.SetFrac64(1, 12)
marshalHelper(t, "0.0833333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333", &a) marshalHelper(t, "0.0833333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333", &a)
type AmountStruct struct {
A Amount
}
var as AmountStruct
as.A.SetFrac64(1, 8)
marshalHelper(t, "<A>0.125</A>", as)
} }
func TestUnmarshalAmount(t *testing.T) { func TestUnmarshalAmount(t *testing.T) {
@ -185,6 +192,13 @@ func TestMarshalDate(t *testing.T) {
// Time zone without textual description // Time zone without textual description
d = NewDate(2017, 3, 14, 15, 9, 26, 53*1000*1000, GMTNodesc) d = NewDate(2017, 3, 14, 15, 9, 26, 53*1000*1000, GMTNodesc)
marshalHelper(t, "20170314150926.053[0]", d) marshalHelper(t, "20170314150926.053[0]", d)
type DateStruct struct {
D Date
}
d = NewDateGMT(2017, 3, 14, 15, 9, 26, 53*1000*1000)
ds := DateStruct{D: *d}
marshalHelper(t, "<D>20170314150926.053[0:GMT]</D>", ds)
} }
func TestUnmarshalDate(t *testing.T) { func TestUnmarshalDate(t *testing.T) {
@ -316,11 +330,24 @@ func TestUnmarshalString(t *testing.T) {
unmarshalHelper(t, "Some Name\n ", &s, &overwritten) unmarshalHelper(t, "Some Name\n ", &s, &overwritten)
} }
func TestStringString(t *testing.T) {
var s String = "foobar"
if s.String() != "foobar" {
t.Fatalf("Unexpected result when returning String.String(): %s\n", s.String())
}
}
func TestMarshalBoolean(t *testing.T) { func TestMarshalBoolean(t *testing.T) {
var b Boolean = true var b Boolean = true
marshalHelper(t, "Y", &b) marshalHelper(t, "Y", &b)
b = false b = false
marshalHelper(t, "N", &b) marshalHelper(t, "N", &b)
type BooleanStruct struct {
B Boolean
}
bs := BooleanStruct{B: true}
marshalHelper(t, "<B>Y</B>", bs)
} }
func TestUnmarshalBoolean(t *testing.T) { func TestUnmarshalBoolean(t *testing.T) {
@ -333,6 +360,17 @@ func TestUnmarshalBoolean(t *testing.T) {
unmarshalHelper(t, "N\n \t", &b, &overwritten) unmarshalHelper(t, "N\n \t", &b, &overwritten)
} }
func TestStringBoolean(t *testing.T) {
var b Boolean = true
if b.String() != "true" {
t.Fatalf("Unexpected string for Boolean.String() for true: %s\n", b.String())
}
b = false
if b.String() != "false" {
t.Fatalf("Unexpected string for Boolean.String() for false: %s\n", b.String())
}
}
func TestMarshalUID(t *testing.T) { func TestMarshalUID(t *testing.T) {
var u UID = "d1cf3d3d-9ef9-4a97-b180-81706829cb04" var u UID = "d1cf3d3d-9ef9-4a97-b180-81706829cb04"
marshalHelper(t, "d1cf3d3d-9ef9-4a97-b180-81706829cb04", &u) marshalHelper(t, "d1cf3d3d-9ef9-4a97-b180-81706829cb04", &u)
@ -394,6 +432,12 @@ func TestRandomUID(t *testing.T) {
func TestMarshalCurrSymbol(t *testing.T) { func TestMarshalCurrSymbol(t *testing.T) {
c, _ := NewCurrSymbol("USD") c, _ := NewCurrSymbol("USD")
marshalHelper(t, "USD", &c) marshalHelper(t, "USD", &c)
type CurrSymbolStruct struct {
CS CurrSymbol
}
css := CurrSymbolStruct{CS: *c}
marshalHelper(t, "<CS>USD</CS>", css)
} }
func TestUnmarshalCurrSymbol(t *testing.T) { func TestUnmarshalCurrSymbol(t *testing.T) {