From 7f5ef5751dbd178b8d27ea81d3c1265c3d754c44 Mon Sep 17 00:00:00 2001 From: Aaron Lindsay Date: Mon, 3 Apr 2017 21:15:08 -0400 Subject: [PATCH] Switch Amount to contain big.Rat instead of being a typedef --- bank_test.go | 13 +++--- cmd/ofx/invtransactions.go | 3 +- creditcard_test.go | 15 +++--- invstmt_test.go | 95 +++++++++++++++++++------------------- types.go | 16 +++---- types_test.go | 28 +++++------ 6 files changed, 80 insertions(+), 90 deletions(-) diff --git a/bank_test.go b/bank_test.go index 13260de..fb0142f 100644 --- a/bank_test.go +++ b/bank_test.go @@ -2,7 +2,6 @@ package ofxgo_test import ( "github.com/aclindsa/ofxgo" - "math/big" "strings" "testing" "time" @@ -153,7 +152,7 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { expected.Signon.Org = "BNK" expected.Signon.Fid = "1987" - var trnamt1, trnamt2 big.Rat + var trnamt1, trnamt2 ofxgo.Amount trnamt1.SetFrac64(-20000, 100) trnamt2.SetFrac64(-30000, 100) dtuser2 := ofxgo.Date(time.Date(2006, 1, 12, 0, 0, 0, 0, GMT)) @@ -165,7 +164,7 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { { TrnType: "CHECK", DtPosted: ofxgo.Date(time.Date(2006, 1, 4, 0, 0, 0, 0, GMT)), - TrnAmt: ofxgo.Amount(trnamt1), + TrnAmt: trnamt1, FiTId: "00592", CheckNum: "2002", }, @@ -173,13 +172,13 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { TrnType: "ATM", DtPosted: ofxgo.Date(time.Date(2006, 1, 12, 0, 0, 0, 0, GMT)), DtUser: &dtuser2, - TrnAmt: ofxgo.Amount(trnamt2), + TrnAmt: trnamt2, FiTId: "00679", }, }, } - var balamt, availbalamt big.Rat + var balamt, availbalamt ofxgo.Amount balamt.SetFrac64(20029, 100) availbalamt.SetFrac64(20029, 100) @@ -198,9 +197,9 @@ func TestUnmarshalBankStatementResponse(t *testing.T) { AcctType: "CHECKING", }, BankTranList: &banktranlist, - BalAmt: ofxgo.Amount(balamt), + BalAmt: balamt, DtAsOf: ofxgo.Date(time.Date(2006, 1, 14, 16, 0, 0, 0, GMT)), - AvailBalAmt: (*ofxgo.Amount)(&availbalamt), + AvailBalAmt: &availbalamt, AvailDtAsOf: &availdtasof, } expected.Bank = append(expected.Bank, &statementResponse) diff --git a/cmd/ofx/invtransactions.go b/cmd/ofx/invtransactions.go index ffbdc74..9b8aff6 100644 --- a/cmd/ofx/invtransactions.go +++ b/cmd/ofx/invtransactions.go @@ -4,7 +4,6 @@ import ( "flag" "fmt" "github.com/aclindsa/ofxgo" - "math/big" "os" ) @@ -65,7 +64,7 @@ func invTransactions() { } if stmt, ok := response.InvStmt[0].(*ofxgo.InvStatementResponse); ok { - availCash := big.Rat(stmt.InvBal.AvailCash) + availCash := stmt.InvBal.AvailCash if availCash.IsInt() && availCash.Num().Int64() != 0 { fmt.Printf("Balance: %s %s (as of %s)\n", stmt.InvBal.AvailCash, stmt.CurDef, stmt.DtAsOf) } diff --git a/creditcard_test.go b/creditcard_test.go index 7a68633..8219179 100644 --- a/creditcard_test.go +++ b/creditcard_test.go @@ -2,7 +2,6 @@ package ofxgo_test import ( "github.com/aclindsa/ofxgo" - "math/big" "strings" "testing" "time" @@ -99,7 +98,7 @@ NEWFILEUID:NONE expected.Signon.Org = "01" expected.Signon.Fid = "81729" - var trnamt1, trnamt2, trnamt3 big.Rat + var trnamt1, trnamt2, trnamt3 ofxgo.Amount trnamt1.SetFrac64(-796, 100) trnamt2.SetFrac64(383046, 100) trnamt3.SetFrac64(-1770, 100) @@ -111,28 +110,28 @@ NEWFILEUID:NONE { TrnType: "DEBIT", DtPosted: ofxgo.Date(time.Date(2017, 2, 9, 12, 0, 0, 0, GMT)), - TrnAmt: ofxgo.Amount(trnamt1), + TrnAmt: trnamt1, FiTId: "2017020924435657040207171600195", Name: "SLICE OF NY", }, { TrnType: "CREDIT", DtPosted: ofxgo.Date(time.Date(2016, 12, 28, 12, 0, 0, 0, GMT)), - TrnAmt: ofxgo.Amount(trnamt2), + TrnAmt: trnamt2, FiTId: "2016122823633637200000258482730", Name: "Payment Thank You Electro", }, { TrnType: "DEBIT", DtPosted: ofxgo.Date(time.Date(2017, 3, 27, 12, 0, 0, 0, GMT)), - TrnAmt: ofxgo.Amount(trnamt3), + TrnAmt: trnamt3, FiTId: "2017032724445727085300442885680", Name: "KROGER FUEL #9999", }, }, } - var balamt, availbalamt big.Rat + var balamt, availbalamt ofxgo.Amount balamt.SetFrac64(-933400, 100) availbalamt.SetFrac64(763017, 100) @@ -149,9 +148,9 @@ NEWFILEUID:NONE AcctId: "9283744488463775", }, BankTranList: &banktranlist, - BalAmt: ofxgo.Amount(balamt), + BalAmt: balamt, DtAsOf: ofxgo.Date(time.Date(2017, 3, 31, 8, 0, 0, 0, EDT)), - AvailBalAmt: (*ofxgo.Amount)(&availbalamt), + AvailBalAmt: &availbalamt, AvailDtAsOf: &availdtasof, } expected.CreditCard = append(expected.CreditCard, &statementResponse) diff --git a/invstmt_test.go b/invstmt_test.go index ec06697..34f1822 100644 --- a/invstmt_test.go +++ b/invstmt_test.go @@ -2,7 +2,6 @@ package ofxgo_test import ( "github.com/aclindsa/ofxgo" - "math/big" "strings" "testing" "time" @@ -308,7 +307,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { expected.Signon.Org = "INVSTRUS" expected.Signon.Fid = "9999" - var units1, unitprice1, commission1, total1, amount2 big.Rat + var units1, unitprice1, commission1, total1, amount2 ofxgo.Amount units1.SetFrac64(100, 1) unitprice1.SetFrac64(229, 1) commission1.SetFrac64(9, 1) @@ -334,10 +333,10 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueId: "78462F103", UniqueIdType: "CUSIP", }, - Units: ofxgo.Amount(units1), - UnitPrice: ofxgo.Amount(unitprice1), - Commission: ofxgo.Amount(commission1), - Total: ofxgo.Amount(total1), + Units: units1, + UnitPrice: unitprice1, + Commission: commission1, + Total: total1, SubAcctSec: "CASH", SubAcctFund: "CASH", }, @@ -352,7 +351,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { DtPosted: ofxgo.Date(time.Date(2017, 1, 20, 0, 0, 0, 0, GMT)), DtUser: &dtuser, DtAvail: &dtavail, - TrnAmt: ofxgo.Amount(amount2), + TrnAmt: amount2, FiTId: "993838", Name: "DEPOSIT", Memo: "CHECK 19980", @@ -363,7 +362,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { }, } - var availcash, marginbalance, shortbalance, balvalue big.Rat + var availcash, marginbalance, shortbalance, balvalue ofxgo.Amount availcash.SetFrac64(1673, 100) marginbalance.SetFrac64(-8192, 10) shortbalance.SetFrac64(0, 1) @@ -372,21 +371,21 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { baldtasof := ofxgo.Date(time.Date(2017, 4, 1, 0, 0, 0, 0, GMT)) invbalance := ofxgo.InvBalance{ - AvailCash: ofxgo.Amount(availcash), - MarginBalance: ofxgo.Amount(marginbalance), - ShortBalance: ofxgo.Amount(shortbalance), + AvailCash: availcash, + MarginBalance: marginbalance, + ShortBalance: shortbalance, BalList: []ofxgo.Balance{ ofxgo.Balance{ Name: "Sweep Int Rate", Desc: "Current interest rate for sweep account balances", BalType: "PERCENT", - Value: ofxgo.Amount(balvalue), + Value: balvalue, DtAsOf: &baldtasof, }, }, } - var balamt, availbalamt, posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2, oounits1, oolimitprice1, oounits2, oolimitprice2 big.Rat + var balamt, availbalamt, posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2, oounits1, oolimitprice1, oounits2, oolimitprice2 ofxgo.Amount balamt.SetFrac64(20029, 100) availbalamt.SetFrac64(20029, 100) posunits1.SetFrac64(200, 1) @@ -422,9 +421,9 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { }, HeldInAcct: "CASH", PosType: "LONG", - Units: ofxgo.Amount(posunits1), - UnitPrice: ofxgo.Amount(posunitprice1), - MktVal: ofxgo.Amount(posmktval1), + Units: posunits1, + UnitPrice: posunitprice1, + MktVal: posmktval1, DtPriceAsOf: ofxgo.Date(time.Date(2017, 3, 31, 16, 0, 0, 0, GMT)), Memo: "Price as of previous close", }, @@ -437,9 +436,9 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { }, HeldInAcct: "CASH", PosType: "LONG", - Units: ofxgo.Amount(posunits2), - UnitPrice: ofxgo.Amount(posunitprice2), - MktVal: ofxgo.Amount(posmktval2), + Units: posunits2, + UnitPrice: posunitprice2, + MktVal: posmktval2, DtPriceAsOf: ofxgo.Date(time.Date(2017, 3, 31, 16, 0, 0, 0, GMT)), }, }, @@ -454,11 +453,11 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueIdType: "CUSIP", }, DtPlaced: ofxgo.Date(time.Date(2017, 3, 10, 12, 44, 45, 0, GMT)), - Units: ofxgo.Amount(oounits1), + Units: oounits1, SubAcct: "CASH", Duration: "GOODTILCANCEL", Restriction: "NONE", - LimitPrice: ofxgo.Amount(oolimitprice1), + LimitPrice: oolimitprice1, }, BuyType: "BUY", UnitType: "SHARES", @@ -471,11 +470,11 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { UniqueIdType: "CUSIP", }, DtPlaced: ofxgo.Date(time.Date(2017, 3, 24, 3, 19, 0, 0, GMT)), - Units: ofxgo.Amount(oounits2), + Units: oounits2, SubAcct: "CASH", Duration: "GOODTILCANCEL", Restriction: "ALLORNONE", - LimitPrice: ofxgo.Amount(oolimitprice2), + LimitPrice: oolimitprice2, }, BuyType: "BUY", }, @@ -483,7 +482,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { } expected.InvStmt = append(expected.InvStmt, &statementResponse) - var yield1, yield2, strikeprice big.Rat + var yield1, yield2, strikeprice ofxgo.Amount yield1.SetFrac64(192, 100) yield2.SetFrac64(17, 1) strikeprice.SetFrac64(79, 1) @@ -500,7 +499,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { Ticker: "SPY", FiId: "99184", }, - Yield: ofxgo.Amount(yield1), + Yield: yield1, AssetClass: "OTHER", }, ofxgo.OptInfo{ @@ -514,7 +513,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { FiId: "882919", }, OptType: "PUT", - StrikePrice: ofxgo.Amount(strikeprice), + StrikePrice: strikeprice, DtExpire: ofxgo.Date(time.Date(2017, 9, 1, 0, 0, 0, 0, GMT)), ShPerCtrct: 100, SecId: &ofxgo.SecurityId{ @@ -533,7 +532,7 @@ func TestUnmarshalInvStatementResponse(t *testing.T) { Ticker: "WHAT", FiId: "883897", }, - Yield: ofxgo.Amount(yield2), + Yield: yield2, AssetClass: "SMALLSTOCK", }, ofxgo.MFInfo{ @@ -734,7 +733,7 @@ NEWFILEUID: NONE expected.Signon.Fid = "1000" // Ignored 1000 - var units1, unitprice1, commission1, fees1, total1, units2, units3 big.Rat + var units1, unitprice1, commission1, fees1, total1, units2, units3 ofxgo.Amount units1.SetFrac64(-1, 1) unitprice1.SetFrac64(35, 100) commission1.SetFrac64(885, 100) @@ -762,11 +761,11 @@ NEWFILEUID: NONE UniqueId: "SPY161216C00226000", UniqueIdType: "CUSIP", }, - Units: ofxgo.Amount(units1), - UnitPrice: ofxgo.Amount(unitprice1), - Commission: ofxgo.Amount(commission1), - Fees: ofxgo.Amount(fees1), - Total: ofxgo.Amount(total1), + Units: units1, + UnitPrice: unitprice1, + Commission: commission1, + Fees: fees1, + Total: total1, SubAcctSec: "CASH", SubAcctFund: "CASH", }, @@ -784,7 +783,7 @@ NEWFILEUID: NONE UniqueIdType: "CUSIP", }, OptAction: "ASSIGN", - Units: ofxgo.Amount(units2), + Units: units2, ShPerCtrct: 100, SubAcctSec: "CASH", }, @@ -799,25 +798,25 @@ NEWFILEUID: NONE UniqueIdType: "CUSIP", }, OptAction: "ASSIGN", - Units: ofxgo.Amount(units3), + Units: units3, ShPerCtrct: 100, SubAcctSec: "CASH", }, }, } - var availcash, marginbalance, shortbalance big.Rat + var availcash, marginbalance, shortbalance ofxgo.Amount availcash.SetFrac64(0, 1) marginbalance.SetFrac64(-0, 1) shortbalance.SetFrac64(0, 1) invbalance := ofxgo.InvBalance{ - AvailCash: ofxgo.Amount(availcash), - MarginBalance: ofxgo.Amount(marginbalance), - ShortBalance: ofxgo.Amount(shortbalance), + AvailCash: availcash, + MarginBalance: marginbalance, + ShortBalance: shortbalance, } - var posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2 big.Rat + var posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2 ofxgo.Amount posunits1.SetFrac64(100, 1) posunitprice1.SetFrac64(79, 1) posmktval1.SetFrac64(79000, 1) @@ -847,9 +846,9 @@ NEWFILEUID: NONE }, HeldInAcct: "CASH", PosType: "LONG", - Units: ofxgo.Amount(posunits1), - UnitPrice: ofxgo.Amount(posunitprice1), - MktVal: ofxgo.Amount(posmktval1), + Units: posunits1, + UnitPrice: posunitprice1, + MktVal: posmktval1, DtPriceAsOf: ofxgo.Date(time.Date(2017, 4, 3, 12, 0, 0, 0, GMT)), }, }, @@ -861,9 +860,9 @@ NEWFILEUID: NONE }, HeldInAcct: "CASH", PosType: "LONG", - Units: ofxgo.Amount(posunits2), - UnitPrice: ofxgo.Amount(posunitprice2), - MktVal: ofxgo.Amount(posmktval2), + Units: posunits2, + UnitPrice: posunitprice2, + MktVal: posmktval2, DtPriceAsOf: ofxgo.Date(time.Date(2017, 4, 3, 12, 0, 0, 0, GMT)), }, }, @@ -872,7 +871,7 @@ NEWFILEUID: NONE } expected.InvStmt = append(expected.InvStmt, &statementResponse) - var strikeprice big.Rat + var strikeprice ofxgo.Amount strikeprice.SetFrac64(226, 1) seclist := ofxgo.SecurityList{ @@ -897,7 +896,7 @@ NEWFILEUID: NONE Ticker: "SPY 161216C00226000", }, OptType: "CALL", - StrikePrice: ofxgo.Amount(strikeprice), + StrikePrice: strikeprice, DtExpire: ofxgo.Date(time.Date(2016, 12, 16, 12, 0, 0, 0, GMT)), ShPerCtrct: 100, }, diff --git a/types.go b/types.go index f31b4f9..c118a71 100644 --- a/types.go +++ b/types.go @@ -37,11 +37,12 @@ func (i Int) Equal(o Int) bool { return i == o } -type Amount big.Rat +type Amount struct { + big.Rat +} func (a *Amount) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var value string - var b big.Rat err := d.DecodeElement(&value, &start) if err != nil { @@ -54,16 +55,14 @@ func (a *Amount) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { // by a comma, so fix that up before attempting to parse it into big.Rat value = strings.Replace(value, ",", ".", 1) - if _, ok := b.SetString(value); !ok { - return errors.New("Failed to parse OFX amount into big.Rat") + if _, ok := a.SetString(value); !ok { + return errors.New("Failed to parse OFX amount") } - *a = Amount(b) return nil } func (a Amount) String() string { - var b big.Rat = big.Rat(a) - return strings.TrimRight(strings.TrimRight(b.FloatString(100), "0"), ".") + return strings.TrimRight(strings.TrimRight(a.FloatString(100), "0"), ".") } func (a *Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) error { @@ -71,8 +70,7 @@ func (a *Amount) MarshalXML(e *xml.Encoder, start xml.StartElement) error { } func (a Amount) Equal(o Amount) bool { - ratA := (*big.Rat)(&a) - return ratA.Cmp((*big.Rat)(&o)) == 0 + return (&a).Cmp(&o.Rat) == 0 } type Date time.Time diff --git a/types_test.go b/types_test.go index 5b0d357..fb302f3 100644 --- a/types_test.go +++ b/types_test.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/aclindsa/go/src/encoding/xml" "github.com/aclindsa/ofxgo" - "math/big" "reflect" "testing" "time" @@ -76,50 +75,47 @@ func TestUnmarshalInt(t *testing.T) { func TestMarshalAmount(t *testing.T) { var a ofxgo.Amount - var b *big.Rat = (*big.Rat)(&a) - b.SetFrac64(8, 1) + a.SetFrac64(8, 1) marshalHelper(t, "8", &a) - b.SetFrac64(1, 8) + a.SetFrac64(1, 8) marshalHelper(t, "0.125", &a) - b.SetFrac64(-1, 200) + a.SetFrac64(-1, 200) marshalHelper(t, "-0.005", &a) - b.SetInt64(0) + a.SetInt64(0) marshalHelper(t, "0", &a) - b.SetInt64(-768276587425) + a.SetInt64(-768276587425) marshalHelper(t, "-768276587425", &a) - b.SetFrac64(1, 12) + a.SetFrac64(1, 12) marshalHelper(t, "0.0833333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333", &a) } func TestUnmarshalAmount(t *testing.T) { var a, overwritten ofxgo.Amount - var b *big.Rat = (*big.Rat)(&a) // Amount/big.Rat needs a special equality test because reflect.DeepEqual // doesn't always return equal for two values that big.Rat.Cmp() does eq := func(a, b interface{}) bool { if amountA, ok := a.(*ofxgo.Amount); ok { if amountB, ok2 := b.(*ofxgo.Amount); ok2 { - ratA := (*big.Rat)(amountA) - return ratA.Cmp((*big.Rat)(amountB)) == 0 + return amountA.Cmp(&amountB.Rat) == 0 } } return false } - b.SetFrac64(12, 1) + a.SetFrac64(12, 1) unmarshalHelper2(t, "12", &a, &overwritten, eq) - b.SetFrac64(-21309, 100) + a.SetFrac64(-21309, 100) unmarshalHelper2(t, "-213.09", &a, &overwritten, eq) - b.SetFrac64(8192, 1000) + a.SetFrac64(8192, 1000) unmarshalHelper2(t, "8.192", &a, &overwritten, eq) unmarshalHelper2(t, "+8.192", &a, &overwritten, eq) - b.SetInt64(0) + a.SetInt64(0) unmarshalHelper2(t, "0", &a, &overwritten, eq) unmarshalHelper2(t, "+0", &a, &overwritten, eq) unmarshalHelper2(t, "-0", &a, &overwritten, eq) - b.SetInt64(-19487135) + a.SetInt64(-19487135) unmarshalHelper2(t, "-19487135", &a, &overwritten, eq) // Make sure stray newlines are handled properly unmarshalHelper2(t, "-19487135\n", &a, &overwritten, eq)