package models import ( "time" ) // Competitor represents a competitor profile type Competitor struct { ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"` Name string `gorm:"size:255;not null" json:"name"` Code string `gorm:"size:100;not null;uniqueIndex" json:"code"` DeliveryBasis string `gorm:"size:50;not null;default:DDP" json:"delivery_basis"` Currency string `gorm:"size:10;not null;default:USD" json:"currency"` // currency of prices in file PriceUplift float64 `gorm:"type:decimal(8,4);not null;default:1.3" json:"price_uplift"` // effective_price = price / price_uplift ColumnMapping []byte `gorm:"type:json" json:"column_mapping,omitempty"` IsActive bool `gorm:"not null;default:true" json:"is_active"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` UpdatedAt time.Time `gorm:"autoUpdateTime" json:"updated_at"` } func (Competitor) TableName() string { return "qt_competitors" } // CompetitorQuote stores a historical price quote from a competitor. // Mirrors stock_log structure: partnumber as-is from file, date = quote date entered by user. // LOT resolution happens at pricelist build time via current p/n mappings. type CompetitorQuote struct { ID uint64 `gorm:"primaryKey;autoIncrement" json:"id"` CompetitorID uint64 `gorm:"not null;index" json:"competitor_id"` Partnumber string `gorm:"size:255;not null;index" json:"partnumber"` Description *string `gorm:"size:500" json:"description,omitempty"` Vendor *string `gorm:"size:255" json:"vendor,omitempty"` Price float64 `gorm:"type:decimal(12,2);not null" json:"price"` // price in USD (always) PriceLoccur *float64 `gorm:"type:decimal(12,2)" json:"price_loccur,omitempty"` // original price in local currency Currency *string `gorm:"size:10" json:"currency,omitempty"` // local currency code Qty float64 `gorm:"type:decimal(12,4);not null;default:1" json:"qty"` Date time.Time `gorm:"type:date;not null" json:"date"` CreatedAt time.Time `gorm:"autoCreateTime" json:"created_at"` Competitor *Competitor `gorm:"foreignKey:CompetitorID" json:"competitor,omitempty"` } func (CompetitorQuote) TableName() string { return "partnumber_log_competitors" } // CompetitorColumnMapping defines how to read Excel columns for a competitor. // Competitor files always contain partnumbers (never lot names directly). // Partnumbers are resolved to lots via qt_partnumber_book_items. type CompetitorColumnMapping struct { Sheet int `json:"sheet"` HeaderRow int `json:"header_row"` PartnumberCol string `json:"partnumber_col"` DescriptionCol string `json:"description_col,omitempty"` VendorCol string `json:"vendor_col,omitempty"` // PriceCol is the legacy single price column (treated as local currency, converted via rateToUSD). PriceCol string `json:"price_col,omitempty"` // PriceUSDCol is an explicit USD price column (no conversion needed). PriceUSDCol string `json:"price_usd_col,omitempty"` // PriceLocCurCol is an explicit local-currency price column (requires conversion via rateToUSD). PriceLocCurCol string `json:"price_loccur_col,omitempty"` QtyCol string `json:"qty_col,omitempty"` SkipRows []int `json:"skip_rows,omitempty"` }