paisa/internal/service/market.go

83 lines
2.0 KiB
Go
Raw Normal View History

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 {
2022-07-16 01:31:48 -04:00
sync.Once
2022-04-09 03:01:12 -04:00
pricesTree map[string]*btree.BTree
}
var pcache priceCache
2022-04-09 03:01:12 -04:00
func loadPriceCache(db *gorm.DB) {
2022-04-09 03:01:12 -04:00
var prices []price.Price
result := db.Find(&prices)
if result.Error != nil {
log.Fatal(result.Error)
}
pcache.pricesTree = make(map[string]*btree.BTree)
2022-04-09 03:01:12 -04:00
for _, price := range prices {
if pcache.pricesTree[price.CommodityName] == nil {
pcache.pricesTree[price.CommodityName] = btree.New(2)
2022-04-09 03:01:12 -04:00
}
pcache.pricesTree[price.CommodityName].ReplaceOrInsert(price)
2022-04-09 03:01:12 -04:00
}
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" && pcache.pricesTree[commodityName] == nil {
pcache.pricesTree[commodityName] = btree.New(2)
2022-04-09 12:45:05 -04:00
for _, p := range postings {
pcache.pricesTree[commodityName].ReplaceOrInsert(price.Price{Date: p.Date, CommodityID: p.Commodity, CommodityName: p.Commodity, Value: p.Amount / p.Quantity})
2022-04-09 12:45:05 -04:00
}
}
}
2022-04-09 03:01:12 -04:00
}
func GetMarketPrice(db *gorm.DB, p posting.Posting, date time.Time) float64 {
2022-07-16 01:31:48 -04:00
pcache.Do(func() { loadPriceCache(db) })
2022-04-09 03:01:12 -04:00
if p.Commodity == "INR" {
return p.Amount
}
pt := pcache.pricesTree[p.Commodity]
2022-04-09 03:01:12 -04:00
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
}
func PopulateMarketPrice(db *gorm.DB, ps []posting.Posting) []posting.Posting {
date := time.Now()
return lo.Map(ps, func(p posting.Posting, _ int) posting.Posting {
p.MarketAmount = GetMarketPrice(db, p, date)
return p
})
}