From 4521bb377adb5a09498f6ea6f6c9da6fbbc3e877 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Thu, 6 Apr 2017 05:58:22 -0400 Subject: [PATCH] Use named constants instead of strings for enum-like OFX fields This adds a python script to generate constants.go when `go generate` is called, and updates the structs, tests, and command-line client to all use the new named constants. --- bank.go | 68 +- bank_test.go | 8 +- cmd/ofx/bankdownload.go | 9 +- cmd/ofx/banktransactions.go | 9 +- common.go | 4 +- constants.go | 2473 +++++++++++++++++++++++++++++++++++ creditcard_test.go | 6 +- generate_constants.py | 155 +++ invstmt.go | 428 +++--- invstmt_test.go | 70 +- profile.go | 6 +- profile_test.go | 22 +- response_test.go | 4 + seclist.go | 68 +- signup.go | 78 +- signup_test.go | 4 +- 16 files changed, 3030 insertions(+), 382 deletions(-) create mode 100644 constants.go create mode 100755 generate_constants.py diff --git a/bank.go b/bank.go index 6ef0deb..723b4ab 100644 --- a/bank.go +++ b/bank.go @@ -45,43 +45,43 @@ type Payee struct { } type ImageData struct { - XMLName xml.Name `xml:"IMAGEDATA"` - ImageType String `xml:"IMAGETYPE"` // One of STATEMENT, TRANSACTION, TAX - ImageRef String `xml:"IMAGEREF"` // URL or identifier, depending on IMAGEREFTYPE - ImageRefType String `xml:"IMAGEREFTYPE"` // One of OPAQUE, URL, FORMURL (see spec for more details on how to access images of each of these types) + XMLName xml.Name `xml:"IMAGEDATA"` + ImageType imageType `xml:"IMAGETYPE"` // One of STATEMENT, TRANSACTION, TAX + ImageRef String `xml:"IMAGEREF"` // URL or identifier, depending on IMAGEREFTYPE + ImageRefType imageRefType `xml:"IMAGEREFTYPE"` // One of OPAQUE, URL, FORMURL (see spec for more details on how to access images of each of these types) // Only one of the next two should be valid at any given time - ImageDelay Int `xml:"IMAGEDELAY,omitempty"` // Number of calendar days from DTSERVER (for statement images) or DTPOSTED (for transaction image) the image will become available - DtImageAvail *Date `xml:"DTIMAGEAVAIL,omitempty"` // Date image will become available - ImageTTL Int `xml:"IMAGETTL,omitempty"` // Number of days after image becomes available that it will remain available - CheckSup String `xml:"CHECKSUP,omitempty"` // What is contained in check images. One of FRONTONLY, BACKONLY, FRONTANDBACK + ImageDelay Int `xml:"IMAGEDELAY,omitempty"` // Number of calendar days from DTSERVER (for statement images) or DTPOSTED (for transaction image) the image will become available + DtImageAvail *Date `xml:"DTIMAGEAVAIL,omitempty"` // Date image will become available + ImageTTL Int `xml:"IMAGETTL,omitempty"` // Number of days after image becomes available that it will remain available + CheckSup checkSup `xml:"CHECKSUP,omitempty"` // What is contained in check images. One of FRONTONLY, BACKONLY, FRONTANDBACK } type Transaction struct { - XMLName xml.Name `xml:"STMTTRN"` - TrnType String `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, OTHER - DtPosted Date `xml:"DTPOSTED"` - DtUser *Date `xml:"DTUSER,omitempty"` - DtAvail *Date `xml:"DTAVAIL,omitempty"` - TrnAmt Amount `xml:"TRNAMT"` - FiTId String `xml:"FITID"` - CorrectFiTId String `xml:"CORRECTFITID,omitempty"` // Transaction Id that this transaction corrects, if present - CorrectAction String `xml:"CORRECTACTION,omitempty"` // One of DELETE, REPLACE - SrvrTId String `xml:"SRVRTID,omitempty"` - CheckNum String `xml:"CHECKNUM,omitempty"` - RefNum String `xml:"REFNUM,omitempty"` - SIC Int `xml:"SIC,omitempty"` // Standard Industrial Code - PayeeId String `xml:"PAYEEID,omitempty"` + XMLName xml.Name `xml:"STMTTRN"` + TrnType trnType `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, OTHER + DtPosted Date `xml:"DTPOSTED"` + DtUser *Date `xml:"DTUSER,omitempty"` + DtAvail *Date `xml:"DTAVAIL,omitempty"` + TrnAmt Amount `xml:"TRNAMT"` + FiTId String `xml:"FITID"` + CorrectFiTId String `xml:"CORRECTFITID,omitempty"` // Transaction Id that this transaction corrects, if present + CorrectAction correctAction `xml:"CORRECTACTION,omitempty"` // One of DELETE, REPLACE + SrvrTId String `xml:"SRVRTID,omitempty"` + CheckNum String `xml:"CHECKNUM,omitempty"` + RefNum String `xml:"REFNUM,omitempty"` + SIC Int `xml:"SIC,omitempty"` // Standard Industrial Code + PayeeId String `xml:"PAYEEID,omitempty"` // Note: Servers should provide NAME or PAYEE, but not both - Name String `xml:"NAME,omitempty"` - Payee *Payee `xml:"PAYEE,omitempty"` - ExtdName String `xml:"EXTDNAME,omitempty"` // Extended name of payee or transaction description - BankAcctTo *BankAcct `xml:"BANKACCTTO,omitempty"` // If the transfer was to a bank account we have the account information for - CCAcctTo *CCAcct `xml:"CCACCTTO,omitempty"` // If the transfer was to a credit card account we have the account information for - Memo String `xml:"MEMO,omitempty"` // Extra information (not in NAME) - ImageData []ImageData `xml:"IMAGEDATA,omitempty"` - Currency String `xml:"CURRENCY,omitempty"` // If different from CURDEF in STMTTRS - OrigCurrency String `xml:"ORIGCURRENCY,omitempty"` // If different from CURDEF in STMTTRS - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST (Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST.) + Name String `xml:"NAME,omitempty"` + Payee *Payee `xml:"PAYEE,omitempty"` + ExtdName String `xml:"EXTDNAME,omitempty"` // Extended name of payee or transaction description + BankAcctTo *BankAcct `xml:"BANKACCTTO,omitempty"` // If the transfer was to a bank account we have the account information for + CCAcctTo *CCAcct `xml:"CCACCTTO,omitempty"` // If the transfer was to a credit card account we have the account information for + Memo String `xml:"MEMO,omitempty"` // Extra information (not in NAME) + ImageData []ImageData `xml:"IMAGEDATA,omitempty"` + Currency String `xml:"CURRENCY,omitempty"` // If different from CURDEF in STMTTRS + OrigCurrency String `xml:"ORIGCURRENCY,omitempty"` // If different from CURDEF in STMTTRS + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST (Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST.) } type TransactionList struct { @@ -93,7 +93,7 @@ type TransactionList struct { type PendingTransaction struct { XMLName xml.Name `xml:"STMTTRN"` - TrnType String `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, HOLD, OTHER + TrnType trnType `xml:"TRNTYPE"` // One of CREDIT, DEBIT, INT (interest earned or paid. Note: Depends on signage of amount), DIV, FEE, SRVCHG (service charge), DEP (deposit), ATM (Note: Depends on signage of amount), POS (Note: Depends on signage of amount), XFER, CHECK, PAYMENT, CASH, DIRECTDEP, DIRECTDEBIT, REPEATPMT, HOLD, OTHER DtTran Date `xml:"DTTRAN"` DtExpire *Date `xml:"DTEXPIRE,omitempty"` // only valid for TrnType==HOLD, the date the hold will expire TrnAmt Amount `xml:"TRNAMT"` @@ -122,7 +122,7 @@ type Balance struct { // DOLLAR = dollar (value formatted DDDD.cc) // PERCENT = percentage (value formatted XXXX.YYYY) // NUMBER = number (value formatted as is) - BalType String `xml:"BALTYPE"` + BalType balType `xml:"BALTYPE"` Value Amount `xml:"VALUE"` DtAsOf *Date `xml:"DTASOF,omitempty"` diff --git a/bank_test.go b/bank_test.go index a08b7d6..240e99f 100644 --- a/bank_test.go +++ b/bank_test.go @@ -59,7 +59,7 @@ func TestMarshalBankStatementRequest(t *testing.T) { BankAcctFrom: ofxgo.BankAcct{ BankId: "318398732", AcctId: "78346129", - AcctType: "CHECKING", + AcctType: ofxgo.AcctTypeChecking, }, Include: true, } @@ -158,14 +158,14 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { DtEnd: *ofxgo.NewDateGMT(2006, 1, 15, 0, 0, 0, 0), Transactions: []ofxgo.Transaction{ { - TrnType: "CHECK", + TrnType: ofxgo.TrnTypeCheck, DtPosted: *ofxgo.NewDateGMT(2006, 1, 4, 0, 0, 0, 0), TrnAmt: trnamt1, FiTId: "00592", CheckNum: "2002", }, { - TrnType: "ATM", + TrnType: ofxgo.TrnTypeATM, DtPosted: *ofxgo.NewDateGMT(2006, 1, 12, 0, 0, 0, 0), DtUser: ofxgo.NewDateGMT(2006, 1, 12, 0, 0, 0, 0), TrnAmt: trnamt2, @@ -188,7 +188,7 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { BankAcctFrom: ofxgo.BankAcct{ BankId: "318398732", AcctId: "78346129", - AcctType: "CHECKING", + AcctType: ofxgo.AcctTypeChecking, }, BankTranList: &banktranlist, BalAmt: balamt, diff --git a/cmd/ofx/bankdownload.go b/cmd/ofx/bankdownload.go index bc80f2b..dd81e2f 100644 --- a/cmd/ofx/bankdownload.go +++ b/cmd/ofx/bankdownload.go @@ -40,6 +40,12 @@ func downloadCheckFlags() bool { func download() { client, query := NewRequest() + acctTypeEnum, err := ofxgo.NewAcctType(acctType) + if err != nil { + fmt.Println("Error parsing accttype:", err) + os.Exit(1) + } + uid, err := ofxgo.RandomUID() if err != nil { fmt.Println("Error creating uid for transaction:", err) @@ -51,10 +57,11 @@ func download() { BankAcctFrom: ofxgo.BankAcct{ BankId: ofxgo.String(bankId), AcctId: ofxgo.String(acctId), - AcctType: ofxgo.String(acctType), + AcctType: acctTypeEnum, }, Include: true, } + query.Bank = append(query.Bank, &statementRequest) response, err := client.RequestNoParse(query) diff --git a/cmd/ofx/banktransactions.go b/cmd/ofx/banktransactions.go index a342458..6c5fc98 100644 --- a/cmd/ofx/banktransactions.go +++ b/cmd/ofx/banktransactions.go @@ -25,6 +25,12 @@ func init() { func bankTransactions() { client, query := NewRequest() + acctTypeEnum, err := ofxgo.NewAcctType(acctType) + if err != nil { + fmt.Println("Error parsing accttype:", err) + os.Exit(1) + } + uid, err := ofxgo.RandomUID() if err != nil { fmt.Println("Error creating uid for transaction:", err) @@ -36,10 +42,11 @@ func bankTransactions() { BankAcctFrom: ofxgo.BankAcct{ BankId: ofxgo.String(bankId), AcctId: ofxgo.String(acctId), - AcctType: ofxgo.String(acctType), + AcctType: acctTypeEnum, }, Include: true, } + query.Bank = append(query.Bank, &statementRequest) response, err := client.Request(query) diff --git a/common.go b/common.go index 26eec5b..0b8662b 100644 --- a/common.go +++ b/common.go @@ -1,5 +1,7 @@ package ofxgo +//go:generate ./generate_constants.py + import ( "errors" "github.com/aclindsa/go/src/encoding/xml" @@ -261,7 +263,7 @@ type BankAcct struct { BankId String `xml:"BANKID"` BranchId String `xml:"BRANCHID,omitempty"` // Unused in USA AcctId String `xml:"ACCTID"` - AcctType String `xml:"ACCTTYPE"` // One of CHECKING, SAVINGS, MONEYMRKT, CREDITLINE, CD + AcctType acctType `xml:"ACCTTYPE"` // One of CHECKING, SAVINGS, MONEYMRKT, CREDITLINE, CD AcctKey String `xml:"ACCTKEY,omitempty"` // Unused in USA } diff --git a/constants.go b/constants.go new file mode 100644 index 0000000..b7e90ff --- /dev/null +++ b/constants.go @@ -0,0 +1,2473 @@ +package ofxgo + +/* + * Do not edit this file by hand. It is auto-generated by calling `go generate`. + * To make changes, edit generate_constants.py, re-run `go generate`, and check + * in the result. + */ + +import ( + "errors" + "fmt" + "github.com/aclindsa/go/src/encoding/xml" + "strings" +) + +type acctType uint + +const ( + AcctTypeChecking acctType = 1 + iota + AcctTypeSavings + AcctTypeMoneyMrkt + AcctTypeCreditLine + AcctTypeCD +) + +var acctTypes = [...]string{"CHECKING", "SAVINGS", "MONEYMRKT", "CREDITLINE", "CD"} + +func (e acctType) Valid() bool { + return e >= AcctTypeChecking && e <= AcctTypeCD +} + +func (e acctType) String() string { + if e.Valid() { + return acctTypes[e-1] + } + return fmt.Sprintf("invalid acctType (%d)", e) +} + +func (e *acctType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range acctTypes { + if s == value { + *e = acctType(i + 1) + return nil + } + } + return errors.New("Invalid AcctType: \"" + in + "\"") +} + +func (e *acctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *acctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid AcctType") + } + enc.EncodeElement(acctTypes[*e-1], start) + return nil +} + +func NewAcctType(s string) (acctType, error) { + var e acctType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type trnType uint + +const ( + TrnTypeCredit trnType = 1 + iota + TrnTypeDebit + TrnTypeInt + TrnTypeDiv + TrnTypeFee + TrnTypeSrvChg + TrnTypeDep + TrnTypeATM + TrnTypePOS + TrnTypeXfer + TrnTypeCheck + TrnTypePayment + TrnTypeCash + TrnTypeDirectDep + TrnTypeDirectDebit + TrnTypeRepeatPmt + TrnTypeHold + TrnTypeOther +) + +var trnTypes = [...]string{"CREDIT", "DEBIT", "INT", "DIV", "FEE", "SRVCHG", "DEP", "ATM", "POS", "XFER", "CHECK", "PAYMENT", "CASH", "DIRECTDEP", "DIRECTDEBIT", "REPEATPMT", "HOLD", "OTHER"} + +func (e trnType) Valid() bool { + return e >= TrnTypeCredit && e <= TrnTypeOther +} + +func (e trnType) String() string { + if e.Valid() { + return trnTypes[e-1] + } + return fmt.Sprintf("invalid trnType (%d)", e) +} + +func (e *trnType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range trnTypes { + if s == value { + *e = trnType(i + 1) + return nil + } + } + return errors.New("Invalid TrnType: \"" + in + "\"") +} + +func (e *trnType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *trnType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid TrnType") + } + enc.EncodeElement(trnTypes[*e-1], start) + return nil +} + +func NewTrnType(s string) (trnType, error) { + var e trnType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type imageType uint + +const ( + ImageTypeStatement imageType = 1 + iota + ImageTypeTransaction + ImageTypeTax +) + +var imageTypes = [...]string{"STATEMENT", "TRANSACTION", "TAX"} + +func (e imageType) Valid() bool { + return e >= ImageTypeStatement && e <= ImageTypeTax +} + +func (e imageType) String() string { + if e.Valid() { + return imageTypes[e-1] + } + return fmt.Sprintf("invalid imageType (%d)", e) +} + +func (e *imageType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range imageTypes { + if s == value { + *e = imageType(i + 1) + return nil + } + } + return errors.New("Invalid ImageType: \"" + in + "\"") +} + +func (e *imageType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *imageType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid ImageType") + } + enc.EncodeElement(imageTypes[*e-1], start) + return nil +} + +func NewImageType(s string) (imageType, error) { + var e imageType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type imageRefType uint + +const ( + ImageRefTypeOpaque imageRefType = 1 + iota + ImageRefTypeURL + ImageRefTypeFormURL +) + +var imageRefTypes = [...]string{"OPAQUE", "URL", "FORMURL"} + +func (e imageRefType) Valid() bool { + return e >= ImageRefTypeOpaque && e <= ImageRefTypeFormURL +} + +func (e imageRefType) String() string { + if e.Valid() { + return imageRefTypes[e-1] + } + return fmt.Sprintf("invalid imageRefType (%d)", e) +} + +func (e *imageRefType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range imageRefTypes { + if s == value { + *e = imageRefType(i + 1) + return nil + } + } + return errors.New("Invalid ImageRefType: \"" + in + "\"") +} + +func (e *imageRefType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *imageRefType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid ImageRefType") + } + enc.EncodeElement(imageRefTypes[*e-1], start) + return nil +} + +func NewImageRefType(s string) (imageRefType, error) { + var e imageRefType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type checkSup uint + +const ( + CheckSupFrontOnly checkSup = 1 + iota + CheckSupBackOnly + CheckSupFrontAndBack +) + +var checkSups = [...]string{"FRONTONLY", "BACKONLY", "FRONTANDBACK"} + +func (e checkSup) Valid() bool { + return e >= CheckSupFrontOnly && e <= CheckSupFrontAndBack +} + +func (e checkSup) String() string { + if e.Valid() { + return checkSups[e-1] + } + return fmt.Sprintf("invalid checkSup (%d)", e) +} + +func (e *checkSup) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range checkSups { + if s == value { + *e = checkSup(i + 1) + return nil + } + } + return errors.New("Invalid CheckSup: \"" + in + "\"") +} + +func (e *checkSup) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *checkSup) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid CheckSup") + } + enc.EncodeElement(checkSups[*e-1], start) + return nil +} + +func NewCheckSup(s string) (checkSup, error) { + var e checkSup + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type correctAction uint + +const ( + CorrectActionDelete correctAction = 1 + iota + CorrectActionReplace +) + +var correctActions = [...]string{"DELETE", "REPLACE"} + +func (e correctAction) Valid() bool { + return e >= CorrectActionDelete && e <= CorrectActionReplace +} + +func (e correctAction) String() string { + if e.Valid() { + return correctActions[e-1] + } + return fmt.Sprintf("invalid correctAction (%d)", e) +} + +func (e *correctAction) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range correctActions { + if s == value { + *e = correctAction(i + 1) + return nil + } + } + return errors.New("Invalid CorrectAction: \"" + in + "\"") +} + +func (e *correctAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *correctAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid CorrectAction") + } + enc.EncodeElement(correctActions[*e-1], start) + return nil +} + +func NewCorrectAction(s string) (correctAction, error) { + var e correctAction + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type balType uint + +const ( + BalTypeDollar balType = 1 + iota + BalTypePercent + BalTypeNumber +) + +var balTypes = [...]string{"DOLLAR", "PERCENT", "NUMBER"} + +func (e balType) Valid() bool { + return e >= BalTypeDollar && e <= BalTypeNumber +} + +func (e balType) String() string { + if e.Valid() { + return balTypes[e-1] + } + return fmt.Sprintf("invalid balType (%d)", e) +} + +func (e *balType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range balTypes { + if s == value { + *e = balType(i + 1) + return nil + } + } + return errors.New("Invalid BalType: \"" + in + "\"") +} + +func (e *balType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *balType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid BalType") + } + enc.EncodeElement(balTypes[*e-1], start) + return nil +} + +func NewBalType(s string) (balType, error) { + var e balType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type inv401kSource uint + +const ( + Inv401kSourcePreTax inv401kSource = 1 + iota + Inv401kSourceAfterTax + Inv401kSourceMatch + Inv401kSourceProfitSharing + Inv401kSourceRollover + Inv401kSourceOtherVest + Inv401kSourceOtherNonVest +) + +var inv401kSources = [...]string{"PRETAX", "AFTERTAX", "MATCH", "PROFITSHARING", "ROLLOVER", "OTHERVEST", "OTHERNONVEST"} + +func (e inv401kSource) Valid() bool { + return e >= Inv401kSourcePreTax && e <= Inv401kSourceOtherNonVest +} + +func (e inv401kSource) String() string { + if e.Valid() { + return inv401kSources[e-1] + } + return fmt.Sprintf("invalid inv401kSource (%d)", e) +} + +func (e *inv401kSource) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range inv401kSources { + if s == value { + *e = inv401kSource(i + 1) + return nil + } + } + return errors.New("Invalid Inv401kSource: \"" + in + "\"") +} + +func (e *inv401kSource) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *inv401kSource) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid Inv401kSource") + } + enc.EncodeElement(inv401kSources[*e-1], start) + return nil +} + +func NewInv401kSource(s string) (inv401kSource, error) { + var e inv401kSource + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type subAcctType uint + +const ( + SubAcctTypeCash subAcctType = 1 + iota + SubAcctTypeMargin + SubAcctTypeShort + SubAcctTypeOther +) + +var subAcctTypes = [...]string{"CASH", "MARGIN", "SHORT", "OTHER"} + +func (e subAcctType) Valid() bool { + return e >= SubAcctTypeCash && e <= SubAcctTypeOther +} + +func (e subAcctType) String() string { + if e.Valid() { + return subAcctTypes[e-1] + } + return fmt.Sprintf("invalid subAcctType (%d)", e) +} + +func (e *subAcctType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range subAcctTypes { + if s == value { + *e = subAcctType(i + 1) + return nil + } + } + return errors.New("Invalid SubAcctType: \"" + in + "\"") +} + +func (e *subAcctType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *subAcctType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid SubAcctType") + } + enc.EncodeElement(subAcctTypes[*e-1], start) + return nil +} + +func NewSubAcctType(s string) (subAcctType, error) { + var e subAcctType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type buyType uint + +const ( + BuyTypeBuy buyType = 1 + iota + BuyTypeBuyToCover +) + +var buyTypes = [...]string{"BUY", "BUYTOCOVER"} + +func (e buyType) Valid() bool { + return e >= BuyTypeBuy && e <= BuyTypeBuyToCover +} + +func (e buyType) String() string { + if e.Valid() { + return buyTypes[e-1] + } + return fmt.Sprintf("invalid buyType (%d)", e) +} + +func (e *buyType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range buyTypes { + if s == value { + *e = buyType(i + 1) + return nil + } + } + return errors.New("Invalid BuyType: \"" + in + "\"") +} + +func (e *buyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *buyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid BuyType") + } + enc.EncodeElement(buyTypes[*e-1], start) + return nil +} + +func NewBuyType(s string) (buyType, error) { + var e buyType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type optAction uint + +const ( + OptActionExercise optAction = 1 + iota + OptActionAssign + OptActionExpire +) + +var optActions = [...]string{"EXERCISE", "ASSIGN", "EXPIRE"} + +func (e optAction) Valid() bool { + return e >= OptActionExercise && e <= OptActionExpire +} + +func (e optAction) String() string { + if e.Valid() { + return optActions[e-1] + } + return fmt.Sprintf("invalid optAction (%d)", e) +} + +func (e *optAction) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range optActions { + if s == value { + *e = optAction(i + 1) + return nil + } + } + return errors.New("Invalid OptAction: \"" + in + "\"") +} + +func (e *optAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *optAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid OptAction") + } + enc.EncodeElement(optActions[*e-1], start) + return nil +} + +func NewOptAction(s string) (optAction, error) { + var e optAction + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type tferAction uint + +const ( + TferActionIn tferAction = 1 + iota + TferActionOut +) + +var tferActions = [...]string{"IN", "OUT"} + +func (e tferAction) Valid() bool { + return e >= TferActionIn && e <= TferActionOut +} + +func (e tferAction) String() string { + if e.Valid() { + return tferActions[e-1] + } + return fmt.Sprintf("invalid tferAction (%d)", e) +} + +func (e *tferAction) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range tferActions { + if s == value { + *e = tferAction(i + 1) + return nil + } + } + return errors.New("Invalid TferAction: \"" + in + "\"") +} + +func (e *tferAction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *tferAction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid TferAction") + } + enc.EncodeElement(tferActions[*e-1], start) + return nil +} + +func NewTferAction(s string) (tferAction, error) { + var e tferAction + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type posType uint + +const ( + PosTypeLong posType = 1 + iota + PosTypeShort +) + +var posTypes = [...]string{"LONG", "SHORT"} + +func (e posType) Valid() bool { + return e >= PosTypeLong && e <= PosTypeShort +} + +func (e posType) String() string { + if e.Valid() { + return posTypes[e-1] + } + return fmt.Sprintf("invalid posType (%d)", e) +} + +func (e *posType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range posTypes { + if s == value { + *e = posType(i + 1) + return nil + } + } + return errors.New("Invalid PosType: \"" + in + "\"") +} + +func (e *posType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *posType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid PosType") + } + enc.EncodeElement(posTypes[*e-1], start) + return nil +} + +func NewPosType(s string) (posType, error) { + var e posType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type secured uint + +const ( + SecuredNaked secured = 1 + iota + SecuredCovered +) + +var secureds = [...]string{"NAKED", "COVERED"} + +func (e secured) Valid() bool { + return e >= SecuredNaked && e <= SecuredCovered +} + +func (e secured) String() string { + if e.Valid() { + return secureds[e-1] + } + return fmt.Sprintf("invalid secured (%d)", e) +} + +func (e *secured) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range secureds { + if s == value { + *e = secured(i + 1) + return nil + } + } + return errors.New("Invalid Secured: \"" + in + "\"") +} + +func (e *secured) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *secured) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid Secured") + } + enc.EncodeElement(secureds[*e-1], start) + return nil +} + +func NewSecured(s string) (secured, error) { + var e secured + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type duration uint + +const ( + DurationDay duration = 1 + iota + DurationGoodTilCancel + DurationImmediate +) + +var durations = [...]string{"DAY", "GOODTILCANCEL", "IMMEDIATE"} + +func (e duration) Valid() bool { + return e >= DurationDay && e <= DurationImmediate +} + +func (e duration) String() string { + if e.Valid() { + return durations[e-1] + } + return fmt.Sprintf("invalid duration (%d)", e) +} + +func (e *duration) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range durations { + if s == value { + *e = duration(i + 1) + return nil + } + } + return errors.New("Invalid Duration: \"" + in + "\"") +} + +func (e *duration) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *duration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid Duration") + } + enc.EncodeElement(durations[*e-1], start) + return nil +} + +func NewDuration(s string) (duration, error) { + var e duration + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type restriction uint + +const ( + RestrictionAllOrNone restriction = 1 + iota + RestrictionMinUnits + RestrictionNone +) + +var restrictions = [...]string{"ALLORNONE", "MINUNITS", "NONE"} + +func (e restriction) Valid() bool { + return e >= RestrictionAllOrNone && e <= RestrictionNone +} + +func (e restriction) String() string { + if e.Valid() { + return restrictions[e-1] + } + return fmt.Sprintf("invalid restriction (%d)", e) +} + +func (e *restriction) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range restrictions { + if s == value { + *e = restriction(i + 1) + return nil + } + } + return errors.New("Invalid Restriction: \"" + in + "\"") +} + +func (e *restriction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *restriction) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid Restriction") + } + enc.EncodeElement(restrictions[*e-1], start) + return nil +} + +func NewRestriction(s string) (restriction, error) { + var e restriction + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type unitType uint + +const ( + UnitTypeShares unitType = 1 + iota + UnitTypeCurrency +) + +var unitTypes = [...]string{"SHARES", "CURRENCY"} + +func (e unitType) Valid() bool { + return e >= UnitTypeShares && e <= UnitTypeCurrency +} + +func (e unitType) String() string { + if e.Valid() { + return unitTypes[e-1] + } + return fmt.Sprintf("invalid unitType (%d)", e) +} + +func (e *unitType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range unitTypes { + if s == value { + *e = unitType(i + 1) + return nil + } + } + return errors.New("Invalid UnitType: \"" + in + "\"") +} + +func (e *unitType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *unitType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid UnitType") + } + enc.EncodeElement(unitTypes[*e-1], start) + return nil +} + +func NewUnitType(s string) (unitType, error) { + var e unitType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type optBuyType uint + +const ( + OptBuyTypeBuyToOpen optBuyType = 1 + iota + OptBuyTypeBuyToClose +) + +var optBuyTypes = [...]string{"BUYTOOPEN", "BUYTOCLOSE"} + +func (e optBuyType) Valid() bool { + return e >= OptBuyTypeBuyToOpen && e <= OptBuyTypeBuyToClose +} + +func (e optBuyType) String() string { + if e.Valid() { + return optBuyTypes[e-1] + } + return fmt.Sprintf("invalid optBuyType (%d)", e) +} + +func (e *optBuyType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range optBuyTypes { + if s == value { + *e = optBuyType(i + 1) + return nil + } + } + return errors.New("Invalid OptBuyType: \"" + in + "\"") +} + +func (e *optBuyType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *optBuyType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid OptBuyType") + } + enc.EncodeElement(optBuyTypes[*e-1], start) + return nil +} + +func NewOptBuyType(s string) (optBuyType, error) { + var e optBuyType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type sellType uint + +const ( + SellTypeSell sellType = 1 + iota + SellTypeSellShort +) + +var sellTypes = [...]string{"SELL", "SELLSHORT"} + +func (e sellType) Valid() bool { + return e >= SellTypeSell && e <= SellTypeSellShort +} + +func (e sellType) String() string { + if e.Valid() { + return sellTypes[e-1] + } + return fmt.Sprintf("invalid sellType (%d)", e) +} + +func (e *sellType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range sellTypes { + if s == value { + *e = sellType(i + 1) + return nil + } + } + return errors.New("Invalid SellType: \"" + in + "\"") +} + +func (e *sellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *sellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid SellType") + } + enc.EncodeElement(sellTypes[*e-1], start) + return nil +} + +func NewSellType(s string) (sellType, error) { + var e sellType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type loanPmtFreq uint + +const ( + LoanPmtFreqWeekly loanPmtFreq = 1 + iota + LoanPmtFreqBiweekly + LoanPmtFreqTwiceMonthly + LoanPmtFreqMonthly + LoanPmtFreqFourWeeks + LoanPmtFreqBiMonthly + LoanPmtFreqQuarterly + LoanPmtFreqSemiannually + LoanPmtFreqAnnually + LoanPmtFreqOther +) + +var loanPmtFreqs = [...]string{"WEEKLY", "BIWEEKLY", "TWICEMONTHLY", "MONTHLY", "FOURWEEKS", "BIMONTHLY", "QUARTERLY", "SEMIANNUALLY", "ANNUALLY", "OTHER"} + +func (e loanPmtFreq) Valid() bool { + return e >= LoanPmtFreqWeekly && e <= LoanPmtFreqOther +} + +func (e loanPmtFreq) String() string { + if e.Valid() { + return loanPmtFreqs[e-1] + } + return fmt.Sprintf("invalid loanPmtFreq (%d)", e) +} + +func (e *loanPmtFreq) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range loanPmtFreqs { + if s == value { + *e = loanPmtFreq(i + 1) + return nil + } + } + return errors.New("Invalid LoanPmtFreq: \"" + in + "\"") +} + +func (e *loanPmtFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *loanPmtFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid LoanPmtFreq") + } + enc.EncodeElement(loanPmtFreqs[*e-1], start) + return nil +} + +func NewLoanPmtFreq(s string) (loanPmtFreq, error) { + var e loanPmtFreq + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type incomeType uint + +const ( + IncomeTypeCGLong incomeType = 1 + iota + IncomeTypeCGShort + IncomeTypeDiv + IncomeTypeInterest + IncomeTypeMisc +) + +var incomeTypes = [...]string{"CGLONG", "CGSHORT", "DIV", "INTEREST", "MISC"} + +func (e incomeType) Valid() bool { + return e >= IncomeTypeCGLong && e <= IncomeTypeMisc +} + +func (e incomeType) String() string { + if e.Valid() { + return incomeTypes[e-1] + } + return fmt.Sprintf("invalid incomeType (%d)", e) +} + +func (e *incomeType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range incomeTypes { + if s == value { + *e = incomeType(i + 1) + return nil + } + } + return errors.New("Invalid IncomeType: \"" + in + "\"") +} + +func (e *incomeType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *incomeType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid IncomeType") + } + enc.EncodeElement(incomeTypes[*e-1], start) + return nil +} + +func NewIncomeType(s string) (incomeType, error) { + var e incomeType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type sellReason uint + +const ( + SellReasonCall sellReason = 1 + iota + SellReasonSell + SellReasonMaturity +) + +var sellReasons = [...]string{"CALL", "SELL", "MATURITY"} + +func (e sellReason) Valid() bool { + return e >= SellReasonCall && e <= SellReasonMaturity +} + +func (e sellReason) String() string { + if e.Valid() { + return sellReasons[e-1] + } + return fmt.Sprintf("invalid sellReason (%d)", e) +} + +func (e *sellReason) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range sellReasons { + if s == value { + *e = sellReason(i + 1) + return nil + } + } + return errors.New("Invalid SellReason: \"" + in + "\"") +} + +func (e *sellReason) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *sellReason) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid SellReason") + } + enc.EncodeElement(sellReasons[*e-1], start) + return nil +} + +func NewSellReason(s string) (sellReason, error) { + var e sellReason + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type optSellType uint + +const ( + OptSellTypeSellToClose optSellType = 1 + iota + OptSellTypeSellToOpen +) + +var optSellTypes = [...]string{"SELLTOCLOSE", "SELLTOOPEN"} + +func (e optSellType) Valid() bool { + return e >= OptSellTypeSellToClose && e <= OptSellTypeSellToOpen +} + +func (e optSellType) String() string { + if e.Valid() { + return optSellTypes[e-1] + } + return fmt.Sprintf("invalid optSellType (%d)", e) +} + +func (e *optSellType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range optSellTypes { + if s == value { + *e = optSellType(i + 1) + return nil + } + } + return errors.New("Invalid OptSellType: \"" + in + "\"") +} + +func (e *optSellType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *optSellType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid OptSellType") + } + enc.EncodeElement(optSellTypes[*e-1], start) + return nil +} + +func NewOptSellType(s string) (optSellType, error) { + var e optSellType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type relType uint + +const ( + RelTypeSpread relType = 1 + iota + RelTypeStraddle + RelTypeNone + RelTypeOther +) + +var relTypes = [...]string{"SPREAD", "STRADDLE", "NONE", "OTHER"} + +func (e relType) Valid() bool { + return e >= RelTypeSpread && e <= RelTypeOther +} + +func (e relType) String() string { + if e.Valid() { + return relTypes[e-1] + } + return fmt.Sprintf("invalid relType (%d)", e) +} + +func (e *relType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range relTypes { + if s == value { + *e = relType(i + 1) + return nil + } + } + return errors.New("Invalid RelType: \"" + in + "\"") +} + +func (e *relType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *relType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid RelType") + } + enc.EncodeElement(relTypes[*e-1], start) + return nil +} + +func NewRelType(s string) (relType, error) { + var e relType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type charType uint + +const ( + CharTypeAlphaOnly charType = 1 + iota + CharTypeNumericOnly + CharTypeAlphaOrNumeric + CharTypeAlphaAndNumeric +) + +var charTypes = [...]string{"ALPHAONLY", "NUMERICONLY", "ALPHAORNUMERIC", "ALPHAANDNUMERIC"} + +func (e charType) Valid() bool { + return e >= CharTypeAlphaOnly && e <= CharTypeAlphaAndNumeric +} + +func (e charType) String() string { + if e.Valid() { + return charTypes[e-1] + } + return fmt.Sprintf("invalid charType (%d)", e) +} + +func (e *charType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range charTypes { + if s == value { + *e = charType(i + 1) + return nil + } + } + return errors.New("Invalid CharType: \"" + in + "\"") +} + +func (e *charType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *charType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid CharType") + } + enc.EncodeElement(charTypes[*e-1], start) + return nil +} + +func NewCharType(s string) (charType, error) { + var e charType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type syncMode uint + +const ( + SyncModeFull syncMode = 1 + iota + SyncModeLite +) + +var syncModes = [...]string{"FULL", "LITE"} + +func (e syncMode) Valid() bool { + return e >= SyncModeFull && e <= SyncModeLite +} + +func (e syncMode) String() string { + if e.Valid() { + return syncModes[e-1] + } + return fmt.Sprintf("invalid syncMode (%d)", e) +} + +func (e *syncMode) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range syncModes { + if s == value { + *e = syncMode(i + 1) + return nil + } + } + return errors.New("Invalid SyncMode: \"" + in + "\"") +} + +func (e *syncMode) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *syncMode) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid SyncMode") + } + enc.EncodeElement(syncModes[*e-1], start) + return nil +} + +func NewSyncMode(s string) (syncMode, error) { + var e syncMode + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type debtType uint + +const ( + DebtTypeCoupon debtType = 1 + iota + DebtTypeZero +) + +var debtTypes = [...]string{"COUPON", "ZERO"} + +func (e debtType) Valid() bool { + return e >= DebtTypeCoupon && e <= DebtTypeZero +} + +func (e debtType) String() string { + if e.Valid() { + return debtTypes[e-1] + } + return fmt.Sprintf("invalid debtType (%d)", e) +} + +func (e *debtType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range debtTypes { + if s == value { + *e = debtType(i + 1) + return nil + } + } + return errors.New("Invalid DebtType: \"" + in + "\"") +} + +func (e *debtType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *debtType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid DebtType") + } + enc.EncodeElement(debtTypes[*e-1], start) + return nil +} + +func NewDebtType(s string) (debtType, error) { + var e debtType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type debtClass uint + +const ( + DebtClassTreasury debtClass = 1 + iota + DebtClassMunicipal + DebtClassCorporate + DebtClassOther +) + +var debtClasss = [...]string{"TREASURY", "MUNICIPAL", "CORPORATE", "OTHER"} + +func (e debtClass) Valid() bool { + return e >= DebtClassTreasury && e <= DebtClassOther +} + +func (e debtClass) String() string { + if e.Valid() { + return debtClasss[e-1] + } + return fmt.Sprintf("invalid debtClass (%d)", e) +} + +func (e *debtClass) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range debtClasss { + if s == value { + *e = debtClass(i + 1) + return nil + } + } + return errors.New("Invalid DebtClass: \"" + in + "\"") +} + +func (e *debtClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *debtClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid DebtClass") + } + enc.EncodeElement(debtClasss[*e-1], start) + return nil +} + +func NewDebtClass(s string) (debtClass, error) { + var e debtClass + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type couponFreq uint + +const ( + CouponFreqMonthly couponFreq = 1 + iota + CouponFreqQuarterly + CouponFreqSemiannual + CouponFreqAnnual + CouponFreqOther +) + +var couponFreqs = [...]string{"MONTHLY", "QUARTERLY", "SEMIANNUAL", "ANNUAL", "OTHER"} + +func (e couponFreq) Valid() bool { + return e >= CouponFreqMonthly && e <= CouponFreqOther +} + +func (e couponFreq) String() string { + if e.Valid() { + return couponFreqs[e-1] + } + return fmt.Sprintf("invalid couponFreq (%d)", e) +} + +func (e *couponFreq) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range couponFreqs { + if s == value { + *e = couponFreq(i + 1) + return nil + } + } + return errors.New("Invalid CouponFreq: \"" + in + "\"") +} + +func (e *couponFreq) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *couponFreq) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid CouponFreq") + } + enc.EncodeElement(couponFreqs[*e-1], start) + return nil +} + +func NewCouponFreq(s string) (couponFreq, error) { + var e couponFreq + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type callType uint + +const ( + CallTypeCall callType = 1 + iota + CallTypePut + CallTypePrefund + CallTypeMaturity +) + +var callTypes = [...]string{"CALL", "PUT", "PREFUND", "MATURITY"} + +func (e callType) Valid() bool { + return e >= CallTypeCall && e <= CallTypeMaturity +} + +func (e callType) String() string { + if e.Valid() { + return callTypes[e-1] + } + return fmt.Sprintf("invalid callType (%d)", e) +} + +func (e *callType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range callTypes { + if s == value { + *e = callType(i + 1) + return nil + } + } + return errors.New("Invalid CallType: \"" + in + "\"") +} + +func (e *callType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *callType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid CallType") + } + enc.EncodeElement(callTypes[*e-1], start) + return nil +} + +func NewCallType(s string) (callType, error) { + var e callType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type assetClass uint + +const ( + AssetClassDomesticBond assetClass = 1 + iota + AssetClassIntlBond + AssetClassLargeStock + AssetClassSmallStock + AssetClassIntlStock + AssetClassMoneyMrkt + AssetClassOther +) + +var assetClasss = [...]string{"DOMESTICBOND", "INTLBOND", "LARGESTOCK", "SMALLSTOCK", "INTLSTOCK", "MONEYMRKT", "OTHER"} + +func (e assetClass) Valid() bool { + return e >= AssetClassDomesticBond && e <= AssetClassOther +} + +func (e assetClass) String() string { + if e.Valid() { + return assetClasss[e-1] + } + return fmt.Sprintf("invalid assetClass (%d)", e) +} + +func (e *assetClass) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range assetClasss { + if s == value { + *e = assetClass(i + 1) + return nil + } + } + return errors.New("Invalid AssetClass: \"" + in + "\"") +} + +func (e *assetClass) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *assetClass) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid AssetClass") + } + enc.EncodeElement(assetClasss[*e-1], start) + return nil +} + +func NewAssetClass(s string) (assetClass, error) { + var e assetClass + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type mfType uint + +const ( + MfTypeOpen mfType = 1 + iota + MfTypeEnd + MfTypeCloseEnd + MfTypeOther +) + +var mfTypes = [...]string{"OPEN", "END", "CLOSEEND", "OTHER"} + +func (e mfType) Valid() bool { + return e >= MfTypeOpen && e <= MfTypeOther +} + +func (e mfType) String() string { + if e.Valid() { + return mfTypes[e-1] + } + return fmt.Sprintf("invalid mfType (%d)", e) +} + +func (e *mfType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range mfTypes { + if s == value { + *e = mfType(i + 1) + return nil + } + } + return errors.New("Invalid MfType: \"" + in + "\"") +} + +func (e *mfType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *mfType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid MfType") + } + enc.EncodeElement(mfTypes[*e-1], start) + return nil +} + +func NewMfType(s string) (mfType, error) { + var e mfType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type optType uint + +const ( + OptTypePut optType = 1 + iota + OptTypeCall +) + +var optTypes = [...]string{"PUT", "CALL"} + +func (e optType) Valid() bool { + return e >= OptTypePut && e <= OptTypeCall +} + +func (e optType) String() string { + if e.Valid() { + return optTypes[e-1] + } + return fmt.Sprintf("invalid optType (%d)", e) +} + +func (e *optType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range optTypes { + if s == value { + *e = optType(i + 1) + return nil + } + } + return errors.New("Invalid OptType: \"" + in + "\"") +} + +func (e *optType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *optType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid OptType") + } + enc.EncodeElement(optTypes[*e-1], start) + return nil +} + +func NewOptType(s string) (optType, error) { + var e optType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type stockType uint + +const ( + StockTypeCommon stockType = 1 + iota + StockTypePreferred + StockTypeConvertible + StockTypeOther +) + +var stockTypes = [...]string{"COMMON", "PREFERRED", "CONVERTIBLE", "OTHER"} + +func (e stockType) Valid() bool { + return e >= StockTypeCommon && e <= StockTypeOther +} + +func (e stockType) String() string { + if e.Valid() { + return stockTypes[e-1] + } + return fmt.Sprintf("invalid stockType (%d)", e) +} + +func (e *stockType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range stockTypes { + if s == value { + *e = stockType(i + 1) + return nil + } + } + return errors.New("Invalid StockType: \"" + in + "\"") +} + +func (e *stockType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *stockType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid StockType") + } + enc.EncodeElement(stockTypes[*e-1], start) + return nil +} + +func NewStockType(s string) (stockType, error) { + var e stockType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type ofxSec uint + +const ( + OfxSecNone ofxSec = 1 + iota + OfxSecType1 +) + +var ofxSecs = [...]string{"NONE", "TYPE 1"} + +func (e ofxSec) Valid() bool { + return e >= OfxSecNone && e <= OfxSecType1 +} + +func (e ofxSec) String() string { + if e.Valid() { + return ofxSecs[e-1] + } + return fmt.Sprintf("invalid ofxSec (%d)", e) +} + +func (e *ofxSec) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range ofxSecs { + if s == value { + *e = ofxSec(i + 1) + return nil + } + } + return errors.New("Invalid OfxSec: \"" + in + "\"") +} + +func (e *ofxSec) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *ofxSec) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid OfxSec") + } + enc.EncodeElement(ofxSecs[*e-1], start) + return nil +} + +func NewOfxSec(s string) (ofxSec, error) { + var e ofxSec + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type holderType uint + +const ( + HolderTypeIndividual holderType = 1 + iota + HolderTypeJoint + HolderTypeCustodial + HolderTypeTrust + HolderTypeOther +) + +var holderTypes = [...]string{"INDIVIDUAL", "JOINT", "CUSTODIAL", "TRUST", "OTHER"} + +func (e holderType) Valid() bool { + return e >= HolderTypeIndividual && e <= HolderTypeOther +} + +func (e holderType) String() string { + if e.Valid() { + return holderTypes[e-1] + } + return fmt.Sprintf("invalid holderType (%d)", e) +} + +func (e *holderType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range holderTypes { + if s == value { + *e = holderType(i + 1) + return nil + } + } + return errors.New("Invalid HolderType: \"" + in + "\"") +} + +func (e *holderType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *holderType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid HolderType") + } + enc.EncodeElement(holderTypes[*e-1], start) + return nil +} + +func NewHolderType(s string) (holderType, error) { + var e holderType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type acctClassification uint + +const ( + AcctClassificationPersonal acctClassification = 1 + iota + AcctClassificationBusiness + AcctClassificationCorporate + AcctClassificationOther +) + +var acctClassifications = [...]string{"PERSONAL", "BUSINESS", "CORPORATE", "OTHER"} + +func (e acctClassification) Valid() bool { + return e >= AcctClassificationPersonal && e <= AcctClassificationOther +} + +func (e acctClassification) String() string { + if e.Valid() { + return acctClassifications[e-1] + } + return fmt.Sprintf("invalid acctClassification (%d)", e) +} + +func (e *acctClassification) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range acctClassifications { + if s == value { + *e = acctClassification(i + 1) + return nil + } + } + return errors.New("Invalid AcctClassification: \"" + in + "\"") +} + +func (e *acctClassification) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *acctClassification) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid AcctClassification") + } + enc.EncodeElement(acctClassifications[*e-1], start) + return nil +} + +func NewAcctClassification(s string) (acctClassification, error) { + var e acctClassification + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type svcStatus uint + +const ( + SvcStatusAvail svcStatus = 1 + iota + SvcStatusPend + SvcStatusActive +) + +var svcStatuss = [...]string{"AVAIL", "PEND", "ACTIVE"} + +func (e svcStatus) Valid() bool { + return e >= SvcStatusAvail && e <= SvcStatusActive +} + +func (e svcStatus) String() string { + if e.Valid() { + return svcStatuss[e-1] + } + return fmt.Sprintf("invalid svcStatus (%d)", e) +} + +func (e *svcStatus) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range svcStatuss { + if s == value { + *e = svcStatus(i + 1) + return nil + } + } + return errors.New("Invalid SvcStatus: \"" + in + "\"") +} + +func (e *svcStatus) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *svcStatus) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid SvcStatus") + } + enc.EncodeElement(svcStatuss[*e-1], start) + return nil +} + +func NewSvcStatus(s string) (svcStatus, error) { + var e svcStatus + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} + +type usProductType uint + +const ( + UsProductType401K usProductType = 1 + iota + UsProductType403B + UsProductTypeIRA + UsProductTypeKEOGH + UsProductTypeOther + UsProductTypeSARSEP + UsProductTypeSimple + UsProductTypeNormal + UsProductTypeTDA + UsProductTypeTrust + UsProductTypeUGMA +) + +var usProductTypes = [...]string{"401K", "403B", "IRA", "KEOGH", "OTHER", "SARSEP", "SIMPLE", "NORMAL", "TDA", "TRUST", "UGMA"} + +func (e usProductType) Valid() bool { + return e >= UsProductType401K && e <= UsProductTypeUGMA +} + +func (e usProductType) String() string { + if e.Valid() { + return usProductTypes[e-1] + } + return fmt.Sprintf("invalid usProductType (%d)", e) +} + +func (e *usProductType) FromString(in string) error { + value := strings.TrimSpace(in) + + for i, s := range usProductTypes { + if s == value { + *e = usProductType(i + 1) + return nil + } + } + return errors.New("Invalid UsProductType: \"" + in + "\"") +} + +func (e *usProductType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { + var value string + err := d.DecodeElement(&value, &start) + if err != nil { + return err + } + + return e.FromString(value) +} + +func (e *usProductType) MarshalXML(enc *xml.Encoder, start xml.StartElement) error { + if *e == 0 { + return nil + } else if !e.Valid() { + return errors.New("Invalid UsProductType") + } + enc.EncodeElement(usProductTypes[*e-1], start) + return nil +} + +func NewUsProductType(s string) (usProductType, error) { + var e usProductType + err := e.FromString(s) + if err != nil { + return 0, err + } + return e, nil +} diff --git a/creditcard_test.go b/creditcard_test.go index 4800968..4bef469 100644 --- a/creditcard_test.go +++ b/creditcard_test.go @@ -105,21 +105,21 @@ NEWFILEUID:NONE DtEnd: *ofxgo.NewDate(2017, 3, 31, 15, 46, 48, 688000000, EDT), Transactions: []ofxgo.Transaction{ { - TrnType: "DEBIT", + TrnType: ofxgo.TrnTypeDebit, DtPosted: *ofxgo.NewDateGMT(2017, 2, 9, 12, 0, 0, 0), TrnAmt: trnamt1, FiTId: "2017020924435657040207171600195", Name: "SLICE OF NY", }, { - TrnType: "CREDIT", + TrnType: ofxgo.TrnTypeCredit, DtPosted: *ofxgo.NewDateGMT(2016, 12, 28, 12, 0, 0, 0), TrnAmt: trnamt2, FiTId: "2016122823633637200000258482730", Name: "Payment Thank You Electro", }, { - TrnType: "DEBIT", + TrnType: ofxgo.TrnTypeDebit, DtPosted: *ofxgo.NewDateGMT(2017, 3, 27, 12, 0, 0, 0), TrnAmt: trnamt3, FiTId: "2017032724445727085300442885680", diff --git a/generate_constants.py b/generate_constants.py new file mode 100755 index 0000000..bec0c01 --- /dev/null +++ b/generate_constants.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python + +enums = { + # Bank/general + "AcctType": ["Checking", "Savings", "MoneyMrkt", "CreditLine", "CD"], + "TrnType": ["Credit", "Debit", "Int", "Div", "Fee", "SrvChg", "Dep", "ATM", "POS", "Xfer", "Check", "Payment", "Cash", "DirectDep", "DirectDebit", "RepeatPmt", "Hold", "Other"], + "ImageType": ["Statement", "Transaction", "Tax"], + "ImageRefType": ["Opaque", "URL", "FormURL"], + "CheckSup": ["FrontOnly", "BackOnly", "FrontAndBack"], + "CorrectAction": ["Delete", "Replace"], + "BalType": ["Dollar", "Percent", "Number"], + + # InvStmt + "Inv401kSource": ["PreTax", "AfterTax", "Match", "ProfitSharing", "Rollover", "OtherVest", "OtherNonVest"], + "SubAcctType": ["Cash", "Margin", "Short", "Other"], # used in fields named: SubAcctSec, HeldInAcct, SubAcctFund + "BuyType": ["Buy", "BuyToCover"], + "OptAction": ["Exercise", "Assign", "Expire"], + "TferAction": ["In", "Out"], + "PosType": ["Long", "Short"], + "Secured": ["Naked", "Covered"], + "Duration": ["Day", "GoodTilCancel", "Immediate"], + "Restriction": ["AllOrNone", "MinUnits", "None"], + "UnitType": ["Shares", "Currency"], + "OptBuyType": ["BuyToOpen", "BuyToClose"], + "SellType": ["Sell", "SellShort"], + "LoanPmtFreq": ["Weekly", "Biweekly", "TwiceMonthly", "Monthly", "FourWeeks", "BiMonthly", "Quarterly", "Semiannually", "Annually", "Other"], + "IncomeType": ["CGLong", "CGShort", "Div", "Interest", "Misc"], + "SellReason": ["Call", "Sell", "Maturity"], + "OptSellType": ["SellToClose", "SellToOpen"], + "RelType": ["Spread", "Straddle", "None", "Other"], + + # Prof + "CharType": ["AlphaOnly", "NumericOnly", "AlphaOrNumeric", "AlphaAndNumeric"], + "SyncMode": ["Full", "Lite"], + + # SecList + "DebtType": ["Coupon", "Zero"], + "DebtClass": ["Treasury", "Municipal", "Corporate", "Other"], + "CouponFreq": ["Monthly", "Quarterly", "Semiannual", "Annual", "Other"], + "CallType": ["Call", "Put", "Prefund", "Maturity"], + "AssetClass": ["DomesticBond", "IntlBond", "LargeStock", "SmallStock", "IntlStock", "MoneyMrkt", "Other"], + "MfType": ["Open", "End", "CloseEnd", "Other"], + "OptType": ["Put", "Call"], + "StockType": ["Common", "Preferred", "Convertible", "Other"], + "OfxSec": ["None", "Type 1"], + + # Signup + "HolderType": ["Individual", "Joint", "Custodial", "Trust", "Other"], + "AcctClassification": ["Personal", "Business", "Corporate", "Other"], + "SvcStatus": ["Avail", "Pend", "Active"], + "UsProductType": ["401K", "403B", "IRA", "KEOGH", "Other", "SARSEP", "Simple", "Normal", "TDA", "Trust", "UGMA"], +} + +header = """package ofxgo + +/* + * Do not edit this file by hand. It is auto-generated by calling `go generate`. + * To make changes, edit generate_constants.py, re-run `go generate`, and check + * in the result. + */ + +import ( + "errors" + "fmt" + "github.com/aclindsa/go/src/encoding/xml" + "strings" +) +""" + +template = """ +type {enumLower} uint + +const ( +{constNames}) + +var {enumLower}s = [...]string{{"{upperValueString}"}} + +func (e {enumLower}) Valid() bool {{ + return e >= {firstValue} && e <= {lastValue} +}} + +func (e {enumLower}) String() string {{ + if e.Valid() {{ + return {enumLower}s[e-1] + }} + return fmt.Sprintf("invalid {enumLower} (%d)", e) +}} + +func (e *{enumLower}) FromString(in string) error {{ + value := strings.TrimSpace(in) + + for i, s := range {enumLower}s {{ + if s == value {{ + *e = {enumLower}(i + 1) + return nil + }} + }} + return errors.New("Invalid {enum}: \\\"" + in + "\\\"") +}} + +func (e *{enumLower}) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {{ + var value string + err := d.DecodeElement(&value, &start) + if err != nil {{ + return err + }} + + return e.FromString(value) +}} + +func (e *{enumLower}) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {{ + if *e == 0 {{ + return nil + }} else if !e.Valid() {{ + return errors.New("Invalid {enum}") + }} + enc.EncodeElement({enumLower}s[*e-1], start) + return nil +}} + +func New{enum}(s string) ({enumLower}, error) {{ + var e {enumLower} + err := e.FromString(s) + if err != nil {{ + return 0, err + }} + return e, nil +}} +""" + +with open("constants.go", 'w') as f: + f.write(header) + + for enum in enums: + enumLower = enum[:1].lower() + enum[1:].replace(" ", "") + firstValue = enum+enums[enum][0].replace(" ", "") + lastValue = enum+enums[enum][-1].replace(" ", "") + + constNames = "\t{firstValue} {enumLower} = 1 + iota\n".format( + enum=enum, + firstValue=firstValue, + enumLower=enumLower) + for value in enums[enum][1:]: + constNames += "\t{enum}{value}\n".format( + enum=enum, + value=value.replace(" ", "")) + + upperValueString = "\", \"".join([s.upper() for s in enums[enum]]) + + f.write(template.format(enum=enum, + enumLower=enumLower, + firstValue=firstValue, + lastValue=lastValue, + constNames=constNames, + upperValueString=upperValueString)) diff --git a/invstmt.go b/invstmt.go index 3543dc7..848ea6b 100644 --- a/invstmt.go +++ b/invstmt.go @@ -48,57 +48,57 @@ type InvTran struct { } type InvBuy struct { - XMLName xml.Name `xml:"INVBUY"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security - Markup Amount `xml:"MARKUP,omitempty"` // Portion of UNITPRICE that is attributed to the dealer markup - Commission Amount `xml:"COMMISSION,omitempty"` - Taxes Amount `xml:"TAXES,omitempty"` - Fees Amount `xml:"FEES,omitempty"` - Load Amount `xml:"LOAD,omitempty"` - Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + XMLName xml.Name `xml:"INVBUY"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security + Markup Amount `xml:"MARKUP,omitempty"` // Portion of UNITPRICE that is attributed to the dealer markup + Commission Amount `xml:"COMMISSION,omitempty"` + Taxes Amount `xml:"TAXES,omitempty"` + Fees Amount `xml:"FEES,omitempty"` + Load Amount `xml:"LOAD,omitempty"` + Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - // The next three elements must either all be provided, or none of htem + // The next three elements must either all be provided, or none of them LoanId String `xml:"LOANID,omitempty"` // For 401(k) accounts only. Indicates that the transaction was due to a loan or a loan repayment, and which loan it was LoanPrincipal Amount `xml:"LOANPRINCIPAL,omitempty"` // For 401(k) accounts only. Indicates how much of the loan repayment was principal LoanInterest Amount `xml:"LOANINTEREST,omitempty"` // For 401(k) accounts only. Indicates how much of the loan repayment was interest - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST - DtPayroll *Date `xml:"DTPAYROLL,omitempty"` // For 401(k)accounts, date the funds for this transaction was obtained via payroll deduction - PriorYearContrib Boolean `xml:"PRIORYEARCONTRIB,omitempty"` // For 401(k) accounts, indicates that this Buy was made with a prior year contribution + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + DtPayroll *Date `xml:"DTPAYROLL,omitempty"` // For 401(k)accounts, date the funds for this transaction was obtained via payroll deduction + PriorYearContrib Boolean `xml:"PRIORYEARCONTRIB,omitempty"` // For 401(k) accounts, indicates that this Buy was made with a prior year contribution } type InvSell struct { - XMLName xml.Name `xml:"INVSELL"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security - Markdown Amount `xml:"MARKDOWN,omitempty"` // Portion of UNITPRICE that is attributed to the dealer markdown - Commission Amount `xml:"COMMISSION,omitempty"` - Taxes Amount `xml:"TAXES,omitempty"` - Fees Amount `xml:"FEES,omitempty"` - Load Amount `xml:"LOAD,omitempty"` - Witholding Amount `xml:"WITHHOLDING,omitempty"` // Federal tax witholdings - TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction - Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis - Gain Amount `xml:"GAIN,omitempty"` // Total gain - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + XMLName xml.Name `xml:"INVSELL"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security + Markdown Amount `xml:"MARKDOWN,omitempty"` // Portion of UNITPRICE that is attributed to the dealer markdown + Commission Amount `xml:"COMMISSION,omitempty"` + Taxes Amount `xml:"TAXES,omitempty"` + Fees Amount `xml:"FEES,omitempty"` + Load Amount `xml:"LOAD,omitempty"` + Witholding Amount `xml:"WITHHOLDING,omitempty"` // Federal tax witholdings + TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction + Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis + Gain Amount `xml:"GAIN,omitempty"` // Total gain + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER LoanId String `xml:"LOANID,omitempty"` // For 401(k) accounts only. Indicates that the transaction was due to a loan or a loan repayment, and which loan it was StateWitholding Amount `xml:"STATEWITHHOLDING,omitempty"` // State tax witholdings Penalty Amount `xml:"PENALTY,omitempty"` // Amount witheld due to penalty - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } type BuyDebt struct { @@ -114,7 +114,7 @@ func (t BuyDebt) TransactionType() string { type BuyMF struct { XMLName xml.Name `xml:"BUYMF"` InvBuy InvBuy `xml:"INVBUY"` - BuyType String `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER (BUYTOCOVER used to close short sales.) + BuyType buyType `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER (BUYTOCOVER used to close short sales.) RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges } @@ -123,10 +123,10 @@ func (t BuyMF) TransactionType() string { } type BuyOpt struct { - XMLName xml.Name `xml:"BUYOPT"` - InvBuy InvBuy `xml:"INVBUY"` - OptBuyType String `xml:"OPTBUYTYPE"` // type of purchase: BUYTOOPEN, BUYTOCLOSE (The BUYTOOPEN buy type is like “ordinary” buying of option and works like stocks.) - ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract + XMLName xml.Name `xml:"BUYOPT"` + InvBuy InvBuy `xml:"INVBUY"` + OptBuyType optBuyType `xml:"OPTBUYTYPE"` // type of purchase: BUYTOOPEN, BUYTOCLOSE (The BUYTOOPEN buy type is like “ordinary” buying of option and works like stocks.) + ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract } func (t BuyOpt) TransactionType() string { @@ -145,7 +145,7 @@ func (t BuyOther) TransactionType() string { type BuyStock struct { XMLName xml.Name `xml:"BUYSTOCK"` InvBuy InvBuy `xml:"INVBUY"` - BuyType String `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER (BUYTOCOVER used to close short sales.) + BuyType buyType `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER (BUYTOCOVER used to close short sales.) } func (t BuyStock) TransactionType() string { @@ -153,15 +153,15 @@ func (t BuyStock) TransactionType() string { } type ClosureOpt struct { - XMLName xml.Name `xml:"CLOSUREOPT"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - OptAction String `xml:"OPTACTION"` // One of EXERCISE, ASSIGN, EXPIRE. The EXERCISE action is used to close out an option that is exercised. The ASSIGN action is used when an option writer is assigned. The EXPIRE action is used when the option’s expired date is reached - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges - Gain Amount `xml:"GAIN,omitempty"` // Total gain + XMLName xml.Name `xml:"CLOSUREOPT"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + OptAction optAction `xml:"OPTACTION"` // One of EXERCISE, ASSIGN, EXPIRE. The EXERCISE action is used to close out an option that is exercised. The ASSIGN action is used when an option writer is assigned. The EXPIRE action is used when the option’s expired date is reached + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges + Gain Amount `xml:"GAIN,omitempty"` // Total gain } func (t ClosureOpt) TransactionType() string { @@ -170,18 +170,18 @@ func (t ClosureOpt) TransactionType() string { // Investment income is realized as cash into the investment account type Income struct { - XMLName xml.Name `xml:"INCOME"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - IncomeType String `xml:"INCOMETYPE"` // Type of investment income: CGLONG (capital gains-long term), CGSHORT (capital gains-short term), DIV (dividend), INTEREST, MISC - Total Amount `xml:"TOTAL"` - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction - Witholding Amount `xml:"WITHHOLDING,omitempty"` // Federal tax witholdings - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"INCOME"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + IncomeType incomeType `xml:"INCOMETYPE"` // Type of investment income: CGLONG (capital gains-long term), CGSHORT (capital gains-short term), DIV (dividend), INTEREST, MISC + Total Amount `xml:"TOTAL"` + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction + Witholding Amount `xml:"WITHHOLDING,omitempty"` // Federal tax witholdings + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t Income) TransactionType() string { @@ -190,15 +190,15 @@ func (t Income) TransactionType() string { // Expense associated with an investment type InvExpense struct { - XMLName xml.Name `xml:"INVEXPENSE"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - Total Amount `xml:"TOTAL"` - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"INVEXPENSE"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + Total Amount `xml:"TOTAL"` + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t InvExpense) TransactionType() string { @@ -207,11 +207,11 @@ func (t InvExpense) TransactionType() string { // Journaling cash holdings between sub-accounts within the same investment account. type JrnlFund struct { - XMLName xml.Name `xml:"JRNLFUND"` - InvTran InvTran `xml:"INVTRAN"` - Total Amount `xml:"TOTAL"` - SubAcctFrom String `xml:"SUBACCTFROM"` // Sub-account cash is being transferred from: CASH, MARGIN, SHORT, OTHER - SubAcctTo String `xml:"SUBACCTTO"` // Sub-account cash is being transferred to: CASH, MARGIN, SHORT, OTHER + XMLName xml.Name `xml:"JRNLFUND"` + InvTran InvTran `xml:"INVTRAN"` + Total Amount `xml:"TOTAL"` + SubAcctFrom subAcctType `xml:"SUBACCTFROM"` // Sub-account cash is being transferred from: CASH, MARGIN, SHORT, OTHER + SubAcctTo subAcctType `xml:"SUBACCTTO"` // Sub-account cash is being transferred to: CASH, MARGIN, SHORT, OTHER } func (t JrnlFund) TransactionType() string { @@ -220,12 +220,12 @@ func (t JrnlFund) TransactionType() string { // Journaling security holdings between sub-accounts within the same investment account. type JrnlSec struct { - XMLName xml.Name `xml:"JRNLSEC"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - SubAcctFrom String `xml:"SUBACCTFROM"` // Sub-account cash is being transferred from: CASH, MARGIN, SHORT, OTHER - SubAcctTo String `xml:"SUBACCTTO"` // Sub-account cash is being transferred to: CASH, MARGIN, SHORT, OTHER - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + XMLName xml.Name `xml:"JRNLSEC"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + SubAcctFrom subAcctType `xml:"SUBACCTFROM"` // Sub-account cash is being transferred from: CASH, MARGIN, SHORT, OTHER + SubAcctTo subAcctType `xml:"SUBACCTTO"` // Sub-account cash is being transferred to: CASH, MARGIN, SHORT, OTHER + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts } func (t JrnlSec) TransactionType() string { @@ -233,12 +233,12 @@ func (t JrnlSec) TransactionType() string { } type MarginInterest struct { - XMLName xml.Name `xml:"MARGININTEREST"` - InvTran InvTran `xml:"INVTRAN"` - Total Amount `xml:"TOTAL"` - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + XMLName xml.Name `xml:"MARGININTEREST"` + InvTran InvTran `xml:"INVTRAN"` + Total Amount `xml:"TOTAL"` + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE } func (t MarginInterest) TransactionType() string { @@ -247,22 +247,22 @@ func (t MarginInterest) TransactionType() string { // REINVEST is a single transaction that contains both income and an investment transaction. If servers can’t track this as a single transaction they should return an INCOME transaction and an INVTRAN. type Reinvest struct { - XMLName xml.Name `xml:"REINVEST"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - IncomeType String `xml:"INCOMETYPE"` // Type of investment income: CGLONG (capital gains-long term), CGSHORT (capital gains-short term), DIV (dividend), INTEREST, MISC - Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security - Commission Amount `xml:"COMMISSION,omitempty"` - Taxes Amount `xml:"TAXES,omitempty"` - Fees Amount `xml:"FEES,omitempty"` - Load Amount `xml:"LOAD,omitempty"` - TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"REINVEST"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + IncomeType incomeType `xml:"INCOMETYPE"` // Type of investment income: CGLONG (capital gains-long term), CGSHORT (capital gains-short term), DIV (dividend), INTEREST, MISC + Total Amount `xml:"TOTAL"` // Transaction total. Buys, sells, etc.:((quan. * (price +/- markup/markdown)) +/-(commission + fees + load + taxes + penalty + withholding + statewithholding)). Distributions, interest, margin interest, misc. expense, etc.: amount. Return of cap: cost basis + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security + Commission Amount `xml:"COMMISSION,omitempty"` + Taxes Amount `xml:"TAXES,omitempty"` + Fees Amount `xml:"FEES,omitempty"` + Load Amount `xml:"LOAD,omitempty"` + TaxExempt Boolean `xml:"TAXEXEMPT,omitempty"` // Tax-exempt transaction + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t Reinvest) TransactionType() string { @@ -270,15 +270,15 @@ func (t Reinvest) TransactionType() string { } type RetOfCap struct { - XMLName xml.Name `xml:"RETOFCAP"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - Total Amount `xml:"TOTAL"` - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"RETOFCAP"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + Total Amount `xml:"TOTAL"` + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t RetOfCap) TransactionType() string { @@ -286,10 +286,10 @@ func (t RetOfCap) TransactionType() string { } type SellDebt struct { - XMLName xml.Name `xml:"SELLDEBT"` - InvSell InvSell `xml:"INVSELL"` - SellReason String `xml:"SELLREASON"` // CALL (the debt was called), SELL (the debt was sold), MATURITY (the debt reached maturity) - AccrdInt Amount `xml:"ACCRDINT,omitempty"` // Accrued interest + XMLName xml.Name `xml:"SELLDEBT"` + InvSell InvSell `xml:"INVSELL"` + SellReason sellReason `xml:"SELLREASON"` // CALL (the debt was called), SELL (the debt was sold), MATURITY (the debt reached maturity) + AccrdInt Amount `xml:"ACCRDINT,omitempty"` // Accrued interest } func (t SellDebt) TransactionType() string { @@ -299,7 +299,7 @@ func (t SellDebt) TransactionType() string { type SellMF struct { XMLName xml.Name `xml:"SELLMF"` InvSell InvSell `xml:"INVSELL"` - SellType String `xml:"SELLTYPE"` // Type of sell. SELL, SELLSHORT + SellType sellType `xml:"SELLTYPE"` // Type of sell. SELL, SELLSHORT AvgCostBasis Amount `xml:"AVGCOSTBASIS"` RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges } @@ -309,13 +309,13 @@ func (t SellMF) TransactionType() string { } type SellOpt struct { - XMLName xml.Name `xml:"SELLOPT"` - InvSell InvSell `xml:"INVSELL"` - OptSellType String `xml:"OPTSELLTYPE"` // For options, type of sell: SELLTOCLOSE, SELLTOOPEN. The SELLTOCLOSE action is selling a previously bought option. The SELLTOOPEN action is writing an option - ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract - RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges - RelType String `xml:"RELTYPE,omitempty"` // Related option transaction type: SPREAD, STRADDLE, NONE, OTHER - Secured String `xml:"SECURED,omitempty"` // NAKED, COVERED + XMLName xml.Name `xml:"SELLOPT"` + InvSell InvSell `xml:"INVSELL"` + OptSellType optSellType `xml:"OPTSELLTYPE"` // For options, type of sell: SELLTOCLOSE, SELLTOOPEN. The SELLTOCLOSE action is selling a previously bought option. The SELLTOOPEN action is writing an option + ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract + RelFiTId String `xml:"RELFITID,omitempty"` // used to relate transactions associated with mutual fund exchanges + RelType relType `xml:"RELTYPE,omitempty"` // Related option transaction type: SPREAD, STRADDLE, NONE, OTHER + Secured secured `xml:"SECURED,omitempty"` // NAKED, COVERED } func (t SellOpt) TransactionType() string { @@ -334,7 +334,7 @@ func (t SellOther) TransactionType() string { type SellStock struct { XMLName xml.Name `xml:"SELLSTOCK"` InvSell InvSell `xml:"INVSELL"` - SellType String `xml:"SELLTYPE"` // Type of sell. SELL, SELLSHORT + SellType sellType `xml:"SELLTYPE"` // Type of sell. SELL, SELLSHORT } func (t SellStock) TransactionType() string { @@ -342,19 +342,19 @@ func (t SellStock) TransactionType() string { } type Split struct { - XMLName xml.Name `xml:"SPLIT"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - OldUnits Amount `xml:"OLDUNITS"` // number of shares before the split - NewUnits Amount `xml:"NEWUNITS"` // number of shares after the split - Numerator Int `xml:"NUMERATOR"` // split ratio numerator - Denominator Int `xml:"DENOMINATOR"` // split ratio denominator - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE - FracCash Amount `xml:"FRACCASH,omitempty"` // cash for fractional units - SubAcctFund String `xml:"SUBACCTFUND,omitempty"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"SPLIT"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + OldUnits Amount `xml:"OLDUNITS"` // number of shares before the split + NewUnits Amount `xml:"NEWUNITS"` // number of shares after the split + Numerator Int `xml:"NUMERATOR"` // split ratio numerator + Denominator Int `xml:"DENOMINATOR"` // split ratio denominator + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + OrigCurrency *Currency `xml:"ORIGCURRENCY,omitempty"` // Overriding currency for UNITPRICE + FracCash Amount `xml:"FRACCASH,omitempty"` // cash for fractional units + SubAcctFund subAcctType `xml:"SUBACCTFUND,omitempty"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t Split) TransactionType() string { @@ -362,18 +362,18 @@ func (t Split) TransactionType() string { } type Transfer struct { - XMLName xml.Name `xml:"TRANSFER"` - InvTran InvTran `xml:"INVTRAN"` - SecId SecurityId `xml:"SECID"` - SubAcctSec String `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - TferAction String `xml:"TFERACTION"` // One of IN, OUT - PosType String `xml:"POSTYPE"` // Position type. One of LONG, SHORT - InvAcctFrom InvAcct `xml:"INVACCTFROM,omitempty"` - AvgCostBasis Amount `xml:"AVGCOSTBASIS,omitempty"` - UnitPrice Amount `xml:"UNITPRICE,omitempty"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security - DtPurchase *Date `xml:"DTPURCHASE,omitempty"` - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"TRANSFER"` + InvTran InvTran `xml:"INVTRAN"` + SecId SecurityId `xml:"SECID"` + SubAcctSec subAcctType `xml:"SUBACCTSEC"` // Sub-account type for this security. One of CASH, MARGIN, SHORT, OTHER + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + TferAction tferAction `xml:"TFERACTION"` // One of IN, OUT + PosType posType `xml:"POSTYPE"` // Position type. One of LONG, SHORT + InvAcctFrom InvAcct `xml:"INVACCTFROM,omitempty"` + AvgCostBasis Amount `xml:"AVGCOSTBASIS,omitempty"` + UnitPrice Amount `xml:"UNITPRICE,omitempty"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security + DtPurchase *Date `xml:"DTPURCHASE,omitempty"` + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // Source of money for this transaction. One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } func (t Transfer) TransactionType() string { @@ -387,7 +387,7 @@ type InvTransaction interface { type InvBankTransaction struct { XMLName xml.Name `xml:"INVBANKTRAN"` Transactions []Transaction `xml:"STMTTRN,omitempty"` - SubAcctFund String `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER + SubAcctFund subAcctType `xml:"SUBACCTFUND"` // Where did the money for the transaction come from or go to? CASH, MARGIN, SHORT, OTHER } // Must be unmarshalled manually due to the structure (don't know what kind of @@ -557,18 +557,18 @@ func (l *InvTranList) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error } type InvPosition struct { - XMLName xml.Name `xml:"INVPOS"` - SecId SecurityId `xml:"SECID"` - HeldInAcct String `xml:"HELDINACCT"` // Sub-account type, one of CASH, MARGIN, SHORT, OTHER - PosType String `xml:"POSTYPE"` // SHORT = Writer for options, Short for all others; LONG = Holder for options, Long for all others. - Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts - UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security - MktVal Amount `xml:"MKTVAL"` // Market value of this position - AvgCostBasis Amount `xml:"AVGCOSTBASIS,omitempty"` // - DtPriceAsOf Date `xml:"DTPRICEASOF"` // Date and time of unit price and market value, and cost basis. If this date is unknown, use 19900101 as the placeholder; do not use 0, - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - Memo String `xml:"MEMO,omitempty"` - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"INVPOS"` + SecId SecurityId `xml:"SECID"` + HeldInAcct subAcctType `xml:"HELDINACCT"` // Sub-account type, one of CASH, MARGIN, SHORT, OTHER + PosType posType `xml:"POSTYPE"` // SHORT = Writer for options, Short for all others; LONG = Holder for options, Long for all others. + Units Amount `xml:"UNITS"` // For stocks, MFs, other, number of shares held. Bonds = face value. Options = number of contracts + UnitPrice Amount `xml:"UNITPRICE"` // For stocks, MFs, other, price per share. Bonds = percentage of par. Option = premium per share of underlying security + MktVal Amount `xml:"MKTVAL"` // Market value of this position + AvgCostBasis Amount `xml:"AVGCOSTBASIS,omitempty"` // + DtPriceAsOf Date `xml:"DTPRICEASOF"` // Date and time of unit price and market value, and cost basis. If this date is unknown, use 19900101 as the placeholder; do not use 0, + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + Memo String `xml:"MEMO,omitempty"` + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } type Position interface { @@ -600,7 +600,7 @@ func (p MFPosition) PositionType() string { type OptPosition struct { XMLName xml.Name `xml:"POSOPT"` InvPos InvPosition `xml:"INVPOS"` - Secured String `xml:"SECURED,omitempty"` // One of NAKED, COVERED + Secured secured `xml:"SECURED,omitempty"` // One of NAKED, COVERED } func (p OptPosition) PositionType() string { @@ -689,21 +689,21 @@ type InvBalance struct { } type OO struct { - XMLName xml.Name `xml:"OO"` - FiTId String `xml:"FITID"` - SrvrTId String `xml:"SRVRTID,omitempty"` - SecId SecurityId `xml:"SECID"` - DtPlaced Date `xml:"DTPLACED"` // Date the order was placed - Units Amount `xml:"UNITS"` // Quantity of the security the open order is for - SubAcct String `xml:"SUBACCT"` // One of CASH, MARGIN, SHORT, OTHER - Duration String `xml:"DURATION"` // How long the order is good for. One of DAY, GOODTILCANCEL, IMMEDIATE - Restriction String `xml:"RESTRICTION"` // Special restriction on the order: One of ALLORNONE, MINUNITS, NONE - MinUnits Amount `xml:"MINUNITS,omitempty"` // Minimum number of units that must be filled for the order - LimitPrice Amount `xml:"LIMITPRICE,omitempty"` - StopPrice Amount `xml:"STOPPRICE,omitempty"` - Memo String `xml:"MEMO,omitempty"` - Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE - Inv401kSource String `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST + XMLName xml.Name `xml:"OO"` + FiTId String `xml:"FITID"` + SrvrTId String `xml:"SRVRTID,omitempty"` + SecId SecurityId `xml:"SECID"` + DtPlaced Date `xml:"DTPLACED"` // Date the order was placed + Units Amount `xml:"UNITS"` // Quantity of the security the open order is for + SubAcct subAcctType `xml:"SUBACCT"` // One of CASH, MARGIN, SHORT, OTHER + Duration duration `xml:"DURATION"` // How long the order is good for. One of DAY, GOODTILCANCEL, IMMEDIATE + Restriction restriction `xml:"RESTRICTION"` // Special restriction on the order: One of ALLORNONE, MINUNITS, NONE + MinUnits Amount `xml:"MINUNITS,omitempty"` // Minimum number of units that must be filled for the order + LimitPrice Amount `xml:"LIMITPRICE,omitempty"` + StopPrice Amount `xml:"STOPPRICE,omitempty"` + Memo String `xml:"MEMO,omitempty"` + Currency *Currency `xml:"CURRENCY,omitempty"` // Overriding currency for UNITPRICE + Inv401kSource inv401kSource `xml:"INV401KSOURCE,omitempty"` // One of PRETAX, AFTERTAX, MATCH, PROFITSHARING, ROLLOVER, OTHERVEST, OTHERNONVEST for 401(k) accounts. Default if not present is OTHERNONVEST. The following cash source types are subject to vesting: MATCH, PROFITSHARING, and OTHERVEST } type OpenOrder interface { @@ -724,8 +724,8 @@ func (o OOBuyDebt) OrderType() string { type OOBuyMF struct { XMLName xml.Name `xml:"OOBUYMF"` OO OO `xml:"OO"` - BuyType String `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER - UnitType String `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY + BuyType buyType `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER + UnitType unitType `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY } func (o OOBuyMF) OrderType() string { @@ -733,9 +733,9 @@ func (o OOBuyMF) OrderType() string { } type OOBuyOpt struct { - XMLName xml.Name `xml:"OOBUYOPT"` - OO OO `xml:"OO"` - OptBuyType String `xml:"OPTBUYTYPE"` // One of BUYTOOPEN, BUYTOCLOSE + XMLName xml.Name `xml:"OOBUYOPT"` + OO OO `xml:"OO"` + OptBuyType optBuyType `xml:"OPTBUYTYPE"` // One of BUYTOOPEN, BUYTOCLOSE } func (o OOBuyOpt) OrderType() string { @@ -745,7 +745,7 @@ func (o OOBuyOpt) OrderType() string { type OOBuyOther struct { XMLName xml.Name `xml:"OOBUYOTHER"` OO OO `xml:"OO"` - UnitType String `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY + UnitType unitType `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY } func (o OOBuyOther) OrderType() string { @@ -755,7 +755,7 @@ func (o OOBuyOther) OrderType() string { type OOBuyStock struct { XMLName xml.Name `xml:"OOBUYSTOCK"` OO OO `xml:"OO"` - BuyType String `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER + BuyType buyType `xml:"BUYTYPE"` // One of BUY, BUYTOCOVER } func (o OOBuyStock) OrderType() string { @@ -774,8 +774,8 @@ func (o OOSellDebt) OrderType() string { type OOSellMF struct { XMLName xml.Name `xml:"OOSELLMF"` OO OO `xml:"OO"` - SellType String `xml:"SELLTYPE"` // One of SELL, SELLSHORT - UnitType String `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY + SellType sellType `xml:"SELLTYPE"` // One of SELL, SELLSHORT + UnitType unitType `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY SellAll Boolean `xml:"SELLALL"` // Sell entire holding } @@ -784,9 +784,9 @@ func (o OOSellMF) OrderType() string { } type OOSellOpt struct { - XMLName xml.Name `xml:"OOSELLOPT"` - OO OO `xml:"OO"` - OptSellType String `xml:"OPTSELLTYPE"` // One of SELLTOOPEN, SELLTOCLOSE + XMLName xml.Name `xml:"OOSELLOPT"` + OO OO `xml:"OO"` + OptSellType optSellType `xml:"OPTSELLTYPE"` // One of SELLTOOPEN, SELLTOCLOSE } func (o OOSellOpt) OrderType() string { @@ -796,7 +796,7 @@ func (o OOSellOpt) OrderType() string { type OOSellOther struct { XMLName xml.Name `xml:"OOSELLOTHER"` OO OO `xml:"OO"` - UnitType String `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY + UnitType unitType `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY } func (o OOSellOther) OrderType() string { @@ -806,7 +806,7 @@ func (o OOSellOther) OrderType() string { type OOSellStock struct { XMLName xml.Name `xml:"OOSELLSTOCK"` OO OO `xml:"OO"` - SellType String `xml:"SELLTYPE"` // One of SELL, SELLSHORT + SellType sellType `xml:"SELLTYPE"` // One of SELL, SELLSHORT } func (o OOSellStock) OrderType() string { @@ -817,7 +817,7 @@ type OOSwitchMF struct { XMLName xml.Name `xml:"SWITCHMF"` OO OO `xml:"OO"` SecId SecurityId `xml:"SECID"` // Security ID of the fund to switch to or purchase - UnitType String `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY + UnitType unitType `xml:"UNITTYPE"` // What the units represent: one of SHARES, CURRENCY SwitchAll Boolean `xml:"SWITCHALL"` // Switch entire holding } @@ -938,22 +938,22 @@ type VestInfo struct { } type LoanInfo struct { - XMLName xml.Name `xml:"VESTINFO"` - LoanID String `xml:"LOANID"` // Identifier of this loan - LoanDesc String `xml:"LOANDESC,omitempty"` // Loan description - InitialLoanBal Amount `xml:"INITIALLOANBAL,omitempty"` // Initial loan balance - LoanStartDate *Date `xml:"LOANSTARTDATE,omitempty"` // Start date of loan - CurrentLoanBal Amount `xml:"CURRENTLOANBAL"` // Current loan principal balance - DtAsOf *Date `xml:"DTASOF"` // Date and time of the current loan balance - LoanRate Amount `xml:"LOANRATE,omitempty"` // Loan annual interest rate - LoanPmtAmt Amount `xml:"LOANPMTAMT,omitempty"` // Loan payment amount - LoanPmtFreq String `xml:"LOANPMTFREQ,omitempty"` // Frequency of loan repayments: WEEKLY, BIWEEKLY, TWICEMONTHLY, MONTHLY, FOURWEEKS, BIMONTHLY, QUARTERLY, SEMIANNUALLY, ANNUALLY, OTHER. See section 10.2.1 for calculation rules. - LoanPmtsInitial Int `xml:"LOANPMTSINITIAL,omitempty"` // Initial number of loan payments. - LoanPmtsRemaining Int `xml:"LOANPMTSREMAINING,omitempty"` // Remaining number of loan payments - LoanMaturityDate *Date `xml:"LOANMATURITYDATE,omitempty"` // Expected loan end date - LoanTotalProjInterest Amount `xml:"LOANTOTALPROJINTEREST,omitempty"` // Total projected interest to be paid on this loan - LoanInterestToDate Amount `xml:"LOANINTERESTTODATE,omitempty"` // Total interested paid to date on this loan - LoanExtPmtDate *Date `xml:"LOANNEXTPMTDATE,omitempty"` // Next payment due date + XMLName xml.Name `xml:"VESTINFO"` + LoanID String `xml:"LOANID"` // Identifier of this loan + LoanDesc String `xml:"LOANDESC,omitempty"` // Loan description + InitialLoanBal Amount `xml:"INITIALLOANBAL,omitempty"` // Initial loan balance + LoanStartDate *Date `xml:"LOANSTARTDATE,omitempty"` // Start date of loan + CurrentLoanBal Amount `xml:"CURRENTLOANBAL"` // Current loan principal balance + DtAsOf *Date `xml:"DTASOF"` // Date and time of the current loan balance + LoanRate Amount `xml:"LOANRATE,omitempty"` // Loan annual interest rate + LoanPmtAmt Amount `xml:"LOANPMTAMT,omitempty"` // Loan payment amount + LoanPmtFreq loanPmtFreq `xml:"LOANPMTFREQ,omitempty"` // Frequency of loan repayments: WEEKLY, BIWEEKLY, TWICEMONTHLY, MONTHLY, FOURWEEKS, BIMONTHLY, QUARTERLY, SEMIANNUALLY, ANNUALLY, OTHER. See section 10.2.1 for calculation rules. + LoanPmtsInitial Int `xml:"LOANPMTSINITIAL,omitempty"` // Initial number of loan payments. + LoanPmtsRemaining Int `xml:"LOANPMTSREMAINING,omitempty"` // Remaining number of loan payments + LoanMaturityDate *Date `xml:"LOANMATURITYDATE,omitempty"` // Expected loan end date + LoanTotalProjInterest Amount `xml:"LOANTOTALPROJINTEREST,omitempty"` // Total projected interest to be paid on this loan + LoanInterestToDate Amount `xml:"LOANINTERESTTODATE,omitempty"` // Total interested paid to date on this loan + LoanExtPmtDate *Date `xml:"LOANNEXTPMTDATE,omitempty"` // Next payment due date } type Inv401KSummaryAggregate struct { diff --git a/invstmt_test.go b/invstmt_test.go index d7baed9..ae66b88 100644 --- a/invstmt_test.go +++ b/invstmt_test.go @@ -331,17 +331,17 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UnitPrice: unitprice1, Commission: commission1, Total: total1, - SubAcctSec: "CASH", - SubAcctFund: "CASH", + SubAcctSec: ofxgo.SubAcctTypeCash, + SubAcctFund: ofxgo.SubAcctTypeCash, }, - BuyType: "BUY", + BuyType: ofxgo.BuyTypeBuy, }, }, BankTransactions: []ofxgo.InvBankTransaction{ ofxgo.InvBankTransaction{ Transactions: []ofxgo.Transaction{ ofxgo.Transaction{ - TrnType: "CREDIT", + TrnType: ofxgo.TrnTypeCredit, DtPosted: *ofxgo.NewDateGMT(2017, 1, 20, 0, 0, 0, 0), DtUser: ofxgo.NewDateGMT(2017, 1, 18, 0, 0, 0, 0), DtAvail: ofxgo.NewDateGMT(2017, 1, 23, 0, 0, 0, 0), @@ -352,7 +352,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { Memo: "CHECK 19980", }, }, - SubAcctFund: "CASH", + SubAcctFund: ofxgo.SubAcctTypeCash, }, }, } @@ -371,7 +371,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { ofxgo.Balance{ Name: "Sweep Int Rate", Desc: "Current interest rate for sweep account balances", - BalType: "PERCENT", + BalType: ofxgo.BalTypePercent, Value: balvalue, DtAsOf: ofxgo.NewDateGMT(2017, 4, 1, 0, 0, 0, 0), }, @@ -412,8 +412,8 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueId: "78462F103", UniqueIdType: "CUSIP", }, - HeldInAcct: "CASH", - PosType: "LONG", + HeldInAcct: ofxgo.SubAcctTypeCash, + PosType: ofxgo.PosTypeLong, Units: posunits1, UnitPrice: posunitprice1, MktVal: posmktval1, @@ -427,8 +427,8 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueId: "129887339", UniqueIdType: "CUSIP", }, - HeldInAcct: "CASH", - PosType: "LONG", + HeldInAcct: ofxgo.SubAcctTypeCash, + PosType: ofxgo.PosTypeLong, Units: posunits2, UnitPrice: posunitprice2, MktVal: posmktval2, @@ -447,13 +447,13 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { }, DtPlaced: *ofxgo.NewDateGMT(2017, 3, 10, 12, 44, 45, 0), Units: oounits1, - SubAcct: "CASH", - Duration: "GOODTILCANCEL", - Restriction: "NONE", + SubAcct: ofxgo.SubAcctTypeCash, + Duration: ofxgo.DurationGoodTilCancel, + Restriction: ofxgo.RestrictionNone, LimitPrice: oolimitprice1, }, - BuyType: "BUY", - UnitType: "SHARES", + BuyType: ofxgo.BuyTypeBuy, + UnitType: ofxgo.UnitTypeShares, }, ofxgo.OOBuyStock{ OO: ofxgo.OO{ @@ -464,12 +464,12 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { }, DtPlaced: *ofxgo.NewDateGMT(2017, 3, 24, 3, 19, 0, 0), Units: oounits2, - SubAcct: "CASH", - Duration: "GOODTILCANCEL", - Restriction: "ALLORNONE", + SubAcct: ofxgo.SubAcctTypeCash, + Duration: ofxgo.DurationGoodTilCancel, + Restriction: ofxgo.RestrictionAllOrNone, LimitPrice: oolimitprice2, }, - BuyType: "BUY", + BuyType: ofxgo.BuyTypeBuy, }, }, } @@ -493,7 +493,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { FiId: "99184", }, Yield: yield1, - AssetClass: "OTHER", + AssetClass: ofxgo.AssetClassOther, }, ofxgo.OptInfo{ SecInfo: ofxgo.SecInfo{ @@ -505,7 +505,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { Ticker: "FERTP", FiId: "882919", }, - OptType: "PUT", + OptType: ofxgo.OptTypePut, StrikePrice: strikeprice, DtExpire: *ofxgo.NewDateGMT(2017, 9, 1, 0, 0, 0, 0), ShPerCtrct: 100, @@ -513,7 +513,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueId: "983322180", UniqueIdType: "CUSIP", }, - AssetClass: "LARGESTOCK", + AssetClass: ofxgo.AssetClassLargeStock, }, ofxgo.StockInfo{ SecInfo: ofxgo.SecInfo{ @@ -526,7 +526,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { FiId: "883897", }, Yield: yield2, - AssetClass: "SMALLSTOCK", + AssetClass: ofxgo.AssetClassSmallStock, }, ofxgo.MFInfo{ SecInfo: ofxgo.SecInfo{ @@ -754,10 +754,10 @@ NEWFILEUID: NONE Commission: commission1, Fees: fees1, Total: total1, - SubAcctSec: "CASH", - SubAcctFund: "CASH", + SubAcctSec: ofxgo.SubAcctTypeCash, + SubAcctFund: ofxgo.SubAcctTypeCash, }, - OptSellType: "SELLTOOPEN", + OptSellType: ofxgo.OptSellTypeSellToOpen, ShPerCtrct: 100, }, ofxgo.ClosureOpt{ @@ -770,10 +770,10 @@ NEWFILEUID: NONE UniqueId: "78462F10", UniqueIdType: "CUSIP", }, - OptAction: "ASSIGN", + OptAction: ofxgo.OptActionAssign, Units: units2, ShPerCtrct: 100, - SubAcctSec: "CASH", + SubAcctSec: ofxgo.SubAcctTypeCash, }, ofxgo.ClosureOpt{ InvTran: ofxgo.InvTran{ @@ -785,10 +785,10 @@ NEWFILEUID: NONE UniqueId: "SPY161216C00226000", UniqueIdType: "CUSIP", }, - OptAction: "ASSIGN", + OptAction: ofxgo.OptActionAssign, Units: units3, ShPerCtrct: 100, - SubAcctSec: "CASH", + SubAcctSec: ofxgo.SubAcctTypeCash, }, }, } @@ -832,8 +832,8 @@ NEWFILEUID: NONE UniqueId: "04956010", UniqueIdType: "CUSIP", }, - HeldInAcct: "CASH", - PosType: "LONG", + HeldInAcct: ofxgo.SubAcctTypeCash, + PosType: ofxgo.PosTypeLong, Units: posunits1, UnitPrice: posunitprice1, MktVal: posmktval1, @@ -846,8 +846,8 @@ NEWFILEUID: NONE UniqueId: "36960410", UniqueIdType: "CUSIP", }, - HeldInAcct: "CASH", - PosType: "LONG", + HeldInAcct: ofxgo.SubAcctTypeCash, + PosType: ofxgo.PosTypeLong, Units: posunits2, UnitPrice: posunitprice2, MktVal: posmktval2, @@ -883,7 +883,7 @@ NEWFILEUID: NONE SecName: "SPY Dec 16 2016 226.00 Call", Ticker: "SPY 161216C00226000", }, - OptType: "CALL", + OptType: ofxgo.OptTypeCall, StrikePrice: strikeprice, DtExpire: *ofxgo.NewDateGMT(2016, 12, 16, 12, 0, 0, 0), ShPerCtrct: 100, diff --git a/profile.go b/profile.go index 43f5908..0afaac2 100644 --- a/profile.go +++ b/profile.go @@ -34,7 +34,7 @@ type SignonInfo struct { SignonRealm String `xml:"SIGNONREALM"` Min Int `xml:"MIN"` // Minimum number of password characters Max Int `xml:"MAX"` // Maximum number of password characters - CharType String `xml:"CHARTYPE"` // ALPHAONLY, NUMERICONLY, ALPHAORNUMERIC, ALPHAANDNUMERIC + CharType charType `xml:"CHARTYPE"` // One of ALPHAONLY, NUMERICONLY, ALPHAORNUMERIC, ALPHAANDNUMERIC CaseSen Boolean `xml:"CASESEN"` // Password is case-sensitive? Special Boolean `xml:"SPECIAL"` // Special characters allowed? Spaces Boolean `xml:"SPACES"` // Spaces allowed? @@ -56,11 +56,11 @@ type MessageSet struct { Name string // (copy of XMLName.Local) Ver Int `xml:"MSGSETCORE>VER"` // Message set version - should always match 'n' in Url String `xml:"MSGSETCORE>URL"` // URL where messages in this set are to be set - OfxSec String `xml:"MSGSETCORE>OFXSEC"` // NONE or 'TYPE 1' + OfxSec ofxSec `xml:"MSGSETCORE>OFXSEC"` // NONE or 'TYPE 1' TranspSec Boolean `xml:"MSGSETCORE>TRANSPSEC"` // Transport-level security must be used SignonRealm String `xml:"MSGSETCORE>SIGNONREALM"` // Used to identify which SignonInfo to use for to this MessageSet Language []String `xml:"MSGSETCORE>LANGUAGE"` // List of supported languages - SyncMode String `xml:"MSGSETCORE>SYNCMODE"` // One of FULL, LITE + SyncMode syncMode `xml:"MSGSETCORE>SYNCMODE"` // One of FULL, LITE RefreshSupt Boolean `xml:"MSGSETCORE>REFRESHSUPT,omitempty"` // Y if server supports Y within synchronizations. This option is irrelevant for full synchronization servers. Clients must ignore (or its absence) if the profile also specifies FULL. For lite synchronization, the default is N. Without Y, lite synchronization servers are not required to support Y requests RespFileER Boolean `xml:"MSGSETCORE>RESPFILEER"` // server supports file-based error recovery SpName String `xml:"MSGSETCORE>SPNAME"` // Name of service provider diff --git a/profile_test.go b/profile_test.go index c385d6d..934ebd0 100644 --- a/profile_test.go +++ b/profile_test.go @@ -233,11 +233,11 @@ NEWFILEUID:NONE Name: "SIGNONMSGSETV1", Ver: 1, Url: "https://ofx.example.com/cgi-ofx/exampleofx", - OfxSec: "NONE", + OfxSec: ofxgo.OfxSecNone, TranspSec: true, SignonRealm: "Example Trade", Language: []ofxgo.String{"ENG"}, - SyncMode: "LITE", + SyncMode: ofxgo.SyncModeLite, RespFileER: false, // Ignored: 300 }, @@ -245,11 +245,11 @@ NEWFILEUID:NONE Name: "SIGNUPMSGSETV1", Ver: 1, Url: "https://ofx.example.com/cgi-ofx/exampleofx", - OfxSec: "NONE", + OfxSec: ofxgo.OfxSecNone, TranspSec: true, SignonRealm: "Example Trade", Language: []ofxgo.String{"ENG"}, - SyncMode: "LITE", + SyncMode: ofxgo.SyncModeLite, RespFileER: false, // Ignored: 300 }, @@ -257,11 +257,11 @@ NEWFILEUID:NONE Name: "INVSTMTMSGSETV1", Ver: 1, Url: "https://ofx.example.com/cgi-ofx/exampleofx", - OfxSec: "NONE", + OfxSec: ofxgo.OfxSecNone, TranspSec: true, SignonRealm: "Example Trade", Language: []ofxgo.String{"ENG"}, - SyncMode: "LITE", + SyncMode: ofxgo.SyncModeLite, RespFileER: false, // Ignored: 300 }, @@ -269,11 +269,11 @@ NEWFILEUID:NONE Name: "SECLISTMSGSETV1", Ver: 1, Url: "https://ofx.example.com/cgi-ofx/exampleofx", - OfxSec: "NONE", + OfxSec: ofxgo.OfxSecNone, TranspSec: true, SignonRealm: "Example Trade", Language: []ofxgo.String{"ENG"}, - SyncMode: "LITE", + SyncMode: ofxgo.SyncModeLite, RespFileER: false, // Ignored: 300 }, @@ -281,11 +281,11 @@ NEWFILEUID:NONE Name: "PROFMSGSETV1", Ver: 1, Url: "https://ofx.example.com/cgi-ofx/exampleofx", - OfxSec: "NONE", + OfxSec: ofxgo.OfxSecNone, TranspSec: true, SignonRealm: "Example Trade", Language: []ofxgo.String{"ENG"}, - SyncMode: "LITE", + SyncMode: ofxgo.SyncModeLite, RespFileER: false, // Ignored: 300 }, @@ -295,7 +295,7 @@ NEWFILEUID:NONE SignonRealm: "Example Trade", Min: 1, Max: 32, - CharType: "ALPHAORNUMERIC", + CharType: ofxgo.CharTypeAlphaOrNumeric, CaseSen: false, Special: true, Spaces: false, diff --git a/response_test.go b/response_test.go index b7a9a38..fce8595 100644 --- a/response_test.go +++ b/response_test.go @@ -121,6 +121,10 @@ func checkEqual(t *testing.T, fieldName string, expected, actual reflect.Value) if expected.String() != actual.String() { t.Fatalf("%s: %s expected to be '%s', found '%s'\n", t.Name(), fieldName, expected.String(), actual.String()) } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if expected.Uint() != actual.Uint() { + t.Fatalf("%s: %s expected to be '%s', found '%s'\n", t.Name(), fieldName, valueToString(expected), valueToString(actual)) + } default: t.Fatalf("%s: %s has unexpected type that didn't provide an Equal() method: %s\n", t.Name(), fieldName, expected.Type().Name()) } diff --git a/seclist.go b/seclist.go index bd85455..883a4f1 100644 --- a/seclist.go +++ b/seclist.go @@ -81,22 +81,22 @@ type SecInfo struct { } type DebtInfo struct { - XMLName xml.Name `xml:"DEBTINFO"` - SecInfo SecInfo `xml:"SECINFO"` - ParValue Amount `xml:"PARVALUE"` - DebtType String `xml:"DEBTTYPE"` // One of COUPON, ZERO (zero coupon) - DebtClass String `xml:"DEBTCLASS,omitempty"` // One of TREASURY, MUNICIPAL, CORPORATE, OTHER - CouponRate Amount `xml:"COUPONRT,omitempty"` // Bond coupon rate for next closest call date - DtCoupon *Date `xml:"DTCOUPON,omitempty"` // Maturity date for next coupon - CouponFreq String `xml:"COUPONFREQ,omitempty"` // When coupons mature - one of MONTHLY, QUARTERLY, SEMIANNUAL, ANNUAL, or OTHER - CallPrice Amount `xml:"CALLPRICE,omitempty"` // Bond call price - YieldToCall Amount `xml:"YIELDTOCALL,omitempty"` // Yield to next call - DtCall *Date `xml:"DTCALL,omitempty"` // Next call date - CallType String `xml:"CALLTYPE,omitempt"` // Type of next call. One of CALL, PUT, PREFUND, MATURITY - YieldToMat Amount `xml:"YIELDTOMAT,omitempty"` // Yield to maturity - DtMat *Date `xml:"DTMAT,omitempty"` // Debt maturity date - AssetClass String `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER - FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class + XMLName xml.Name `xml:"DEBTINFO"` + SecInfo SecInfo `xml:"SECINFO"` + ParValue Amount `xml:"PARVALUE"` + DebtType debtType `xml:"DEBTTYPE"` // One of COUPON, ZERO (zero coupon) + DebtClass debtClass `xml:"DEBTCLASS,omitempty"` // One of TREASURY, MUNICIPAL, CORPORATE, OTHER + CouponRate Amount `xml:"COUPONRT,omitempty"` // Bond coupon rate for next closest call date + DtCoupon *Date `xml:"DTCOUPON,omitempty"` // Maturity date for next coupon + CouponFreq couponFreq `xml:"COUPONFREQ,omitempty"` // When coupons mature - one of MONTHLY, QUARTERLY, SEMIANNUAL, ANNUAL, or OTHER + CallPrice Amount `xml:"CALLPRICE,omitempty"` // Bond call price + YieldToCall Amount `xml:"YIELDTOCALL,omitempty"` // Yield to next call + DtCall *Date `xml:"DTCALL,omitempty"` // Next call date + CallType callType `xml:"CALLTYPE,omitempt"` // Type of next call. One of CALL, PUT, PREFUND, MATURITY + YieldToMat Amount `xml:"YIELDTOMAT,omitempty"` // Yield to maturity + DtMat *Date `xml:"DTMAT,omitempty"` // Debt maturity date + AssetClass assetClass `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER + FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class } func (i DebtInfo) SecurityType() string { @@ -104,9 +104,9 @@ func (i DebtInfo) SecurityType() string { } type AssetPortion struct { - XMLName xml.Name `xml:"PORTION"` - AssetClass String `xml:"ASSETCLASS"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER - Percent Amount `xml:"PERCENT"` // Percentage of the fund that falls under this asset class + XMLName xml.Name `xml:"PORTION"` + AssetClass assetClass `xml:"ASSETCLASS"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER + Percent Amount `xml:"PERCENT"` // Percentage of the fund that falls under this asset class } type FiAssetPortion struct { @@ -118,7 +118,7 @@ type FiAssetPortion struct { type MFInfo struct { XMLName xml.Name `xml:"MFINFO"` SecInfo SecInfo `xml:"SECINFO"` - MfType String `xml:"MFTYPE"` // One of OPEN, END, CLOSEEND, OTHER + MfType mfType `xml:"MFTYPE"` // One of OPEN, END, CLOSEEND, OTHER Yield Amount `xml:"YIELD,omitempty"` // Current yield reported as the dividend expressed as a portion of the current stock price DtYieldAsOf *Date `xml:"DTYIELDASOF,omitempty"` // Date YIELD is valid for AssetClasses []AssetPortion `xml:"MFASSETCLASS>PORTION"` @@ -132,12 +132,12 @@ func (i MFInfo) SecurityType() string { type OptInfo struct { XMLName xml.Name `xml:"OPTINFO"` SecInfo SecInfo `xml:"SECINFO"` - OptType String `xml:"OPTTYPE"` // One of PUT, CALL + OptType optType `xml:"OPTTYPE"` // One of PUT, CALL StrikePrice Amount `xml:"STRIKEPRICE"` DtExpire Date `xml:"DTEXPIRE"` // Expiration date ShPerCtrct Int `xml:"SHPERCTRCT"` // Shares per contract SecId *SecurityId `xml:"SECID,omitempty"` // Security ID of the underlying security - AssetClass String `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER + AssetClass assetClass `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class } @@ -146,11 +146,11 @@ func (i OptInfo) SecurityType() string { } type OtherInfo struct { - XMLName xml.Name `xml:"OTHERINFO"` - SecInfo SecInfo `xml:"SECINFO"` - TypeDesc String `xml:"TYPEDESC,omitempty"` // Description of security type - AssetClass String `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER - FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class + XMLName xml.Name `xml:"OTHERINFO"` + SecInfo SecInfo `xml:"SECINFO"` + TypeDesc String `xml:"TYPEDESC,omitempty"` // Description of security type + AssetClass assetClass `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER + FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class } func (i OtherInfo) SecurityType() string { @@ -158,13 +158,13 @@ func (i OtherInfo) SecurityType() string { } type StockInfo struct { - XMLName xml.Name `xml:"STOCKINFO"` - SecInfo SecInfo `xml:"SECINFO"` - StockType String `xml:"STOCKTYPE,omitempty"` // One of COMMON, PREFERRED, CONVERTIBLE, OTHER - Yield Amount `xml:"YIELD,omitempty"` // Current yield reported as the dividend expressed as a portion of the current stock price - DtYieldAsOf *Date `xml:"DTYIELDASOF,omitempty"` // Date YIELD is valid for - AssetClass String `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER - FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class + XMLName xml.Name `xml:"STOCKINFO"` + SecInfo SecInfo `xml:"SECINFO"` + StockType stockType `xml:"STOCKTYPE,omitempty"` // One of COMMON, PREFERRED, CONVERTIBLE, OTHER + Yield Amount `xml:"YIELD,omitempty"` // Current yield reported as the dividend expressed as a portion of the current stock price + DtYieldAsOf *Date `xml:"DTYIELDASOF,omitempty"` // Date YIELD is valid for + AssetClass assetClass `xml:"ASSETCLASS,omitempty"` // One of DOMESTICBOND, INTLBOND, LARGESTOCK, SMALLSTOCK, INTLSTOCK, MONEYMRKT, OTHER + FiAssetClass String `xml:"FIASSETCLASS,omitempty"` // FI-defined asset class } func (i StockInfo) SecurityType() string { diff --git a/signup.go b/signup.go index dbec7cb..1f3380c 100644 --- a/signup.go +++ b/signup.go @@ -29,34 +29,34 @@ func (r *AcctInfoRequest) Type() messageType { type HolderInfo struct { XMLName xml.Name - FirstName String `xml:"FIRSTNAME"` - MiddleName String `xml:"MIDDLENAME,omitempty"` - LastName String `xml:"LASTNAME"` - Addr1 String `xml:"ADDR1"` - Addr2 String `xml:"ADDR2,omitempty"` - Addr3 String `xml:"ADDR3,omitempty"` - City String `xml:"CITY"` - State String `xml:"STATE"` - PostalCode String `xml:"POSTALCODE"` - Country String `xml:"COUNTRY,omitempty"` - DayPhone String `xml:"DAYPHONE,omitempty"` - EvePhone String `xml:"EVEPHONE,omitempty"` - Email String `xml:"EMAIL,omitempty"` - HolderType String `xml:"HOLDERTYPE,omitempty"` // One of INDIVIDUAL, JOINT, CUSTODIAL, TRUST, OTHER + FirstName String `xml:"FIRSTNAME"` + MiddleName String `xml:"MIDDLENAME,omitempty"` + LastName String `xml:"LASTNAME"` + Addr1 String `xml:"ADDR1"` + Addr2 String `xml:"ADDR2,omitempty"` + Addr3 String `xml:"ADDR3,omitempty"` + City String `xml:"CITY"` + State String `xml:"STATE"` + PostalCode String `xml:"POSTALCODE"` + Country String `xml:"COUNTRY,omitempty"` + DayPhone String `xml:"DAYPHONE,omitempty"` + EvePhone String `xml:"EVEPHONE,omitempty"` + Email String `xml:"EMAIL,omitempty"` + HolderType holderType `xml:"HOLDERTYPE,omitempty"` // One of INDIVIDUAL, JOINT, CUSTODIAL, TRUST, OTHER } type BankAcctInfo struct { - XMLName xml.Name `xml:"BANKACCTINFO"` - BankAcctFrom BankAcct `xml:"BANKACCTFROM"` - SupTxDl Boolean `xml:"SUPTXDL"` // Supports downloading transactions (as opposed to balance only) - XferSrc Boolean `xml:"XFERSRC"` // Enabled as source for intra/interbank transfer - XferDest Boolean `xml:"XFERDEST"` // Enabled as destination for intra/interbank transfer - MaturityDate Date `xml:"MATURITYDATE,omitempty"` // Maturity date for CD, if CD - MaturityAmt Amount `xml:"MATURITYAMOUNT,omitempty"` // Maturity amount for CD, if CD - MinBalReq Amount `xml:"MINBALREQ,omitempty"` // Minimum balance required to avoid service fees - AcctClassification String `xml:"ACCTCLASSIFICATION,omitempty"` // One of PERSONAL, BUSINESS, CORPORATE, OTHER - OverdraftLimit Amount `xml:"OVERDRAFTLIMIT,omitempty"` - SvcStatus String `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE + XMLName xml.Name `xml:"BANKACCTINFO"` + BankAcctFrom BankAcct `xml:"BANKACCTFROM"` + SupTxDl Boolean `xml:"SUPTXDL"` // Supports downloading transactions (as opposed to balance only) + XferSrc Boolean `xml:"XFERSRC"` // Enabled as source for intra/interbank transfer + XferDest Boolean `xml:"XFERDEST"` // Enabled as destination for intra/interbank transfer + MaturityDate Date `xml:"MATURITYDATE,omitempty"` // Maturity date for CD, if CD + MaturityAmt Amount `xml:"MATURITYAMOUNT,omitempty"` // Maturity amount for CD, if CD + MinBalReq Amount `xml:"MINBALREQ,omitempty"` // Minimum balance required to avoid service fees + AcctClassification acctClassification `xml:"ACCTCLASSIFICATION,omitempty"` // One of PERSONAL, BUSINESS, CORPORATE, OTHER + OverdraftLimit Amount `xml:"OVERDRAFTLIMIT,omitempty"` + SvcStatus svcStatus `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE } // Make pointers to these structs print nicely @@ -65,13 +65,13 @@ func (bai *BankAcctInfo) String() string { } type CCAcctInfo struct { - XMLName xml.Name `xml:"CCACCTINFO"` - CCAcctFrom CCAcct `xml:"CCACCTFROM"` - SupTxDl Boolean `xml:"SUPTXDL"` // Supports downloading transactions (as opposed to balance only) - XferSrc Boolean `xml:"XFERSRC"` // Enabled as source for intra/interbank transfer - XferDest Boolean `xml:"XFERDEST"` // Enabled as destination for intra/interbank transfer - AcctClassification String `xml:"ACCTCLASSIFICATION,omitempty"` // One of PERSONAL, BUSINESS, CORPORATE, OTHER - SvcStatus String `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE + XMLName xml.Name `xml:"CCACCTINFO"` + CCAcctFrom CCAcct `xml:"CCACCTFROM"` + SupTxDl Boolean `xml:"SUPTXDL"` // Supports downloading transactions (as opposed to balance only) + XferSrc Boolean `xml:"XFERSRC"` // Enabled as source for intra/interbank transfer + XferDest Boolean `xml:"XFERDEST"` // Enabled as destination for intra/interbank transfer + AcctClassification acctClassification `xml:"ACCTCLASSIFICATION,omitempty"` // One of PERSONAL, BUSINESS, CORPORATE, OTHER + SvcStatus svcStatus `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE } // Make pointers to these structs print nicely @@ -80,13 +80,13 @@ func (ci *CCAcctInfo) String() string { } type InvAcctInfo struct { - XMLName xml.Name `xml:"INVACCTINFO"` - InvAcctFrom InvAcct `xml:"INVACCTFROM"` - UsProductType String `xml:"USPRODUCTTYPE"` // One of 401K, 403B, IRA, KEOGH, OTHER, SARSEP, SIMPLE, NORMAL, TDA, TRUST, UGMA - Checking Boolean `xml:"CHECKING"` // Has check-writing privileges - SvcStatus String `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE - InvAcctType String `xml:"INVACCTTYPE,omitempty"` // One of INDIVIDUAL, JOINT, TRUST, CORPORATE - OptionLevel String `xml:"OPTIONLEVEL,omitempty"` // Text desribing option trading privileges + XMLName xml.Name `xml:"INVACCTINFO"` + InvAcctFrom InvAcct `xml:"INVACCTFROM"` + UsProductType usProductType `xml:"USPRODUCTTYPE"` // One of 401K, 403B, IRA, KEOGH, OTHER, SARSEP, SIMPLE, NORMAL, TDA, TRUST, UGMA + Checking Boolean `xml:"CHECKING"` // Has check-writing privileges + SvcStatus svcStatus `xml:"SVCSTATUS"` // One of AVAIL (available, but not yet requested), PEND (requested, but not yet available), ACTIVE + InvAcctType acctClassification `xml:"INVACCTTYPE,omitempty"` // One of INDIVIDUAL, JOINT, TRUST, CORPORATE + OptionLevel String `xml:"OPTIONLEVEL,omitempty"` // Text desribing option trading privileges } // Make pointers to these structs print nicely diff --git a/signup_test.go b/signup_test.go index 2d83ebd..ed4f27e 100644 --- a/signup_test.go +++ b/signup_test.go @@ -126,12 +126,12 @@ func TestUnmarshalAcctInfoResponse(t *testing.T) { BankAcctFrom: ofxgo.BankAcct{ BankId: "8367556009", AcctId: "000999847", - AcctType: "MONEYMRKT", + AcctType: ofxgo.AcctTypeMoneyMrkt, }, SupTxDl: true, XferSrc: true, XferDest: true, - SvcStatus: "ACTIVE", + SvcStatus: ofxgo.SvcStatusActive, } acctInfoResponse := ofxgo.AcctInfoResponse{