Fusionne dev dans feat/endpoint-alertes-predictives

Resout les conflits additifs entre les routes alerts, recommendations
et stats mergees sur dev (PR #79, PR #82) pendant le developpement de
cette branche : deps.py, router.py, openapi.py, openapi.json,
test_openapi.py et 20-backend.md conservent desormais les trois routes.
This commit is contained in:
Johan LEROY
2026-09-16 14:25:49 +02:00
23 changed files with 1193 additions and 11 deletions
+21
View File
@@ -0,0 +1,21 @@
from collections.abc import Sequence
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.energy import Reading
class ReadingRepository:
def __init__(self, session: AsyncSession) -> None:
self._session = session
async def latest_by_site(self) -> Sequence[Reading]:
# `.distinct(site_id)` compile en `DISTINCT ON (site_id)` sous PostgreSQL : une seule
# ligne par site, la plus récente grâce à l'ordre composite qui suit.
requete = (
select(Reading)
.distinct(Reading.site_id)
.order_by(Reading.site_id, Reading.timestamp.desc())
)
return (await self._session.execute(requete)).scalars().all()
@@ -0,0 +1,22 @@
from collections.abc import Sequence
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.energy import Recommendation
class RecommendationRepository:
def __init__(self, session: AsyncSession) -> None:
self._session = session
async def list_all(self) -> Sequence[Recommendation]:
requete = select(Recommendation).order_by(Recommendation.recommendation_id)
return (await self._session.scalars(requete)).all()
async def get_by_id(self, recommendation_id: int) -> Recommendation | None:
requete = select(Recommendation).where(
Recommendation.recommendation_id == recommendation_id
)
recommendation: Recommendation | None = await self._session.scalar(requete)
return recommendation