2017-12-07 21:05:55 -05:00
package db
import (
"fmt"
"github.com/aclindsa/moneygo/internal/models"
"time"
)
2017-12-12 19:40:38 -05:00
// Price is a mirror of models.Price with the Value broken out into whole and
// fractional components
type Price struct {
PriceId int64
SecurityId int64
CurrencyId int64
Date time . Time
WholeValue int64
FractionalValue int64
RemoteId string // unique ID from source, for detecting duplicates
}
func NewPrice ( p * models . Price ) ( * Price , error ) {
whole , err := p . Value . Whole ( )
if err != nil {
return nil , err
}
fractional , err := p . Value . Fractional ( MaxPrecision )
if err != nil {
return nil , err
}
return & Price {
PriceId : p . PriceId ,
SecurityId : p . SecurityId ,
CurrencyId : p . CurrencyId ,
Date : p . Date ,
WholeValue : whole ,
FractionalValue : fractional ,
RemoteId : p . RemoteId ,
} , nil
}
func ( p Price ) Price ( ) * models . Price {
price := & models . Price {
PriceId : p . PriceId ,
SecurityId : p . SecurityId ,
CurrencyId : p . CurrencyId ,
Date : p . Date ,
RemoteId : p . RemoteId ,
}
price . Value . FromParts ( p . WholeValue , p . FractionalValue , MaxPrecision )
return price
}
2017-12-07 21:05:55 -05:00
func ( tx * Tx ) PriceExists ( price * models . Price ) ( bool , error ) {
2017-12-12 19:40:38 -05:00
p , err := NewPrice ( price )
if err != nil {
return false , err
}
var prices [ ] * Price
_ , err = tx . Select ( & prices , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date=? AND WholeValue=? AND FractionalValue=?" , p . SecurityId , p . CurrencyId , p . Date , p . WholeValue , p . FractionalValue )
2017-12-07 21:05:55 -05:00
return len ( prices ) > 0 , err
}
func ( tx * Tx ) InsertPrice ( price * models . Price ) error {
2017-12-12 19:40:38 -05:00
p , err := NewPrice ( price )
if err != nil {
return err
}
err = tx . Insert ( p )
if err != nil {
return err
}
* price = * p . Price ( )
return nil
2017-12-07 21:05:55 -05:00
}
func ( tx * Tx ) GetPrice ( priceid , securityid int64 ) ( * models . Price , error ) {
2017-12-12 19:40:38 -05:00
var price Price
2017-12-07 21:05:55 -05:00
err := tx . SelectOne ( & price , "SELECT * from prices where PriceId=? AND SecurityId=?" , priceid , securityid )
if err != nil {
return nil , err
}
2017-12-12 19:40:38 -05:00
return price . Price ( ) , nil
2017-12-07 21:05:55 -05:00
}
func ( tx * Tx ) GetPrices ( securityid int64 ) ( * [ ] * models . Price , error ) {
2017-12-12 19:40:38 -05:00
var prices [ ] * Price
var modelprices [ ] * models . Price
2017-12-07 21:05:55 -05:00
_ , err := tx . Select ( & prices , "SELECT * from prices where SecurityId=?" , securityid )
if err != nil {
return nil , err
}
2017-12-12 19:40:38 -05:00
for _ , p := range prices {
modelprices = append ( modelprices , p . Price ( ) )
}
return & modelprices , nil
2017-12-07 21:05:55 -05:00
}
// Return the latest price for security in currency units before date
func ( tx * Tx ) GetLatestPrice ( security , currency * models . Security , date * time . Time ) ( * models . Price , error ) {
2017-12-12 19:40:38 -05:00
var price Price
2017-12-07 21:05:55 -05:00
err := tx . SelectOne ( & price , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date <= ? ORDER BY Date DESC LIMIT 1" , security . SecurityId , currency . SecurityId , date )
if err != nil {
return nil , err
}
2017-12-12 19:40:38 -05:00
return price . Price ( ) , nil
2017-12-07 21:05:55 -05:00
}
// Return the earliest price for security in currency units after date
func ( tx * Tx ) GetEarliestPrice ( security , currency * models . Security , date * time . Time ) ( * models . Price , error ) {
2017-12-12 19:40:38 -05:00
var price Price
2017-12-07 21:05:55 -05:00
err := tx . SelectOne ( & price , "SELECT * from prices where SecurityId=? AND CurrencyId=? AND Date >= ? ORDER BY Date ASC LIMIT 1" , security . SecurityId , currency . SecurityId , date )
if err != nil {
return nil , err
}
2017-12-12 19:40:38 -05:00
return price . Price ( ) , nil
2017-12-07 21:05:55 -05:00
}
func ( tx * Tx ) UpdatePrice ( price * models . Price ) error {
2017-12-12 19:40:38 -05:00
p , err := NewPrice ( price )
if err != nil {
return err
}
count , err := tx . Update ( p )
2017-12-07 21:05:55 -05:00
if err != nil {
return err
}
if count != 1 {
return fmt . Errorf ( "Expected to update 1 price, was going to update %d" , count )
}
2017-12-12 19:40:38 -05:00
* price = * p . Price ( )
2017-12-07 21:05:55 -05:00
return nil
}
func ( tx * Tx ) DeletePrice ( price * models . Price ) error {
2017-12-12 19:40:38 -05:00
p , err := NewPrice ( price )
if err != nil {
return err
}
count , err := tx . Delete ( p )
2017-12-07 21:05:55 -05:00
if err != nil {
return err
}
if count != 1 {
return fmt . Errorf ( "Expected to delete 1 price, was going to delete %d" , count )
}
2017-12-12 19:40:38 -05:00
* price = * p . Price ( )
2017-12-07 21:05:55 -05:00
return nil
}