Files
orion/app/modules/analytics/schemas/stats.py
Samir Boulahtit a8fae0fbc7 feat: implement metrics provider pattern for modular dashboard statistics
This commit introduces a protocol-based metrics architecture that allows
each module to provide its own statistics for dashboards without creating
cross-module dependencies.

Key changes:
- Add MetricsProviderProtocol and MetricValue dataclass in contracts module
- Add StatsAggregatorService in core module that discovers and aggregates
  metrics from all enabled modules
- Implement metrics providers for all modules:
  - tenancy: vendor/user counts, team members, domains
  - customers: customer counts
  - cms: pages, media files
  - catalog: products
  - inventory: stock levels
  - orders: order counts, revenue
  - marketplace: import jobs, staging products
- Update dashboard routes to use StatsAggregator instead of direct imports
- Fix VendorPlatform junction table usage (Vendor.platform_id doesn't exist)
- Add comprehensive documentation for the pattern

This architecture ensures:
- Dashboards always work (aggregator in core)
- Each module owns its metrics (no cross-module coupling)
- Optional modules are truly optional (can be removed without breaking app)
- Multi-platform vendors are properly supported via VendorPlatform table

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 21:11:29 +01:00

181 lines
5.2 KiB
Python

# app/modules/analytics/schemas/stats.py
"""
Analytics module schemas for statistics and reporting.
Base dashboard schemas are defined in core.schemas.dashboard.
This module re-exports them for backward compatibility and adds
analytics-specific schemas (trends, reports, etc.).
"""
from datetime import datetime
from decimal import Decimal
from typing import Any
from pydantic import BaseModel, Field
# Re-export base dashboard schemas from core for backward compatibility
# These are the canonical definitions in core module
from app.modules.core.schemas.dashboard import (
AdminDashboardResponse,
ImportStatsResponse,
MarketplaceStatsResponse,
OrderStatsBasicResponse,
PlatformStatsResponse,
ProductStatsResponse,
StatsResponse,
UserStatsResponse,
VendorCustomerStats,
VendorDashboardStatsResponse,
VendorInfo,
VendorOrderStats,
VendorProductStats,
VendorRevenueStats,
VendorStatsResponse,
)
# ============================================================================
# Vendor Analytics (Analytics-specific, not in core)
# ============================================================================
class VendorAnalyticsImports(BaseModel):
"""Vendor import analytics."""
count: int = Field(0, description="Number of imports in period")
class VendorAnalyticsCatalog(BaseModel):
"""Vendor catalog analytics."""
products_added: int = Field(0, description="Products added in period")
class VendorAnalyticsInventory(BaseModel):
"""Vendor inventory analytics."""
total_locations: int = Field(0, description="Total inventory locations")
class VendorAnalyticsResponse(BaseModel):
"""Vendor analytics response schema.
Used by: GET /api/v1/vendor/analytics
"""
period: str = Field(..., description="Analytics period (e.g., '30d')")
start_date: str = Field(..., description="Period start date")
imports: VendorAnalyticsImports
catalog: VendorAnalyticsCatalog
inventory: VendorAnalyticsInventory
# ============================================================================
# Code Quality Dashboard Statistics
# ============================================================================
class ValidatorStats(BaseModel):
"""Statistics for a single validator type."""
total_violations: int = 0
errors: int = 0
warnings: int = 0
last_scan: str | None = None
class CodeQualityDashboardStatsResponse(BaseModel):
"""Code quality dashboard statistics response schema.
Used by: GET /api/v1/admin/code-quality/stats
Supports multiple validator types: architecture, security, performance.
When validator_type is specified, returns stats for that type only.
When not specified, returns combined stats with per-validator breakdown.
"""
total_violations: int
errors: int
warnings: int
info: int = 0
open: int
assigned: int
resolved: int
ignored: int
technical_debt_score: int
trend: list[dict[str, Any]] = Field(default_factory=list)
by_severity: dict[str, Any] = Field(default_factory=dict)
by_rule: dict[str, Any] = Field(default_factory=dict)
by_module: dict[str, Any] = Field(default_factory=dict)
top_files: list[dict[str, Any]] = Field(default_factory=list)
last_scan: str | None = None
validator_type: str | None = None # Set when filtering by type
by_validator: dict[str, ValidatorStats] = Field(
default_factory=dict,
description="Per-validator breakdown (architecture, security, performance)",
)
# ============================================================================
# Customer Statistics (Coming Soon)
# ============================================================================
class CustomerStatsResponse(BaseModel):
"""Schema for customer statistics."""
customer_id: int
total_orders: int
total_spent: Decimal
average_order_value: Decimal
last_order_date: datetime | None
first_order_date: datetime | None
lifetime_value: Decimal
# ============================================================================
# Order Statistics (Coming Soon)
# ============================================================================
class OrderStatsResponse(BaseModel):
"""Schema for order statistics."""
total_orders: int
pending_orders: int
processing_orders: int
shipped_orders: int
delivered_orders: int
cancelled_orders: int
total_revenue: Decimal
average_order_value: Decimal
__all__ = [
# Re-exported from core.schemas.dashboard (for backward compatibility)
"StatsResponse",
"MarketplaceStatsResponse",
"ImportStatsResponse",
"UserStatsResponse",
"VendorStatsResponse",
"ProductStatsResponse",
"PlatformStatsResponse",
"OrderStatsBasicResponse",
"AdminDashboardResponse",
"VendorProductStats",
"VendorOrderStats",
"VendorCustomerStats",
"VendorRevenueStats",
"VendorInfo",
"VendorDashboardStatsResponse",
# Analytics-specific schemas
"VendorAnalyticsImports",
"VendorAnalyticsCatalog",
"VendorAnalyticsInventory",
"VendorAnalyticsResponse",
"ValidatorStats",
"CodeQualityDashboardStatsResponse",
"CustomerStatsResponse",
"OrderStatsResponse",
]