2017-10-04 19:35:59 -04:00
package handlers
2017-07-13 21:32:25 -04:00
import (
2017-12-02 06:14:47 -05:00
"github.com/aclindsa/moneygo/internal/models"
2017-12-06 21:09:47 -05:00
"github.com/aclindsa/moneygo/internal/store/db"
2017-11-10 20:13:49 -05:00
"log"
"net/http"
2017-07-13 21:32:25 -04:00
"time"
)
2017-12-06 21:09:47 -05:00
func CreatePriceIfNotExist ( tx * db . Tx , price * models . Price ) error {
2017-07-13 21:32:25 -04:00
if len ( price . RemoteId ) == 0 {
// Always create a new price if we can't match on the RemoteId
2017-11-10 20:13:49 -05:00
err := tx . Insert ( price )
2017-07-13 21:32:25 -04:00
if err != nil {
return err
}
return nil
}
2017-12-04 21:05:17 -05:00
var prices [ ] * models . Price
2017-07-13 21:32:25 -04:00
2017-10-14 19:41:13 -04:00
_ , err := tx . Select ( & prices , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date=? AND Value=?" , price . SecurityId , price . CurrencyId , price . Date , price . Value )
2017-07-13 21:32:25 -04:00
if err != nil {
return err
}
if len ( prices ) > 0 {
return nil // price already exists
}
2017-11-10 20:13:49 -05:00
err = tx . Insert ( price )
2017-07-13 21:32:25 -04:00
if err != nil {
return err
}
return nil
}
2017-12-06 21:09:47 -05:00
func GetPrice ( tx * db . Tx , priceid , securityid int64 ) ( * models . Price , error ) {
2017-12-04 21:05:17 -05:00
var p models . Price
2017-11-16 19:17:51 -05:00
err := tx . SelectOne ( & p , "SELECT * from prices where PriceId=? AND SecurityId=?" , priceid , securityid )
2017-11-10 20:13:49 -05:00
if err != nil {
return nil , err
}
return & p , nil
}
2017-12-06 21:09:47 -05:00
func GetPrices ( tx * db . Tx , securityid int64 ) ( * [ ] * models . Price , error ) {
2017-12-04 21:05:17 -05:00
var prices [ ] * models . Price
2017-11-10 20:13:49 -05:00
2017-11-16 19:17:51 -05:00
_ , err := tx . Select ( & prices , "SELECT * from prices where SecurityId=?" , securityid )
2017-11-10 20:13:49 -05:00
if err != nil {
return nil , err
}
return & prices , nil
}
2017-07-13 21:32:25 -04:00
// Return the latest price for security in currency units before date
2017-12-06 21:09:47 -05:00
func GetLatestPrice ( tx * db . Tx , security , currency * models . Security , date * time . Time ) ( * models . Price , error ) {
2017-12-04 21:05:17 -05:00
var p models . Price
2017-10-14 19:41:13 -04:00
err := tx . SelectOne ( & p , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date <= ? ORDER BY Date DESC LIMIT 1" , security . SecurityId , currency . SecurityId , date )
2017-07-13 21:32:25 -04:00
if err != nil {
return nil , err
}
return & p , nil
}
// Return the earliest price for security in currency units after date
2017-12-06 21:09:47 -05:00
func GetEarliestPrice ( tx * db . Tx , security , currency * models . Security , date * time . Time ) ( * models . Price , error ) {
2017-12-04 21:05:17 -05:00
var p models . Price
2017-10-14 19:41:13 -04:00
err := tx . SelectOne ( & p , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date >= ? ORDER BY Date ASC LIMIT 1" , security . SecurityId , currency . SecurityId , date )
2017-07-13 21:32:25 -04:00
if err != nil {
return nil , err
}
return & p , nil
}
// Return the price for security in currency closest to date
2017-12-06 21:09:47 -05:00
func GetClosestPrice ( tx * db . Tx , security , currency * models . Security , date * time . Time ) ( * models . Price , error ) {
2017-10-14 19:41:13 -04:00
earliest , _ := GetEarliestPrice ( tx , security , currency , date )
latest , err := GetLatestPrice ( tx , security , currency , date )
2017-07-13 21:32:25 -04:00
// Return early if either earliest or latest are invalid
if earliest == nil {
return latest , err
} else if err != nil {
return earliest , nil
}
howlate := earliest . Date . Sub ( * date )
howearly := date . Sub ( latest . Date )
if howearly < howlate {
return latest , nil
} else {
return earliest , nil
}
}
2017-11-10 20:13:49 -05:00
2017-12-02 06:14:47 -05:00
func PriceHandler ( r * http . Request , context * Context , user * models . User , securityid int64 ) ResponseWriterWriter {
2017-11-16 19:17:51 -05:00
security , err := GetSecurity ( context . Tx , securityid , user . UserId )
2017-11-10 20:13:49 -05:00
if err != nil {
2017-11-16 19:17:51 -05:00
return NewError ( 3 /*Invalid Request*/ )
2017-11-10 20:13:49 -05:00
}
if r . Method == "POST" {
2017-12-04 21:05:17 -05:00
var price models . Price
2017-11-13 20:48:19 -05:00
if err := ReadJSON ( r , & price ) ; err != nil {
2017-11-10 20:13:49 -05:00
return NewError ( 3 /*Invalid Request*/ )
}
price . PriceId = - 1
2017-11-16 19:17:51 -05:00
if price . SecurityId != security . SecurityId {
2017-11-10 20:13:49 -05:00
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
_ , err = GetSecurity ( context . Tx , price . CurrencyId , user . UserId )
2017-11-10 20:13:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
err = context . Tx . Insert ( & price )
2017-11-10 20:13:49 -05:00
if err != nil {
log . Print ( err )
return NewError ( 999 /*Internal Error*/ )
}
return ResponseWrapper { 201 , & price }
} else if r . Method == "GET" {
2017-11-12 21:12:49 -05:00
if context . LastLevel ( ) {
2017-11-16 19:17:51 -05:00
//Return all this security's prices
2017-12-04 21:05:17 -05:00
var pl models . PriceList
2017-11-10 20:13:49 -05:00
2017-11-16 19:17:51 -05:00
prices , err := GetPrices ( context . Tx , security . SecurityId )
2017-11-10 20:13:49 -05:00
if err != nil {
log . Print ( err )
return NewError ( 999 /*Internal Error*/ )
}
pl . Prices = prices
return & pl
2017-11-12 21:12:49 -05:00
}
2017-11-10 20:13:49 -05:00
2017-11-12 21:12:49 -05:00
priceid , err := context . NextID ( )
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
2017-11-10 20:13:49 -05:00
}
2017-11-12 21:12:49 -05:00
2017-11-16 19:17:51 -05:00
price , err := GetPrice ( context . Tx , priceid , security . SecurityId )
2017-11-12 21:12:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
return price
2017-11-10 20:13:49 -05:00
} else {
2017-11-12 21:12:49 -05:00
priceid , err := context . NextID ( )
2017-11-10 20:13:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
if r . Method == "PUT" {
2017-12-04 21:05:17 -05:00
var price models . Price
2017-11-13 20:48:19 -05:00
if err := ReadJSON ( r , & price ) ; err != nil || price . PriceId != priceid {
2017-11-10 20:13:49 -05:00
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
_ , err = GetSecurity ( context . Tx , price . SecurityId , user . UserId )
2017-11-10 20:13:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
_ , err = GetSecurity ( context . Tx , price . CurrencyId , user . UserId )
2017-11-10 20:13:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
count , err := context . Tx . Update ( & price )
2017-11-10 20:13:49 -05:00
if err != nil || count != 1 {
log . Print ( err )
return NewError ( 999 /*Internal Error*/ )
}
return & price
} else if r . Method == "DELETE" {
2017-11-16 19:17:51 -05:00
price , err := GetPrice ( context . Tx , priceid , security . SecurityId )
2017-11-10 20:13:49 -05:00
if err != nil {
return NewError ( 3 /*Invalid Request*/ )
}
2017-11-12 20:17:27 -05:00
count , err := context . Tx . Delete ( price )
2017-11-10 20:13:49 -05:00
if err != nil || count != 1 {
log . Print ( err )
return NewError ( 999 /*Internal Error*/ )
}
return SuccessWriter { }
}
}
return NewError ( 3 /*Invalid Request*/ )
}