Add engagement margin reporting

This commit is contained in:
tegwick 2026-08-10 20:43:05 +02:00
parent 33883e0977
commit 8338c501ed
10 changed files with 397 additions and 8 deletions

View file

@ -5,7 +5,14 @@ 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
from fin_hub.services.ledger import (
client_margin_report,
import_csv,
monthly_burn_series,
monthly_summary,
record_engagement_price,
set_opening_balance,
)
FIXTURES = Path(__file__).parent / "fixtures"
@ -84,6 +91,107 @@ def test_existing_ledger_schema_is_migrated_additively(tmp_path: Path):
}.issubset(columns)
def test_engagement_price_and_margin_report(tmp_path: Path):
source = tmp_path / "attributed.csv"
source.write_text(
"product,amount,currency,invoice_date,client_id,application_id,app_instance_id\n"
"Managed cluster,42.00,EUR,2026-07-01,acme,portal,prod-01\n",
encoding="utf-8",
)
ledger = tmp_path / "ledger.db"
import_csv(source, "hosteurope", ledger_path=ledger)
price = record_engagement_price(
client_id="acme",
application_id="portal",
app_instance_id="prod-01",
period_month="2026-07",
amount=100.0,
currency="eur",
source="agreement-2026-01",
ledger_path=ledger,
)
margins = client_margin_report(ledger_path=ledger)
assert margins[0].price_id == price.id
assert margins[0].revenue == 100.0
assert margins[0].attributed_cost == 42.0
assert margins[0].margin == 58.0
assert margins[0].currency == "EUR"
def test_engagement_price_revision_supersedes_prior_price(tmp_path: Path):
ledger = tmp_path / "ledger.db"
original = record_engagement_price(
client_id="acme",
application_id="portal",
app_instance_id="prod-01",
period_month="2026-07",
amount=100.0,
currency="EUR",
source="agreement-v1",
ledger_path=ledger,
)
revision = record_engagement_price(
client_id="acme",
application_id="portal",
app_instance_id="prod-01",
period_month="2026-07",
amount=120.0,
currency="EUR",
source="agreement-v2",
revision_of=original.id,
ledger_path=ledger,
)
margins = client_margin_report(ledger_path=ledger)
assert [(row.price_id, row.revenue) for row in margins] == [(revision.id, 120.0)]
def test_engagement_price_requires_explicit_revision(tmp_path: Path):
ledger = tmp_path / "ledger.db"
kwargs = {
"client_id": "acme",
"application_id": "portal",
"app_instance_id": "prod-01",
"period_month": "2026-07",
"amount": 100.0,
"currency": "EUR",
"source": "agreement",
"ledger_path": ledger,
}
original = record_engagement_price(**kwargs)
with pytest.raises(ValueError, match=original.id):
record_engagement_price(**kwargs)
def test_margin_does_not_join_cost_in_another_currency(tmp_path: Path):
source = tmp_path / "attributed.csv"
source.write_text(
"product,amount,currency,invoice_date,client_id,application_id,app_instance_id\n"
"Managed cluster,42.00,USD,2026-07-01,acme,portal,prod-01\n",
encoding="utf-8",
)
ledger = tmp_path / "ledger.db"
import_csv(source, "hosteurope", ledger_path=ledger)
record_engagement_price(
client_id="acme",
application_id="portal",
app_instance_id="prod-01",
period_month="2026-07",
amount=100.0,
currency="EUR",
source="agreement",
ledger_path=ledger,
)
margin = client_margin_report(ledger_path=ledger)[0]
assert margin.attributed_cost == 0.0
assert margin.margin == 100.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)

View file

@ -1,6 +1,14 @@
"""Smoke tests for fin-hub model registration."""
from fin_hub.models import Budget, BurnRate, Commitment, RunwayProjection, ServiceCost, TokenSpend
from fin_hub.models import (
Budget,
BurnRate,
Commitment,
EngagementPrice,
RunwayProjection,
ServiceCost,
TokenSpend,
)
from hub_core.models.base import Base
@ -12,6 +20,7 @@ def test_fin_models_register_on_metadata():
assert "fin_runway_projections" in tables
assert "fin_token_spends" in tables
assert "fin_service_costs" in tables
assert "fin_engagement_prices" in tables
def test_model_classes_importable():
@ -21,6 +30,7 @@ def test_model_classes_importable():
assert RunwayProjection.__tablename__ == "fin_runway_projections"
assert TokenSpend.__tablename__ == "fin_token_spends"
assert ServiceCost.__tablename__ == "fin_service_costs"
assert EngagementPrice.__tablename__ == "fin_engagement_prices"
def test_service_cost_has_external_attribution_seam():