refactor(arch): eliminate all cross-module model imports in service layer
Some checks failed
CI / ruff (push) Successful in 9s
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / pytest (push) Has been cancelled

Enforce MOD-025/MOD-026 rules: zero top-level cross-module model imports
remain in any service file. All 66 files migrated using deferred import
patterns (method-body, _get_model() helpers, instance-cached self._Model)
and new cross-module service methods in tenancy. Documentation updated
with Pattern 6 (deferred imports), migration plan marked complete, and
violations status reflects 84→0 service-layer violations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-27 06:13:15 +01:00
parent e3a52f6536
commit 86e85a98b8
66 changed files with 2242 additions and 1295 deletions

View File

@@ -8,6 +8,8 @@ Provides functionality for:
- Notification statistics and queries
"""
from __future__ import annotations
import logging
from datetime import datetime, timedelta
from typing import Any
@@ -16,7 +18,6 @@ from sqlalchemy import and_, case
from sqlalchemy.orm import Session
from app.modules.messaging.models.admin_notification import AdminNotification
from app.modules.tenancy.models import PlatformAlert
from app.modules.tenancy.schemas.admin import (
AdminNotificationCreate,
PlatformAlertCreate,
@@ -25,6 +26,13 @@ from app.modules.tenancy.schemas.admin import (
logger = logging.getLogger(__name__)
def _get_platform_alert_model():
"""Deferred import for PlatformAlert model (lives in tenancy, consumed by messaging)."""
from app.modules.tenancy.models import PlatformAlert
return PlatformAlert
# ============================================================================
# NOTIFICATION TYPES
# ============================================================================
@@ -475,6 +483,7 @@ class PlatformAlertService:
auto_generated: bool = True,
) -> PlatformAlert:
"""Create a new platform alert."""
PlatformAlert = _get_platform_alert_model()
now = datetime.utcnow()
alert = PlatformAlert(
@@ -527,6 +536,7 @@ class PlatformAlertService:
Returns:
Tuple of (alerts, total_count, active_count, critical_count)
"""
PlatformAlert = _get_platform_alert_model()
query = db.query(PlatformAlert)
# Apply filters
@@ -587,6 +597,7 @@ class PlatformAlertService:
resolution_notes: str | None = None,
) -> PlatformAlert | None:
"""Resolve a platform alert."""
PlatformAlert = _get_platform_alert_model()
alert = db.query(PlatformAlert).filter(PlatformAlert.id == alert_id).first()
if alert and not alert.is_resolved:
@@ -602,6 +613,7 @@ class PlatformAlertService:
def get_statistics(self, db: Session) -> dict[str, int]:
"""Get alert statistics."""
PlatformAlert = _get_platform_alert_model()
today_start = datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
total = db.query(PlatformAlert).count()
@@ -644,6 +656,7 @@ class PlatformAlertService:
alert_id: int,
) -> PlatformAlert | None:
"""Increment occurrence count for repeated alert."""
PlatformAlert = _get_platform_alert_model()
alert = db.query(PlatformAlert).filter(PlatformAlert.id == alert_id).first()
if alert:
@@ -660,6 +673,7 @@ class PlatformAlertService:
title: str,
) -> PlatformAlert | None:
"""Find an active alert with same type and title."""
PlatformAlert = _get_platform_alert_model()
return (
db.query(PlatformAlert)
.filter(