Files
QuoteForge/internal/repository/category.go
Mikhail Chusavitin d32b1c5d0c Добавлены сортировка по категориям, секции PCI и автосохранение
Основные изменения:

1. CSV экспорт и веб-интерфейс:
   - Компоненты теперь сортируются по иерархии категорий (display_order)
   - Категории отображаются в правильном порядке: BB, CPU, MEM, GPU и т.д.
   - Компоненты без категории отображаются в конце

2. Раздел PCI в конфигураторе:
   - Разделен на секции: GPU/DPU, NIC/HCA, HBA
   - Улучшена навигация и выбор компонентов

3. Сохранение "своей цены":
   - Добавлено поле custom_price в модель Configuration
   - Создана миграция 002_add_custom_price.sql
   - "Своя цена" сохраняется при сохранении конфигурации
   - При загрузке конфигурации восстанавливается сохраненная цена

4. Автосохранение:
   - Конфигурация автоматически сохраняется через 1 секунду после изменений
   - Debounce предотвращает избыточные запросы
   - Автосохранение работает для всех изменений (компоненты, количество, цена)

5. Дополнительно:
   - Добавлен cmd/importer для импорта метаданных из таблицы lot
   - Создан скрипт apply_migration.sh для применения миграций
   - Оптимизирована работа с категориями в ExportService

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-30 17:48:44 +03:00

77 lines
1.9 KiB
Go

package repository
import (
"git.mchus.pro/mchus/quoteforge/internal/models"
"gorm.io/gorm"
)
type CategoryRepository struct {
db *gorm.DB
}
func NewCategoryRepository(db *gorm.DB) *CategoryRepository {
return &CategoryRepository{db: db}
}
func (r *CategoryRepository) GetAll() ([]models.Category, error) {
var categories []models.Category
err := r.db.Order("display_order ASC").Find(&categories).Error
return categories, err
}
func (r *CategoryRepository) GetByCode(code string) (*models.Category, error) {
var category models.Category
err := r.db.Where("code = ?", code).First(&category).Error
if err != nil {
return nil, err
}
return &category, nil
}
func (r *CategoryRepository) GetByID(id uint) (*models.Category, error) {
var category models.Category
err := r.db.First(&category, id).Error
if err != nil {
return nil, err
}
return &category, nil
}
// CreateIfNotExists creates a new category if it doesn't exist, returns existing one if it does
func (r *CategoryRepository) CreateIfNotExists(code string) (*models.Category, error) {
// Try to find existing
existing, err := r.GetByCode(code)
if err == nil {
return existing, nil
}
// Get max display order to put new category at the end
var maxOrder int
r.db.Model(&models.Category{}).Select("COALESCE(MAX(display_order), 0)").Scan(&maxOrder)
// Create new category
newCat := &models.Category{
Code: code,
Name: code, // Use code as name initially
NameRu: code,
DisplayOrder: maxOrder + 1,
IsRequired: false,
}
if err := r.db.Create(newCat).Error; err != nil {
return nil, err
}
return newCat, nil
}
// Create creates a new category
func (r *CategoryRepository) Create(category *models.Category) error {
return r.db.Create(category).Error
}
// Update updates an existing category
func (r *CategoryRepository) Update(category *models.Category) error {
return r.db.Save(category).Error
}