refactor: fix architecture violations with provider patterns and dependency inversion
Major changes: - Add AuditProvider protocol for cross-module audit logging - Move customer order operations to orders module (dependency inversion) - Add customer order metrics via MetricsProvider pattern - Fix missing db parameter in get_admin_context() calls - Move ProductMedia relationship to catalog module (proper ownership) - Add marketplace breakdown stats to marketplace_widgets New files: - contracts/audit.py - AuditProviderProtocol - core/services/audit_aggregator.py - Aggregates audit providers - monitoring/services/audit_provider.py - Monitoring audit implementation - orders/services/customer_order_service.py - Customer order operations - orders/routes/api/vendor_customer_orders.py - Customer order endpoints - catalog/services/product_media_service.py - Product media service - Architecture documentation for patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,11 +9,12 @@ by the global exception handler.
|
||||
|
||||
import logging
|
||||
|
||||
from fastapi import APIRouter, Body, Depends, Path, Query
|
||||
from fastapi import APIRouter, Body, Depends, Path, Query, Request
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_admin_api
|
||||
from app.core.database import get_db
|
||||
from app.modules.core.services.stats_aggregator import stats_aggregator
|
||||
from app.modules.tenancy.services.admin_service import admin_service
|
||||
from models.schema.auth import UserContext
|
||||
from models.schema.auth import (
|
||||
@@ -104,25 +105,60 @@ def create_user(
|
||||
)
|
||||
|
||||
|
||||
def _get_platform_id(request: Request, current_admin: UserContext) -> int:
|
||||
"""Get platform_id from available sources."""
|
||||
# From JWT token
|
||||
if current_admin.token_platform_id:
|
||||
return current_admin.token_platform_id
|
||||
# From request state
|
||||
platform = getattr(request.state, "platform", None)
|
||||
if platform:
|
||||
return platform.id
|
||||
# First accessible platform
|
||||
if current_admin.accessible_platform_ids:
|
||||
return current_admin.accessible_platform_ids[0]
|
||||
# Fallback
|
||||
return 1
|
||||
|
||||
|
||||
@admin_platform_users_router.get("/stats")
|
||||
def get_user_statistics(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: UserContext = Depends(get_current_admin_api),
|
||||
):
|
||||
"""Get user statistics for admin dashboard (Admin only)."""
|
||||
try:
|
||||
from app.modules.analytics.services.stats_service import stats_service
|
||||
"""Get user statistics for admin dashboard (Admin only).
|
||||
|
||||
return stats_service.get_user_statistics(db)
|
||||
except ImportError:
|
||||
# Analytics module not available - return empty stats
|
||||
logger.warning("Analytics module not available for user statistics")
|
||||
return {
|
||||
"total_users": 0,
|
||||
"active_users": 0,
|
||||
"inactive_users": 0,
|
||||
"admin_users": 0,
|
||||
}
|
||||
Uses the stats_aggregator to get user metrics from the tenancy module's
|
||||
MetricsProvider, ensuring no cross-module import violations.
|
||||
"""
|
||||
platform_id = _get_platform_id(request, current_admin)
|
||||
|
||||
# Get metrics from stats_aggregator (tenancy module provides user stats)
|
||||
metrics = stats_aggregator.get_admin_dashboard_stats(db=db, platform_id=platform_id)
|
||||
|
||||
# Extract user stats from tenancy metrics
|
||||
tenancy_metrics = metrics.get("tenancy", [])
|
||||
|
||||
# Build response from metric values
|
||||
stats = {
|
||||
"total_users": 0,
|
||||
"active_users": 0,
|
||||
"inactive_users": 0,
|
||||
"admin_users": 0,
|
||||
}
|
||||
|
||||
for metric in tenancy_metrics:
|
||||
if metric.key == "tenancy.total_users":
|
||||
stats["total_users"] = int(metric.value)
|
||||
elif metric.key == "tenancy.active_users":
|
||||
stats["active_users"] = int(metric.value)
|
||||
elif metric.key == "tenancy.inactive_users":
|
||||
stats["inactive_users"] = int(metric.value)
|
||||
elif metric.key == "tenancy.admin_users":
|
||||
stats["admin_users"] = int(metric.value)
|
||||
|
||||
return stats
|
||||
|
||||
|
||||
@admin_platform_users_router.get("/search", response_model=UserSearchResponse)
|
||||
|
||||
Reference in New Issue
Block a user