Some checks failed
Release / build (windows-latest) (push) Has been cancelled
v0.2.6 still had comment lines in schema.sql that changed the SHA-384 checksum. sqlx requires byte-for-byte match with the originally applied migration SQL. schema.sql is now identical to the v0.2.4 original. Migrations 4 (is_inputable column) and 5 (import_config_templates table) in lib.rs handle adding these to existing databases. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
166 lines
6.6 KiB
SQL
166 lines
6.6 KiB
SQL
-- Simpl'Résultat Database Schema
|
|
|
|
CREATE TABLE IF NOT EXISTS import_sources (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
description TEXT,
|
|
date_format TEXT NOT NULL DEFAULT '%d/%m/%Y',
|
|
delimiter TEXT NOT NULL DEFAULT ';',
|
|
encoding TEXT NOT NULL DEFAULT 'utf-8',
|
|
column_mapping TEXT NOT NULL, -- JSON mapping
|
|
skip_lines INTEGER NOT NULL DEFAULT 0,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS imported_files (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
source_id INTEGER NOT NULL,
|
|
filename TEXT NOT NULL,
|
|
file_hash TEXT NOT NULL,
|
|
import_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
row_count INTEGER NOT NULL DEFAULT 0,
|
|
status TEXT NOT NULL DEFAULT 'completed', -- 'completed', 'partial', 'error'
|
|
notes TEXT,
|
|
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE CASCADE,
|
|
UNIQUE(source_id, file_hash)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS categories (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
parent_id INTEGER,
|
|
color TEXT,
|
|
icon TEXT,
|
|
type TEXT NOT NULL DEFAULT 'expense', -- 'expense', 'income', 'transfer'
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (parent_id) REFERENCES categories(id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS suppliers (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
normalized_name TEXT NOT NULL,
|
|
category_id INTEGER,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS keywords (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
keyword TEXT NOT NULL,
|
|
category_id INTEGER NOT NULL,
|
|
supplier_id INTEGER,
|
|
priority INTEGER NOT NULL DEFAULT 0,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
|
UNIQUE(keyword, category_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS transactions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
date DATE NOT NULL,
|
|
description TEXT NOT NULL,
|
|
amount REAL NOT NULL,
|
|
category_id INTEGER,
|
|
supplier_id INTEGER,
|
|
source_id INTEGER,
|
|
file_id INTEGER,
|
|
original_description TEXT,
|
|
notes TEXT,
|
|
is_manually_categorized INTEGER NOT NULL DEFAULT 0,
|
|
is_split INTEGER NOT NULL DEFAULT 0,
|
|
parent_transaction_id INTEGER,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (supplier_id) REFERENCES suppliers(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (source_id) REFERENCES import_sources(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (file_id) REFERENCES imported_files(id) ON DELETE SET NULL,
|
|
FOREIGN KEY (parent_transaction_id) REFERENCES transactions(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS adjustments (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
description TEXT,
|
|
date DATE NOT NULL,
|
|
is_recurring INTEGER NOT NULL DEFAULT 0,
|
|
recurrence_rule TEXT, -- JSON rule for recurring adjustments
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS adjustment_entries (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
adjustment_id INTEGER NOT NULL,
|
|
category_id INTEGER NOT NULL,
|
|
amount REAL NOT NULL,
|
|
description TEXT,
|
|
FOREIGN KEY (adjustment_id) REFERENCES adjustments(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS budget_entries (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
category_id INTEGER NOT NULL,
|
|
year INTEGER NOT NULL,
|
|
month INTEGER NOT NULL, -- 1-12
|
|
amount REAL NOT NULL,
|
|
notes TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
|
UNIQUE(category_id, year, month)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS budget_templates (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
description TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS budget_template_entries (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
template_id INTEGER NOT NULL,
|
|
category_id INTEGER NOT NULL,
|
|
amount REAL NOT NULL,
|
|
FOREIGN KEY (template_id) REFERENCES budget_templates(id) ON DELETE CASCADE,
|
|
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE,
|
|
UNIQUE(template_id, category_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_preferences (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_date ON transactions(date);
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_category ON transactions(category_id);
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_supplier ON transactions(supplier_id);
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_source ON transactions(source_id);
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_file ON transactions(file_id);
|
|
CREATE INDEX IF NOT EXISTS idx_transactions_parent ON transactions(parent_transaction_id);
|
|
CREATE INDEX IF NOT EXISTS idx_categories_parent ON categories(parent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_categories_type ON categories(type);
|
|
CREATE INDEX IF NOT EXISTS idx_suppliers_category ON suppliers(category_id);
|
|
CREATE INDEX IF NOT EXISTS idx_suppliers_normalized ON suppliers(normalized_name);
|
|
CREATE INDEX IF NOT EXISTS idx_keywords_category ON keywords(category_id);
|
|
CREATE INDEX IF NOT EXISTS idx_keywords_keyword ON keywords(keyword);
|
|
CREATE INDEX IF NOT EXISTS idx_budget_entries_period ON budget_entries(year, month);
|
|
CREATE INDEX IF NOT EXISTS idx_adjustment_entries_adjustment ON adjustment_entries(adjustment_id);
|
|
CREATE INDEX IF NOT EXISTS idx_imported_files_source ON imported_files(source_id);
|
|
|
|
-- Default preferences
|
|
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('language', 'fr');
|
|
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('theme', 'light');
|
|
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('currency', 'EUR');
|
|
INSERT OR IGNORE INTO user_preferences (key, value) VALUES ('date_format', 'DD/MM/YYYY');
|