Overview: separate admin/operator accounts into their own category (excluded from member counts)
This commit is contained in:
1 parent
a7a283d552
commit
2eab2abb0d
1 file changed
+41
-21
+41
-21
@@ -2250,6 +2250,16 @@ async def admin_held_refund(hold_id: int, request: Request):
|
||||
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")
|
||||
@limiter.limit("30/minute")
|
||||
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)
|
||||
|
||||
members = []
|
||||
admins = []
|
||||
total_spend = 0.0
|
||||
total_all_time = 0.0
|
||||
for email, active, balance, user_id in rows:
|
||||
team = teams.get(f"member:{email}", {})
|
||||
spend = float(team.get("spend") or 0.0)
|
||||
total_spend += spend
|
||||
member_all_time = all_time_spend.get(f"member:{email}", 0.0)
|
||||
total_all_time += member_all_time
|
||||
credits = get_credit_balance(email)
|
||||
eff = compute_max_budget(
|
||||
float(balance) if balance is not None else MEMBER_BUDGET,
|
||||
credits,
|
||||
spend,
|
||||
)
|
||||
members.append(
|
||||
{
|
||||
"email": email,
|
||||
"all_time_spend": round(member_all_time, 2),
|
||||
"username": usernames.get(user_id),
|
||||
"activated": invite_accepted.get(user_id, False),
|
||||
"active": bool(active),
|
||||
"manual": email.lower() in MANUAL_MEMBERS,
|
||||
"balance": float(balance) if balance is not None else MEMBER_BUDGET,
|
||||
"credit_balance": credits,
|
||||
"credits_remaining": max(0.0, credits - eff["credits_used"]),
|
||||
"allowance_used": eff["allowance_used"],
|
||||
"credits_used": eff["credits_used"],
|
||||
"spend": spend,
|
||||
"remaining": max(eff["max_budget"] - spend, 0.0),
|
||||
"reset_at": team.get("budget_reset_at"),
|
||||
"cloudron_user_id": user_id,
|
||||
}
|
||||
)
|
||||
entry = {
|
||||
"email": email,
|
||||
"all_time_spend": round(member_all_time, 2),
|
||||
"username": usernames.get(user_id),
|
||||
"activated": invite_accepted.get(user_id, False),
|
||||
"active": bool(active),
|
||||
"manual": email.lower() in MANUAL_MEMBERS,
|
||||
"balance": float(balance) if balance is not None else MEMBER_BUDGET,
|
||||
"credit_balance": credits,
|
||||
"credits_remaining": max(0.0, credits - eff["credits_used"]),
|
||||
"allowance_used": eff["allowance_used"],
|
||||
"credits_used": eff["credits_used"],
|
||||
"spend": spend,
|
||||
"remaining": max(eff["max_budget"] - spend, 0.0),
|
||||
"reset_at": team.get("budget_reset_at"),
|
||||
"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 {
|
||||
"members": members,
|
||||
"admins": admins,
|
||||
"totals": {
|
||||
"members": len(members),
|
||||
"active": sum(1 for m in members if m["active"]),
|
||||
|
||||
Reference in new issue
Block a user