111 lines
3.5 KiB
Python
111 lines
3.5 KiB
Python
import pytest
|
|
|
|
from fin_hub.coupling.ops_hub import ServiceCostLine, build_service_cost_report
|
|
from fin_hub.ingest.hosteurope import parse_hosteurope_csv
|
|
from pathlib import Path
|
|
|
|
|
|
def test_build_service_cost_report_groups_by_service():
|
|
rows = parse_hosteurope_csv(Path(__file__).parent / "fixtures" / "hosteurope.csv")
|
|
lines = [
|
|
ServiceCostLine(
|
|
service_id=row.service_id,
|
|
environment=row.environment,
|
|
period_month=row.period_month,
|
|
amount=row.amount,
|
|
currency=row.currency,
|
|
source=row.source,
|
|
)
|
|
for row in rows
|
|
]
|
|
report = build_service_cost_report(lines)
|
|
assert report["signal"] == "service_cost_attribution"
|
|
assert len(report["services"]) == 2
|
|
assert report["totals_by_period_currency"] == [
|
|
{"period_month": "2026-06", "currency": "EUR", "total": pytest.approx(99.8)}
|
|
]
|
|
assert report["attributions"][0]["cost_attribution_key"] is None
|
|
assert report["unattributed"][0]["total"] == pytest.approx(99.8)
|
|
|
|
|
|
def test_build_service_cost_report_groups_by_client_attribution():
|
|
lines = [
|
|
ServiceCostLine(
|
|
service_id="cluster",
|
|
environment="production",
|
|
period_month="2026-07",
|
|
amount=42.0,
|
|
currency="EUR",
|
|
source="fixture",
|
|
client_id="acme",
|
|
application_id="portal",
|
|
app_instance_id="prod-01",
|
|
cost_attribution_key="client:acme|app:portal|instance:prod-01",
|
|
)
|
|
]
|
|
|
|
report = build_service_cost_report(lines)
|
|
|
|
assert report["attributions"] == [
|
|
{
|
|
"cost_attribution_key": "client:acme|app:portal|instance:prod-01",
|
|
"client_id": "acme",
|
|
"application_id": "portal",
|
|
"app_instance_id": "prod-01",
|
|
"environment": "production",
|
|
"currency": "EUR",
|
|
"months": {"2026-07": 42.0},
|
|
"total": 42.0,
|
|
}
|
|
]
|
|
|
|
|
|
def test_client_attribution_totals_do_not_mix_currencies():
|
|
common = {
|
|
"service_id": "cluster",
|
|
"environment": "production",
|
|
"period_month": "2026-07",
|
|
"source": "fixture",
|
|
"client_id": "acme",
|
|
"application_id": "portal",
|
|
"app_instance_id": "prod-01",
|
|
}
|
|
report = build_service_cost_report(
|
|
[
|
|
ServiceCostLine(amount=42.0, currency="EUR", **common),
|
|
ServiceCostLine(amount=50.0, currency="USD", **common),
|
|
]
|
|
)
|
|
|
|
assert {(row["currency"], row["total"]) for row in report["attributions"]} == {
|
|
("EUR", 42.0),
|
|
("USD", 50.0),
|
|
}
|
|
|
|
|
|
def test_service_totals_do_not_mix_currency_or_environment():
|
|
common = {
|
|
"service_id": "cluster",
|
|
"period_month": "2026-07",
|
|
"source": "fixture",
|
|
}
|
|
report = build_service_cost_report(
|
|
[
|
|
ServiceCostLine(amount=10.0, currency="EUR", environment="production", **common),
|
|
ServiceCostLine(amount=20.0, currency="USD", environment="production", **common),
|
|
ServiceCostLine(amount=30.0, currency="EUR", environment="development", **common),
|
|
]
|
|
)
|
|
|
|
assert {
|
|
(row["environment"], row["currency"], row["total"])
|
|
for row in report["services"]
|
|
} == {
|
|
("production", "EUR", 10.0),
|
|
("production", "USD", 20.0),
|
|
("development", "EUR", 30.0),
|
|
}
|
|
assert report["totals_by_period_currency"] == [
|
|
{"period_month": "2026-07", "currency": "EUR", "total": 40.0},
|
|
{"period_month": "2026-07", "currency": "USD", "total": 20.0},
|
|
]
|