Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions examples/trackd_byod_gnucash_demo/README.md
Original file line number Diff line number Diff line change
@@ -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/`.
5 changes: 5 additions & 0 deletions examples/trackd_byod_gnucash_demo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Track D BYOD project config
[trackd]
profile = "core_gl"
tables_dir = "tables"
adapter = "gnucash_gl"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
account_id,account_name,account_type,normal_side
22 changes: 22 additions & 0 deletions examples/trackd_byod_gnucash_demo/tables/gl_journal.csv
Original file line number Diff line number Diff line change
@@ -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
51 changes: 51 additions & 0 deletions tests/test_trackd_byod_gnucash_demo_example_smoke.py
Original file line number Diff line number Diff line change
@@ -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