summaryrefslogtreecommitdiff
path: root/src/db.c
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-20 12:59:05 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-20 12:59:05 +0200
commite5abd28a9806ee8f4239a1db068876be82363975 (patch)
tree2af68cbd748e49f7547226c06b233240a2f252c5 /src/db.c
parent9ee8cb18b1017dce11e7c8c9b7fafad301cb766e (diff)
downloadbokf-e5abd28a9806ee8f4239a1db068876be82363975.tar.gz
bokf-e5abd28a9806ee8f4239a1db068876be82363975.zip
bank: import SEB CSV and match against vouchers (schema v8)
Diffstat (limited to 'src/db.c')
-rw-r--r--src/db.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/db.c b/src/db.c
index c809bea..7e23cb0 100644
--- a/src/db.c
+++ b/src/db.c
@@ -271,6 +271,39 @@ static const char SCHEMA_V1[] =
" key TEXT NOT NULL,"
" value TEXT NOT NULL,"
" PRIMARY KEY (org_id, key)"
+ ") STRICT;\n"
+
+ "CREATE TABLE bank_transactions ("
+ " org_id INTEGER NOT NULL REFERENCES orgs(id),"
+ " id INTEGER PRIMARY KEY,"
+ " account TEXT NOT NULL,"
+ " booked_at TEXT NOT NULL,"
+ " value_date TEXT NOT NULL,"
+ " text TEXT NOT NULL,"
+ " type TEXT NOT NULL,"
+ " amount_ore INTEGER NOT NULL,"
+ " balance_ore INTEGER,"
+ " source TEXT NOT NULL,"
+ " source_hash BLOB NOT NULL CHECK (length(source_hash) = 32),"
+ " imported_at TEXT NOT NULL,"
+ " imported_by INTEGER NOT NULL REFERENCES users(id),"
+ " UNIQUE (org_id, id),"
+ " UNIQUE (org_id, source_hash)"
+ ") STRICT;\n"
+ "CREATE INDEX idx_bank_tx_date ON bank_transactions(org_id, booked_at);\n"
+
+ "CREATE TABLE bank_matches ("
+ " org_id INTEGER NOT NULL,"
+ " transaction_id INTEGER NOT NULL,"
+ " voucher_id INTEGER NOT NULL,"
+ " matched_at TEXT NOT NULL,"
+ " matched_by INTEGER NOT NULL REFERENCES users(id),"
+ " kind TEXT NOT NULL DEFAULT 'manual'"
+ " CHECK (kind IN ('manual','auto')),"
+ " PRIMARY KEY (org_id, transaction_id, voucher_id),"
+ " FOREIGN KEY (org_id, transaction_id)"
+ " REFERENCES bank_transactions(org_id, id),"
+ " FOREIGN KEY (org_id, voucher_id) REFERENCES vouchers(org_id, id)"
") STRICT;\n";
static const char SCHEMA_V2[] =
@@ -458,6 +491,50 @@ static int db_upgrade_v7(sqlite3 *db, char **err)
err);
}
+/* v8: bank reconciliation — imported statement evidence and the mutable
+ transaction/voucher links (phase 1 never books anything). */
+static int db_upgrade_v8(sqlite3 *db, char **err)
+{
+ if (db_exec(db,
+ "CREATE TABLE IF NOT EXISTS bank_transactions ("
+ " org_id INTEGER NOT NULL REFERENCES orgs(id),"
+ " id INTEGER PRIMARY KEY,"
+ " account TEXT NOT NULL,"
+ " booked_at TEXT NOT NULL,"
+ " value_date TEXT NOT NULL,"
+ " text TEXT NOT NULL,"
+ " type TEXT NOT NULL,"
+ " amount_ore INTEGER NOT NULL,"
+ " balance_ore INTEGER,"
+ " source TEXT NOT NULL,"
+ " source_hash BLOB NOT NULL CHECK (length(source_hash) = 32),"
+ " imported_at TEXT NOT NULL,"
+ " imported_by INTEGER NOT NULL REFERENCES users(id),"
+ " UNIQUE (org_id, id),"
+ " UNIQUE (org_id, source_hash)"
+ ") STRICT;"
+ "CREATE INDEX IF NOT EXISTS idx_bank_tx_date"
+ " ON bank_transactions(org_id, booked_at);",
+ err) != 0)
+ return -1;
+ return db_exec(db,
+ "CREATE TABLE IF NOT EXISTS bank_matches ("
+ " org_id INTEGER NOT NULL,"
+ " transaction_id INTEGER NOT NULL,"
+ " voucher_id INTEGER NOT NULL,"
+ " matched_at TEXT NOT NULL,"
+ " matched_by INTEGER NOT NULL REFERENCES users(id),"
+ " kind TEXT NOT NULL DEFAULT 'manual'"
+ " CHECK (kind IN ('manual','auto')),"
+ " PRIMARY KEY (org_id, transaction_id, voucher_id),"
+ " FOREIGN KEY (org_id, transaction_id)"
+ " REFERENCES bank_transactions(org_id, id),"
+ " FOREIGN KEY (org_id, voucher_id)"
+ " REFERENCES vouchers(org_id, id)"
+ ") STRICT",
+ err);
+}
+
static int db_upgrade(sqlite3 *db, int from, char **err)
{
if (db_exec(db, "BEGIN IMMEDIATE", err) != 0)
@@ -486,6 +563,10 @@ static int db_upgrade(sqlite3 *db, int from, char **err)
db_exec(db, "ROLLBACK", NULL);
return -1;
}
+ if (from < 8 && db_upgrade_v8(db, err) != 0) {
+ db_exec(db, "ROLLBACK", NULL);
+ return -1;
+ }
char *sql = sqlite3_mprintf(
"UPDATE meta SET value='%d' WHERE key='schema_version'",
BOKF_SCHEMA_VERSION);