feat: add single endpoint for merchant subscriptions with usage data
Replace N+1 per-platform API calls on merchant detail page with a single
GET /admin/subscriptions/merchants/{id} endpoint. Extract shared
subscription+usage aggregation logic into a reusable service method and
refactor the store endpoint to use it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -286,6 +286,70 @@ class AdminSubscriptionService:
|
||||
p = db.query(Platform).filter(Platform.id == platform_id).first()
|
||||
return p.name if p else None
|
||||
|
||||
# =========================================================================
|
||||
# Merchant Subscriptions with Usage
|
||||
# =========================================================================
|
||||
|
||||
def get_merchant_subscriptions_with_usage(
|
||||
self, db: Session, merchant_id: int
|
||||
) -> list[dict]:
|
||||
"""Get all subscriptions for a merchant with tier info and feature usage.
|
||||
|
||||
Returns a list of dicts, each containing:
|
||||
- subscription: serialized MerchantSubscription
|
||||
- tier: tier info dict (code, name, feature_codes)
|
||||
- features: list of quantitative usage metrics
|
||||
- platform_id: int
|
||||
- platform_name: str
|
||||
"""
|
||||
from app.modules.billing.schemas import MerchantSubscriptionAdminResponse
|
||||
from app.modules.billing.services.feature_service import feature_service
|
||||
from app.modules.billing.services.subscription_service import (
|
||||
subscription_service,
|
||||
)
|
||||
|
||||
subs = subscription_service.get_merchant_subscriptions(db, merchant_id)
|
||||
platforms_map = self.get_platform_names_map(db)
|
||||
|
||||
results = []
|
||||
for sub in subs:
|
||||
features_summary = feature_service.get_merchant_features_summary(
|
||||
db, merchant_id, sub.platform_id
|
||||
)
|
||||
|
||||
tier_info = None
|
||||
if sub.tier:
|
||||
tier_info = {
|
||||
"code": sub.tier.code,
|
||||
"name": sub.tier.name,
|
||||
"feature_codes": [
|
||||
fl.feature_code for fl in (sub.tier.feature_limits or [])
|
||||
],
|
||||
}
|
||||
|
||||
usage_metrics = []
|
||||
for fs in features_summary:
|
||||
if fs.feature_type == "quantitative" and fs.enabled:
|
||||
usage_metrics.append({
|
||||
"name": fs.name_key.replace("_", " ").title(),
|
||||
"current": fs.current or 0,
|
||||
"limit": fs.limit,
|
||||
"percentage": fs.percent_used or 0,
|
||||
"is_unlimited": fs.limit is None,
|
||||
"is_at_limit": fs.remaining == 0 if fs.remaining is not None else False,
|
||||
"is_approaching_limit": (fs.percent_used or 0) >= 80,
|
||||
})
|
||||
|
||||
results.append({
|
||||
"subscription": MerchantSubscriptionAdminResponse.model_validate(sub).model_dump(),
|
||||
"tier": tier_info,
|
||||
"features": usage_metrics,
|
||||
"platform_id": sub.platform_id,
|
||||
"platform_name": platforms_map.get(sub.platform_id, ""),
|
||||
})
|
||||
|
||||
return results
|
||||
|
||||
# =========================================================================
|
||||
# Statistics
|
||||
# =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user