Implement global vendor mappings with bundle support and seen-based ignore

This commit is contained in:
Mikhail Chusavitin
2026-02-18 19:54:07 +03:00
parent b94dd3d015
commit c22328bf03
21 changed files with 2048 additions and 342 deletions

View File

@@ -128,7 +128,35 @@ func main() {
slog.Error("seeding categories failed", "error", err)
os.Exit(1)
}
slog.Info("migrations completed")
slog.Info("gorm migrations completed")
// Also apply SQL migrations in migrate-only mode.
sqlMigrationsPath := filepath.Join("migrations")
needsMigrations, err := models.NeedsSQLMigrations(mariaDB, sqlMigrationsPath)
if err != nil {
if models.IsMigrationPermissionError(err) {
slog.Info("SQL migrations skipped: insufficient database privileges", "path", sqlMigrationsPath, "error", err)
} else {
slog.Error("SQL migrations check failed", "path", sqlMigrationsPath, "error", err)
os.Exit(1)
}
} else if needsMigrations {
if err := models.RunSQLMigrations(mariaDB, sqlMigrationsPath); err != nil {
if models.IsMigrationPermissionError(err) {
slog.Info("SQL migrations skipped: insufficient database privileges", "path", sqlMigrationsPath, "error", err)
} else {
slog.Error("SQL migrations failed", "path", sqlMigrationsPath, "error", err)
os.Exit(1)
}
} else {
slog.Info("SQL migrations applied", "path", sqlMigrationsPath)
}
} else {
slog.Info("SQL migrations not needed", "path", sqlMigrationsPath)
}
slog.Info("migrate-only mode completed; exiting without starting web server")
return
}
// Always apply SQL migrations on startup when database is available.
@@ -338,6 +366,7 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
alertService := alerts.NewService(alertRepo, componentRepo, priceRepo, statsRepo, cfg.Alerts, cfg.Pricing)
pricelistService := pricelist.NewService(mariaDB, pricelistRepo, componentRepo, pricingService)
stockImportService := services.NewStockImportService(mariaDB, pricelistService)
vendorMappingService := services.NewVendorMappingService(mariaDB)
// Create task manager
taskManager := tasks.NewManager()
@@ -353,6 +382,7 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
priceRepo,
statsRepo,
stockImportService,
vendorMappingService,
dbUser,
taskManager,
)
@@ -546,6 +576,7 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
router.GET("/pricelists", webHandler.Pricelists)
router.GET("/pricelists/:id", webHandler.PricelistDetail)
router.GET("/admin/pricing", webHandler.AdminPricing)
router.GET("/vendor-mappings", webHandler.VendorMappings)
partials := router.Group("/partials")
{
@@ -601,9 +632,12 @@ func setupRouter(cfg *config.Config, configPath string, connMgr *db.ConnectionMa
pricingAdmin.GET("/stock/unmapped-partnumbers", pricingHandler.GetUnmappedPartnumbers)
pricingAdmin.POST("/stock/mappings", pricingHandler.UpsertStockMapping)
pricingAdmin.DELETE("/stock/mappings/:partnumber", pricingHandler.DeleteStockMapping)
pricingAdmin.GET("/stock/ignore-rules", pricingHandler.ListStockIgnoreRules)
pricingAdmin.POST("/stock/ignore-rules", pricingHandler.UpsertStockIgnoreRule)
pricingAdmin.DELETE("/stock/ignore-rules/:id", pricingHandler.DeleteStockIgnoreRule)
pricingAdmin.GET("/vendor-mappings", pricingHandler.ListVendorMappings)
pricingAdmin.GET("/vendor-mappings/detail", pricingHandler.GetVendorMappingDetail)
pricingAdmin.POST("/vendor-mappings", pricingHandler.UpsertVendorMapping)
pricingAdmin.DELETE("/vendor-mappings", pricingHandler.DeleteVendorMapping)
pricingAdmin.POST("/vendor-mappings/ignore", pricingHandler.IgnoreVendorMapping)
pricingAdmin.POST("/vendor-mappings/unignore", pricingHandler.UnignoreVendorMapping)
pricingAdmin.GET("/alerts", pricingHandler.ListAlerts)
pricingAdmin.POST("/alerts/:id/acknowledge", pricingHandler.AcknowledgeAlert)
pricingAdmin.POST("/alerts/:id/resolve", pricingHandler.ResolveAlert)