Основные изменения: 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>
77 lines
1.9 KiB
Go
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
|
|
}
|