fix(backend): traite la revue de phyri0s sur la PR #84

Tri non déterministe : `latest_for_site` départage désormais les égalités de
timestamp par `reading_id` décroissant, comme `list_history`. `uq_reading_source`
autorise deux lignes au même `site_id`+`timestamp` quand la `source` diffère, donc
le `LIMIT 1` pouvait renvoyer l'une ou l'autre d'un appel à l'autre.

Tests : trois tests `integration` sur `latest_for_site` (plus récente, égalité de
timestamp, isolation par site). Le test d'égalité échoue sans le correctif ci-dessus.

Duplication : `DataQuality` et le repli vers `critical` sortent dans
`app/services/data_quality.py`, partagé par `stats.py`, `site.py` et `sensor.py`,
qui en portaient trois copies indépendantes. Supprime au passage deux
`# type: ignore[assignment]`.
This commit is contained in:
Johan LEROY
2026-09-18 10:28:04 +02:00
parent d167b64188
commit 5eb74aa64a
6 changed files with 74 additions and 22 deletions
+2 -9
View File
@@ -1,15 +1,11 @@
from collections.abc import Sequence
from dataclasses import dataclass
from datetime import datetime
from typing import Literal
from app.models.energy import Site
from app.repositories.reading import ReadingRepository
from app.repositories.site import SiteRepository
DataQuality = Literal["good", "partial", "degraded", "critical"]
QUALITES_CONNUES: frozenset[str] = frozenset({"good", "partial", "degraded", "critical"})
from app.services.data_quality import DataQuality, qualite_ou_critique
class SiteError(Exception):
@@ -70,9 +66,6 @@ class SiteService:
data_quality="critical",
)
qualite: DataQuality = "critical"
if derniere.data_quality in QUALITES_CONNUES:
qualite = derniere.data_quality # type: ignore[assignment]
return SiteCurrentReading(
timestamp=derniere.timestamp,
site_id=site.site_id,
@@ -85,5 +78,5 @@ class SiteService:
temperature_celsius=derniere.temperature_celsius,
humidity_percent=derniere.humidity_percent,
null_reasons=derniere.null_reasons or [],
data_quality=qualite,
data_quality=qualite_ou_critique(derniere.data_quality),
)