Add append-only plan entitlements (token, multiplier, or named plan). Unknown capacity stays unknown and requires a plan label. Plan-month reporting joins booked euros to entitlement without session logs.
163 lines
5 KiB
Python
163 lines
5 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from fin_hub.services.ledger import (
|
|
import_csv,
|
|
list_current_plan_entitlements,
|
|
plan_month_report,
|
|
record_plan_entitlement,
|
|
)
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures"
|
|
|
|
|
|
def test_unknown_token_entitlement_requires_plan_label(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
with pytest.raises(ValueError, match="plan_label"):
|
|
record_plan_entitlement(
|
|
provider="anthropic",
|
|
plan="claude-max",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity="unknown",
|
|
source="vendor-plan",
|
|
ledger_path=ledger,
|
|
)
|
|
record = record_plan_entitlement(
|
|
provider="anthropic",
|
|
plan="claude-max",
|
|
period_month="2026-08",
|
|
unit="plan",
|
|
plan_label="Max 20x",
|
|
source="vendor-plan",
|
|
ledger_path=ledger,
|
|
)
|
|
assert record.quantity is None
|
|
assert record.quantity_unknown is True
|
|
assert record.unit == "plan"
|
|
assert record.plan_label == "Max 20x"
|
|
|
|
|
|
def test_plan_entitlement_revision_is_append_only(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
original = record_plan_entitlement(
|
|
provider="openai",
|
|
provider_account="org-demo",
|
|
plan="api-prepaid",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity=1_000_000,
|
|
currency="EUR",
|
|
source="dashboard-v1",
|
|
ledger_path=ledger,
|
|
)
|
|
with pytest.raises(ValueError, match=original.id):
|
|
record_plan_entitlement(
|
|
provider="openai",
|
|
provider_account="org-demo",
|
|
plan="api-prepaid",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity=2_000_000,
|
|
currency="EUR",
|
|
source="dashboard-v2",
|
|
ledger_path=ledger,
|
|
)
|
|
revised = record_plan_entitlement(
|
|
provider="openai",
|
|
provider_account="org-demo",
|
|
plan="api-prepaid",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity=2_000_000,
|
|
currency="EUR",
|
|
source="dashboard-v2",
|
|
revision_of=original.id,
|
|
ledger_path=ledger,
|
|
)
|
|
current = list_current_plan_entitlements(ledger_path=ledger)
|
|
assert [row.id for row in current] == [revised.id]
|
|
assert current[0].quantity == 2_000_000
|
|
assert current[0].revision_of == original.id
|
|
assert current[0].quantity_unknown is False
|
|
|
|
|
|
def test_plan_month_report_joins_booked_cost_to_unknown_capacity(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
import_csv(FIXTURES / "ai-plans.csv", "ai-plan", ledger_path=ledger)
|
|
record_plan_entitlement(
|
|
provider="anthropic",
|
|
plan="claude-max",
|
|
period_month="2026-08",
|
|
unit="plan",
|
|
plan_label="Max 20x",
|
|
currency="EUR",
|
|
source="vendor-plan",
|
|
ledger_path=ledger,
|
|
)
|
|
record_plan_entitlement(
|
|
provider="openai",
|
|
provider_account="org-demo",
|
|
plan="api-prepaid",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity=500_000,
|
|
currency="EUR",
|
|
source="usage-dashboard",
|
|
ledger_path=ledger,
|
|
)
|
|
|
|
rows = {f"{row.provider}:{row.plan}": row for row in plan_month_report(ledger_path=ledger)}
|
|
claude = rows["anthropic:claude-max"]
|
|
assert claude.booked_amount == 200
|
|
assert claude.booked_currency == "EUR"
|
|
assert claude.entitled_quantity is None
|
|
assert claude.quantity_unknown is True
|
|
assert claude.plan_label == "Max 20x"
|
|
assert claude.join_status == "matched"
|
|
openai = rows["openai:api-prepaid"]
|
|
assert openai.booked_amount == 40
|
|
assert openai.entitled_quantity == 500_000
|
|
assert openai.join_status == "matched"
|
|
|
|
|
|
def test_plan_month_does_not_silently_join_currency_mismatch(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
import_csv(FIXTURES / "ai-plans.csv", "ai-plan", ledger_path=ledger)
|
|
record_plan_entitlement(
|
|
provider="anthropic",
|
|
plan="claude-max",
|
|
period_month="2026-08",
|
|
unit="token",
|
|
quantity=100,
|
|
currency="USD",
|
|
source="vendor-plan",
|
|
ledger_path=ledger,
|
|
)
|
|
row = plan_month_report(ledger_path=ledger, period_month="2026-08")[0]
|
|
assert row.provider == "anthropic"
|
|
assert row.booked_currency == "EUR"
|
|
assert row.entitled_quantity == 100
|
|
assert row.join_status == "currency_mismatch"
|
|
|
|
|
|
def test_multiplier_does_not_invent_a_token_ceiling(tmp_path: Path):
|
|
ledger = tmp_path / "ledger.db"
|
|
record = record_plan_entitlement(
|
|
provider="anthropic",
|
|
plan="claude-max",
|
|
period_month="2026-08",
|
|
unit="multiplier",
|
|
quantity=20,
|
|
plan_label="Max 20x",
|
|
source="vendor-plan",
|
|
ledger_path=ledger,
|
|
)
|
|
assert record.unit == "multiplier"
|
|
assert record.quantity == 20
|
|
assert record.quantity_unknown is False
|
|
report = plan_month_report(ledger_path=ledger)
|
|
assert report[0].join_status == "entitlement_only"
|
|
assert report[0].booked_amount is None
|
|
assert report[0].entitled_quantity == 20
|