feat(billing): scope parameter on /view/statistics endpoint
- New query parameter scope: personal/mandate/all - personal: filters to only current user's transactions (ignores admin role) - mandate: filters by mandateId parameter - all: existing RBAC-filtered behavior (default) Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
e24ef42617
commit
3777839a5c
1 changed files with 27 additions and 14 deletions
|
|
@ -989,16 +989,17 @@ def getUserViewStatistics(
|
|||
period: str = Query(default="month", description="Period: 'day' or 'month'"),
|
||||
year: int = Query(default=None, description="Year"),
|
||||
month: Optional[int] = Query(None, description="Month (1-12, required for period='day')"),
|
||||
scope: str = Query(default="all", description="Scope: 'personal' (own costs only), 'mandate' (filter by mandateId), 'all' (RBAC-filtered)"),
|
||||
mandateId: Optional[str] = Query(None, description="Mandate ID filter (used with scope='mandate')"),
|
||||
ctx: RequestContext = Depends(getRequestContext)
|
||||
) -> ViewStatisticsResponse:
|
||||
"""
|
||||
Get aggregated usage statistics across all user's mandates.
|
||||
|
||||
RBAC filtering:
|
||||
- SysAdmin: statistics across all mandates
|
||||
- Mandate-Admin: statistics for mandates they administrate
|
||||
- Feature-Instance-Admin: statistics for their feature instances
|
||||
- Regular user: only their own usage statistics
|
||||
Scope:
|
||||
- personal: only the current user's own transactions (ignores admin role)
|
||||
- mandate: transactions for a specific mandate (requires mandateId parameter)
|
||||
- all: RBAC-filtered (SysAdmin sees everything, admin sees mandate, user sees own)
|
||||
|
||||
- period='month': returns monthly time series for the given year
|
||||
- period='day': returns daily time series for the given month/year
|
||||
|
|
@ -1015,22 +1016,34 @@ def getUserViewStatistics(
|
|||
billingInterface = getBillingInterface(ctx.user, ctx.mandateId)
|
||||
|
||||
# Evaluate RBAC scope
|
||||
scope = _getBillingDataScope(ctx.user)
|
||||
rbacScope = _getBillingDataScope(ctx.user)
|
||||
|
||||
# Determine mandate IDs for data loading
|
||||
if scope.isGlobalAdmin:
|
||||
mandateIds = None
|
||||
if rbacScope.isGlobalAdmin:
|
||||
loadMandateIds = None
|
||||
else:
|
||||
mandateIds = scope.adminMandateIds + scope.memberMandateIds
|
||||
if not mandateIds:
|
||||
loadMandateIds = rbacScope.adminMandateIds + rbacScope.memberMandateIds
|
||||
if not loadMandateIds:
|
||||
logger.warning("No mandate IDs found for user")
|
||||
return ViewStatisticsResponse()
|
||||
|
||||
# Get all transactions
|
||||
allTransactions = billingInterface.getUserTransactionsForMandates(mandateIds, limit=10000)
|
||||
# Scope=mandate: restrict to specific mandate
|
||||
if scope == "mandate" and mandateId:
|
||||
loadMandateIds = [mandateId]
|
||||
|
||||
# Apply RBAC filter
|
||||
allTransactions = _filterTransactionsByScope(allTransactions, scope)
|
||||
# Get all transactions
|
||||
allTransactions = billingInterface.getUserTransactionsForMandates(loadMandateIds, limit=10000)
|
||||
|
||||
# Apply RBAC filter (respects admin/user roles)
|
||||
allTransactions = _filterTransactionsByScope(allTransactions, rbacScope)
|
||||
|
||||
# Scope=personal: further filter to only own transactions
|
||||
if scope == "personal":
|
||||
userId = str(ctx.user.id)
|
||||
allTransactions = [
|
||||
t for t in allTransactions
|
||||
if (t.get("createdByUserId") or t.get("userId")) == userId
|
||||
]
|
||||
|
||||
logger.info(f"View statistics: {len(allTransactions)} RBAC-filtered transactions for period={period}, year={year}, month={month}")
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue