Add SQLite-backed cost ledger with import/summary CLI, cron-friendly evaluate command with federation emit, and dogfood evidence artefact generation from fixture CSVs.
60 lines
No EOL
2.2 KiB
Python
60 lines
No EOL
2.2 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from fin_hub.services.evaluate import evaluate_runway
|
|
from fin_hub.services.evidence import build_runway_report, seed_fixture_ledger, write_runway_evidence
|
|
from fin_hub.services.ledger import import_csv, monthly_burn_series, monthly_summary, set_opening_balance
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures"
|
|
|
|
|
|
def test_ledger_import_and_monthly_summary(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
set_opening_balance(ledger, 12000.0)
|
|
|
|
cloud = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger)
|
|
host = import_csv(FIXTURES / "hosteurope.csv", "hosteurope", ledger_path=ledger)
|
|
|
|
assert cloud.rows_imported == 3
|
|
assert host.rows_imported == 2
|
|
|
|
rollups = monthly_summary(ledger_path=ledger)
|
|
eur_totals = {rollup.period_month: rollup.total for rollup in rollups if rollup.currency == "EUR"}
|
|
assert eur_totals["2026-06"] == pytest.approx(85.5 + 99.8)
|
|
|
|
burns = monthly_burn_series(ledger_path=ledger, currency="EUR")
|
|
assert burns == [pytest.approx(185.3)]
|
|
|
|
|
|
def test_ledger_import_skips_unchanged_file(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
first = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger)
|
|
second = import_csv(FIXTURES / "cloud-costs.csv", "cloud", ledger_path=ledger)
|
|
assert first.rows_imported == 3
|
|
assert second.skipped is True
|
|
assert second.rows_imported == 0
|
|
|
|
|
|
def test_evaluate_runway_from_ledger(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
seed_fixture_ledger(ledger_path=ledger, opening_balance=12000.0)
|
|
report = evaluate_runway(ledger_path=ledger, alert_threshold_months=3.0)
|
|
assert report["runway"]["current_balance"] == 12000.0
|
|
assert report["runway"]["monthly_burn"] > 0
|
|
|
|
|
|
def test_build_runway_report_and_write_evidence(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
seed_fixture_ledger(ledger_path=ledger, opening_balance=12000.0)
|
|
text = build_runway_report(ledger_path=ledger)
|
|
assert "Runway Dogfood Evidence" in text
|
|
assert "2026-06" in text
|
|
|
|
output = write_runway_evidence(
|
|
ledger_path=ledger,
|
|
output_dir=tmp_path / "evidence",
|
|
opening_balance=12000.0,
|
|
)
|
|
assert output.exists()
|
|
assert "runway-dogfood-" in output.name |