# app/modules/tenancy/services/tenancy_metrics.py """ Metrics provider for the tenancy module. Provides metrics for: - Vendor counts and status - User counts and activation - Team members (vendor users) - Custom domains """ import logging from typing import TYPE_CHECKING from sqlalchemy.orm import Session from app.modules.contracts.metrics import ( MetricValue, MetricsContext, MetricsProviderProtocol, ) if TYPE_CHECKING: pass logger = logging.getLogger(__name__) class TenancyMetricsProvider: """ Metrics provider for tenancy module. Provides vendor, user, and organizational metrics. """ @property def metrics_category(self) -> str: return "tenancy" def get_vendor_metrics( self, db: Session, vendor_id: int, context: MetricsContext | None = None, ) -> list[MetricValue]: """ Get metrics for a specific vendor. For vendors, this provides: - Team member count - Custom domains count """ from app.modules.tenancy.models import VendorDomain, VendorUser try: # Team members count team_count = ( db.query(VendorUser) .filter(VendorUser.vendor_id == vendor_id, VendorUser.is_active == True) .count() ) # Custom domains count domains_count = ( db.query(VendorDomain) .filter(VendorDomain.vendor_id == vendor_id) .count() ) # Verified domains count verified_domains_count = ( db.query(VendorDomain) .filter( VendorDomain.vendor_id == vendor_id, VendorDomain.is_verified == True, ) .count() ) return [ MetricValue( key="tenancy.team_members", value=team_count, label="Team Members", category="tenancy", icon="users", description="Active team members with access to this vendor", ), MetricValue( key="tenancy.domains", value=domains_count, label="Custom Domains", category="tenancy", icon="globe", description="Custom domains configured for this vendor", ), MetricValue( key="tenancy.verified_domains", value=verified_domains_count, label="Verified Domains", category="tenancy", icon="check-circle", description="Custom domains that have been verified", ), ] except Exception as e: logger.warning(f"Failed to get tenancy vendor metrics: {e}") return [] def get_platform_metrics( self, db: Session, platform_id: int, context: MetricsContext | None = None, ) -> list[MetricValue]: """ Get metrics aggregated for a platform. For platforms, this provides: - Total vendors - Active vendors - Verified vendors - Total users - Active users """ from app.modules.tenancy.models import AdminPlatform, User, Vendor, VendorPlatform try: # Vendor metrics - using VendorPlatform junction table # Get vendor IDs that are on this platform platform_vendor_ids = ( db.query(VendorPlatform.vendor_id) .filter(VendorPlatform.platform_id == platform_id) .subquery() ) total_vendors = ( db.query(Vendor) .filter(Vendor.id.in_(platform_vendor_ids)) .count() ) # Active vendors on this platform (vendor active AND membership active) active_vendor_ids = ( db.query(VendorPlatform.vendor_id) .filter( VendorPlatform.platform_id == platform_id, VendorPlatform.is_active == True, ) .subquery() ) active_vendors = ( db.query(Vendor) .filter( Vendor.id.in_(active_vendor_ids), Vendor.is_active == True, ) .count() ) verified_vendors = ( db.query(Vendor) .filter( Vendor.id.in_(platform_vendor_ids), Vendor.is_verified == True, ) .count() ) pending_vendors = ( db.query(Vendor) .filter( Vendor.id.in_(active_vendor_ids), Vendor.is_active == True, Vendor.is_verified == False, ) .count() ) inactive_vendors = total_vendors - active_vendors # User metrics - using AdminPlatform junction table # Get user IDs that have access to this platform platform_user_ids = ( db.query(AdminPlatform.user_id) .filter( AdminPlatform.platform_id == platform_id, AdminPlatform.is_active == True, ) .subquery() ) total_users = ( db.query(User) .filter(User.id.in_(platform_user_ids)) .count() ) active_users = ( db.query(User) .filter( User.id.in_(platform_user_ids), User.is_active == True, ) .count() ) admin_users = ( db.query(User) .filter( User.id.in_(platform_user_ids), User.role == "admin", ) .count() ) inactive_users = total_users - active_users # Calculate rates verification_rate = ( (verified_vendors / total_vendors * 100) if total_vendors > 0 else 0 ) user_activation_rate = ( (active_users / total_users * 100) if total_users > 0 else 0 ) return [ # Vendor metrics MetricValue( key="tenancy.total_vendors", value=total_vendors, label="Total Vendors", category="tenancy", icon="store", description="Total number of vendors on this platform", ), MetricValue( key="tenancy.active_vendors", value=active_vendors, label="Active Vendors", category="tenancy", icon="check-circle", description="Vendors that are currently active", ), MetricValue( key="tenancy.verified_vendors", value=verified_vendors, label="Verified Vendors", category="tenancy", icon="badge-check", description="Vendors that have been verified", ), MetricValue( key="tenancy.pending_vendors", value=pending_vendors, label="Pending Vendors", category="tenancy", icon="clock", description="Active vendors pending verification", ), MetricValue( key="tenancy.inactive_vendors", value=inactive_vendors, label="Inactive Vendors", category="tenancy", icon="pause-circle", description="Vendors that are not currently active", ), MetricValue( key="tenancy.vendor_verification_rate", value=round(verification_rate, 1), label="Verification Rate", category="tenancy", icon="percent", unit="%", description="Percentage of vendors that are verified", ), # User metrics MetricValue( key="tenancy.total_users", value=total_users, label="Total Users", category="tenancy", icon="users", description="Total number of users on this platform", ), MetricValue( key="tenancy.active_users", value=active_users, label="Active Users", category="tenancy", icon="user-check", description="Users that are currently active", ), MetricValue( key="tenancy.admin_users", value=admin_users, label="Admin Users", category="tenancy", icon="shield", description="Users with admin role", ), MetricValue( key="tenancy.inactive_users", value=inactive_users, label="Inactive Users", category="tenancy", icon="user-x", description="Users that are not currently active", ), MetricValue( key="tenancy.user_activation_rate", value=round(user_activation_rate, 1), label="User Activation Rate", category="tenancy", icon="percent", unit="%", description="Percentage of users that are active", ), ] except Exception as e: logger.warning(f"Failed to get tenancy platform metrics: {e}") return [] # Singleton instance tenancy_metrics_provider = TenancyMetricsProvider() __all__ = ["TenancyMetricsProvider", "tenancy_metrics_provider"]