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>
This commit is contained in:
2026-02-22 21:28:59 +01:00
parent 42b894094a
commit ff852f1ab3
9 changed files with 372 additions and 15 deletions

View File

@@ -394,6 +394,84 @@ class TenancyMetricsProvider:
logger.warning(f"Failed to get tenancy platform metrics: {e}")
return []
def get_merchant_metrics(
self,
db: Session,
merchant_id: int,
context: MetricsContext | None = None,
) -> list[MetricValue]:
"""
Get metrics scoped to a specific merchant.
Provides:
- Total stores owned by this merchant
- Active stores
- Distinct active team members across all merchant stores
"""
from app.modules.tenancy.models import Store, StoreUser
try:
total_stores = (
db.query(Store)
.filter(Store.merchant_id == merchant_id)
.count()
)
active_stores = (
db.query(Store)
.filter(
Store.merchant_id == merchant_id,
Store.is_active == True,
)
.count()
)
# Distinct active team members across all merchant stores
merchant_store_ids = (
db.query(Store.id)
.filter(Store.merchant_id == merchant_id)
.subquery()
)
team_members = (
db.query(func.count(func.distinct(StoreUser.user_id)))
.filter(
StoreUser.store_id.in_(merchant_store_ids),
StoreUser.is_active == True,
)
.scalar()
or 0
)
return [
MetricValue(
key="tenancy.total_stores",
value=total_stores,
label="Total Stores",
category="tenancy",
icon="shopping-bag",
description="Total stores owned by this merchant",
),
MetricValue(
key="tenancy.active_stores",
value=active_stores,
label="Active Stores",
category="tenancy",
icon="check-circle",
description="Active stores owned by this merchant",
),
MetricValue(
key="tenancy.team_members",
value=team_members,
label="Team Members",
category="tenancy",
icon="users",
description="Distinct active team members across all stores",
),
]
except Exception as e:
logger.warning(f"Failed to get tenancy merchant metrics: {e}")
return []
# Singleton instance
tenancy_metrics_provider = TenancyMetricsProvider()