Overview: separate admin/operator accounts into their own category (excluded from member counts)

This commit is contained in:
Inferencebot committed 2026-10-08 15:08:21 -06:00
1 parent a7a283d552
commit 2eab2abb0d
1 file changed
+41 -21
+41 -21
View File
@@ -2250,6 +2250,16 @@ async def admin_held_refund(hold_id: int, request: Request):
return {"status": "refunded", "id": hold_id} return {"status": "refunded", "id": hold_id}
# Operator accounts — shown under a separate "admin" status in the panel and
# excluded from the member counts. They're infrastructure accounts (the SSO
# owner and the bot), not dues-paying members.
OPERATOR_EMAILS = {
e.strip().lower()
for e in os.environ.get("OPERATOR_EMAILS", "info@inference.coop,bot@inference.coop").split(",")
if e.strip()
}
@app.get("/admin/overview") @app.get("/admin/overview")
@limiter.limit("30/minute") @limiter.limit("30/minute")
async def admin_overview(request: Request): async def admin_overview(request: Request):
@@ -2326,42 +2336,52 @@ async def admin_overview(request: Request):
logger.warning("admin overview: all-time spend query failed: %s", e) logger.warning("admin overview: all-time spend query failed: %s", e)
members = [] members = []
admins = []
total_spend = 0.0 total_spend = 0.0
total_all_time = 0.0 total_all_time = 0.0
for email, active, balance, user_id in rows: for email, active, balance, user_id in rows:
team = teams.get(f"member:{email}", {}) team = teams.get(f"member:{email}", {})
spend = float(team.get("spend") or 0.0) spend = float(team.get("spend") or 0.0)
total_spend += spend
member_all_time = all_time_spend.get(f"member:{email}", 0.0) member_all_time = all_time_spend.get(f"member:{email}", 0.0)
total_all_time += member_all_time
credits = get_credit_balance(email) credits = get_credit_balance(email)
eff = compute_max_budget( eff = compute_max_budget(
float(balance) if balance is not None else MEMBER_BUDGET, float(balance) if balance is not None else MEMBER_BUDGET,
credits, credits,
spend, spend,
) )
members.append( entry = {
{ "email": email,
"email": email, "all_time_spend": round(member_all_time, 2),
"all_time_spend": round(member_all_time, 2), "username": usernames.get(user_id),
"username": usernames.get(user_id), "activated": invite_accepted.get(user_id, False),
"activated": invite_accepted.get(user_id, False), "active": bool(active),
"active": bool(active), "manual": email.lower() in MANUAL_MEMBERS,
"manual": email.lower() in MANUAL_MEMBERS, "balance": float(balance) if balance is not None else MEMBER_BUDGET,
"balance": float(balance) if balance is not None else MEMBER_BUDGET, "credit_balance": credits,
"credit_balance": credits, "credits_remaining": max(0.0, credits - eff["credits_used"]),
"credits_remaining": max(0.0, credits - eff["credits_used"]), "allowance_used": eff["allowance_used"],
"allowance_used": eff["allowance_used"], "credits_used": eff["credits_used"],
"credits_used": eff["credits_used"], "spend": spend,
"spend": spend, "remaining": max(eff["max_budget"] - spend, 0.0),
"remaining": max(eff["max_budget"] - spend, 0.0), "reset_at": team.get("budget_reset_at"),
"reset_at": team.get("budget_reset_at"), "cloudron_user_id": user_id,
"cloudron_user_id": user_id, }
} if email.lower() in OPERATOR_EMAILS:
) # Operator accounts: surfaced under a separate "admin" category in
# the panel, excluded from member counts and aggregates (their
# usage is a collective expense, not member activity).
entry["admin"] = True
admins.append(entry)
total_spend += spend
total_all_time += member_all_time
else:
members.append(entry)
total_spend += spend
total_all_time += member_all_time
return { return {
"members": members, "members": members,
"admins": admins,
"totals": { "totals": {
"members": len(members), "members": len(members),
"active": sum(1 for m in members if m["active"]), "active": sum(1 for m in members if m["active"]),