Files
Portfolio-Engine/internal/database/main.go
2026-03-25 16:54:46 +01:00

120 lines
3.8 KiB
Go

package database
import (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
func InitDB(db *sql.DB) {
schema := `
CREATE TABLE IF NOT EXISTS currencies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT NOT NULL UNIQUE,
name TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
currency_id INTEGER NOT NULL,
shares INTEGER NOT NULL,
product INTEGER NOT NULL CHECK(product IN (0, 1, 2, 3)),
type INTEGER NOT NULL CHECK(type IN (0, 1)),
price REAL NOT NULL
traded_at DATETIME NOT NULL
);
CREATE TABLE IF NOT EXISTS position (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
shares INTEGER NOT NULL,
weight REAL NOT NULL,
CostBases REAL NOT NULL,
);
CREATE TABLE IF NOT EXISTS companies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
shares_outstanding INTEGER NOT NULL,
price REAL NOT NULL,
currency_id INTEGER NOT NULL,
FOREIGN KEY (currency_id) REFERENCES currencies(id)
);
CREATE TABLE IF NOT EXISTS periods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL CHECK(type IN ('Q', 'H', 'Y')),
year INTEGER NOT NULL,
idx INTEGER NOT NULL,
start_date TEXT NOT NULL,
end_date TEXT NOT NULL,
UNIQUE(type, year, idx)
);
CREATE TABLE IF NOT EXISTS category (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
parent_id INTEGER,
name TEXT NOT NULL,
FOREIGN KEY (company_id) REFERENCES companies(id),
FOREIGN KEY (parent_id) REFERENCES category(id),
UNIQUE(company_id, name)
);
CREATE TABLE IF NOT EXISTS revenue_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
currency_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
period_id INTEGER NOT NULL,
value REAL NOT NULL,
FOREIGN KEY (company_id) REFERENCES companies(id),
FOREIGN KEY (currency_id) REFERENCES currencies(id),
FOREIGN KEY (category_id) REFERENCES category(id),
FOREIGN KEY (period_id) REFERENCES periods(id),
UNIQUE(company_id, category_id, period_id)
);`
if _, err := db.Exec(schema); err != nil {
log.Fatal("Failed to create tables:", err)
}
fmt.Println("Tables ready")
}
func MigrateAddUniqueToRevenueEntries(db *sql.DB) error {
steps := []string{
// 1. copy existing data into a temp table with the new constraint
`CREATE TABLE IF NOT EXISTS revenue_entries_new (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
currency_id INTEGER NOT NULL,
category_id INTEGER NOT NULL,
period_id INTEGER NOT NULL,
value REAL NOT NULL,
FOREIGN KEY (company_id) REFERENCES companies(id),
FOREIGN KEY (currency_id) REFERENCES currencies(id),
FOREIGN KEY (category_id) REFERENCES category(id),
FOREIGN KEY (period_id) REFERENCES periods(id),
UNIQUE(company_id, category_id, period_id)
)`,
// 2. copy data over
`INSERT OR IGNORE INTO revenue_entries_new
SELECT id, company_id, currency_id, category_id, period_id, value
FROM revenue_entries`,
// 3. drop old table
`DROP TABLE revenue_entries`,
// 4. rename new table
`ALTER TABLE revenue_entries_new RENAME TO revenue_entries`,
}
for _, step := range steps {
if _, err := db.Exec(step); err != nil {
return fmt.Errorf("migration failed: %w", err)
}
}
return nil
}