feat: record AI-plan entitlements without inventing token ceilings
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.
This commit is contained in:
parent
6d4a4f0032
commit
5f27958e7d
6 changed files with 589 additions and 1 deletions
163
tests/test_plan_entitlement.py
Normal file
163
tests/test_plan_entitlement.py
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue