Renamed module path git.mchus.pro/mchus/quoteforge → git.mchus.pro/mchus/priceforge, renamed package quoteforge → priceforge, moved binary from cmd/qfs to cmd/pfs.
93 lines
3.0 KiB
Go
93 lines
3.0 KiB
Go
package models
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
)
|
|
|
|
type PriceMethod string
|
|
|
|
const (
|
|
PriceMethodManual PriceMethod = "manual"
|
|
PriceMethodMedian PriceMethod = "median"
|
|
PriceMethodAverage PriceMethod = "average"
|
|
PriceMethodWeightedMedian PriceMethod = "weighted_median"
|
|
)
|
|
|
|
type Specs map[string]interface{}
|
|
|
|
func (s Specs) Value() (driver.Value, error) {
|
|
return json.Marshal(s)
|
|
}
|
|
|
|
func (s *Specs) Scan(value interface{}) error {
|
|
if value == nil {
|
|
*s = make(Specs)
|
|
return nil
|
|
}
|
|
bytes, ok := value.([]byte)
|
|
if !ok {
|
|
return errors.New("type assertion to []byte failed")
|
|
}
|
|
return json.Unmarshal(bytes, s)
|
|
}
|
|
|
|
type LotMetadata struct {
|
|
LotName string `gorm:"column:lot_name;primaryKey;size:255" json:"lot_name"`
|
|
CategoryID *uint `gorm:"column:category_id" json:"category_id"`
|
|
Model string `gorm:"size:100" json:"model"`
|
|
Specs Specs `gorm:"type:json" json:"specs"`
|
|
CurrentPrice *float64 `gorm:"type:decimal(12,2)" json:"current_price"`
|
|
PriceMethod PriceMethod `gorm:"type:enum('manual','median','average','weighted_median');default:'median'" json:"price_method"`
|
|
PricePeriodDays int `gorm:"default:90" json:"price_period_days"`
|
|
PriceCoefficient float64 `gorm:"type:decimal(5,2);default:0" json:"price_coefficient"`
|
|
ManualPrice *float64 `gorm:"type:decimal(12,2)" json:"manual_price"`
|
|
PriceUpdatedAt *time.Time `json:"price_updated_at"`
|
|
RequestCount int `gorm:"default:0" json:"request_count"`
|
|
LastRequestDate *time.Time `gorm:"type:date" json:"last_request_date"`
|
|
PopularityScore float64 `gorm:"type:decimal(10,4);default:0" json:"popularity_score"`
|
|
MetaPrices string `gorm:"size:1000" json:"meta_prices"`
|
|
MetaMethod string `gorm:"size:20" json:"meta_method"`
|
|
MetaPeriodDays int `gorm:"default:90" json:"meta_period_days"`
|
|
IsHidden bool `gorm:"default:false" json:"is_hidden"`
|
|
|
|
// Relations
|
|
Lot *Lot `gorm:"foreignKey:LotName;references:LotName" json:"lot,omitempty"`
|
|
Category *Category `gorm:"foreignKey:CategoryID" json:"category,omitempty"`
|
|
}
|
|
|
|
func (LotMetadata) TableName() string {
|
|
return "qt_lot_metadata"
|
|
}
|
|
|
|
type PriceFreshness string
|
|
|
|
const (
|
|
FreshnessFresh PriceFreshness = "fresh"
|
|
FreshnessNormal PriceFreshness = "normal"
|
|
FreshnessStale PriceFreshness = "stale"
|
|
FreshnessCritical PriceFreshness = "critical"
|
|
)
|
|
|
|
func (m *LotMetadata) GetPriceFreshness(greenDays, yellowDays, redDays, minQuotes int) PriceFreshness {
|
|
if m.CurrentPrice == nil || *m.CurrentPrice == 0 {
|
|
return FreshnessCritical
|
|
}
|
|
if m.PriceUpdatedAt == nil {
|
|
return FreshnessCritical
|
|
}
|
|
|
|
daysSince := int(time.Since(*m.PriceUpdatedAt).Hours() / 24)
|
|
|
|
if daysSince < greenDays && m.RequestCount >= minQuotes {
|
|
return FreshnessFresh
|
|
} else if daysSince < yellowDays {
|
|
return FreshnessNormal
|
|
} else if daysSince < redDays {
|
|
return FreshnessStale
|
|
}
|
|
return FreshnessCritical
|
|
}
|