Files
orion/app/modules/billing/services/billing_metrics.py
Samir Boulahtit ff852f1ab3 fix: use metrics provider pattern for merchant dashboard stats
The merchant dashboard was showing subscription count as "Total Stores".
Add get_merchant_metrics() to MetricsProviderProtocol and implement it
in tenancy, billing, and customer providers. Dashboard now fetches real
stats from a new /merchants/core/dashboard/stats endpoint and displays
4 cards: active subscriptions, total stores, customers, team members.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 21:28:59 +01:00

155 lines
4.5 KiB
Python

# app/modules/billing/services/billing_metrics.py
"""
Metrics provider for the billing module.
Provides metrics for:
- Subscription counts (total, active, trial)
"""
import logging
from sqlalchemy import func
from sqlalchemy.orm import Session
from app.modules.contracts.metrics import (
MetricsContext,
MetricValue,
)
logger = logging.getLogger(__name__)
class BillingMetricsProvider:
"""
Metrics provider for billing module.
Provides subscription metrics at the platform level.
"""
@property
def metrics_category(self) -> str:
return "billing"
def get_store_metrics(
self,
db: Session,
store_id: int,
context: MetricsContext | None = None,
) -> list[MetricValue]:
"""
Get metrics for a specific store.
Subscriptions are merchant-level, not store-level, so no store metrics.
"""
return []
def get_platform_metrics(
self,
db: Session,
platform_id: int,
context: MetricsContext | None = None,
) -> list[MetricValue]:
"""
Get subscription metrics aggregated for a platform.
Provides:
- Total subscriptions
- Active subscriptions (active + trial)
- Trial subscriptions
"""
from app.modules.billing.models import MerchantSubscription, SubscriptionStatus
try:
total_subs = (
db.query(func.count(MerchantSubscription.id)).scalar() or 0
)
active_subs = (
db.query(func.count(MerchantSubscription.id))
.filter(MerchantSubscription.status.in_(["active", "trial"]))
.scalar()
or 0
)
trial_subs = (
db.query(func.count(MerchantSubscription.id))
.filter(MerchantSubscription.status == SubscriptionStatus.TRIAL.value)
.scalar()
or 0
)
return [
MetricValue(
key="billing.total_subscriptions",
value=total_subs,
label="Total Subscriptions",
category="billing",
icon="credit-card",
description="Total number of merchant subscriptions",
),
MetricValue(
key="billing.active_subscriptions",
value=active_subs,
label="Active Subscriptions",
category="billing",
icon="check-circle",
description="Subscriptions with active or trial status",
),
MetricValue(
key="billing.trial_subscriptions",
value=trial_subs,
label="Trial Subscriptions",
category="billing",
icon="clock",
description="Subscriptions currently in trial period",
),
]
except Exception as e:
logger.warning(f"Failed to get billing platform metrics: {e}")
return []
def get_merchant_metrics(
self,
db: Session,
merchant_id: int,
context: MetricsContext | None = None,
) -> list[MetricValue]:
"""
Get subscription metrics for a specific merchant.
Provides:
- Active subscriptions (active + trial)
"""
from app.modules.billing.models import MerchantSubscription
try:
active_subs = (
db.query(func.count(MerchantSubscription.id))
.filter(
MerchantSubscription.merchant_id == merchant_id,
MerchantSubscription.status.in_(["active", "trial"]),
)
.scalar()
or 0
)
return [
MetricValue(
key="billing.active_subscriptions",
value=active_subs,
label="Active Subscriptions",
category="billing",
icon="clipboard-list",
description="Active or trial subscriptions for this merchant",
),
]
except Exception as e:
logger.warning(f"Failed to get billing merchant metrics: {e}")
return []
# Singleton instance
billing_metrics_provider = BillingMetricsProvider()
__all__ = ["BillingMetricsProvider", "billing_metrics_provider"]