Improve pricing modal performance and charting

This commit is contained in:
Mikhail Chusavitin
2026-03-17 12:37:58 +03:00
parent df5be91353
commit df14da2265
5 changed files with 451 additions and 111 deletions

View File

@@ -25,29 +25,29 @@ type ComponentFilter struct {
}
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")
baseQuery := r.db.Table("qt_lot_metadata AS m").
Joins("LEFT JOIN lot AS l ON l.lot_name = m.lot_name").
Joins("LEFT JOIN qt_categories AS c ON c.id = m.category_id")
if filter.Category != "" {
query = query.Joins("JOIN qt_categories ON qt_lot_metadata.category_id = qt_categories.id").
Where("qt_categories.code = ?", filter.Category)
baseQuery = baseQuery.Where("c.code = ?", filter.Category)
}
if filter.Search != "" {
search := "%" + filter.Search + "%"
query = query.Where("lot_name LIKE ? OR model LIKE ?", search, search)
baseQuery = baseQuery.Where("m.lot_name LIKE ? OR m.model LIKE ?", search, search)
}
if filter.HasPrice {
query = query.Where("current_price IS NOT NULL AND current_price > 0")
baseQuery = baseQuery.Where("m.current_price IS NOT NULL AND m.current_price > 0")
}
if filter.ExcludeHidden {
query = query.Where("is_hidden = ? OR is_hidden IS NULL", false)
baseQuery = baseQuery.Where("m.is_hidden = ? OR m.is_hidden IS NULL", false)
}
query.Count(&total)
if err := baseQuery.Count(&total).Error; err != nil {
return nil, 0, err
}
// Apply sorting
sortDir := "ASC"
@@ -55,30 +55,65 @@ func (r *ComponentRepository) List(filter ComponentFilter, offset, limit int) ([
sortDir = "DESC"
}
query := baseQuery.Session(&gorm.Session{})
switch filter.SortField {
case "popularity_score":
query = query.Order("popularity_score " + sortDir)
query = query.Order("m.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)
query = query.Order("CASE WHEN m.current_price IS NULL OR m.current_price = 0 THEN 1 ELSE 0 END").
Order("m.current_price " + sortDir)
case "lot_name":
query = query.Order("lot_name " + sortDir)
query = query.Order("m.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").
Select("m.*, l.lot_description AS lot_description, c.id AS category_join_id, c.code AS category_code, (SELECT COUNT(*) FROM lot_log WHERE lot_log.lot = m.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")
Order("CASE WHEN m.current_price IS NULL OR m.current_price = 0 THEN 1 ELSE 0 END").
Order("m.popularity_score DESC")
}
err := query.
type componentRow struct {
models.LotMetadata
LotDescription string `gorm:"column:lot_description"`
CategoryJoinID *uint `gorm:"column:category_join_id"`
CategoryCode *string `gorm:"column:category_code"`
}
var rows []componentRow
selectQuery := query
if filter.SortField != "quote_count" {
selectQuery = selectQuery.Select("m.*, l.lot_description AS lot_description, c.id AS category_join_id, c.code AS category_code")
}
err := selectQuery.
Offset(offset).
Limit(limit).
Find(&components).Error
Scan(&rows).Error
if err != nil {
return nil, total, err
}
components := make([]models.LotMetadata, len(rows))
for i, row := range rows {
comp := row.LotMetadata
comp.Lot = &models.Lot{
LotName: comp.LotName,
LotDescription: row.LotDescription,
}
if row.CategoryCode != nil || row.CategoryJoinID != nil {
comp.Category = &models.Category{
ID: 0,
Code: "",
}
if row.CategoryJoinID != nil {
comp.Category.ID = *row.CategoryJoinID
}
if row.CategoryCode != nil {
comp.Category.Code = *row.CategoryCode
}
}
components[i] = comp
}
return components, total, err
}