package repository import ( "time" "github.com/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 Vendor string Search string HasPrice bool } 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.Vendor != "" { query = query.Where("vendor = ?", filter.Vendor) } 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") } query.Count(&total) // Sort by popularity + freshness, no price goes last err := query. Order("CASE WHEN current_price IS NULL OR current_price = 0 THEN 1 ELSE 0 END"). Order("popularity_score DESC"). 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) Create(component *models.LotMetadata) error { return r.db.Create(component).Error } func (r *ComponentRepository) GetVendors(category string) ([]string, error) { var vendors []string query := r.db.Model(&models.LotMetadata{}).Distinct("vendor") if category != "" { query = query.Joins("JOIN qt_categories ON qt_lot_metadata.category_id = qt_categories.id"). Where("qt_categories.code = ?", category) } err := query.Pluck("vendor", &vendors).Error return vendors, err } 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 }