init
This commit is contained in:
69
cmd/migrate/main.go
Normal file
69
cmd/migrate/main.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"path/filepath"
|
||||
|
||||
"accounting-app/internal/config"
|
||||
"accounting-app/internal/database"
|
||||
"accounting-app/internal/models"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Load .env file from project root (try multiple locations)
|
||||
envPaths := []string{
|
||||
".env", // Current directory
|
||||
"../.env", // Parent directory (when running from backend/)
|
||||
"../../.env", // Two levels up (when running from backend/cmd/migrate/)
|
||||
filepath.Join("..", "..", ".env"), // Explicit path
|
||||
}
|
||||
|
||||
for _, envPath := range envPaths {
|
||||
if err := godotenv.Load(envPath); err == nil {
|
||||
log.Printf("Loaded environment from: %s", envPath)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
cfg := config.Load()
|
||||
|
||||
// Initialize database connection
|
||||
db, err := database.Initialize(
|
||||
cfg.DBHost,
|
||||
cfg.DBPort,
|
||||
cfg.DBUser,
|
||||
cfg.DBPassword,
|
||||
cfg.DBName,
|
||||
cfg.DBCharset,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
|
||||
// Get underlying SQL DB for cleanup
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get underlying database: %v", err)
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
|
||||
log.Println("Starting database migration...")
|
||||
|
||||
// Run auto migration for all models
|
||||
if err := db.AutoMigrate(models.AllModels()...); err != nil {
|
||||
log.Fatalf("Failed to run migrations: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Database migration completed successfully!")
|
||||
|
||||
// Initialize system categories (refund and reimbursement)
|
||||
log.Println("Initializing system categories...")
|
||||
if err := models.InitSystemCategories(db); err != nil {
|
||||
log.Fatalf("Failed to initialize system categories: %v", err)
|
||||
}
|
||||
|
||||
log.Println("System categories initialized successfully!")
|
||||
}
|
||||
114
cmd/server/main.go
Normal file
114
cmd/server/main.go
Normal file
@@ -0,0 +1,114 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"accounting-app/internal/cache"
|
||||
"accounting-app/internal/config"
|
||||
"accounting-app/internal/database"
|
||||
"accounting-app/internal/repository"
|
||||
"accounting-app/internal/router"
|
||||
"accounting-app/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Load .env file from project root (try multiple locations)
|
||||
envPaths := []string{
|
||||
".env", // Current directory
|
||||
"../.env", // Parent directory (when running from backend/)
|
||||
"../../.env", // Two levels up (when running from backend/cmd/server/)
|
||||
filepath.Join("..", "..", ".env"), // Explicit path
|
||||
}
|
||||
|
||||
for _, envPath := range envPaths {
|
||||
if err := godotenv.Load(envPath); err == nil {
|
||||
log.Printf("Loaded environment from: %s", envPath)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
cfg := config.Load()
|
||||
|
||||
// Initialize database connection (no migrations or seeding)
|
||||
db, err := database.Initialize(
|
||||
cfg.DBHost,
|
||||
cfg.DBPort,
|
||||
cfg.DBUser,
|
||||
cfg.DBPassword,
|
||||
cfg.DBName,
|
||||
cfg.DBCharset,
|
||||
)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
|
||||
// Get underlying SQL DB for cleanup
|
||||
sqlDB, err := db.DB()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get underlying database: %v", err)
|
||||
}
|
||||
defer sqlDB.Close()
|
||||
|
||||
// Initialize YunAPI client (needed for both Redis and non-Redis modes)
|
||||
exchangeRateRepo := repository.NewExchangeRateRepository(db)
|
||||
yunAPIClient := service.NewYunAPIClientWithConfig(
|
||||
cfg.YunAPIURL,
|
||||
cfg.YunAPIKey,
|
||||
cfg.MaxRetries,
|
||||
exchangeRateRepo,
|
||||
)
|
||||
|
||||
// Create context for scheduler
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
var r *gin.Engine
|
||||
|
||||
// Try to initialize Redis connection
|
||||
// If Redis is available, use the new V2 exchange rate system with caching
|
||||
// If Redis is not available, fall back to the old system
|
||||
// Requirements: 3.1 (sync on start)
|
||||
redisClient, err := cache.NewRedisClient(cfg)
|
||||
if err != nil {
|
||||
// Redis not available - fall back to old system
|
||||
log.Printf("Warning: Redis connection failed (%v), falling back to non-cached exchange rate system", err)
|
||||
|
||||
// Use old scheduler
|
||||
scheduler := service.NewExchangeRateScheduler(yunAPIClient, cfg.SyncInterval)
|
||||
go scheduler.Start(ctx)
|
||||
|
||||
// Setup router without Redis
|
||||
r = router.Setup(db, yunAPIClient, cfg)
|
||||
} else {
|
||||
// Redis is available - use new V2 system with caching
|
||||
log.Println("Redis connected successfully, using cached exchange rate system")
|
||||
defer redisClient.Close()
|
||||
|
||||
// Setup router with Redis support (returns engine and sync scheduler)
|
||||
var syncScheduler *service.SyncScheduler
|
||||
r, syncScheduler = router.SetupWithRedis(db, yunAPIClient, redisClient, cfg)
|
||||
|
||||
// Start the new SyncScheduler in background
|
||||
// This will perform initial sync immediately (Requirement 3.1)
|
||||
go syncScheduler.Start(ctx)
|
||||
}
|
||||
|
||||
// Get port from config or environment
|
||||
port := cfg.ServerPort
|
||||
if envPort := os.Getenv("PORT"); envPort != "" {
|
||||
port = envPort
|
||||
}
|
||||
|
||||
// Start server
|
||||
log.Printf("Starting server on port %s...", port)
|
||||
if err := r.Run(":" + port); err != nil {
|
||||
log.Fatalf("Failed to start server: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user