package models import ( "log/slog" "strings" "gorm.io/gorm" ) // AllModels returns all models for auto-migration func AllModels() []interface{} { return []interface{}{ &Category{}, &LotMetadata{}, &Project{}, &Configuration{}, &PriceOverride{}, &PricingAlert{}, &ComponentUsageStats{}, &Pricelist{}, &PricelistItem{}, } } // Migrate runs auto-migration for all QuoteForge tables // Handles MySQL constraint errors gracefully for existing tables func Migrate(db *gorm.DB) error { for _, model := range AllModels() { if err := db.AutoMigrate(model); err != nil { // Skip known MySQL constraint errors for existing tables errStr := err.Error() if strings.Contains(errStr, "Can't DROP") || strings.Contains(errStr, "Duplicate key name") || strings.Contains(errStr, "check that it exists") || strings.Contains(errStr, "Cannot change column") || strings.Contains(errStr, "used in a foreign key constraint") { slog.Warn("migration warning (skipped)", "model", model, "error", errStr) continue } return err } } return nil } // SeedCategories upserts default categories, updating display_order on existing rows. func SeedCategories(db *gorm.DB) error { for _, cat := range DefaultCategories { var existing Category if err := db.Where("code = ?", cat.Code).First(&existing).Error; err != nil { if err := db.Create(&cat).Error; err != nil { return err } } else { if err := db.Model(&existing).Update("display_order", cat.DisplayOrder).Error; err != nil { return err } } } return nil }