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"` // 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 }