Files
speiseplan/db.go
clawd df9e7c5541 v0.2.1 — Code Review Fixes
Fixes:
- CRITICAL: compareVersions used string comparison, fails for 1.10 vs 1.9 (now numeric)
- CRITICAL: Double CloseDatabase() in main.go (defer + OnShutdown)
- CRITICAL: Tailwind v4 in package.json but v3 config/syntax (downgraded to v3)
- CRITICAL: react-router-dom v7 with v5 types (switched to v6, removed deprecated types)
- IMPORTANT: UpdatePlanEntry hook signature mismatch (7 args vs Go's 4)
- IMPORTANT: AllergenPicker hidden checkbox inaccessible to screenreaders (sr-only)
- IMPORTANT: weekHelper getWeekFromDate returned wrong ISO year for edge cases
- IMPORTANT: getWeeksInYear bug for years where Dec 31 is in week 1 of next year
- IMPORTANT: getDateFromWeek off-by-one for some years (use Jan 4 anchor)
- IMPORTANT: ProductSearch click-outside missed dropdown (use container ref)
- IMPORTANT: seed.go LastInsertId=0 on INSERT OR IGNORE skip
- IMPORTANT: SQLite missing PRAGMA foreign_keys=ON and WAL mode
- IMPORTANT: AdditivePicker ADDITIVE_NAMES used numeric IDs but data uses letters
- IMPORTANT: Missing role=dialog/aria-modal on all modal dialogs
- IMPORTANT: Missing Escape key handler on ProductForm modal
- IMPORTANT: Sidebar NavLink aria-current used function instead of string
- IMPORTANT: useProducts searchProducts null safety for allergens/additives
- NICE-TO-HAVE: Added aria-live=polite to WeekPlanner for dynamic updates
- NICE-TO-HAVE: Added postcss.config.js for Tailwind v3
- NICE-TO-HAVE: Updated model comments to match actual day/meal conventions
- NICE-TO-HAVE: Modernized vite/typescript/plugin versions
2026-02-20 10:11:54 +00:00

131 lines
3.0 KiB
Go

package main
import (
"fmt"
"os"
"path/filepath"
"github.com/jmoiron/sqlx"
_ "modernc.org/sqlite"
)
var db *sqlx.DB
// InitDatabase initialisiert die SQLite-Datenbank
func InitDatabase() error {
// DB-Datei im User-Home-Verzeichnis
homeDir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("failed to get user home directory: %w", err)
}
dbPath := filepath.Join(homeDir, "speiseplan.db")
// Verbindung zur Datenbank herstellen
database, err := sqlx.Open("sqlite", dbPath)
if err != nil {
return fmt.Errorf("failed to open database: %w", err)
}
db = database
// SQLite Pragmas setzen
db.MustExec("PRAGMA journal_mode=WAL")
db.MustExec("PRAGMA foreign_keys=ON")
// Schema erstellen
if err := createSchema(); err != nil {
return fmt.Errorf("failed to create schema: %w", err)
}
// Seed-Daten einfügen
if err := SeedDatabase(); err != nil {
return fmt.Errorf("failed to seed database: %w", err)
}
return nil
}
// createSchema erstellt das Datenbankschema
func createSchema() error {
schema := `
-- 14 EU-Allergene (gesetzlich vorgeschrieben, LMIV Verordnung)
CREATE TABLE IF NOT EXISTS allergens (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
category TEXT NOT NULL DEFAULT 'allergen'
);
-- Zusatzstoffe (deutsche Lebensmittelkennzeichnung)
CREATE TABLE IF NOT EXISTS additives (
id TEXT PRIMARY KEY,
name TEXT NOT NULL
);
-- Produkte
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
multiline BOOLEAN DEFAULT FALSE
);
-- Produkt-Allergen-Zuordnung (n:m)
CREATE TABLE IF NOT EXISTS product_allergens (
product_id INTEGER REFERENCES products(id) ON DELETE CASCADE,
allergen_id TEXT REFERENCES allergens(id),
PRIMARY KEY (product_id, allergen_id)
);
-- Produkt-Zusatzstoff-Zuordnung (n:m)
CREATE TABLE IF NOT EXISTS product_additives (
product_id INTEGER REFERENCES products(id) ON DELETE CASCADE,
additive_id TEXT REFERENCES additives(id),
PRIMARY KEY (product_id, additive_id)
);
-- Wochenpläne
CREATE TABLE IF NOT EXISTS week_plans (
id INTEGER PRIMARY KEY AUTOINCREMENT,
year INTEGER NOT NULL,
week INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(year, week)
);
-- Einträge im Wochenplan
CREATE TABLE IF NOT EXISTS plan_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
week_plan_id INTEGER REFERENCES week_plans(id) ON DELETE CASCADE,
day INTEGER NOT NULL,
meal TEXT NOT NULL,
slot INTEGER NOT NULL DEFAULT 0,
product_id INTEGER REFERENCES products(id),
custom_text TEXT,
group_label TEXT
);
-- Sondertage
CREATE TABLE IF NOT EXISTS special_days (
id INTEGER PRIMARY KEY AUTOINCREMENT,
week_plan_id INTEGER REFERENCES week_plans(id) ON DELETE CASCADE,
day INTEGER NOT NULL,
type TEXT NOT NULL,
label TEXT
);`
_, err := db.Exec(schema)
return err
}
// GetDB gibt die Datenbankverbindung zurück
func GetDB() *sqlx.DB {
return db
}
// CloseDatabase schließt die Datenbankverbindung
func CloseDatabase() error {
if db != nil {
return db.Close()
}
return nil
}