# app/modules/catalog/services/catalog_metrics.py """ Metrics provider for the catalog module. Provides metrics for: - Product counts - Active/inactive products - Featured products """ import logging from datetime import datetime, timedelta from typing import TYPE_CHECKING from sqlalchemy import func from sqlalchemy.orm import Session from app.modules.contracts.metrics import ( MetricsContext, MetricValue, ) if TYPE_CHECKING: pass logger = logging.getLogger(__name__) class CatalogMetricsProvider: """ Metrics provider for catalog module. Provides product-related metrics for store and platform dashboards. """ @property def metrics_category(self) -> str: return "catalog" def get_store_metrics( self, db: Session, store_id: int, context: MetricsContext | None = None, ) -> list[MetricValue]: """ Get product metrics for a specific store. Provides: - Total products - Active products - Featured products - New products (in period) """ from app.modules.catalog.models import Product try: # Total products total_products = ( db.query(Product).filter(Product.store_id == store_id).count() ) # Active products active_products = ( db.query(Product) .filter(Product.store_id == store_id, Product.is_active == True) .count() ) # Featured products featured_products = ( db.query(Product) .filter( Product.store_id == store_id, Product.is_featured == True, Product.is_active == True, ) .count() ) # New products (default to last 30 days) date_from = context.date_from if context else None if date_from is None: date_from = datetime.utcnow() - timedelta(days=30) new_products_query = db.query(Product).filter( Product.store_id == store_id, Product.created_at >= date_from, ) if context and context.date_to: new_products_query = new_products_query.filter( Product.created_at <= context.date_to ) new_products = new_products_query.count() # Products with translations ( db.query(func.count(func.distinct(Product.id))) .filter(Product.store_id == store_id) .join(Product.translations) .scalar() or 0 ) return [ MetricValue( key="catalog.total_products", value=total_products, label="Total Products", category="catalog", icon="box", description="Total products in catalog", ), MetricValue( key="catalog.active_products", value=active_products, label="Active Products", category="catalog", icon="check-circle", description="Products that are active and visible", ), MetricValue( key="catalog.featured_products", value=featured_products, label="Featured Products", category="catalog", icon="star", description="Products marked as featured", ), MetricValue( key="catalog.new_products", value=new_products, label="New Products", category="catalog", icon="plus-circle", description="Products added in the period", ), ] except Exception as e: logger.warning(f"Failed to get catalog store metrics: {e}") return [] def get_platform_metrics( self, db: Session, platform_id: int, context: MetricsContext | None = None, ) -> list[MetricValue]: """ Get product metrics aggregated for a platform. Aggregates catalog data across all stores. """ from app.modules.catalog.models import Product from app.modules.tenancy.services.platform_service import platform_service try: # Get all store IDs for this platform via platform service store_ids = platform_service.get_store_ids_for_platform(db, platform_id) # Total products total_products = ( db.query(Product).filter(Product.store_id.in_(store_ids)).count() ) # Active products active_products = ( db.query(Product) .filter(Product.store_id.in_(store_ids), Product.is_active == True) .count() ) # Featured products featured_products = ( db.query(Product) .filter( Product.store_id.in_(store_ids), Product.is_featured == True, Product.is_active == True, ) .count() ) # Stores with products stores_with_products = ( db.query(func.count(func.distinct(Product.store_id))) .filter(Product.store_id.in_(store_ids)) .scalar() or 0 ) # Average products per store total_stores = ( db.query(StorePlatform) .filter( StorePlatform.platform_id == platform_id, StorePlatform.is_active == True, ) .count() ) avg_products = round(total_products / total_stores, 1) if total_stores > 0 else 0 return [ MetricValue( key="catalog.total_products", value=total_products, label="Total Products", category="catalog", icon="box", description="Total products across all stores", ), MetricValue( key="catalog.active_products", value=active_products, label="Active Products", category="catalog", icon="check-circle", description="Products that are active and visible", ), MetricValue( key="catalog.featured_products", value=featured_products, label="Featured Products", category="catalog", icon="star", description="Products marked as featured", ), MetricValue( key="catalog.stores_with_products", value=stores_with_products, label="Stores with Products", category="catalog", icon="store", description="Stores that have created products", ), MetricValue( key="catalog.avg_products_per_store", value=avg_products, label="Avg Products/Store", category="catalog", icon="calculator", description="Average products per store", ), ] except Exception as e: logger.warning(f"Failed to get catalog platform metrics: {e}") return [] # Singleton instance catalog_metrics_provider = CatalogMetricsProvider() __all__ = ["CatalogMetricsProvider", "catalog_metrics_provider"]