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

@@ -0,0 +1,22 @@
# app/modules/core/routes/api/merchant.py
"""
Core module merchant API routes.
Auto-discovered by the route system (merchant.py in routes/api/ triggers
registration under /api/v1/merchants/core/*).
Aggregates:
- /dashboard/* - Merchant dashboard statistics
"""
from fastapi import APIRouter
from .merchant_dashboard import merchant_dashboard_router
ROUTE_CONFIG = {
"prefix": "/core",
}
router = APIRouter()
router.include_router(merchant_dashboard_router, tags=["merchant-dashboard"])

View File

@@ -0,0 +1,58 @@
# app/modules/core/routes/api/merchant_dashboard.py
"""
Merchant dashboard statistics endpoint.
Merchant Context: Uses get_merchant_for_current_user to resolve the merchant
from the JWT token. The dependency guarantees an active merchant exists.
This module uses the StatsAggregator service from core to collect metrics from all
enabled modules via the MetricsProvider protocol.
"""
import logging
from fastapi import APIRouter, Depends, Request
from sqlalchemy.orm import Session
from app.api.deps import get_merchant_for_current_user
from app.core.database import get_db
from app.modules.core.schemas.dashboard import MerchantDashboardStatsResponse
from app.modules.core.services.stats_aggregator import stats_aggregator
merchant_dashboard_router = APIRouter(prefix="/dashboard")
logger = logging.getLogger(__name__)
@merchant_dashboard_router.get("/stats", response_model=MerchantDashboardStatsResponse)
def get_merchant_dashboard_stats(
request: Request,
merchant=Depends(get_merchant_for_current_user),
db: Session = Depends(get_db),
):
"""
Get merchant-scoped dashboard statistics.
Returns aggregated statistics for the current merchant:
- Active subscriptions
- Total stores
- Total customers across all stores
- Team members across all stores
Merchant is resolved from the JWT token.
Requires Authorization header (API endpoint).
"""
platform = getattr(request.state, "platform", None)
platform_id = platform.id if platform else 1
flat = stats_aggregator.get_merchant_stats_flat(
db=db,
merchant_id=merchant.id,
platform_id=platform_id,
)
return MerchantDashboardStatsResponse(
active_subscriptions=int(flat.get("billing.active_subscriptions", 0)),
total_stores=int(flat.get("tenancy.total_stores", 0)),
total_customers=int(flat.get("customers.total", 0)),
team_members=int(flat.get("tenancy.team_members", 0)),
)