1
0
mirror of https://github.com/aclindsa/moneygo.git synced 2025-06-14 13:58:37 -04:00

Store currency/security values/prices using big.Rat natively

This adds 'shadow' types used only by the store/db internal package whch
handle converting these types to their DB-equivalent values. This change
should allow reports to be generated significantly faster since it
allows a large portion of the computation to be shifted to the database
engines.
This commit is contained in:
2017-12-12 19:40:38 -05:00
parent 483adb5c56
commit a357d38eee
22 changed files with 695 additions and 201 deletions

View File

@ -202,6 +202,19 @@ func uploadFile(client *http.Client, filename, urlsuffix string) error {
return nil
}
func NewAmount(amt string) models.Amount {
var a models.Amount
if _, ok := a.SetString(amt); !ok {
panic("Unable to call Amount.SetString()")
}
return a
}
func amountsMatch(a models.Amount, amt string) bool {
cmp := NewAmount(amt)
return a.Cmp(&cmp.Rat) == 0
}
func accountBalanceHelper(t *testing.T, client *http.Client, account *models.Account, balance string) {
t.Helper()
transactions, err := getAccountTransactions(client, account.AccountId, 0, 0, "")
@ -209,7 +222,7 @@ func accountBalanceHelper(t *testing.T, client *http.Client, account *models.Acc
t.Fatalf("Couldn't fetch account transactions for '%s': %s\n", account.Name, err)
}
if transactions.EndingBalance != balance {
if !amountsMatch(transactions.EndingBalance, balance) {
t.Errorf("Expected ending balance for '%s' to be '%s', but found %s\n", account.Name, balance, transactions.EndingBalance)
}
}

View File

@ -114,11 +114,11 @@ func TestImportGnucash(t *testing.T) {
}
var p1787, p2894, p3170 bool
for _, price := range *prices.Prices {
if price.CurrencyId == d.securities[0].SecurityId && price.Value == "17.87" {
if price.CurrencyId == d.securities[0].SecurityId && amountsMatch(price.Value, "17.87") {
p1787 = true
} else if price.CurrencyId == d.securities[0].SecurityId && price.Value == "28.94" {
} else if price.CurrencyId == d.securities[0].SecurityId && amountsMatch(price.Value, "28.94") {
p2894 = true
} else if price.CurrencyId == d.securities[0].SecurityId && price.Value == "31.70" {
} else if price.CurrencyId == d.securities[0].SecurityId && amountsMatch(price.Value, "31.70") {
p3170 = true
}
}

View File

@ -68,7 +68,7 @@ func TestCreatePrice(t *testing.T) {
if !p.Date.Equal(orig.Date) {
t.Errorf("Date doesn't match")
}
if p.Value != orig.Value {
if p.Value.Cmp(&orig.Value.Rat) != 0 {
t.Errorf("Value doesn't match")
}
if p.RemoteId != orig.RemoteId {
@ -98,7 +98,7 @@ func TestGetPrice(t *testing.T) {
if !p.Date.Equal(orig.Date) {
t.Errorf("Date doesn't match")
}
if p.Value != orig.Value {
if p.Value.Cmp(&orig.Value.Rat) != 0 {
t.Errorf("Value doesn't match")
}
if p.RemoteId != orig.RemoteId {
@ -132,7 +132,7 @@ func TestGetPrices(t *testing.T) {
found := false
for _, p := range *pl.Prices {
if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date.Equal(orig.Date) && p.Value == orig.Value && p.RemoteId == orig.RemoteId {
if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date.Equal(orig.Date) && p.Value.Cmp(&orig.Value.Rat) == 0 && p.RemoteId == orig.RemoteId {
if _, ok := foundIds[p.PriceId]; ok {
continue
}
@ -146,7 +146,11 @@ func TestGetPrices(t *testing.T) {
}
}
if numprices != len(*pl.Prices) {
if pl.Prices == nil {
if numprices != 0 {
t.Fatalf("Expected %d prices, received 0", numprices)
}
} else if numprices != len(*pl.Prices) {
t.Fatalf("Expected %d prices, received %d", numprices, len(*pl.Prices))
}
}
@ -162,7 +166,7 @@ func TestUpdatePrice(t *testing.T) {
tmp := curr.SecurityId
curr.SecurityId = curr.CurrencyId
curr.CurrencyId = tmp
curr.Value = "5.55"
curr.Value = NewAmount("5.55")
curr.Date = time.Date(2019, time.June, 5, 12, 5, 6, 7, time.UTC)
curr.RemoteId = "something"
@ -181,7 +185,7 @@ func TestUpdatePrice(t *testing.T) {
if !p.Date.Equal(curr.Date) {
t.Errorf("Date doesn't match")
}
if p.Value != curr.Value {
if p.Value.Cmp(&curr.Value.Rat) != 0 {
t.Errorf("Value doesn't match")
}
if p.RemoteId != curr.RemoteId {

View File

@ -213,35 +213,35 @@ var data = []TestData{
SecurityId: 1,
CurrencyId: 0,
Date: time.Date(2017, time.January, 2, 21, 0, 0, 0, time.UTC),
Value: "225.24",
Value: NewAmount("225.24"),
RemoteId: "12387-129831-1238",
},
{
SecurityId: 1,
CurrencyId: 0,
Date: time.Date(2017, time.January, 3, 21, 0, 0, 0, time.UTC),
Value: "226.58",
Value: NewAmount("226.58"),
RemoteId: "12387-129831-1239",
},
{
SecurityId: 1,
CurrencyId: 0,
Date: time.Date(2017, time.January, 4, 21, 0, 0, 0, time.UTC),
Value: "226.40",
Value: NewAmount("226.40"),
RemoteId: "12387-129831-1240",
},
{
SecurityId: 1,
CurrencyId: 0,
Date: time.Date(2017, time.January, 5, 21, 0, 0, 0, time.UTC),
Value: "227.21",
Value: NewAmount("227.21"),
RemoteId: "12387-129831-1241",
},
{
SecurityId: 0,
CurrencyId: 3,
Date: time.Date(2017, time.November, 16, 18, 49, 53, 0, time.UTC),
Value: "0.85",
Value: NewAmount("0.85"),
RemoteId: "USDEUR819298714",
},
},
@ -313,13 +313,13 @@ var data = []TestData{
Status: models.Reconciled,
AccountId: 1,
SecurityId: -1,
Amount: "-5.6",
Amount: NewAmount("-5.6"),
},
{
Status: models.Reconciled,
AccountId: 3,
SecurityId: -1,
Amount: "5.6",
Amount: NewAmount("5.6"),
},
},
},
@ -332,13 +332,13 @@ var data = []TestData{
Status: models.Reconciled,
AccountId: 1,
SecurityId: -1,
Amount: "-81.59",
Amount: NewAmount("-81.59"),
},
{
Status: models.Reconciled,
AccountId: 3,
SecurityId: -1,
Amount: "81.59",
Amount: NewAmount("81.59"),
},
},
},
@ -351,13 +351,13 @@ var data = []TestData{
Status: models.Reconciled,
AccountId: 1,
SecurityId: -1,
Amount: "-39.99",
Amount: NewAmount("-39.99"),
},
{
Status: models.Entered,
AccountId: 4,
SecurityId: -1,
Amount: "39.99",
Amount: NewAmount("39.99"),
},
},
},
@ -370,13 +370,13 @@ var data = []TestData{
Status: models.Reconciled,
AccountId: 5,
SecurityId: -1,
Amount: "-24.56",
Amount: NewAmount("-24.56"),
},
{
Status: models.Entered,
AccountId: 6,
SecurityId: -1,
Amount: "24.56",
Amount: NewAmount("24.56"),
},
},
},

View File

@ -120,7 +120,7 @@ func ensureTransactionsMatch(t *testing.T, expected, tran *models.Transaction, a
origsplit.RemoteId == origsplit.RemoteId &&
origsplit.Number == s.Number &&
origsplit.Memo == s.Memo &&
origsplit.Amount == s.Amount &&
origsplit.Amount.Cmp(&s.Amount.Rat) == 0 &&
(!matchsplitids || origsplit.SplitId == s.SplitId) {
if _, ok := foundIds[s.SplitId]; ok {
@ -187,13 +187,13 @@ func TestCreateTransaction(t *testing.T) {
Status: models.Reconciled,
AccountId: d.accounts[1].AccountId,
SecurityId: -1,
Amount: "-39.98",
Amount: NewAmount("-39.98"),
},
{
Status: models.Entered,
AccountId: d.accounts[4].AccountId,
SecurityId: -1,
Amount: "39.99",
Amount: NewAmount("39.99"),
},
},
}
@ -333,7 +333,7 @@ func TestUpdateTransaction(t *testing.T) {
tran.UserId = curr.UserId
// Make sure we can't create an unbalanced transaction
tran.Splits[len(tran.Splits)-1].Amount = "42"
tran.Splits[len(tran.Splits)-1].Amount = NewAmount("42")
_, err = updateTransaction(d.clients[orig.UserId], tran)
if err == nil {
t.Fatalf("Expected error updating imbalanced transaction")