Bridge global catalogue DB to per-store product catalogue
Adds a separate CatalogueDB (pgvector) connection alongside the main nearledb, plus a new catalogue module (repository/service/controller/ routes) to browse it by brand, category, and keyword, with brand optional so the whole ~237-product catalogue can be browsed unfiltered. Adds the actual bridge: importing a catalogue product snapshots it into the tenant's own products table (keyed on brand+catalogueid, since a catalogue row's bare id is only unique within its own brand table), then links it via the existing productlocations upsert. Re-importing tops up stock and refreshes price instead of duplicating. Also adds an imported-refs endpoint so the frontend can badge already-imported items without diffing full product lists, and wires the new AWS S3 image store used to resolve catalogue product photos. Bumps Go/Docker to 1.24 for the AWS SDK dependency this needs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package db
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
@@ -12,6 +13,10 @@ import (
|
||||
|
||||
var (
|
||||
DB *gorm.DB
|
||||
// CatalogueDB is a separate connection to the pgvector/catalogue database.
|
||||
// It is intentionally isolated from DB (nearledb) so catalogue integration
|
||||
// never touches the main database.
|
||||
CatalogueDB *gorm.DB
|
||||
)
|
||||
|
||||
// --------------------
|
||||
@@ -36,6 +41,44 @@ func Connect() {
|
||||
|
||||
setupDB(DB)
|
||||
fmt.Println("✅ Database connected")
|
||||
|
||||
connectCatalogueDB()
|
||||
connectImageStore()
|
||||
}
|
||||
|
||||
// connectCatalogueDB opens the read-only connection to the catalogue
|
||||
// (pgvector) database. If its env vars are not set, catalogue endpoints
|
||||
// are simply unavailable — this must never block startup of the main app.
|
||||
func connectCatalogueDB() {
|
||||
host := getEnv("CATALOGUE_DB_HOST", "")
|
||||
if host == "" {
|
||||
fmt.Println("⚠️ Catalogue DB env vars not set, skipping catalogue DB connection")
|
||||
return
|
||||
}
|
||||
|
||||
// Built as a URL (not a keyword=value DSN) and percent-encoded via
|
||||
// net/url, because this credential's password contains characters
|
||||
// (quotes, #) that the keyword=value DSN format would misparse as
|
||||
// quoting/comment syntax.
|
||||
dsnURL := url.URL{
|
||||
Scheme: "postgres",
|
||||
User: url.UserPassword(mustEnv("CATALOGUE_DB_USER"), mustEnv("CATALOGUE_DB_PASSWORD")),
|
||||
Host: fmt.Sprintf("%s:%s", host, getEnv("CATALOGUE_DB_PORT", "5432")),
|
||||
Path: "/" + mustEnv("CATALOGUE_DB_NAME"),
|
||||
}
|
||||
q := dsnURL.Query()
|
||||
q.Set("sslmode", "disable")
|
||||
dsnURL.RawQuery = q.Encode()
|
||||
|
||||
catalogueDB, err := gorm.Open(postgres.Open(dsnURL.String()), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Println("❌ Could not connect to catalogue database:", err)
|
||||
return
|
||||
}
|
||||
|
||||
setupDB(catalogueDB)
|
||||
CatalogueDB = catalogueDB
|
||||
fmt.Println("✅ Catalogue database connected")
|
||||
}
|
||||
|
||||
func setupDB(database *gorm.DB) {
|
||||
@@ -53,16 +96,17 @@ func setupDB(database *gorm.DB) {
|
||||
// --------------------
|
||||
|
||||
func CloseDB() {
|
||||
if DB == nil {
|
||||
return
|
||||
if DB != nil {
|
||||
if sqlDB, err := DB.DB(); err == nil {
|
||||
sqlDB.Close()
|
||||
}
|
||||
}
|
||||
sqlDB, err := DB.DB()
|
||||
if err != nil {
|
||||
log.Println("Error retrieving sql.DB:", err)
|
||||
return
|
||||
if CatalogueDB != nil {
|
||||
if sqlDB, err := CatalogueDB.DB(); err == nil {
|
||||
sqlDB.Close()
|
||||
}
|
||||
}
|
||||
fmt.Println("Connection closed Successfully")
|
||||
sqlDB.Close()
|
||||
}
|
||||
|
||||
// --------------------
|
||||
|
||||
Reference in New Issue
Block a user