Move credit cards to the right message set

They don't belong in with the banking message set like they were, even
though they're in the same section in the spec...
This commit is contained in:
Aaron Lindsay 2017-03-22 20:01:30 -04:00
parent 753249c16e
commit 6491311dbc
4 changed files with 113 additions and 79 deletions

View File

@ -6,14 +6,14 @@ import (
)
type StatementRequest struct {
XMLName xml.Name `xml:"STMTTRNRQ"`
TrnUID UID `xml:"TRNUID"`
BankAcctFrom BankAcct `xml:"STMTRQ>BANKACCTFROM"`
DtStart Date `xml:"STMTRQ>INCTRAN>DTSTART,omitempty"`
DtEnd Date `xml:"STMTRQ>INCTRAN>DTEND,omitempty"`
Include Boolean `xml:"STMTRQ>INCTRAN>INCLUDE"` // Include transactions (instead of just balance)
IncludePending Boolean `xml:"STMTRQ>INCLUDEPENDING,omitempty"` // Include pending transactions
IncludeTranImage Boolean `xml:"STMTRQ>INCLUDETRANIMAGE,omitempty"` // Include transaction images
XMLName xml.Name `xml:"STMTTRNRQ"`
TrnUID UID `xml:"TRNUID"`
BankAcctFrom BankAcct `xml:"STMTRQ>BANKACCTFROM"`
DtStart Date `xml:"STMTRQ>INCTRAN>DTSTART,omitempty"`
DtEnd Date `xml:"STMTRQ>INCTRAN>DTEND,omitempty"`
Include Boolean `xml:"STMTRQ>INCTRAN>INCLUDE"` // Include transactions (instead of just balance)
IncludePending Boolean `xml:"STMTRQ>INCLUDEPENDING,omitempty"` // Include pending transactions
IncTranImg Boolean `xml:"STMTRQ>INCTRANIMG,omitempty"` // Include transaction images
}
func (r *StatementRequest) Name() string {
@ -27,28 +27,6 @@ func (r *StatementRequest) Valid() (bool, error) {
return true, nil
}
type CCStatementRequest struct {
XMLName xml.Name `xml:"CCSTMTTRNRQ"`
TrnUID UID `xml:"TRNUID"`
CCAcctFrom CCAcct `xml:"CCSTMTRQ>CCACCTFROM"`
DtStart Date `xml:"CCSTMTRQ>INCTRAN>DTSTART,omitempty"`
DtEnd Date `xml:"CCSTMTRQ>INCTRAN>DTEND,omitempty"`
Include Boolean `xml:"CCSTMTRQ>INCTRAN>INCLUDE"` // Include transactions (instead of just balance)
IncludePending Boolean `xml:"CCSTMTRQ>INCLUDEPENDING,omitempty"` // Include pending transactions
IncludeTranImage Boolean `xml:"CCSTMTRQ>INCLUDETRANIMAGE,omitempty"` // Include transaction images
}
func (r *CCStatementRequest) Name() string {
return "CCSTMTTRNRQ"
}
func (r *CCStatementRequest) Valid() (bool, error) {
if ok, err := r.TrnUID.Valid(); !ok {
return false, err
}
return true, nil
}
type Payee struct {
XMLName xml.Name `xml:"PAYEE"`
Name String `xml:"NAME"`
@ -173,37 +151,6 @@ func (sr StatementResponse) Valid() (bool, error) {
return true, nil
}
type CCStatementResponse struct {
XMLName xml.Name `xml:"CCSTMTTRNRS"`
TrnUID UID `xml:"TRNUID"`
CurDef String `xml:"CCSTMTRS>CURDEF"`
CCAcctFrom CCAcct `xml:"CCSTMTRS>CCACCTFROM"`
BankTranList TransactionList `xml:"CCSTMTRS>BANKTRANLIST,omitempty"`
//BANKTRANLISTP
BalAmt Amount `xml:"CCSTMTRS>LEDGERBAL>BALAMT"`
DtAsOf Date `xml:"CCSTMTRS>LEDGERBAL>DTASOF"`
AvailBalAmt Amount `xml:"CCSTMTRS>AVAILBAL>BALAMT,omitempty"`
AvailDtAsOf Date `xml:"CCSTMTRS>AVAILBAL>DTASOF,omitempty"`
CashAdvBalAmt Amount `xml:"CCSTMTRS>CASHADVBALAMT,omitempty"` // Only for CREDITLINE accounts, available balance for cash advances
IntRatePurch Amount `xml:"CCSTMTRS>INTRATEPURCH,omitempty"` // Current interest rate for purchases
IntRateCash Amount `xml:"CCSTMTRS>INTRATECASH,omitempty"` // Current interest rate for cash advances
IntRateXfer Amount `xml:"CCSTMTRS>INTRATEXFER,omitempty"` // Current interest rate for cash advances
RewardName String `xml:"CCSTMTRS>REWARDINFO>NAME,omitempty"` // Name of the reward program referred to by the next two elements
RewardBal Amount `xml:"CCSTMTRS>REWARDINFO>REWARDBAL,omitempty"` // Current balance of the reward program
RewardEarned Amount `xml:"CCSTMTRS>REWARDINFO>REWARDEARNED,omitempty"` // Reward amount earned YTD
BalList []Balance `xml:"CCSTMTRS>BALLIST>BAL,omitempty"`
MktgInfo String `xml:"CCSTMTRS>MKTGINFO,omitempty"` // Marketing information
}
func (sr CCStatementResponse) Name() string {
return "CCSTMTTRNRS"
}
func (sr CCStatementResponse) Valid() (bool, error) {
//TODO implement
return true, nil
}
func DecodeBankingMessageSet(d *xml.Decoder, start xml.StartElement) ([]Message, error) {
var msgs []Message
for {
@ -221,12 +168,6 @@ func DecodeBankingMessageSet(d *xml.Decoder, start xml.StartElement) ([]Message,
return nil, err
}
msgs = append(msgs, Message(info))
case "CCSTMTTRNRS":
var info CCStatementResponse
if err := d.DecodeElement(&info, &startElement); err != nil {
return nil, err
}
msgs = append(msgs, Message(info))
default:
return nil, errors.New("Unsupported banking response tag: " + startElement.Name.Local)
}

85
creditcards.go Normal file
View File

@ -0,0 +1,85 @@
package ofxgo
import (
"errors"
"github.com/golang/go/src/encoding/xml"
)
type CCStatementRequest struct {
XMLName xml.Name `xml:"CCSTMTTRNRQ"`
TrnUID UID `xml:"TRNUID"`
CCAcctFrom CCAcct `xml:"CCSTMTRQ>CCACCTFROM"`
DtStart Date `xml:"CCSTMTRQ>INCTRAN>DTSTART,omitempty"`
DtEnd Date `xml:"CCSTMTRQ>INCTRAN>DTEND,omitempty"`
Include Boolean `xml:"CCSTMTRQ>INCTRAN>INCLUDE"` // Include transactions (instead of just balance)
IncludePending Boolean `xml:"CCSTMTRQ>INCLUDEPENDING,omitempty"` // Include pending transactions
IncTranImg Boolean `xml:"CCSTMTRQ>INCTRANIMG,omitempty"` // Include transaction images
}
func (r *CCStatementRequest) Name() string {
return "CCSTMTTRNRQ"
}
func (r *CCStatementRequest) Valid() (bool, error) {
if ok, err := r.TrnUID.Valid(); !ok {
return false, err
}
return true, nil
}
type CCStatementResponse struct {
XMLName xml.Name `xml:"CCSTMTTRNRS"`
TrnUID UID `xml:"TRNUID"`
CurDef String `xml:"CCSTMTRS>CURDEF"`
CCAcctFrom CCAcct `xml:"CCSTMTRS>CCACCTFROM"`
BankTranList TransactionList `xml:"CCSTMTRS>BANKTRANLIST,omitempty"`
//BANKTRANLISTP
BalAmt Amount `xml:"CCSTMTRS>LEDGERBAL>BALAMT"`
DtAsOf Date `xml:"CCSTMTRS>LEDGERBAL>DTASOF"`
AvailBalAmt Amount `xml:"CCSTMTRS>AVAILBAL>BALAMT,omitempty"`
AvailDtAsOf Date `xml:"CCSTMTRS>AVAILBAL>DTASOF,omitempty"`
CashAdvBalAmt Amount `xml:"CCSTMTRS>CASHADVBALAMT,omitempty"` // Only for CREDITLINE accounts, available balance for cash advances
IntRatePurch Amount `xml:"CCSTMTRS>INTRATEPURCH,omitempty"` // Current interest rate for purchases
IntRateCash Amount `xml:"CCSTMTRS>INTRATECASH,omitempty"` // Current interest rate for cash advances
IntRateXfer Amount `xml:"CCSTMTRS>INTRATEXFER,omitempty"` // Current interest rate for cash advances
RewardName String `xml:"CCSTMTRS>REWARDINFO>NAME,omitempty"` // Name of the reward program referred to by the next two elements
RewardBal Amount `xml:"CCSTMTRS>REWARDINFO>REWARDBAL,omitempty"` // Current balance of the reward program
RewardEarned Amount `xml:"CCSTMTRS>REWARDINFO>REWARDEARNED,omitempty"` // Reward amount earned YTD
BalList []Balance `xml:"CCSTMTRS>BALLIST>BAL,omitempty"`
MktgInfo String `xml:"CCSTMTRS>MKTGINFO,omitempty"` // Marketing information
}
func (sr CCStatementResponse) Name() string {
return "CCSTMTTRNRS"
}
func (sr CCStatementResponse) Valid() (bool, error) {
//TODO implement
return true, nil
}
func DecodeCCMessageSet(d *xml.Decoder, start xml.StartElement) ([]Message, error) {
var msgs []Message
for {
tok, err := nextNonWhitespaceToken(d)
if err != nil {
return nil, err
} else if end, ok := tok.(xml.EndElement); ok && end.Name.Local == start.Name.Local {
// If we found the end of our starting element, we're done parsing
return msgs, nil
} else if startElement, ok := tok.(xml.StartElement); ok {
switch startElement.Name.Local {
case "CCSTMTTRNRS":
var info CCStatementResponse
if err := d.DecodeElement(&info, &startElement); err != nil {
return nil, err
}
msgs = append(msgs, Message(info))
default:
return nil, errors.New("Unsupported banking response tag: " + startElement.Name.Local)
}
} else {
return nil, errors.New("Didn't find an opening element")
}
}
}

View File

@ -7,12 +7,12 @@ import (
)
type Request struct {
URL string
Version string // OFX version string, overwritten in Client.Request()
Signon SignonRequest //<SIGNONMSGSETV1>
Signup []Message //<SIGNUPMSGSETV1>
Banking []Message //<BANKMSGSETV1>
//<CREDITCARDMSGSETV1>
URL string
Version string // OFX version string, overwritten in Client.Request()
Signon SignonRequest //<SIGNONMSGSETV1>
Signup []Message //<SIGNUPMSGSETV1>
Banking []Message //<BANKMSGSETV1>
CreditCards []Message //<CREDITCARDMSGSETV1>
//<LOANMSGSETV1>
Investments []Message //<INVSTMTMSGSETV1>
//<INTERXFERMSGSETV1>
@ -106,6 +106,9 @@ NEWFILEUID:NONE
if err := marshalMessageSet(encoder, oq.Banking, "BANKMSGSRQV1"); err != nil {
return nil, err
}
if err := marshalMessageSet(encoder, oq.CreditCards, "CREDITCARDMSGSRQV1"); err != nil {
return nil, err
}
if err := marshalMessageSet(encoder, oq.Investments, "INVSTMTMSGSRQV1"); err != nil {
return nil, err
}

View File

@ -10,11 +10,11 @@ import (
)
type Response struct {
Version string // String for OFX header, defaults to 203
Signon SignonResponse //<SIGNONMSGSETV1>
Signup []Message //<SIGNUPMSGSETV1>
Banking []Message //<BANKMSGSETV1>
//<CREDITCARDMSGSETV1>
Version string // String for OFX header, defaults to 203
Signon SignonResponse //<SIGNONMSGSETV1>
Signup []Message //<SIGNUPMSGSETV1>
Banking []Message //<BANKMSGSETV1>
CreditCards []Message //<CREDITCARDMSGSETV1>
//<LOANMSGSETV1>
Investments []Message //<INVSTMTMSGSETV1>
//<INTERXFERMSGSETV1>
@ -269,7 +269,12 @@ func ParseResponse(reader io.Reader) (*Response, error) {
return nil, err
}
or.Banking = msgs
//case "CREDITCARDMSGSRSV1":
case "CREDITCARDMSGSRSV1":
msgs, err := DecodeCCMessageSet(decoder, start)
if err != nil {
return nil, err
}
or.CreditCards = msgs
//case "LOANMSGSRSV1":
case "INVSTMTMSGSRSV1":
msgs, err := DecodeInvestmentsMessageSet(decoder, start)