package repository import ( "time" "git.mchus.pro/mchus/quoteforge/internal/models" "gorm.io/gorm" ) type ComponentRepository struct { db *gorm.DB } func NewComponentRepository(db *gorm.DB) *ComponentRepository { return &ComponentRepository{db: db} } type ComponentFilter struct { Category string Search string HasPrice bool ExcludeHidden bool SortField string SortDir string } func (r *ComponentRepository) List(filter ComponentFilter, offset, limit int) ([]models.LotMetadata, int64, error) { var components []models.LotMetadata var total int64 query := r.db.Model(&models.LotMetadata{}). Preload("Lot"). Preload("Category") if filter.Category != "" { query = query.Joins("JOIN qt_categories ON qt_lot_metadata.category_id = qt_categories.id"). Where("qt_categories.code = ?", filter.Category) } if filter.Search != "" { search := "%" + filter.Search + "%" query = query.Where("lot_name LIKE ? OR model LIKE ?", search, search) } if filter.HasPrice { query = query.Where("current_price IS NOT NULL AND current_price > 0") } if filter.ExcludeHidden { query = query.Where("is_hidden = ? OR is_hidden IS NULL", false) } query.Count(&total) // Apply sorting sortDir := "ASC" if filter.SortDir == "desc" { sortDir = "DESC" } switch filter.SortField { case "popularity_score": query = query.Order("popularity_score " + sortDir) case "current_price": query = query.Order("CASE WHEN current_price IS NULL OR current_price = 0 THEN 1 ELSE 0 END"). 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. Order("CASE WHEN current_price IS NULL OR current_price = 0 THEN 1 ELSE 0 END"). Order("popularity_score DESC") } err := query. Offset(offset). Limit(limit). Find(&components).Error return components, total, err } func (r *ComponentRepository) GetByLotName(lotName string) (*models.LotMetadata, error) { var component models.LotMetadata err := r.db. Preload("Lot"). Preload("Category"). Where("lot_name = ?", lotName). First(&component).Error if err != nil { return nil, err } return &component, nil } func (r *ComponentRepository) GetMultiple(lotNames []string) ([]models.LotMetadata, error) { var components []models.LotMetadata err := r.db. Preload("Lot"). Preload("Category"). Where("lot_name IN ?", lotNames). Find(&components).Error return components, err } func (r *ComponentRepository) Update(component *models.LotMetadata) error { return r.db.Save(component).Error } func (r *ComponentRepository) DB() *gorm.DB { return r.db } func (r *ComponentRepository) Create(component *models.LotMetadata) error { return r.db.Create(component).Error } func (r *ComponentRepository) IncrementRequestCount(lotName string) error { now := time.Now() return r.db.Model(&models.LotMetadata{}). Where("lot_name = ?", lotName). Updates(map[string]interface{}{ "request_count": gorm.Expr("request_count + 1"), "last_request_date": now, }).Error } // GetAllLots returns all lots from the existing lot table func (r *ComponentRepository) GetAllLots() ([]models.Lot, error) { var lots []models.Lot err := r.db.Find(&lots).Error return lots, err } // GetLotsWithoutMetadata returns lots that don't have qt_lot_metadata entries func (r *ComponentRepository) GetLotsWithoutMetadata() ([]models.Lot, error) { var lots []models.Lot err := r.db. Where("lot_name NOT IN (SELECT lot_name FROM qt_lot_metadata)"). Find(&lots).Error return lots, err }