2022-04-09 03:01:12 -04:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/ananthakumaran/paisa/internal/model/posting"
|
|
|
|
"github.com/ananthakumaran/paisa/internal/model/price"
|
2022-04-14 01:41:03 -04:00
|
|
|
"github.com/ananthakumaran/paisa/internal/utils"
|
2022-04-09 03:01:12 -04:00
|
|
|
"github.com/google/btree"
|
2022-04-09 12:45:05 -04:00
|
|
|
"github.com/samber/lo"
|
2022-04-09 03:01:12 -04:00
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
)
|
|
|
|
|
|
|
|
type priceCache struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
pricesTree map[string]*btree.BTree
|
|
|
|
}
|
|
|
|
|
|
|
|
var cache priceCache
|
|
|
|
|
|
|
|
func loadCache(db *gorm.DB) {
|
|
|
|
cache.mu.Lock()
|
|
|
|
defer cache.mu.Unlock()
|
|
|
|
|
|
|
|
if cache.pricesTree != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var prices []price.Price
|
|
|
|
result := db.Find(&prices)
|
|
|
|
if result.Error != nil {
|
|
|
|
log.Fatal(result.Error)
|
|
|
|
}
|
|
|
|
cache.pricesTree = make(map[string]*btree.BTree)
|
|
|
|
|
|
|
|
for _, price := range prices {
|
|
|
|
if cache.pricesTree[price.CommodityName] == nil {
|
|
|
|
cache.pricesTree[price.CommodityName] = btree.New(2)
|
|
|
|
}
|
|
|
|
|
|
|
|
cache.pricesTree[price.CommodityName].ReplaceOrInsert(price)
|
|
|
|
}
|
2022-04-09 12:45:05 -04:00
|
|
|
|
|
|
|
var postings []posting.Posting
|
|
|
|
result = db.Find(&postings)
|
|
|
|
if result.Error != nil {
|
|
|
|
log.Fatal(result.Error)
|
|
|
|
}
|
|
|
|
|
|
|
|
for commodityName, postings := range lo.GroupBy(postings, func(p posting.Posting) string { return p.Commodity }) {
|
|
|
|
if postings[0].Commodity != "INR" && cache.pricesTree[commodityName] == nil {
|
|
|
|
cache.pricesTree[commodityName] = btree.New(2)
|
|
|
|
for _, p := range postings {
|
|
|
|
cache.pricesTree[commodityName].ReplaceOrInsert(price.Price{Date: p.Date, CommodityID: p.Commodity, CommodityName: p.Commodity, Value: p.Amount / p.Quantity})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-04-09 03:01:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func GetMarketPrice(db *gorm.DB, p posting.Posting, date time.Time) float64 {
|
|
|
|
loadCache(db)
|
|
|
|
if p.Commodity == "INR" {
|
|
|
|
return p.Amount
|
|
|
|
}
|
|
|
|
|
|
|
|
pt := cache.pricesTree[p.Commodity]
|
|
|
|
if pt != nil {
|
|
|
|
|
2022-04-14 01:41:03 -04:00
|
|
|
pc := utils.BTreeDescendFirstLessOrEqual(pt, price.Price{Date: date})
|
|
|
|
if pc.Value != 0 {
|
2022-04-09 03:01:12 -04:00
|
|
|
return p.Quantity * pc.Value
|
|
|
|
}
|
2022-04-09 12:45:05 -04:00
|
|
|
} else {
|
2022-04-14 01:41:03 -04:00
|
|
|
log.Info("Not found ", p)
|
2022-04-09 03:01:12 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return p.Amount
|
|
|
|
}
|