Fix Issue 7: Enforce repository pattern consistency
- Added 5 new service methods for complete database coverage: * get_series_without_nfo() * count_all() * count_with_nfo() * count_with_tmdb_id() * count_with_tvdb_id() - Eliminated all direct database queries from business logic: * series_manager_service.py - now uses AnimeSeriesService * anime_service.py - now uses service layer methods - Documented architecture decision in ARCHITECTURE.md: * Service layer IS the repository layer * No direct SQLAlchemy queries allowed outside service layer - All database access must go through service methods - 1449 tests passing, repository pattern enforced
This commit is contained in:
@@ -297,6 +297,111 @@ class AnimeSeriesService:
|
||||
|
||||
result = await db.execute(query)
|
||||
return list(result.scalars().all())
|
||||
|
||||
@staticmethod
|
||||
async def get_series_without_nfo(
|
||||
db: AsyncSession,
|
||||
limit: Optional[int] = None,
|
||||
offset: int = 0,
|
||||
) -> List[AnimeSeries]:
|
||||
"""Get anime series without NFO files.
|
||||
|
||||
Returns series where has_nfo is False.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
limit: Optional limit for results
|
||||
offset: Offset for pagination
|
||||
|
||||
Returns:
|
||||
List of AnimeSeries without NFO files
|
||||
"""
|
||||
query = (
|
||||
select(AnimeSeries)
|
||||
.where(AnimeSeries.has_nfo == False) # noqa: E712
|
||||
.order_by(AnimeSeries.name)
|
||||
.offset(offset)
|
||||
)
|
||||
|
||||
if limit:
|
||||
query = query.limit(limit)
|
||||
|
||||
result = await db.execute(query)
|
||||
return list(result.scalars().all())
|
||||
|
||||
@staticmethod
|
||||
async def count_all(db: AsyncSession) -> int:
|
||||
"""Count total number of anime series.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
|
||||
Returns:
|
||||
Total count of series
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
result = await db.execute(
|
||||
select(func.count()).select_from(AnimeSeries)
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
@staticmethod
|
||||
async def count_with_nfo(db: AsyncSession) -> int:
|
||||
"""Count anime series with NFO files.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
|
||||
Returns:
|
||||
Count of series with has_nfo=True
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
result = await db.execute(
|
||||
select(func.count())
|
||||
.select_from(AnimeSeries)
|
||||
.where(AnimeSeries.has_nfo == True) # noqa: E712
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
@staticmethod
|
||||
async def count_with_tmdb_id(db: AsyncSession) -> int:
|
||||
"""Count anime series with TMDB ID.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
|
||||
Returns:
|
||||
Count of series with tmdb_id set
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
result = await db.execute(
|
||||
select(func.count())
|
||||
.select_from(AnimeSeries)
|
||||
.where(AnimeSeries.tmdb_id.isnot(None))
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
@staticmethod
|
||||
async def count_with_tvdb_id(db: AsyncSession) -> int:
|
||||
"""Count anime series with TVDB ID.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
|
||||
Returns:
|
||||
Count of series with tvdb_id set
|
||||
"""
|
||||
from sqlalchemy import func
|
||||
|
||||
result = await db.execute(
|
||||
select(func.count())
|
||||
.select_from(AnimeSeries)
|
||||
.where(AnimeSeries.tvdb_id.isnot(None))
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
|
||||
# ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user