From 78599e80b6a22eb48e6edce56cfeee14763591db Mon Sep 17 00:00:00 2001 From: Max R Date: Fri, 22 May 2026 19:50:13 -0400 Subject: [PATCH 1/2] fix --- manager_for_ynab/sankey/sankey.sql | 26 ++-- testing/fixtures.py | 11 ++ testing/seed.sql | 158 +++++++++------------ tests/pending_income/seed-transactions.sql | 4 +- tests/sankey/seed.sql | 156 +++++++++++++++----- tests/sankey/test.py | 8 +- 6 files changed, 216 insertions(+), 147 deletions(-) diff --git a/manager_for_ynab/sankey/sankey.sql b/manager_for_ynab/sankey/sankey.sql index d43e3f7..8df579a 100644 --- a/manager_for_ynab/sankey/sankey.sql +++ b/manager_for_ynab/sankey/sankey.sql @@ -1,17 +1,19 @@ WITH filtered_transactions AS ( SELECT - category_group_id - , category_group_name - , category_id - , category_name - , amount - , internal - , COALESCE(payee_name, '') AS payee_name - FROM flat_transactions + ft.category_group_id + , ft.category_group_name + , ft.category_id + , ft.category_name + , ft.amount + , cg.internal AS category_group_internal + , COALESCE(ft.payee_name, '') AS payee_name + FROM flat_transactions AS ft + LEFT JOIN category_groups AS cg + ON ft.category_group_id = cg.id WHERE - "date" BETWEEN ? AND ? - AND LOWER(cleared) = 'reconciled' - AND COALESCE(payee_name, '') != 'Starting Balance' + ft."date" BETWEEN ? AND ? + AND LOWER(ft.cleared) = 'reconciled' + AND COALESCE(ft.payee_name, '') != 'Starting Balance' ) , ready_to_assign_income AS ( @@ -42,7 +44,7 @@ WITH filtered_transactions AS ( , category_name AS payee_name , SUM(amount) AS amount FROM filtered_transactions - WHERE NOT internal + WHERE NOT category_group_internal GROUP BY category_group_id , category_group_name diff --git a/testing/fixtures.py b/testing/fixtures.py index f25180f..34784dd 100644 --- a/testing/fixtures.py +++ b/testing/fixtures.py @@ -1,4 +1,5 @@ import sqlite3 +from importlib.resources import files from pathlib import Path from typing import Any from uuid import uuid4 @@ -6,6 +7,15 @@ import pytest +_DDL_SQL = ( + files("sqlite_export_for_ynab.ddl").joinpath("create-relations.sql").read_text() +) + + +def apply_ddl(con: sqlite3.Connection) -> None: + con.executescript(_DDL_SQL) + + PLAN_ID_1 = str(uuid4()) _TESTING = Path(__file__).parent _SEED_SQL = _TESTING / "seed.sql" @@ -40,6 +50,7 @@ def seed_sql(*extra_paths: Path) -> str: def execute_seed(con: sqlite3.Connection, *extra_paths: Path) -> None: + apply_ddl(con) for statement in seed_sql(*extra_paths).split(";"): statement = statement.strip() if statement: diff --git a/testing/seed.sql b/testing/seed.sql index fc06d1b..8cd86af 100644 --- a/testing/seed.sql +++ b/testing/seed.sql @@ -1,12 +1,9 @@ -CREATE TABLE plans ( - id TEXT PRIMARY KEY - , name TEXT - , currency_format_currency_symbol TEXT - , currency_format_iso_code TEXT -) -; - -INSERT INTO plans VALUES ( +INSERT INTO plans ( + id + , name + , currency_format_currency_symbol + , currency_format_iso_code +) VALUES ( :plan_id , 'My Plan' , '$' @@ -14,18 +11,15 @@ INSERT INTO plans VALUES ( ) ; -CREATE TABLE accounts ( - id TEXT PRIMARY KEY - , plan_id TEXT - , cleared_balance INT - , closed BOOLEAN - , deleted BOOLEAN - , name TEXT - , type TEXT -) -; - -INSERT INTO accounts VALUES ( +INSERT INTO accounts ( + id + , plan_id + , cleared_balance + , closed + , deleted + , name + , type +) VALUES ( :checking_account_id , :plan_id , 430000 @@ -36,7 +30,15 @@ INSERT INTO accounts VALUES ( ) ; -INSERT INTO accounts VALUES ( +INSERT INTO accounts ( + id + , plan_id + , cleared_balance + , closed + , deleted + , name + , type +) VALUES ( :credit_card_account_id , :plan_id , -200000 @@ -47,16 +49,13 @@ INSERT INTO accounts VALUES ( ) ; -CREATE TABLE categories ( - id TEXT PRIMARY KEY - , plan_id TEXT - , deleted BOOLEAN - , category_group_name TEXT - , name TEXT -) -; - -INSERT INTO categories VALUES ( +INSERT INTO categories ( + id + , plan_id + , deleted + , category_group_name + , name +) VALUES ( :ready_to_assign_category_id , :plan_id , 0 @@ -65,7 +64,13 @@ INSERT INTO categories VALUES ( ) ; -INSERT INTO categories VALUES ( +INSERT INTO categories ( + id + , plan_id + , deleted + , category_group_name + , name +) VALUES ( :credit_card_category_id , :plan_id , 0 @@ -74,7 +79,13 @@ INSERT INTO categories VALUES ( ) ; -INSERT INTO categories VALUES ( +INSERT INTO categories ( + id + , plan_id + , deleted + , category_group_name + , name +) VALUES ( :dining_out_category_id , :plan_id , 0 @@ -83,7 +94,13 @@ INSERT INTO categories VALUES ( ) ; -INSERT INTO categories VALUES ( +INSERT INTO categories ( + id + , plan_id + , deleted + , category_group_name + , name +) VALUES ( :duplicate_credit_card_category_id , :plan_id , 1 @@ -92,16 +109,13 @@ INSERT INTO categories VALUES ( ) ; -CREATE TABLE payees ( - id TEXT PRIMARY KEY - , plan_id TEXT - , deleted BOOLEAN - , name TEXT - , transfer_account_id TEXT -) -; - -INSERT INTO payees VALUES ( +INSERT INTO payees ( + id + , plan_id + , deleted + , name + , transfer_account_id +) VALUES ( :employer_payee_id , :plan_id , 0 @@ -110,7 +124,13 @@ INSERT INTO payees VALUES ( ) ; -INSERT INTO payees VALUES ( +INSERT INTO payees ( + id + , plan_id + , deleted + , name + , transfer_account_id +) VALUES ( :transfer_payee_id , :plan_id , 0 @@ -118,49 +138,3 @@ INSERT INTO payees VALUES ( , :checking_account_id ) ; - -CREATE TABLE transactions ( - id TEXT PRIMARY KEY - , plan_id TEXT - , account_id TEXT - , account_name TEXT - , "date" TEXT - , amount INT - , amount_formatted TEXT - , payee_name TEXT - , import_payee_name TEXT - , cleared TEXT - , approved BOOLEAN - , matched_transaction_id TEXT - , deleted BOOLEAN -) -; - -CREATE TABLE subtransactions ( - transfer_transaction_id TEXT - , deleted BOOLEAN -) -; - -CREATE TABLE scheduled_transactions ( - id TEXT PRIMARY KEY - , plan_id TEXT - , account_id TEXT - , account_name TEXT - , amount INT - , amount_formatted TEXT - , amount_currency REAL - , category_id TEXT - , category_name TEXT - , date_first TEXT - , date_next TEXT - , deleted BOOLEAN - , flag_color TEXT - , flag_name TEXT - , frequency TEXT - , memo TEXT - , payee_id TEXT - , payee_name TEXT - , transfer_account_id TEXT -) -; diff --git a/tests/pending_income/seed-transactions.sql b/tests/pending_income/seed-transactions.sql index 8160491..0d527b0 100644 --- a/tests/pending_income/seed-transactions.sql +++ b/tests/pending_income/seed-transactions.sql @@ -126,4 +126,6 @@ INSERT INTO transactions ( ) ; -INSERT INTO subtransactions VALUES ('transfer', 0); +INSERT INTO subtransactions (id, transfer_transaction_id, deleted) +VALUES ('subtxn-transfer', 'transfer', 0) +; diff --git a/tests/sankey/seed.sql b/tests/sankey/seed.sql index c66356c..b21e3b8 100644 --- a/tests/sankey/seed.sql +++ b/tests/sankey/seed.sql @@ -1,114 +1,192 @@ -CREATE TABLE flat_transactions ( - category_group_id TEXT - , category_group_name TEXT - , category_id TEXT - , category_name TEXT - , amount INT - , cleared TEXT - , "date" TEXT - , payee_name TEXT - , internal BOOLEAN -) +INSERT INTO plans (id, name) VALUES ('plan-1', 'My Plan'); + +INSERT INTO category_groups (id, plan_id, name, internal) VALUES +('internal-group', 'plan-1', 'Internal Master Category', 1) +, ('bills-group', 'plan-1', 'Bills', 0) +, ('food-group', 'plan-1', 'Food', 0) +, ('gifts-group', 'plan-1', 'Gifts', 0) +, ('inflow-group', 'plan-1', 'Inflow', 1) ; -INSERT INTO flat_transactions VALUES +INSERT INTO categories ( + id, plan_id, category_group_id, category_group_name, name, internal +) VALUES ( - 'internal-group' + 'ready-to-assign' + , 'plan-1' + , 'internal-group' + , 'Internal Master Category' + , 'Inflow: Ready to Assign' + , 1 +) +, ( + 'rent' + , 'plan-1' + , 'bills-group' + , 'Bills' + , 'Rent' + , 0 +) +, ( + 'groceries' + , 'plan-1' + , 'food-group' + , 'Food' + , 'Groceries' + , 0 +) +, ( + 'restaurants' + , 'plan-1' + , 'food-group' + , 'Food' + , 'Restaurants' + , 0 +) +, ( + 'gifts' + , 'plan-1' + , 'gifts-group' + , 'Gifts' + , 'Gifts' + , 0 +) +, ( + 'hidden' + , 'plan-1' + , 'internal-group' , 'Internal Master Category' + , 'Hidden' + , 1 +) +, ( + 'inflow-ready-to-assign' + , 'plan-1' + , 'inflow-group' + , 'Inflow' + , 'Inflow: Ready to Assign' + , 1 +) +; + +INSERT INTO transactions ( + id + , plan_id + , category_id + , category_name + , amount + , cleared + , "date" + , payee_name + , approved + , deleted +) VALUES +( + 't-employer' + , 'plan-1' , 'ready-to-assign' , 'Inflow: Ready to Assign' , 500000 , 'reconciled' , '2026-04-01' , 'Employer' - , TRUE + , 1 + , 0 ) , ( - 'bills-group' - , 'Bills' + 't-rent-april' + , 'plan-1' , 'rent' , 'Rent' , -120000 , 'reconciled' , '2026-04-02' , 'Landlord' - , FALSE + , 1 + , 0 ) , ( - 'food-group' - , 'Food' + 't-groceries' + , 'plan-1' , 'groceries' , 'Groceries' , -45500 , 'Reconciled' , '2026-04-03' , 'Market' - , FALSE + , 1 + , 0 ) , ( - 'food-group' - , 'Food' + 't-restaurants' + , 'plan-1' , 'restaurants' , 'Restaurants' , -20000 , 'cleared' , '2026-04-03' , 'Cafe' - , FALSE + , 1 + , 0 ) , ( - 'gifts-group' - , 'Gifts' + 't-gifts-in' + , 'plan-1' , 'gifts' , 'Gifts' , 100000 , 'reconciled' , '2026-04-03' , 'Maria Oculam' - , FALSE + , 1 + , 0 ) , ( - 'gifts-group' - , 'Gifts' + 't-gifts-out' + , 'plan-1' , 'gifts' , 'Gifts' , -40000 , 'reconciled' , '2026-04-04' , 'Gift Shop' - , FALSE + , 1 + , 0 ) , ( - 'internal-group' - , 'Internal Master Category' + 't-hidden' + , 'plan-1' , 'hidden' , 'Hidden' , -10000 , 'reconciled' , '2026-04-03' , 'Hidden' - , TRUE + , 1 + , 0 ) , ( - 'bills-group' - , 'Bills' + 't-rent-may' + , 'plan-1' , 'rent' , 'Rent' , -10000 , 'reconciled' , '2026-05-01' , 'Landlord' - , FALSE + , 1 + , 0 ) , ( - 'inflow-group' - , 'Inflow' - , 'ready-to-assign' + 't-starting-balance' + , 'plan-1' + , 'inflow-ready-to-assign' , 'Inflow: Ready to Assign' , 100000 , 'reconciled' , '2026-04-04' , 'Starting Balance' - , TRUE + , 1 + , 0 ) ; diff --git a/tests/sankey/test.py b/tests/sankey/test.py index 056f092..300906a 100644 --- a/tests/sankey/test.py +++ b/tests/sankey/test.py @@ -1,3 +1,4 @@ +import sqlite3 from datetime import date from decimal import Decimal from pathlib import Path @@ -16,6 +17,7 @@ from manager_for_ynab.sankey import sankey from manager_for_ynab.sankey import SankeyRow from manager_for_ynab.sankey import SortBy +from testing.fixtures import apply_ddl _SEED_SQL = Path(__file__).with_name("seed.sql") @@ -29,9 +31,9 @@ def test_today_returns_current_date(): async def db(tmp_path: Path) -> Path: path = tmp_path / "db.sqlite" - async with aiosqlite.connect(path) as con: - await con.executescript(_SEED_SQL.read_text()) - await con.commit() + with sqlite3.connect(path) as con: + apply_ddl(con) + con.executescript(_SEED_SQL.read_text()) return path From d25d6a7eacfc6e14551714fbdef6b27ebfca86c0 Mon Sep 17 00:00:00 2001 From: Max R Date: Fri, 22 May 2026 20:04:07 -0400 Subject: [PATCH 2/2] fix --- manager_for_ynab/sankey/sankey.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/manager_for_ynab/sankey/sankey.sql b/manager_for_ynab/sankey/sankey.sql index 8df579a..3aefec9 100644 --- a/manager_for_ynab/sankey/sankey.sql +++ b/manager_for_ynab/sankey/sankey.sql @@ -5,11 +5,11 @@ WITH filtered_transactions AS ( , ft.category_id , ft.category_name , ft.amount - , cg.internal AS category_group_internal + , c.internal AS category_internal , COALESCE(ft.payee_name, '') AS payee_name FROM flat_transactions AS ft - LEFT JOIN category_groups AS cg - ON ft.category_group_id = cg.id + LEFT JOIN categories AS c + ON ft.category_id = c.id WHERE ft."date" BETWEEN ? AND ? AND LOWER(ft.cleared) = 'reconciled' @@ -44,7 +44,7 @@ WITH filtered_transactions AS ( , category_name AS payee_name , SUM(amount) AS amount FROM filtered_transactions - WHERE NOT category_group_internal + WHERE NOT category_internal GROUP BY category_group_id , category_group_name