up
This commit is contained in:
219
cmd/server/main.go
Normal file
219
cmd/server/main.go
Normal file
@@ -0,0 +1,219 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/f4bpo/rental-manager/internal/auth"
|
||||
"github.com/f4bpo/rental-manager/internal/calendar"
|
||||
"github.com/f4bpo/rental-manager/internal/category"
|
||||
"github.com/f4bpo/rental-manager/internal/db"
|
||||
"github.com/f4bpo/rental-manager/internal/document"
|
||||
"github.com/f4bpo/rental-manager/internal/fiscal"
|
||||
"github.com/f4bpo/rental-manager/internal/ical"
|
||||
"github.com/f4bpo/rental-manager/internal/importer"
|
||||
"github.com/f4bpo/rental-manager/internal/loan"
|
||||
"github.com/f4bpo/rental-manager/internal/property"
|
||||
"github.com/f4bpo/rental-manager/internal/transaction"
|
||||
"github.com/f4bpo/rental-manager/web"
|
||||
)
|
||||
|
||||
func corsMiddleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
origin := r.Header.Get("Origin")
|
||||
if strings.Contains(origin, "localhost") {
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
|
||||
}
|
||||
if r.Method == "OPTIONS" {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
database, err := db.Init("./data/rental.db")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to init database: %v", err)
|
||||
}
|
||||
defer database.Close()
|
||||
|
||||
if err := db.Migrate(database); err != nil {
|
||||
log.Fatalf("failed to run migrations: %v", err)
|
||||
}
|
||||
|
||||
propertyStore := property.NewStore(database)
|
||||
transactionStore := transaction.NewStore(database)
|
||||
documentStore := document.NewStore(database)
|
||||
documentStore.Migrate()
|
||||
calendarStore := calendar.NewStore(database)
|
||||
userStore := auth.NewStore(database)
|
||||
categoryStore := category.NewStore(database)
|
||||
|
||||
if userStore.Count() == 0 {
|
||||
u, err := userStore.Create("admin@rental.local", "Administrateur", "admin1234")
|
||||
if err != nil {
|
||||
log.Printf("⚠ impossible de créer l'utilisateur par défaut: %v", err)
|
||||
} else {
|
||||
log.Printf("✓ Utilisateur par défaut créé — email: %s / mdp: admin1234", u.Email)
|
||||
}
|
||||
}
|
||||
|
||||
loanStore := loan.NewStore(database)
|
||||
loanStore.Migrate()
|
||||
|
||||
// Seed tableaux d'amortissement si pas encore importés
|
||||
loans, _ := loanStore.ListLoans("")
|
||||
if len(loans) == 0 {
|
||||
log.Println("ℹ Tableaux d'amortissement non encore configurés.")
|
||||
log.Println(" Ajoutez vos prêts dans la page Prêts et uploadez les échéances.")
|
||||
}
|
||||
|
||||
icalService := ical.NewService(calendarStore, propertyStore)
|
||||
icalService.StartSync()
|
||||
|
||||
authHandler := auth.NewHandler(userStore)
|
||||
propertyHandler := property.NewHandler(propertyStore)
|
||||
transactionHandler := transaction.NewHandler(transactionStore)
|
||||
documentHandler := document.NewHandler(documentStore, "./data/documents")
|
||||
calendarHandler := calendar.NewHandler(calendarStore)
|
||||
fiscalHandler := fiscal.NewHandler(transactionStore, documentStore)
|
||||
categoryHandler := category.NewHandler(categoryStore)
|
||||
importHandler := importer.NewHandler(database)
|
||||
loanHandler := loan.NewHandler(loanStore)
|
||||
|
||||
r := mux.NewRouter()
|
||||
r.Use(corsMiddleware)
|
||||
|
||||
api := r.PathPrefix("/api").Subrouter()
|
||||
|
||||
api.HandleFunc("/auth/login", authHandler.Login).Methods("POST", "OPTIONS")
|
||||
api.HandleFunc("/auth/logout", authHandler.Logout).Methods("POST", "OPTIONS")
|
||||
api.HandleFunc("/auth/register", func(w http.ResponseWriter, r *http.Request) {
|
||||
if userStore.Count() > 0 {
|
||||
auth.Middleware(userStore)(http.HandlerFunc(authHandler.Register)).ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
authHandler.Register(w, r)
|
||||
}).Methods("POST", "OPTIONS")
|
||||
|
||||
protected := api.NewRoute().Subrouter()
|
||||
protected.Use(auth.Middleware(userStore))
|
||||
|
||||
// Profil & utilisateurs
|
||||
protected.HandleFunc("/me", authHandler.Me).Methods("GET")
|
||||
protected.HandleFunc("/me", authHandler.UpdateProfile).Methods("PUT")
|
||||
protected.HandleFunc("/me/password", authHandler.UpdatePassword).Methods("PUT")
|
||||
protected.HandleFunc("/users", authHandler.ListUsers).Methods("GET")
|
||||
protected.HandleFunc("/users/{id}", authHandler.DeleteUser).Methods("DELETE")
|
||||
|
||||
// Catégories
|
||||
protected.HandleFunc("/categories", categoryHandler.List).Methods("GET")
|
||||
protected.HandleFunc("/categories", categoryHandler.Create).Methods("POST")
|
||||
protected.HandleFunc("/categories/{id}", categoryHandler.Update).Methods("PUT")
|
||||
protected.HandleFunc("/categories/{id}", categoryHandler.Delete).Methods("DELETE")
|
||||
|
||||
// Biens
|
||||
protected.HandleFunc("/properties", propertyHandler.List).Methods("GET")
|
||||
protected.HandleFunc("/properties", propertyHandler.Create).Methods("POST")
|
||||
protected.HandleFunc("/properties/{id}", propertyHandler.Get).Methods("GET")
|
||||
protected.HandleFunc("/properties/{id}", propertyHandler.Update).Methods("PUT")
|
||||
protected.HandleFunc("/properties/{id}", propertyHandler.Delete).Methods("DELETE")
|
||||
|
||||
// Transactions
|
||||
protected.HandleFunc("/transactions", transactionHandler.List).Methods("GET")
|
||||
protected.HandleFunc("/transactions", transactionHandler.Create).Methods("POST")
|
||||
protected.HandleFunc("/transactions/summary", transactionHandler.Summary).Methods("GET")
|
||||
protected.HandleFunc("/transactions/monthly", transactionHandler.Monthly).Methods("GET")
|
||||
protected.HandleFunc("/transactions/categories", transactionHandler.CategoryBreakdown).Methods("GET")
|
||||
protected.HandleFunc("/transactions/{id}", transactionHandler.Get).Methods("GET")
|
||||
protected.HandleFunc("/transactions/{id}", transactionHandler.Update).Methods("PUT")
|
||||
protected.HandleFunc("/transactions/{id}", transactionHandler.Delete).Methods("DELETE")
|
||||
protected.HandleFunc("/transactions/{id}/split", transactionHandler.SplitTransaction).Methods("POST")
|
||||
|
||||
// Import QIF
|
||||
protected.HandleFunc("/import/preview", importHandler.Preview).Methods("POST")
|
||||
protected.HandleFunc("/import/check", importHandler.Check).Methods("POST")
|
||||
protected.HandleFunc("/import/qif", importHandler.Import).Methods("POST")
|
||||
|
||||
// Documents
|
||||
protected.HandleFunc("/documents", documentHandler.List).Methods("GET")
|
||||
protected.HandleFunc("/documents", documentHandler.Upload).Methods("POST")
|
||||
protected.HandleFunc("/documents/export", documentHandler.Export).Methods("GET")
|
||||
protected.HandleFunc("/documents/{id}", documentHandler.Get).Methods("GET")
|
||||
protected.HandleFunc("/documents/{id}", documentHandler.Delete).Methods("DELETE")
|
||||
protected.HandleFunc("/documents/{id}/download", documentHandler.Download).Methods("GET")
|
||||
|
||||
// Calendrier
|
||||
protected.HandleFunc("/calendar", calendarHandler.List).Methods("GET")
|
||||
protected.HandleFunc("/calendar", calendarHandler.CreateEvent).Methods("POST")
|
||||
protected.HandleFunc("/calendar/stats", calendarHandler.Stats).Methods("GET")
|
||||
protected.HandleFunc("/calendar/sync", func(w http.ResponseWriter, r *http.Request) {
|
||||
results := icalService.SyncAll()
|
||||
if results == nil {
|
||||
results = []ical.SyncResult{}
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(results)
|
||||
}).Methods("POST")
|
||||
protected.HandleFunc("/calendar/{id}", calendarHandler.UpdateEvent).Methods("PUT")
|
||||
protected.HandleFunc("/calendar/{id}", calendarHandler.DeleteEvent).Methods("DELETE")
|
||||
|
||||
// Prêts immobiliers
|
||||
protected.HandleFunc("/loans", loanHandler.ListLoans).Methods("GET")
|
||||
protected.HandleFunc("/loans", loanHandler.CreateLoan).Methods("POST")
|
||||
// Routes statiques AVANT les routes avec {id}
|
||||
protected.HandleFunc("/loans/split", loanHandler.GetSplitForAmount).Methods("GET")
|
||||
protected.HandleFunc("/loans/upload-pdf", loanHandler.UploadPDF).Methods("POST")
|
||||
protected.HandleFunc("/loans/create", loanHandler.CreateLoanManual).Methods("POST")
|
||||
// Routes avec paramètre {id}
|
||||
protected.HandleFunc("/loans/{id}", loanHandler.DeleteLoan).Methods("DELETE")
|
||||
protected.HandleFunc("/loans/{id}/lines", loanHandler.GetLines).Methods("GET")
|
||||
protected.HandleFunc("/loans/{id}/lines", loanHandler.UploadLines).Methods("POST")
|
||||
protected.HandleFunc("/loans/{id}/split", loanHandler.SplitByDate).Methods("GET")
|
||||
protected.HandleFunc("/loans/{id}/summary", loanHandler.AnnualSummary).Methods("GET")
|
||||
protected.HandleFunc("/loans/{id}/reload", loanHandler.ReloadLines).Methods("POST")
|
||||
|
||||
// Export fiscal
|
||||
protected.HandleFunc("/fiscal/export", fiscalHandler.Export).Methods("GET")
|
||||
protected.HandleFunc("/fiscal/summary", fiscalHandler.Summary).Methods("GET")
|
||||
|
||||
// Arrêt du serveur
|
||||
protected.HandleFunc("/shutdown", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
go func() { os.Exit(0) }()
|
||||
}).Methods("POST")
|
||||
|
||||
// Frontend embarqué
|
||||
assets, err := web.Assets()
|
||||
if err != nil {
|
||||
log.Fatalf("embed frontend: %v", err)
|
||||
}
|
||||
fileServer := http.FileServer(http.FS(assets))
|
||||
r.PathPrefix("/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
path := strings.TrimPrefix(r.URL.Path, "/")
|
||||
if path == "" {
|
||||
path = "index.html"
|
||||
}
|
||||
if _, err := assets.Open(path); err != nil {
|
||||
r.URL.Path = "/"
|
||||
}
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
port := os.Getenv("PORT")
|
||||
if port == "" {
|
||||
port = "9000"
|
||||
}
|
||||
log.Printf("🏠 Rental Manager démarré sur http://localhost:%s", port)
|
||||
log.Fatal(http.ListenAndServe(":"+port, r))
|
||||
}
|
||||
Reference in New Issue
Block a user