generated from coulomb/repo-seed
Complete Economic Observatory MVP (ADAPTIVE-WP-0002)
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.
This commit is contained in:
48
projects/coulomb-pricing/observatory/credits.py
Normal file
48
projects/coulomb-pricing/observatory/credits.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from .load import _read_json, default_data_dir
|
||||
|
||||
TWOPLACES = Decimal("0.01")
|
||||
|
||||
|
||||
def _money(value: Decimal) -> Decimal:
|
||||
return value.quantize(TWOPLACES, rounding=ROUND_HALF_UP)
|
||||
|
||||
|
||||
def load_credit_wallets(data_dir=None) -> dict[str, Any]:
|
||||
root = data_dir or default_data_dir()
|
||||
path = Path(root) / "credit_wallets.json"
|
||||
if not path.exists():
|
||||
return {"version": 1, "currency": "EUR", "wallets": []}
|
||||
return _read_json(path)
|
||||
|
||||
|
||||
def build_credit_summary(raw: dict, usage_by_member: dict[str, Decimal], period: str) -> dict:
|
||||
wallets = []
|
||||
for item in raw.get("wallets", []):
|
||||
member_id = item["member_id"]
|
||||
allowance = Decimal(str(item.get("monthly_allowance_eur", "0")))
|
||||
used = usage_by_member.get(member_id, Decimal(str(item.get("used_eur", "0"))))
|
||||
remaining = max(Decimal("0"), allowance - used)
|
||||
wallets.append(
|
||||
{
|
||||
"member_id": member_id,
|
||||
"period": period,
|
||||
"monthly_allowance_eur": _money(allowance),
|
||||
"used_eur": _money(used),
|
||||
"remaining_eur": _money(remaining),
|
||||
"overage_eur": _money(max(Decimal("0"), used - allowance)),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"period": period,
|
||||
"currency": raw.get("currency", "EUR"),
|
||||
"wallet_count": len(wallets),
|
||||
"wallets": wallets,
|
||||
"notes": "Observatory-only credit accounting; no customer billing in MVP.",
|
||||
}
|
||||
Reference in New Issue
Block a user