233 lines
6.1 KiB
Python
233 lines
6.1 KiB
Python
"""
|
|
ⒸAngelaMos | 2025
|
|
repository.py
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
from uuid import UUID
|
|
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.orm import selectinload
|
|
|
|
from config import ProgramStatus, ProgramVisibility
|
|
from core.base_repository import BaseRepository
|
|
from .Program import Program
|
|
from .Asset import Asset
|
|
from .RewardTier import RewardTier
|
|
|
|
|
|
class ProgramRepository(BaseRepository[Program]):
|
|
"""
|
|
Repository for Program model database operations
|
|
"""
|
|
model = Program
|
|
|
|
@classmethod
|
|
async def get_by_slug(
|
|
cls,
|
|
session: AsyncSession,
|
|
slug: str,
|
|
) -> Program | None:
|
|
"""
|
|
Get program by slug
|
|
"""
|
|
result = await session.execute(
|
|
select(Program).where(Program.slug == slug)
|
|
)
|
|
return result.scalars().first()
|
|
|
|
@classmethod
|
|
async def get_by_slug_with_details(
|
|
cls,
|
|
session: AsyncSession,
|
|
slug: str,
|
|
) -> Program | None:
|
|
"""
|
|
Get program by slug with assets and reward tiers
|
|
"""
|
|
result = await session.execute(
|
|
select(Program).where(Program.slug == slug).options(
|
|
selectinload(Program.assets),
|
|
selectinload(Program.reward_tiers),
|
|
)
|
|
)
|
|
return result.scalars().first()
|
|
|
|
@classmethod
|
|
async def get_by_id_with_details(
|
|
cls,
|
|
session: AsyncSession,
|
|
program_id: UUID,
|
|
) -> Program | None:
|
|
"""
|
|
Get program by ID with assets and reward tiers
|
|
"""
|
|
result = await session.execute(
|
|
select(Program).where(Program.id == program_id).options(
|
|
selectinload(Program.assets),
|
|
selectinload(Program.reward_tiers),
|
|
)
|
|
)
|
|
return result.scalars().first()
|
|
|
|
@classmethod
|
|
async def slug_exists(
|
|
cls,
|
|
session: AsyncSession,
|
|
slug: str,
|
|
) -> bool:
|
|
"""
|
|
Check if slug is already taken
|
|
"""
|
|
result = await session.execute(
|
|
select(Program.id).where(Program.slug == slug)
|
|
)
|
|
return result.scalars().first() is not None
|
|
|
|
@classmethod
|
|
async def get_public_programs(
|
|
cls,
|
|
session: AsyncSession,
|
|
skip: int = 0,
|
|
limit: int = 20,
|
|
) -> Sequence[Program]:
|
|
"""
|
|
Get active public programs
|
|
"""
|
|
result = await session.execute(
|
|
select(Program).where(
|
|
Program.status == ProgramStatus.ACTIVE,
|
|
Program.visibility == ProgramVisibility.PUBLIC,
|
|
).order_by(Program.created_at.desc()
|
|
).offset(skip).limit(limit)
|
|
)
|
|
return result.scalars().all()
|
|
|
|
@classmethod
|
|
async def count_public_programs(
|
|
cls,
|
|
session: AsyncSession,
|
|
) -> int:
|
|
"""
|
|
Count active public programs
|
|
"""
|
|
result = await session.execute(
|
|
select(func.count()).select_from(Program).where(
|
|
Program.status == ProgramStatus.ACTIVE,
|
|
Program.visibility == ProgramVisibility.PUBLIC,
|
|
)
|
|
)
|
|
return result.scalar_one()
|
|
|
|
@classmethod
|
|
async def get_by_company(
|
|
cls,
|
|
session: AsyncSession,
|
|
company_id: UUID,
|
|
skip: int = 0,
|
|
limit: int = 20,
|
|
) -> Sequence[Program]:
|
|
"""
|
|
Get programs by company/owner
|
|
"""
|
|
result = await session.execute(
|
|
select(Program).where(Program.company_id == company_id
|
|
).order_by(Program.created_at.desc()
|
|
).offset(skip).limit(limit)
|
|
)
|
|
return result.scalars().all()
|
|
|
|
@classmethod
|
|
async def count_by_company(
|
|
cls,
|
|
session: AsyncSession,
|
|
company_id: UUID,
|
|
) -> int:
|
|
"""
|
|
Count programs by company
|
|
"""
|
|
result = await session.execute(
|
|
select(func.count()).select_from(Program).where(
|
|
Program.company_id == company_id
|
|
)
|
|
)
|
|
return result.scalar_one()
|
|
|
|
|
|
class AssetRepository(BaseRepository[Asset]):
|
|
"""
|
|
Repository for Asset model database operations
|
|
"""
|
|
model = Asset
|
|
|
|
@classmethod
|
|
async def get_by_program(
|
|
cls,
|
|
session: AsyncSession,
|
|
program_id: UUID,
|
|
) -> Sequence[Asset]:
|
|
"""
|
|
Get all assets for a program
|
|
"""
|
|
result = await session.execute(
|
|
select(Asset).where(
|
|
Asset.program_id == program_id
|
|
).order_by(Asset.in_scope.desc(),
|
|
Asset.created_at)
|
|
)
|
|
return result.scalars().all()
|
|
|
|
|
|
class RewardTierRepository(BaseRepository[RewardTier]):
|
|
"""
|
|
Repository for RewardTier model database operations
|
|
"""
|
|
model = RewardTier
|
|
|
|
@classmethod
|
|
async def get_by_program(
|
|
cls,
|
|
session: AsyncSession,
|
|
program_id: UUID,
|
|
) -> Sequence[RewardTier]:
|
|
"""
|
|
Get all reward tiers for a program
|
|
"""
|
|
result = await session.execute(
|
|
select(RewardTier).where(RewardTier.program_id == program_id)
|
|
)
|
|
return result.scalars().all()
|
|
|
|
@classmethod
|
|
async def get_by_program_and_severity(
|
|
cls,
|
|
session: AsyncSession,
|
|
program_id: UUID,
|
|
severity: str,
|
|
) -> RewardTier | None:
|
|
"""
|
|
Get reward tier by program and severity
|
|
"""
|
|
result = await session.execute(
|
|
select(RewardTier).where(
|
|
RewardTier.program_id == program_id,
|
|
RewardTier.severity == severity,
|
|
)
|
|
)
|
|
return result.scalars().first()
|
|
|
|
@classmethod
|
|
async def delete_by_program(
|
|
cls,
|
|
session: AsyncSession,
|
|
program_id: UUID,
|
|
) -> None:
|
|
"""
|
|
Delete all reward tiers for a program
|
|
"""
|
|
tiers = await cls.get_by_program(session, program_id)
|
|
for tier in tiers:
|
|
await session.delete(tier)
|
|
await session.flush()
|