This commit is contained in:
2026-04-11 12:12:07 +02:00
parent 3bc6e2e080
commit 5b3c5ebb2f
92 changed files with 10948 additions and 35 deletions

150
internal/db/db.go Normal file
View File

@@ -0,0 +1,150 @@
package db
import (
"database/sql"
"log"
_ "modernc.org/sqlite"
)
func Init(path string) (*sql.DB, error) {
db, err := sql.Open("sqlite", path+"?_foreign_keys=on&_journal_mode=WAL")
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
return nil, err
}
log.Printf("✓ SQLite connecté : %s", path)
return db, nil
}
func Migrate(db *sql.DB) error {
migrations := []string{
sqlCreateUsers,
sqlCreateProperties,
sqlCreateCalendarEvents,
sqlCreateCategories,
sqlCreateTransactions,
sqlCreateDocuments,
sqlCreateFiscalExports,
sqlCreateIcalSyncLog,
sqlSeedCategories,
}
for _, m := range migrations {
if _, err := db.Exec(m); err != nil {
return err
}
}
log.Println("✓ Migrations appliquées")
return nil
}
const sqlCreateUsers = `
CREATE TABLE IF NOT EXISTS users (
id TEXT PRIMARY KEY,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`
const sqlCreateProperties = `
CREATE TABLE IF NOT EXISTS properties (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
address TEXT NOT NULL,
type TEXT NOT NULL CHECK(type IN ('airbnb','longterm')),
bank_account TEXT,
ical_url TEXT,
notes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`
const sqlCreateCalendarEvents = `
CREATE TABLE IF NOT EXISTS calendar_events (
id TEXT PRIMARY KEY,
property_id TEXT NOT NULL REFERENCES properties(id) ON DELETE CASCADE,
title TEXT,
start_date DATE NOT NULL,
end_date DATE NOT NULL,
source TEXT NOT NULL CHECK(source IN ('airbnb','manual')),
ical_uid TEXT,
notes TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(property_id, ical_uid)
);`
const sqlCreateCategories = `
CREATE TABLE IF NOT EXISTS categories (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
type TEXT NOT NULL CHECK(type IN ('income','expense')),
tax_deductible INTEGER DEFAULT 0,
description TEXT
);`
const sqlCreateTransactions = `
CREATE TABLE IF NOT EXISTS transactions (
id TEXT PRIMARY KEY,
property_id TEXT NOT NULL REFERENCES properties(id) ON DELETE CASCADE,
category_id TEXT REFERENCES categories(id),
type TEXT NOT NULL CHECK(type IN ('income','expense')),
amount REAL NOT NULL,
date DATE NOT NULL,
description TEXT,
created_by TEXT REFERENCES users(id),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`
const sqlCreateDocuments = `
CREATE TABLE IF NOT EXISTS documents (
id TEXT PRIMARY KEY,
property_id TEXT NOT NULL REFERENCES properties(id) ON DELETE CASCADE,
transaction_id TEXT REFERENCES transactions(id) ON DELETE SET NULL,
filename TEXT NOT NULL,
original_name TEXT NOT NULL,
file_path TEXT NOT NULL,
mime_type TEXT,
fiscal_year INTEGER,
uploaded_by TEXT REFERENCES users(id),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`
const sqlCreateFiscalExports = `
CREATE TABLE IF NOT EXISTS fiscal_exports (
id TEXT PRIMARY KEY,
property_id TEXT NOT NULL REFERENCES properties(id) ON DELETE CASCADE,
fiscal_year INTEGER NOT NULL,
file_path TEXT NOT NULL,
generated_by TEXT REFERENCES users(id),
generated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);`
const sqlCreateIcalSyncLog = `
CREATE TABLE IF NOT EXISTS ical_sync_log (
id TEXT PRIMARY KEY,
property_id TEXT NOT NULL REFERENCES properties(id) ON DELETE CASCADE,
synced_at DATETIME DEFAULT CURRENT_TIMESTAMP,
status TEXT NOT NULL CHECK(status IN ('ok','error')),
events_imported INTEGER DEFAULT 0,
error_message TEXT
);`
// Catégories de base prêtes à l'emploi
const sqlSeedCategories = `
INSERT OR IGNORE INTO categories (id, name, type, tax_deductible) VALUES
('cat-loyer', 'Loyer perçu', 'income', 0),
('cat-airbnb', 'Revenu Airbnb', 'income', 0),
('cat-charges', 'Charges copropriété', 'expense', 1),
('cat-travaux', 'Travaux & réparations', 'expense', 1),
('cat-assurance', 'Assurance', 'expense', 1),
('cat-taxe', 'Taxe foncière', 'expense', 1),
('cat-interets', 'Intérêts emprunt', 'expense', 1),
('cat-menage', 'Ménage & entretien', 'expense', 1),
('cat-gestion', 'Frais de gestion', 'expense', 1),
('cat-electricite', 'Électricité', 'expense', 1),
('cat-eau', 'Eau', 'expense', 1),
('cat-internet', 'Internet', 'expense', 1),
('cat-autre-dep', 'Autre dépense', 'expense', 0),
('cat-autre-rev', 'Autre revenu', 'income', 0);`