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:
@@ -20,7 +20,7 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import get_current_admin_api
|
||||
from app.core.database import get_db
|
||||
from app.modules.contracts.widgets import ListWidget
|
||||
from app.modules.contracts.widgets import BreakdownWidget, ListWidget
|
||||
from app.modules.core.schemas.dashboard import (
|
||||
AdminDashboardResponse,
|
||||
ImportStatsResponse,
|
||||
@@ -219,29 +219,37 @@ def get_comprehensive_stats(
|
||||
"/stats/marketplace", response_model=list[MarketplaceStatsResponse]
|
||||
)
|
||||
def get_marketplace_stats(
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
current_admin: UserContext = Depends(get_current_admin_api),
|
||||
):
|
||||
"""Get statistics broken down by marketplace (Admin only)."""
|
||||
# For detailed marketplace breakdown, we still use the analytics service
|
||||
# as the MetricsProvider pattern is for aggregated stats
|
||||
try:
|
||||
from app.modules.analytics.services.stats_service import stats_service
|
||||
"""Get statistics broken down by marketplace (Admin only).
|
||||
|
||||
marketplace_stats = stats_service.get_marketplace_breakdown_stats(db=db)
|
||||
return [
|
||||
MarketplaceStatsResponse(
|
||||
marketplace=stat["marketplace"],
|
||||
total_products=stat["total_products"],
|
||||
unique_vendors=stat["unique_vendors"],
|
||||
unique_brands=stat["unique_brands"],
|
||||
)
|
||||
for stat in marketplace_stats
|
||||
]
|
||||
except ImportError:
|
||||
# Analytics module not available
|
||||
logger.warning("Analytics module not available for marketplace breakdown stats")
|
||||
return []
|
||||
Uses the widget_aggregator to get marketplace breakdown data from the
|
||||
marketplace module's WidgetProvider, avoiding cross-module violations.
|
||||
"""
|
||||
platform_id = _get_platform_id(request, current_admin)
|
||||
|
||||
# Get widgets from marketplace module via aggregator
|
||||
widgets = widget_aggregator.get_admin_dashboard_widgets(db=db, platform_id=platform_id)
|
||||
|
||||
# Extract marketplace breakdown widget
|
||||
marketplace_widgets = widgets.get("marketplace", [])
|
||||
for widget in marketplace_widgets:
|
||||
if widget.key == "marketplace.breakdown" and isinstance(widget.data, BreakdownWidget):
|
||||
# Transform breakdown items to MarketplaceStatsResponse
|
||||
return [
|
||||
MarketplaceStatsResponse(
|
||||
marketplace=item.label,
|
||||
total_products=int(item.value),
|
||||
unique_vendors=int(item.secondary_value or 0),
|
||||
unique_brands=0, # Not included in breakdown widget
|
||||
)
|
||||
for item in widget.data.items
|
||||
]
|
||||
|
||||
# No breakdown widget found
|
||||
return []
|
||||
|
||||
|
||||
@admin_dashboard_router.get("/stats/platform", response_model=PlatformStatsResponse)
|
||||
|
||||
@@ -20,8 +20,8 @@ from app.core.config import settings as app_settings
|
||||
from app.core.database import get_db
|
||||
from app.exceptions import ResourceNotFoundException
|
||||
from app.modules.tenancy.exceptions import ConfirmationRequiredException
|
||||
from app.modules.monitoring.services.admin_audit_service import admin_audit_service
|
||||
from app.modules.core.services.admin_settings_service import admin_settings_service
|
||||
from app.modules.core.services.audit_aggregator import audit_aggregator
|
||||
from models.schema.auth import UserContext
|
||||
from app.modules.tenancy.schemas.admin import (
|
||||
AdminSettingCreate,
|
||||
@@ -116,7 +116,7 @@ def create_setting(
|
||||
)
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="create_setting",
|
||||
@@ -147,7 +147,7 @@ def update_setting(
|
||||
)
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="update_setting",
|
||||
@@ -176,7 +176,7 @@ def upsert_setting(
|
||||
)
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="upsert_setting",
|
||||
@@ -233,7 +233,7 @@ def set_rows_per_page(
|
||||
db=db, setting_data=setting_data, admin_user_id=current_admin.id
|
||||
)
|
||||
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="update_setting",
|
||||
@@ -288,7 +288,7 @@ def delete_setting(
|
||||
)
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="delete_setting",
|
||||
@@ -586,7 +586,7 @@ def update_email_settings(
|
||||
updated_keys.append(field)
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="update_email_settings",
|
||||
@@ -625,7 +625,7 @@ def reset_email_settings(
|
||||
deleted_count += 1
|
||||
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="reset_email_settings",
|
||||
@@ -688,7 +688,7 @@ def send_test_email(
|
||||
# Check if email was actually sent (send_raw returns EmailLog, not boolean)
|
||||
if email_log.status == "sent":
|
||||
# Log action
|
||||
admin_audit_service.log_action(
|
||||
audit_aggregator.log(
|
||||
db=db,
|
||||
admin_user_id=current_admin.id,
|
||||
action="send_test_email",
|
||||
|
||||
Reference in New Issue
Block a user