mirror of
https://github.com/aclindsa/moneygo.git
synced 2024-10-31 16:00:05 -04:00
API: Move prices under securities
For example, instead of GETting /prices/5 to query a price with ID 5, you now must GET /securities/2/prices/5 (assuming price 5's SecurityId is 2)
This commit is contained in:
parent
81610adb72
commit
c48c50d2c5
@ -94,8 +94,6 @@ func (ah *APIHandler) route(r *http.Request) ResponseWriterWriter {
|
|||||||
return ah.txWrapper(SecurityHandler, r, context)
|
return ah.txWrapper(SecurityHandler, r, context)
|
||||||
case "securitytemplates":
|
case "securitytemplates":
|
||||||
return SecurityTemplateHandler(r, context)
|
return SecurityTemplateHandler(r, context)
|
||||||
case "prices":
|
|
||||||
return ah.txWrapper(PriceHandler, r, context)
|
|
||||||
case "accounts":
|
case "accounts":
|
||||||
return ah.txWrapper(AccountHandler, r, context)
|
return ah.txWrapper(AccountHandler, r, context)
|
||||||
case "transactions":
|
case "transactions":
|
||||||
|
@ -69,19 +69,19 @@ func CreatePriceIfNotExist(tx *Tx, price *Price) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPrice(tx *Tx, priceid, userid int64) (*Price, error) {
|
func GetPrice(tx *Tx, priceid, securityid int64) (*Price, error) {
|
||||||
var p Price
|
var p Price
|
||||||
err := tx.SelectOne(&p, "SELECT * from prices where PriceId=? AND SecurityId IN (SELECT SecurityId FROM securities WHERE UserId=?)", priceid, userid)
|
err := tx.SelectOne(&p, "SELECT * from prices where PriceId=? AND SecurityId=?", priceid, securityid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPrices(tx *Tx, userid int64) (*[]*Price, error) {
|
func GetPrices(tx *Tx, securityid int64) (*[]*Price, error) {
|
||||||
var prices []*Price
|
var prices []*Price
|
||||||
|
|
||||||
_, err := tx.Select(&prices, "SELECT * from prices where SecurityId IN (SELECT SecurityId FROM securities WHERE UserId=?)", userid)
|
_, err := tx.Select(&prices, "SELECT * from prices where SecurityId=?", securityid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -129,10 +129,10 @@ func GetClosestPrice(tx *Tx, security, currency *Security, date *time.Time) (*Pr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
func PriceHandler(r *http.Request, context *Context, user *User, securityid int64) ResponseWriterWriter {
|
||||||
user, err := GetUserFromSession(context.Tx, r)
|
security, err := GetSecurity(context.Tx, securityid, user.UserId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(1 /*Not Signed In*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
@ -142,8 +142,7 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
}
|
}
|
||||||
price.PriceId = -1
|
price.PriceId = -1
|
||||||
|
|
||||||
_, err = GetSecurity(context.Tx, price.SecurityId, user.UserId)
|
if price.SecurityId != security.SecurityId {
|
||||||
if err != nil {
|
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
_, err = GetSecurity(context.Tx, price.CurrencyId, user.UserId)
|
_, err = GetSecurity(context.Tx, price.CurrencyId, user.UserId)
|
||||||
@ -160,10 +159,10 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
return ResponseWrapper{201, &price}
|
return ResponseWrapper{201, &price}
|
||||||
} else if r.Method == "GET" {
|
} else if r.Method == "GET" {
|
||||||
if context.LastLevel() {
|
if context.LastLevel() {
|
||||||
//Return all prices
|
//Return all this security's prices
|
||||||
var pl PriceList
|
var pl PriceList
|
||||||
|
|
||||||
prices, err := GetPrices(context.Tx, user.UserId)
|
prices, err := GetPrices(context.Tx, security.SecurityId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
return NewError(999 /*Internal Error*/)
|
return NewError(999 /*Internal Error*/)
|
||||||
@ -178,7 +177,7 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
price, err := GetPrice(context.Tx, priceid, user.UserId)
|
price, err := GetPrice(context.Tx, priceid, security.SecurityId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
@ -212,7 +211,7 @@ func PriceHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
|
|
||||||
return &price
|
return &price
|
||||||
} else if r.Method == "DELETE" {
|
} else if r.Method == "DELETE" {
|
||||||
price, err := GetPrice(context.Tx, priceid, user.UserId)
|
price, err := GetPrice(context.Tx, priceid, security.SecurityId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
|
@ -10,22 +10,22 @@ import (
|
|||||||
|
|
||||||
func createPrice(client *http.Client, price *handlers.Price) (*handlers.Price, error) {
|
func createPrice(client *http.Client, price *handlers.Price) (*handlers.Price, error) {
|
||||||
var p handlers.Price
|
var p handlers.Price
|
||||||
err := create(client, price, &p, "/v1/prices/")
|
err := create(client, price, &p, "/v1/securities/"+strconv.FormatInt(price.SecurityId, 10)+"/prices/")
|
||||||
return &p, err
|
return &p, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrice(client *http.Client, priceid int64) (*handlers.Price, error) {
|
func getPrice(client *http.Client, priceid, securityid int64) (*handlers.Price, error) {
|
||||||
var p handlers.Price
|
var p handlers.Price
|
||||||
err := read(client, &p, "/v1/prices/"+strconv.FormatInt(priceid, 10))
|
err := read(client, &p, "/v1/securities/"+strconv.FormatInt(securityid, 10)+"/prices/"+strconv.FormatInt(priceid, 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrices(client *http.Client) (*handlers.PriceList, error) {
|
func getPrices(client *http.Client, securityid int64) (*handlers.PriceList, error) {
|
||||||
var pl handlers.PriceList
|
var pl handlers.PriceList
|
||||||
err := read(client, &pl, "/v1/prices/")
|
err := read(client, &pl, "/v1/securities/"+strconv.FormatInt(securityid, 10)+"/prices/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -34,7 +34,7 @@ func getPrices(client *http.Client) (*handlers.PriceList, error) {
|
|||||||
|
|
||||||
func updatePrice(client *http.Client, price *handlers.Price) (*handlers.Price, error) {
|
func updatePrice(client *http.Client, price *handlers.Price) (*handlers.Price, error) {
|
||||||
var p handlers.Price
|
var p handlers.Price
|
||||||
err := update(client, price, &p, "/v1/prices/"+strconv.FormatInt(price.PriceId, 10))
|
err := update(client, price, &p, "/v1/securities/"+strconv.FormatInt(price.SecurityId, 10)+"/prices/"+strconv.FormatInt(price.PriceId, 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ func updatePrice(client *http.Client, price *handlers.Price) (*handlers.Price, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func deletePrice(client *http.Client, p *handlers.Price) error {
|
func deletePrice(client *http.Client, p *handlers.Price) error {
|
||||||
err := remove(client, "/v1/prices/"+strconv.FormatInt(p.PriceId, 10))
|
err := remove(client, "/v1/securities/"+strconv.FormatInt(p.SecurityId, 10)+"/prices/"+strconv.FormatInt(p.PriceId, 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ func TestGetPrice(t *testing.T) {
|
|||||||
curr := d.prices[i]
|
curr := d.prices[i]
|
||||||
|
|
||||||
userid := data[0].securities[orig.SecurityId].UserId
|
userid := data[0].securities[orig.SecurityId].UserId
|
||||||
p, err := getPrice(d.clients[userid], curr.PriceId)
|
p, err := getPrice(d.clients[userid], curr.PriceId, curr.SecurityId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error fetching price: %s\n", err)
|
t.Fatalf("Error fetching price: %s\n", err)
|
||||||
}
|
}
|
||||||
@ -109,39 +109,45 @@ func TestGetPrice(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetPrices(t *testing.T) {
|
func TestGetPrices(t *testing.T) {
|
||||||
RunWith(t, &data[0], func(t *testing.T, d *TestData) {
|
RunWith(t, &data[0], func(t *testing.T, d *TestData) {
|
||||||
pl, err := getPrices(d.clients[0])
|
for origsecurityid, security := range d.securities {
|
||||||
if err != nil {
|
if data[0].securities[origsecurityid].UserId != 0 {
|
||||||
t.Fatalf("Error fetching prices: %s\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
numprices := 0
|
|
||||||
foundIds := make(map[int64]bool)
|
|
||||||
for i := 0; i < len(data[0].prices); i++ {
|
|
||||||
orig := data[0].prices[i]
|
|
||||||
|
|
||||||
if data[0].securities[orig.SecurityId].UserId != 0 {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
numprices += 1
|
|
||||||
|
|
||||||
found := false
|
pl, err := getPrices(d.clients[0], security.SecurityId)
|
||||||
for _, p := range *pl.Prices {
|
if err != nil {
|
||||||
if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date != orig.Date && p.Value != orig.Value && p.RemoteId != orig.RemoteId {
|
t.Fatalf("Error fetching prices: %s\n", err)
|
||||||
if _, ok := foundIds[p.PriceId]; ok {
|
}
|
||||||
continue
|
|
||||||
|
numprices := 0
|
||||||
|
foundIds := make(map[int64]bool)
|
||||||
|
for i := 0; i < len(data[0].prices); i++ {
|
||||||
|
orig := data[0].prices[i]
|
||||||
|
|
||||||
|
if orig.SecurityId != int64(origsecurityid) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
numprices += 1
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, p := range *pl.Prices {
|
||||||
|
if p.SecurityId == d.securities[orig.SecurityId].SecurityId && p.CurrencyId == d.securities[orig.CurrencyId].SecurityId && p.Date == orig.Date && p.Value == orig.Value && p.RemoteId == orig.RemoteId {
|
||||||
|
if _, ok := foundIds[p.PriceId]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
foundIds[p.PriceId] = true
|
||||||
|
found = true
|
||||||
|
break
|
||||||
}
|
}
|
||||||
foundIds[p.PriceId] = true
|
}
|
||||||
found = true
|
if !found {
|
||||||
break
|
t.Errorf("Unable to find matching price: %+v", orig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
|
||||||
t.Errorf("Unable to find matching price: %+v", orig)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if numprices != len(*pl.Prices) {
|
if numprices != len(*pl.Prices) {
|
||||||
t.Fatalf("Expected %d prices, received %d", numprices, len(*pl.Prices))
|
t.Fatalf("Expected %d prices, received %d", numprices, len(*pl.Prices))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -196,7 +202,7 @@ func TestDeletePrice(t *testing.T) {
|
|||||||
t.Fatalf("Error deleting price: %s\n", err)
|
t.Fatalf("Error deleting price: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = getPrice(d.clients[userid], curr.PriceId)
|
_, err = getPrice(d.clients[userid], curr.PriceId, curr.SecurityId)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Expected error fetching deleted price")
|
t.Fatalf("Expected error fetching deleted price")
|
||||||
}
|
}
|
||||||
|
@ -253,6 +253,17 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "POST" {
|
if r.Method == "POST" {
|
||||||
|
if !context.LastLevel() {
|
||||||
|
securityid, err := context.NextID()
|
||||||
|
if err != nil {
|
||||||
|
return NewError(3 /*Invalid Request*/)
|
||||||
|
}
|
||||||
|
if context.NextLevel() != "prices" {
|
||||||
|
return NewError(3 /*Invalid Request*/)
|
||||||
|
}
|
||||||
|
return PriceHandler(r, context, user, securityid)
|
||||||
|
}
|
||||||
|
|
||||||
var security Security
|
var security Security
|
||||||
if err := ReadJSON(r, &security); err != nil {
|
if err := ReadJSON(r, &security); err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
@ -285,6 +296,14 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !context.LastLevel() {
|
||||||
|
if context.NextLevel() != "prices" {
|
||||||
|
return NewError(3 /*Invalid Request*/)
|
||||||
|
}
|
||||||
|
return PriceHandler(r, context, user, securityid)
|
||||||
|
}
|
||||||
|
|
||||||
security, err := GetSecurity(context.Tx, securityid, user.UserId)
|
security, err := GetSecurity(context.Tx, securityid, user.UserId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
@ -297,6 +316,13 @@ func SecurityHandler(r *http.Request, context *Context) ResponseWriterWriter {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(3 /*Invalid Request*/)
|
return NewError(3 /*Invalid Request*/)
|
||||||
}
|
}
|
||||||
|
if !context.LastLevel() {
|
||||||
|
if context.NextLevel() != "prices" {
|
||||||
|
return NewError(3 /*Invalid Request*/)
|
||||||
|
}
|
||||||
|
return PriceHandler(r, context, user, securityid)
|
||||||
|
}
|
||||||
|
|
||||||
if r.Method == "PUT" {
|
if r.Method == "PUT" {
|
||||||
var security Security
|
var security Security
|
||||||
if err := ReadJSON(r, &security); err != nil || security.SecurityId != securityid {
|
if err := ReadJSON(r, &security); err != nil || security.SecurityId != securityid {
|
||||||
|
@ -200,6 +200,15 @@ var data = []TestData{
|
|||||||
Type: handlers.Currency,
|
Type: handlers.Currency,
|
||||||
AlternateId: "978",
|
AlternateId: "978",
|
||||||
},
|
},
|
||||||
|
handlers.Security{
|
||||||
|
UserId: 0,
|
||||||
|
Name: "EUR",
|
||||||
|
Description: "Euro",
|
||||||
|
Symbol: "€",
|
||||||
|
Precision: 2,
|
||||||
|
Type: handlers.Currency,
|
||||||
|
AlternateId: "978",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
prices: []handlers.Price{
|
prices: []handlers.Price{
|
||||||
handlers.Price{
|
handlers.Price{
|
||||||
@ -230,6 +239,13 @@ var data = []TestData{
|
|||||||
Value: "227.21",
|
Value: "227.21",
|
||||||
RemoteId: "12387-129831-1241",
|
RemoteId: "12387-129831-1241",
|
||||||
},
|
},
|
||||||
|
handlers.Price{
|
||||||
|
SecurityId: 0,
|
||||||
|
CurrencyId: 3,
|
||||||
|
Date: time.Date(2017, time.November, 16, 18, 49, 53, 0, time.UTC),
|
||||||
|
Value: "0.85",
|
||||||
|
RemoteId: "USDEUR819298714",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
accounts: []handlers.Account{
|
accounts: []handlers.Account{
|
||||||
handlers.Account{
|
handlers.Account{
|
||||||
|
Loading…
Reference in New Issue
Block a user