feat(backend): expose GET /api/v1/readings avec fenetre bornee et pagination
This commit is contained in:
@@ -6,6 +6,8 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.energy import Reading, Site
|
||||
from app.repositories.reading import ReadingRepository
|
||||
from tests.repositories.test_site import creer as creer_site
|
||||
from tests.repositories.test_site import identifiant as identifiant_site
|
||||
|
||||
pytestmark = pytest.mark.integration
|
||||
|
||||
@@ -25,6 +27,20 @@ def lecture(site_id: str, *, timestamp: datetime, consumption_kw: float) -> Read
|
||||
)
|
||||
|
||||
|
||||
async def creer_lecture(session: AsyncSession, *, site_id: str, **overrides: object) -> Reading:
|
||||
reading = Reading(
|
||||
site_id=site_id,
|
||||
timestamp=overrides.get("timestamp", datetime(2026, 9, 16, tzinfo=UTC)),
|
||||
source=overrides.get("source", "api_current"),
|
||||
consumption_kw=overrides.get("consumption_kw", 10.0),
|
||||
data_quality=overrides.get("data_quality", "good"),
|
||||
raw_data=overrides.get("raw_data", {}),
|
||||
)
|
||||
session.add(reading)
|
||||
await session.flush()
|
||||
return reading
|
||||
|
||||
|
||||
async def test_latest_by_site_keeps_only_the_most_recent_reading(session: AsyncSession) -> None:
|
||||
site_id = identifiant()
|
||||
maintenant = datetime.now(UTC)
|
||||
@@ -70,3 +86,110 @@ async def test_latest_by_site_returns_one_row_per_site(session: AsyncSession) ->
|
||||
await session.rollback()
|
||||
|
||||
assert identifiants == {premier, second}
|
||||
|
||||
|
||||
async def test_list_history_orders_the_readings_by_timestamp_descending(
|
||||
session: AsyncSession,
|
||||
) -> None:
|
||||
site = await creer_site(session)
|
||||
depot = ReadingRepository(session)
|
||||
ancienne = await creer_lecture(
|
||||
session, site_id=site.site_id, timestamp=datetime(2026, 9, 1, tzinfo=UTC)
|
||||
)
|
||||
recente = await creer_lecture(
|
||||
session, site_id=site.site_id, timestamp=datetime(2026, 9, 15, tzinfo=UTC)
|
||||
)
|
||||
|
||||
resultats = await depot.list_history(
|
||||
start=datetime(2026, 8, 1, tzinfo=UTC),
|
||||
end=datetime(2026, 10, 1, tzinfo=UTC),
|
||||
limit=100,
|
||||
offset=0,
|
||||
)
|
||||
identifiants = [
|
||||
r.reading_id for r in resultats if r.reading_id in (ancienne.reading_id, recente.reading_id)
|
||||
]
|
||||
await session.rollback()
|
||||
|
||||
assert identifiants == [recente.reading_id, ancienne.reading_id]
|
||||
|
||||
|
||||
async def test_list_history_filters_by_site_id(session: AsyncSession) -> None:
|
||||
premier = await creer_site(session)
|
||||
second = await creer_site(session)
|
||||
depot = ReadingRepository(session)
|
||||
voulue = await creer_lecture(session, site_id=premier.site_id)
|
||||
await creer_lecture(session, site_id=second.site_id)
|
||||
|
||||
resultats = await depot.list_history(
|
||||
site_id=premier.site_id,
|
||||
start=datetime(2026, 8, 1, tzinfo=UTC),
|
||||
end=datetime(2026, 10, 1, tzinfo=UTC),
|
||||
limit=100,
|
||||
offset=0,
|
||||
)
|
||||
identifiants = [r.reading_id for r in resultats]
|
||||
await session.rollback()
|
||||
|
||||
assert identifiants == [voulue.reading_id]
|
||||
|
||||
|
||||
async def test_list_history_excludes_readings_outside_the_window(session: AsyncSession) -> None:
|
||||
site = await creer_site(session)
|
||||
depot = ReadingRepository(session)
|
||||
dedans = await creer_lecture(
|
||||
session, site_id=site.site_id, timestamp=datetime(2026, 9, 10, tzinfo=UTC)
|
||||
)
|
||||
await creer_lecture(session, site_id=site.site_id, timestamp=datetime(2026, 8, 1, tzinfo=UTC))
|
||||
await creer_lecture(session, site_id=site.site_id, timestamp=datetime(2026, 10, 1, tzinfo=UTC))
|
||||
|
||||
resultats = await depot.list_history(
|
||||
site_id=site.site_id,
|
||||
start=datetime(2026, 9, 1, tzinfo=UTC),
|
||||
end=datetime(2026, 9, 30, tzinfo=UTC),
|
||||
limit=100,
|
||||
offset=0,
|
||||
)
|
||||
identifiants = [r.reading_id for r in resultats]
|
||||
await session.rollback()
|
||||
|
||||
assert identifiants == [dedans.reading_id]
|
||||
|
||||
|
||||
async def test_list_history_respects_limit_and_offset(session: AsyncSession) -> None:
|
||||
site = await creer_site(session)
|
||||
depot = ReadingRepository(session)
|
||||
lectures = [
|
||||
await creer_lecture(
|
||||
session, site_id=site.site_id, timestamp=datetime(2026, 9, jour, tzinfo=UTC)
|
||||
)
|
||||
for jour in (1, 2, 3)
|
||||
]
|
||||
|
||||
resultats = await depot.list_history(
|
||||
site_id=site.site_id,
|
||||
start=datetime(2026, 8, 1, tzinfo=UTC),
|
||||
end=datetime(2026, 10, 1, tzinfo=UTC),
|
||||
limit=1,
|
||||
offset=1,
|
||||
)
|
||||
identifiants = [r.reading_id for r in resultats]
|
||||
await session.rollback()
|
||||
|
||||
assert identifiants == [lectures[1].reading_id]
|
||||
|
||||
|
||||
async def test_list_history_returns_an_empty_list_when_there_is_nothing(
|
||||
session: AsyncSession,
|
||||
) -> None:
|
||||
depot = ReadingRepository(session)
|
||||
|
||||
resultats = await depot.list_history(
|
||||
site_id=identifiant_site(),
|
||||
start=datetime(2026, 8, 1, tzinfo=UTC),
|
||||
end=datetime(2026, 10, 1, tzinfo=UTC),
|
||||
limit=100,
|
||||
offset=0,
|
||||
)
|
||||
|
||||
assert list(resultats) == []
|
||||
|
||||
Reference in New Issue
Block a user