diff --git a/examples/trackd_byod_gnucash_demo/README.md b/examples/trackd_byod_gnucash_demo/README.md new file mode 100644 index 0000000..f8489f6 --- /dev/null +++ b/examples/trackd_byod_gnucash_demo/README.md @@ -0,0 +1,12 @@ +# Track D — BYOD GnuCash Demo (core_gl) + +This is a small runnable example project for the Track D BYOD pipeline using the +`gnucash_gl` adapter. + +## Run + +```bash +pystatsv1 trackd byod normalize --project . +``` + +Outputs are written under `normalized/`. diff --git a/examples/trackd_byod_gnucash_demo/config.toml b/examples/trackd_byod_gnucash_demo/config.toml new file mode 100644 index 0000000..07890c3 --- /dev/null +++ b/examples/trackd_byod_gnucash_demo/config.toml @@ -0,0 +1,5 @@ +# Track D BYOD project config +[trackd] +profile = "core_gl" +tables_dir = "tables" +adapter = "gnucash_gl" diff --git a/examples/trackd_byod_gnucash_demo/tables/chart_of_accounts.csv b/examples/trackd_byod_gnucash_demo/tables/chart_of_accounts.csv new file mode 100644 index 0000000..cd195e2 --- /dev/null +++ b/examples/trackd_byod_gnucash_demo/tables/chart_of_accounts.csv @@ -0,0 +1 @@ +account_id,account_name,account_type,normal_side diff --git a/examples/trackd_byod_gnucash_demo/tables/gl_journal.csv b/examples/trackd_byod_gnucash_demo/tables/gl_journal.csv new file mode 100644 index 0000000..874307d --- /dev/null +++ b/examples/trackd_byod_gnucash_demo/tables/gl_journal.csv @@ -0,0 +1,22 @@ +Date,Transaction ID,Number,Description,Full Account Name,Account Name,Amount (Num.) +2026-01-01,TXN-0001,,Owner investment,Assets:Current Assets:Checking,Checking,5000.00 +2026-01-01,TXN-0001,,Owner investment,Equity:Owner Capital,Owner Capital,5000.00 +2026-01-02,TXN-0002,,Buy shipping supplies,Expenses:Supplies,Supplies,120.00 +2026-01-02,TXN-0002,,Buy shipping supplies,Assets:Current Assets:Checking,Checking,-120.00 +2026-01-03,TXN-0003,,Online sale (order #1001),Assets:Current Assets:Checking,Checking,250.00 +2026-01-03,TXN-0003,,Online sale (order #1001),Income:Sales,Sales,250.00 +2026-01-04,TXN-0004,,Rent payment,Expenses:Rent,Rent,800.00 +2026-01-04,TXN-0004,,Rent payment,Assets:Current Assets:Checking,Checking,-800.00 +2026-01-05,TXN-0005,,Online sale (order #1002),Assets:Current Assets:Checking,Checking,300.00 +2026-01-05,TXN-0005,,Online sale (order #1002),Income:Sales,Sales,300.00 +2026-01-05,TXN-0006,,Ship order #1001,Expenses:Shipping,Shipping,20.00 +2026-01-05,TXN-0006,,Ship order #1001,Assets:Current Assets:Checking,Checking,-20.00 +2026-01-06,TXN-0007,,Instagram ads,Expenses:Advertising,Advertising,50.00 +2026-01-06,TXN-0007,,Instagram ads,Assets:Current Assets:Checking,Checking,-50.00 +2026-01-07,TXN-0008,,Online sale (order #1003),Assets:Current Assets:Checking,Checking,180.00 +2026-01-07,TXN-0008,,Online sale (order #1003),Income:Sales,Sales,180.00 +2026-01-09,TXN-0009,,Online sale (order #1004) + sales tax,Assets:Current Assets:Checking,Checking,105.00 +2026-01-09,TXN-0009,,Online sale (order #1004) + sales tax,Income:Sales,Sales,100.00 +2026-01-09,TXN-0009,,Online sale (order #1004) + sales tax,Liabilities:Sales Tax Payable,Sales Tax Payable,5.00 +2026-01-10,TXN-0010,,Buy label printer (card),Assets:Equipment,Equipment,600.00 +2026-01-10,TXN-0010,,Buy label printer (card),Liabilities:Credit Card,Credit Card,600.00 diff --git a/tests/test_trackd_byod_gnucash_demo_example_smoke.py b/tests/test_trackd_byod_gnucash_demo_example_smoke.py new file mode 100644 index 0000000..5ae3d66 --- /dev/null +++ b/tests/test_trackd_byod_gnucash_demo_example_smoke.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import csv +import shutil +from pathlib import Path + +from pystatsv1.cli import main + + +def test_trackd_byod_gnucash_demo_example_smoke(tmp_path: Path) -> None: + repo_root = Path(__file__).resolve().parents[1] + src = repo_root / "examples" / "trackd_byod_gnucash_demo" + assert src.exists(), "examples/trackd_byod_gnucash_demo is missing" + + proj = tmp_path / "trackd_byod_gnucash_demo" + shutil.copytree(src, proj) + + rc = main(["trackd", "byod", "normalize", "--project", str(proj)]) + assert rc == 0 + + normalized = proj / "normalized" + gl_path = normalized / "gl_journal.csv" + coa_path = normalized / "chart_of_accounts.csv" + assert gl_path.exists() + assert coa_path.exists() + + with gl_path.open("r", encoding="utf-8", newline="") as f: + reader = csv.DictReader(f) + assert reader.fieldnames is not None + for col in ("txn_id", "date", "doc_id", "description", "account_id", "debit", "credit"): + assert col in reader.fieldnames + rows = list(reader) + + assert rows, "expected normalized gl_journal rows" + + # Spot-check a known account and a known credit-normal split. + assert any(r["account_id"] == "Assets:Current Assets:Checking" for r in rows) + assert any( + r["account_id"] == "Equity:Owner Capital" and r["credit"] == "5000.00" for r in rows + ) + + with coa_path.open("r", encoding="utf-8", newline="") as f: + reader = csv.DictReader(f) + assert reader.fieldnames is not None + for col in ("account_id", "account_name", "account_type", "normal_side"): + assert col in reader.fieldnames + coa_rows = list(reader) + + ids = {r["account_id"] for r in coa_rows} + assert "Assets:Current Assets:Checking" in ids + assert "Equity:Owner Capital" in ids