mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
173 lines
5.9 KiB
Go
173 lines
5.9 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/gin-contrib/cors"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"go.uber.org/zap"
|
|
|
|
"rmser/config"
|
|
"rmser/internal/infrastructure/db"
|
|
"rmser/internal/infrastructure/ocr_client"
|
|
|
|
"rmser/internal/transport/http/middleware"
|
|
tgBot "rmser/internal/transport/telegram"
|
|
|
|
// Repositories
|
|
accountPkg "rmser/internal/infrastructure/repository/account"
|
|
catalogPkg "rmser/internal/infrastructure/repository/catalog"
|
|
draftsPkg "rmser/internal/infrastructure/repository/drafts"
|
|
invoicesPkg "rmser/internal/infrastructure/repository/invoices"
|
|
ocrRepoPkg "rmser/internal/infrastructure/repository/ocr"
|
|
opsRepoPkg "rmser/internal/infrastructure/repository/operations"
|
|
recipesPkg "rmser/internal/infrastructure/repository/recipes"
|
|
recRepoPkg "rmser/internal/infrastructure/repository/recommendations"
|
|
suppliersPkg "rmser/internal/infrastructure/repository/suppliers"
|
|
|
|
"rmser/internal/infrastructure/rms"
|
|
|
|
// Services
|
|
draftsServicePkg "rmser/internal/services/drafts"
|
|
ocrServicePkg "rmser/internal/services/ocr"
|
|
recServicePkg "rmser/internal/services/recommend"
|
|
"rmser/internal/services/sync"
|
|
|
|
// Handlers
|
|
"rmser/internal/transport/http/handlers"
|
|
|
|
"rmser/pkg/crypto"
|
|
"rmser/pkg/logger"
|
|
)
|
|
|
|
func main() {
|
|
// 1. Config
|
|
cfg, err := config.LoadConfig(".")
|
|
if err != nil {
|
|
log.Fatalf("Ошибка загрузки конфига: %v", err)
|
|
}
|
|
|
|
// 2. Logger
|
|
logger.Init(cfg.App.Mode)
|
|
defer logger.Log.Sync()
|
|
|
|
logger.Log.Info("Запуск приложения rmser", zap.String("mode", cfg.App.Mode))
|
|
|
|
// 3. Crypto & DB
|
|
if cfg.Security.SecretKey == "" {
|
|
logger.Log.Fatal("Security.SecretKey не задан в конфиге!")
|
|
}
|
|
cryptoManager := crypto.NewCryptoManager(cfg.Security.SecretKey)
|
|
database := db.NewPostgresDB(cfg.DB.DSN)
|
|
|
|
// 4. Repositories
|
|
accountRepo := accountPkg.NewRepository(database)
|
|
catalogRepo := catalogPkg.NewRepository(database)
|
|
recipesRepo := recipesPkg.NewRepository(database)
|
|
invoicesRepo := invoicesPkg.NewRepository(database)
|
|
opsRepo := opsRepoPkg.NewRepository(database)
|
|
recRepo := recRepoPkg.NewRepository(database)
|
|
ocrRepo := ocrRepoPkg.NewRepository(database)
|
|
draftsRepo := draftsPkg.NewRepository(database)
|
|
supplierRepo := suppliersPkg.NewRepository(database)
|
|
|
|
// 5. RMS Factory
|
|
rmsFactory := rms.NewFactory(accountRepo, cryptoManager)
|
|
|
|
// 6. Services
|
|
pyClient := ocr_client.NewClient(cfg.OCR.ServiceURL)
|
|
|
|
syncService := sync.NewService(rmsFactory, accountRepo, catalogRepo, recipesRepo, invoicesRepo, opsRepo, supplierRepo)
|
|
recService := recServicePkg.NewService(recRepo)
|
|
ocrService := ocrServicePkg.NewService(ocrRepo, catalogRepo, draftsRepo, accountRepo, pyClient)
|
|
draftsService := draftsServicePkg.NewService(draftsRepo, ocrRepo, catalogRepo, accountRepo, supplierRepo, rmsFactory)
|
|
|
|
// 7. Handlers
|
|
draftsHandler := handlers.NewDraftsHandler(draftsService)
|
|
ocrHandler := handlers.NewOCRHandler(ocrService)
|
|
recommendHandler := handlers.NewRecommendationsHandler(recService)
|
|
settingsHandler := handlers.NewSettingsHandler(accountRepo, catalogRepo)
|
|
|
|
// 8. Telegram Bot (Передаем syncService)
|
|
if cfg.Telegram.Token != "" {
|
|
// !!! syncService добавлен в аргументы
|
|
bot, err := tgBot.NewBot(cfg.Telegram, ocrService, syncService, accountRepo, rmsFactory, cryptoManager)
|
|
if err != nil {
|
|
logger.Log.Fatal("Ошибка создания Telegram бота", zap.Error(err))
|
|
}
|
|
go bot.Start()
|
|
defer bot.Stop()
|
|
}
|
|
|
|
// 9. HTTP Server
|
|
if cfg.App.Mode == "release" {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
}
|
|
r := gin.Default()
|
|
|
|
corsConfig := cors.DefaultConfig()
|
|
corsConfig.AllowAllOrigins = true
|
|
corsConfig.AllowMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"}
|
|
corsConfig.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-Telegram-User-ID"}
|
|
r.Use(cors.New(corsConfig))
|
|
|
|
api := r.Group("/api")
|
|
|
|
api.Use(middleware.AuthMiddleware(accountRepo, cfg.Telegram.Token))
|
|
{
|
|
// Drafts & Invoices
|
|
api.GET("/drafts", draftsHandler.GetDrafts)
|
|
api.GET("/drafts/:id", draftsHandler.GetDraft)
|
|
api.DELETE("/drafts/:id", draftsHandler.DeleteDraft)
|
|
// Items CRUD
|
|
api.POST("/drafts/:id/items", draftsHandler.AddDraftItem)
|
|
api.DELETE("/drafts/:id/items/:itemId", draftsHandler.DeleteDraftItem)
|
|
api.PATCH("/drafts/:id/items/:itemId", draftsHandler.UpdateItem)
|
|
api.POST("/drafts/:id/commit", draftsHandler.CommitDraft)
|
|
api.POST("/drafts/container", draftsHandler.AddContainer)
|
|
|
|
// Settings
|
|
api.GET("/settings", settingsHandler.GetSettings)
|
|
api.POST("/settings", settingsHandler.UpdateSettings)
|
|
|
|
// Dictionaries
|
|
api.GET("/dictionaries", draftsHandler.GetDictionaries)
|
|
api.GET("/dictionaries/groups", settingsHandler.GetGroupsTree)
|
|
api.GET("/dictionaries/stores", draftsHandler.GetStores)
|
|
|
|
// Recommendations
|
|
api.GET("/recommendations", recommendHandler.GetRecommendations)
|
|
|
|
// OCR & Matching
|
|
api.GET("/ocr/catalog", ocrHandler.GetCatalog)
|
|
api.GET("/ocr/matches", ocrHandler.GetMatches)
|
|
api.POST("/ocr/match", ocrHandler.SaveMatch)
|
|
api.DELETE("/ocr/match", ocrHandler.DeleteMatch)
|
|
api.GET("/ocr/unmatched", ocrHandler.GetUnmatched)
|
|
api.GET("/ocr/search", ocrHandler.SearchProducts)
|
|
|
|
// Manual Sync Trigger
|
|
api.POST("/sync/all", func(c *gin.Context) {
|
|
userID := c.MustGet("userID").(uuid.UUID)
|
|
// Запускаем в горутине, чтобы не держать соединение
|
|
go func() {
|
|
if err := syncService.SyncAllData(userID); err != nil {
|
|
logger.Log.Error("Manual sync failed", zap.Error(err))
|
|
}
|
|
}()
|
|
c.JSON(200, gin.H{"status": "sync_started", "message": "Синхронизация запущена в фоне"})
|
|
})
|
|
}
|
|
|
|
r.GET("/health", func(c *gin.Context) {
|
|
c.JSON(200, gin.H{"status": "ok", "time": time.Now().Format(time.RFC3339)})
|
|
})
|
|
|
|
logger.Log.Info("Сервер запускается", zap.String("port", cfg.App.Port))
|
|
if err := r.Run(":" + cfg.App.Port); err != nil {
|
|
logger.Log.Fatal("Ошибка запуска сервера", zap.Error(err))
|
|
}
|
|
}
|