refactor: убрать qt_pricelist_sync_status, lot_log и лишние права БД
- Удалить все записи в qt_pricelist_sync_status (RecordSyncHeartbeat и ensureUserSyncStatusTable); ListUserSyncStatuses переведён на qt_client_schema_state - Подавлять устаревший OFFLINE_UNVERIFIED_SCHEMA в UI когда соединение уже восстановлено - Удалить все обращения к lot_log: repository/price.go, сортировка quote_count в component.go, UpdatePopularityScores в stats.go, модель LotLog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,11 +63,6 @@ func (r *ComponentRepository) List(filter ComponentFilter, offset, limit int) ([
|
||||
Order("current_price " + sortDir)
|
||||
case "lot_name":
|
||||
query = query.Order("lot_name " + sortDir)
|
||||
case "quote_count":
|
||||
// Sort by quote count from lot_log table
|
||||
query = query.
|
||||
Select("qt_lot_metadata.*, (SELECT COUNT(*) FROM lot_log WHERE lot_log.lot = qt_lot_metadata.lot_name) as quote_count_sort").
|
||||
Order("quote_count_sort " + sortDir)
|
||||
default:
|
||||
// Default: sort by popularity, no price goes last
|
||||
query = query.
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"git.mchus.pro/mchus/quoteforge/internal/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PriceRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewPriceRepository(db *gorm.DB) *PriceRepository {
|
||||
return &PriceRepository{db: db}
|
||||
}
|
||||
|
||||
type PricePoint struct {
|
||||
Price float64
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
// GetPriceHistory returns price history from lot_log for a component
|
||||
func (r *PriceRepository) GetPriceHistory(lotName string, periodDays int) ([]PricePoint, error) {
|
||||
var points []PricePoint
|
||||
since := time.Now().AddDate(0, 0, -periodDays)
|
||||
|
||||
err := r.db.Model(&models.LotLog{}).
|
||||
Select("price, date").
|
||||
Where("lot = ? AND date >= ?", lotName, since).
|
||||
Order("date DESC").
|
||||
Scan(&points).Error
|
||||
|
||||
return points, err
|
||||
}
|
||||
|
||||
// GetLatestPrice returns the most recent price for a component
|
||||
func (r *PriceRepository) GetLatestPrice(lotName string) (*PricePoint, error) {
|
||||
var point PricePoint
|
||||
err := r.db.Model(&models.LotLog{}).
|
||||
Select("price, date").
|
||||
Where("lot = ?", lotName).
|
||||
Order("date DESC").
|
||||
First(&point).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &point, nil
|
||||
}
|
||||
|
||||
// GetPriceOverride returns active override for a component
|
||||
func (r *PriceRepository) GetPriceOverride(lotName string) (*models.PriceOverride, error) {
|
||||
var override models.PriceOverride
|
||||
today := time.Now().Truncate(24 * time.Hour)
|
||||
|
||||
err := r.db.
|
||||
Where("lot_name = ?", lotName).
|
||||
Where("valid_from <= ?", today).
|
||||
Where("valid_until IS NULL OR valid_until >= ?", today).
|
||||
Order("valid_from DESC").
|
||||
First(&override).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &override, nil
|
||||
}
|
||||
|
||||
// CreatePriceOverride creates a new price override
|
||||
func (r *PriceRepository) CreatePriceOverride(override *models.PriceOverride) error {
|
||||
return r.db.Create(override).Error
|
||||
}
|
||||
|
||||
// GetPriceOverrides returns all overrides for a component
|
||||
func (r *PriceRepository) GetPriceOverrides(lotName string) ([]models.PriceOverride, error) {
|
||||
var overrides []models.PriceOverride
|
||||
err := r.db.
|
||||
Where("lot_name = ?", lotName).
|
||||
Order("valid_from DESC").
|
||||
Find(&overrides).Error
|
||||
return overrides, err
|
||||
}
|
||||
|
||||
// DeletePriceOverride deletes an override
|
||||
func (r *PriceRepository) DeletePriceOverride(id uint) error {
|
||||
return r.db.Delete(&models.PriceOverride{}, id).Error
|
||||
}
|
||||
|
||||
// GetQuoteCount returns the number of quotes in lot_log for a period
|
||||
func (r *PriceRepository) GetQuoteCount(lotName string, periodDays int) (int64, error) {
|
||||
var count int64
|
||||
since := time.Now().AddDate(0, 0, -periodDays)
|
||||
|
||||
err := r.db.Model(&models.LotLog{}).
|
||||
Where("lot = ? AND date >= ?", lotName, since).
|
||||
Count(&count).Error
|
||||
|
||||
return count, err
|
||||
}
|
||||
|
||||
// GetQuoteCounts returns quote counts for multiple lot names
|
||||
func (r *PriceRepository) GetQuoteCounts(lotNames []string) (map[string]int64, error) {
|
||||
type Result struct {
|
||||
Lot string
|
||||
Count int64
|
||||
}
|
||||
var results []Result
|
||||
|
||||
err := r.db.Model(&models.LotLog{}).
|
||||
Select("lot, COUNT(*) as count").
|
||||
Where("lot IN ?", lotNames).
|
||||
Group("lot").
|
||||
Scan(&results).Error
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
counts := make(map[string]int64)
|
||||
for _, r := range results {
|
||||
counts[r.Lot] = r.Count
|
||||
}
|
||||
return counts, nil
|
||||
}
|
||||
@@ -91,25 +91,3 @@ func (r *StatsRepository) ResetMonthlyCounters() error {
|
||||
Update("quotes_last_30d", 0).Error
|
||||
}
|
||||
|
||||
// UpdatePopularityScores recalculates popularity_score in qt_lot_metadata
|
||||
// based on supplier quotes from lot_log table
|
||||
func (r *StatsRepository) UpdatePopularityScores() error {
|
||||
// Formula: popularity_score = quotes_last_30d * 3 + quotes_last_90d * 1 + quotes_total * 0.1
|
||||
// This gives more weight to recent supplier activity
|
||||
return r.db.Exec(`
|
||||
UPDATE qt_lot_metadata m
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
lot,
|
||||
COUNT(*) as quotes_total,
|
||||
SUM(CASE WHEN date >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 ELSE 0 END) as quotes_last_30d,
|
||||
SUM(CASE WHEN date >= DATE_SUB(NOW(), INTERVAL 90 DAY) THEN 1 ELSE 0 END) as quotes_last_90d
|
||||
FROM lot_log
|
||||
GROUP BY lot
|
||||
) s ON m.lot_name = s.lot
|
||||
SET m.popularity_score = COALESCE(
|
||||
s.quotes_last_30d * 3 + s.quotes_last_90d * 1 + s.quotes_total * 0.1,
|
||||
0
|
||||
)
|
||||
`).Error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user