generated from coulomb/repo-seed
Add file-based Bubble, Stripe, and OpenRouter importers; usage attribution, cost allocation, pricing simulator, credit wallets, and recommendations in the dashboard API. Document whynot-design UI workflow and archive the finished workplan with all ten tasks marked done.
42 lines
1.4 KiB
Python
42 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from observatory.importers.bubble import import_membership
|
|
from observatory.importers.openrouter import import_usage
|
|
from observatory.importers.stripe import import_payments
|
|
|
|
IMPORTS = Path(__file__).resolve().parent.parent / "data" / "imports"
|
|
|
|
|
|
def test_bubble_import_maps_active_member() -> None:
|
|
import json
|
|
|
|
export = json.loads((IMPORTS / "bubble-export.sample.json").read_text(encoding="utf-8"))
|
|
payload = import_membership(export)
|
|
|
|
assert len(payload["members"]) == 1
|
|
assert payload["members"][0]["id"] == "member-tegwick"
|
|
assert payload["members"][0]["status"] == "active"
|
|
assert payload["members"][0]["source"] == "bubble"
|
|
|
|
|
|
def test_stripe_import_normalises_charge() -> None:
|
|
import json
|
|
|
|
export = json.loads((IMPORTS / "stripe-export.sample.json").read_text(encoding="utf-8"))
|
|
payload = import_payments(export)
|
|
|
|
assert payload["records"][0]["gross_amount"] == "8.99"
|
|
assert payload["records"][0]["net_amount"] == "8.55"
|
|
assert payload["records"][0]["member_username"] == "tegwick"
|
|
|
|
|
|
def test_openrouter_import_converts_cost_to_eur() -> None:
|
|
import json
|
|
|
|
export = json.loads((IMPORTS / "openrouter-export.sample.json").read_text(encoding="utf-8"))
|
|
payload = import_usage(export, fx_usd_eur="0.92")
|
|
|
|
assert payload["records"][0]["cost_eur"] == "0.06"
|
|
assert payload["records"][0]["member_id"] == "member-tegwick" |