2017-03-14 10:31:14 -04:00
package ofxgo
import (
"errors"
2017-03-22 20:59:40 -04:00
"github.com/aclindsa/go/src/encoding/xml"
2017-03-14 10:31:14 -04:00
)
type StatementRequest struct {
2017-03-30 10:24:26 -04:00
XMLName xml . Name ` xml:"STMTTRNRQ" `
TrnUID UID ` xml:"TRNUID" `
CltCookie String ` xml:"CLTCOOKIE,omitempty" `
TAN String ` xml:"TAN,omitempty" ` // Transaction authorization number
// TODO `xml:"OFXEXTENSION,omitempty"`
2017-03-22 20:01:30 -04:00
BankAcctFrom BankAcct ` xml:"STMTRQ>BANKACCTFROM" `
2017-03-29 05:31:01 -04:00
DtStart * Date ` xml:"STMTRQ>INCTRAN>DTSTART,omitempty" `
DtEnd * Date ` xml:"STMTRQ>INCTRAN>DTEND,omitempty" `
2017-03-22 20:01:30 -04:00
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
2017-03-14 10:31:14 -04:00
}
func ( r * StatementRequest ) Name ( ) string {
return "STMTTRNRQ"
}
func ( r * StatementRequest ) Valid ( ) ( bool , error ) {
2017-03-29 05:41:28 -04:00
// TODO implement
2017-03-14 10:31:14 -04:00
return true , nil
}
type Payee struct {
XMLName xml . Name ` xml:"PAYEE" `
Name String ` xml:"NAME" `
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" `
Phone String ` xml:"PHONE" `
}
2017-03-17 21:35:42 -04:00
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)
// 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
2017-03-29 05:31:01 -04:00
DtImageAvail * Date ` xml:"DTIMAGEAVAIL,omitempty" ` // Date image will become available
2017-03-17 21:35:42 -04:00
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
}
2017-03-14 10:31:14 -04:00
type Transaction struct {
XMLName xml . Name ` xml:"STMTTRN" `
2017-03-17 21:35:42 -04:00
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
2017-03-14 10:31:14 -04:00
DtPosted Date ` xml:"DTPOSTED" `
2017-03-29 05:31:01 -04:00
DtUser * Date ` xml:"DTUSER,omitempty" `
DtAvail * Date ` xml:"DTAVAIL,omitempty" `
2017-03-14 10:31:14 -04:00
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" `
// Note: Servers should provide NAME or PAYEE, but not both
2017-03-17 21:35:42 -04:00
Name String ` xml:"NAME,omitempty" `
2017-03-29 05:31:01 -04:00
Payee * Payee ` xml:"PAYEE,omitempty" `
2017-03-17 21:35:42 -04:00
ExtdName String ` xml:"EXTDNAME,omitempty" ` // Extended name of payee or transaction description
2017-03-29 05:31:01 -04:00
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
2017-03-17 21:35:42 -04:00
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.)
2017-03-14 10:31:14 -04:00
}
type TransactionList struct {
XMLName xml . Name ` xml:"BANKTRANLIST" `
DtStart Date ` xml:"DTSTART" `
DtEnd Date ` xml:"DTEND" `
2017-03-17 21:35:42 -04:00
Transactions [ ] Transaction ` xml:"STMTTRN,omitempty" `
}
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
DtTran Date ` xml:"DTTRAN" `
2017-03-29 05:31:01 -04:00
DtExpire * Date ` xml:"DTEXPIRE,omitempty" ` // only valid for TrnType==HOLD, the date the hold will expire
2017-03-17 21:35:42 -04:00
TrnAmt Amount ` xml:"TRNAMT" `
RefNum String ` xml:"REFNUM,omitempty" `
Name String ` xml:"NAME,omitempty" `
ExtdName String ` xml:"EXTDNAME,omitempty" ` // Extended name of payee or transaction description
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
}
// List of pending transactions
type PendingTransactionList struct {
XMLName xml . Name ` xml:"BANKTRANLISTP" `
DtAsOf Date ` xml:"DTASOF" `
Transactions [ ] PendingTransaction ` xml:"STMTTRNP,omitempty" `
}
type Balance struct {
XMLName xml . Name ` xml:"BAL" `
Name String ` xml:"NAME" `
Desc String ` xml:"DESC" `
// Balance type:
// DOLLAR = dollar (value formatted DDDD.cc)
// PERCENT = percentage (value formatted XXXX.YYYY)
// NUMBER = number (value formatted as is)
BalType String ` xml:"BALTYPE" `
2017-03-29 05:31:01 -04:00
Value Amount ` xml:"VALUE" `
DtAsOf * Date ` xml:"DTASOF,omitempty" `
Currency * Currency ` xml:"CURRENCY,omitempty" ` // if BALTYPE is DOLLAR
2017-03-14 10:31:14 -04:00
}
type StatementResponse struct {
2017-03-30 10:24:26 -04:00
XMLName xml . Name ` xml:"STMTTRNRS" `
TrnUID UID ` xml:"TRNUID" `
Status Status ` xml:"STATUS" `
CltCookie String ` xml:"CLTCOOKIE,omitempty" `
// TODO `xml:"OFXEXTENSION,omitempty"`
2017-03-29 05:31:01 -04:00
CurDef String ` xml:"STMTRS>CURDEF" `
BankAcctFrom BankAcct ` xml:"STMTRS>BANKACCTFROM" `
BankTranList * TransactionList ` xml:"STMTRS>BANKTRANLIST,omitempty" `
BankTranListP * PendingTransactionList ` xml:"STMTRS>BANKTRANLISTP,omitempty" `
BalAmt Amount ` xml:"STMTRS>LEDGERBAL>BALAMT" `
DtAsOf Date ` xml:"STMTRS>LEDGERBAL>DTASOF" `
AvailBalAmt * Amount ` xml:"STMTRS>AVAILBAL>BALAMT,omitempty" `
AvailDtAsOf * Date ` xml:"STMTRS>AVAILBAL>DTASOF,omitempty" `
CashAdvBalAmt * Amount ` xml:"STMTRS>CASHADVBALAMT,omitempty" ` // Only for CREDITLINE accounts, available balance for cash advances
IntRate * Amount ` xml:"STMTRS>INTRATE,omitempty" ` // Current interest rate
BalList [ ] Balance ` xml:"STMTRS>BALLIST>BAL,omitempty" `
MktgInfo String ` xml:"STMTRS>MKTGINFO,omitempty" ` // Marketing information
2017-03-14 10:31:14 -04:00
}
func ( sr StatementResponse ) Name ( ) string {
return "STMTTRNRS"
}
func ( sr StatementResponse ) Valid ( ) ( bool , error ) {
//TODO implement
return true , nil
}
2017-03-17 21:35:42 -04:00
2017-03-25 06:23:30 -04:00
func decodeBankingMessageSet ( d * xml . Decoder , start xml . StartElement ) ( [ ] Message , error ) {
2017-03-14 10:31:14 -04:00
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 "STMTTRNRS" :
var info StatementResponse
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" )
}
}
}