Files
goodie/cmd/odoo-server/main.go
Marc 66383adf06 feat: Portal, Email Inbound, Discuss + module improvements
- Portal: /my/* routes, signup, password reset, portal user support
- Email Inbound: IMAP polling (go-imap/v2), thread matching
- Discuss: mail.channel, long-polling bus, DM, unread count
- Cron: ir.cron runner (goroutine scheduler)
- Bank Import, CSV/Excel Import
- Automation (ir.actions.server)
- Fetchmail service
- HR Payroll model
- Various fixes across account, sale, stock, purchase, crm, hr, project

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 18:41:57 +02:00

143 lines
3.7 KiB
Go

// Odoo Go Server — Main entrypoint
// Mirrors: odoo-bin
//
// Usage:
//
// go run ./cmd/odoo-server
// ODOO_DB_HOST=localhost ODOO_DB_PORT=5432 go run ./cmd/odoo-server
package main
import (
"context"
"log"
"os"
"os/signal"
"path/filepath"
"syscall"
"github.com/jackc/pgx/v5/pgxpool"
// Import all modules (register models via init())
_ "odoo-go/addons/base"
_ "odoo-go/addons/mail"
_ "odoo-go/addons/account"
_ "odoo-go/addons/product"
_ "odoo-go/addons/sale"
_ "odoo-go/addons/stock"
_ "odoo-go/addons/purchase"
_ "odoo-go/addons/hr"
_ "odoo-go/addons/project"
_ "odoo-go/addons/crm"
_ "odoo-go/addons/fleet"
_ "odoo-go/addons/l10n_de"
// Google integrations (opt-in, only active with API keys)
_ "odoo-go/addons/google_address"
_ "odoo-go/addons/google_translate"
_ "odoo-go/addons/google_calendar"
"odoo-go/pkg/modules"
"odoo-go/pkg/server"
"odoo-go/pkg/service"
"odoo-go/pkg/tools"
)
func main() {
log.SetFlags(log.Ltime | log.Lshortfile)
// Load configuration
cfg := tools.DefaultConfig()
cfg.LoadFromEnv()
// Auto-detect frontend/ directory relative to the binary if not set
if cfg.FrontendDir == "" {
exe, _ := os.Executable()
candidate := filepath.Join(filepath.Dir(exe), "frontend")
if _, err := os.Stat(candidate); err != nil {
// Try relative to working directory
candidate = "frontend"
}
cfg.FrontendDir = candidate
}
// Auto-detect build/ directory
if cfg.BuildDir == "" {
exe, _ := os.Executable()
candidate := filepath.Join(filepath.Dir(exe), "build")
if _, err := os.Stat(candidate); err != nil {
candidate = "build"
}
cfg.BuildDir = candidate
}
log.Printf("odoo: Odoo Go Server 19.0")
log.Printf("odoo: database: %s@%s:%d/%s", cfg.DBUser, cfg.DBHost, cfg.DBPort, cfg.DBName)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Handle shutdown signals
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigCh
log.Printf("odoo: received signal %s, shutting down...", sig)
cancel()
}()
// Connect to database
pool, err := pgxpool.New(ctx, cfg.DSN())
if err != nil {
log.Fatalf("odoo: database connection failed: %v", err)
}
defer pool.Close()
if err := pool.Ping(ctx); err != nil {
log.Fatalf("odoo: database ping failed: %v", err)
}
log.Println("odoo: database connected")
// Load modules (base is auto-registered via init())
log.Println("odoo: loading modules...")
if err := modules.LoadModules(modules.All()); err != nil {
log.Fatalf("odoo: module loading failed: %v", err)
}
log.Printf("odoo: %d modules loaded", len(modules.All()))
// Initialize database schema
log.Println("odoo: initializing database schema...")
if err := service.InitDatabase(ctx, pool); err != nil {
log.Fatalf("odoo: schema init failed: %v", err)
}
// Migrate schema: add any missing columns for newly registered fields
log.Println("odoo: running schema migration...")
if err := service.MigrateSchema(ctx, pool); err != nil {
log.Printf("odoo: schema migration warning: %v", err)
}
// Check if database needs setup
if service.NeedsSetup(ctx, pool) {
log.Println("odoo: database is empty — database manager will be shown at /web/database/manager")
} else {
log.Println("odoo: database already initialized")
}
// Initialize session table
if err := server.InitSessionTable(ctx, pool); err != nil {
log.Printf("odoo: session table init warning: %v", err)
}
// Start cron scheduler
cronScheduler := service.NewCronScheduler(pool)
cronScheduler.Start()
defer cronScheduler.Stop()
// Start HTTP server
srv := server.New(cfg, pool)
log.Printf("odoo: starting HTTP service on %s:%d", cfg.HTTPInterface, cfg.HTTPPort)
if err := srv.Start(); err != nil {
log.Fatalf("odoo: server error: %v", err)
}
}