fix(meters): close open schedules on replacement
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
Some checks are pending
CI - Tests et Syntax / lint-and-test (push) Waiting to run
This commit is contained in:
parent
a66d937e96
commit
e870b070aa
3 changed files with 19 additions and 5 deletions
|
|
@ -28,6 +28,19 @@ TREATED_WITHOUT_READING = "TRAITÉE SANS RELEVÉ"
|
|||
CANCELLED = "ANNULÉE"
|
||||
|
||||
|
||||
def cancel_open_occurrences_for_meter(meter, *, commit=False):
|
||||
"""Clôture explicitement les échéances ouvertes d'un compteur remplacé."""
|
||||
schedules = MeterReadingSchedule.query.filter_by(meter_id=meter.id).all()
|
||||
for schedule in schedules:
|
||||
schedule.is_active = False
|
||||
for occurrence in MeterReadingOccurrence.query.filter_by(schedule_id=schedule.id, status=TODO).all():
|
||||
occurrence.status = CANCELLED
|
||||
occurrence.no_reading_reason = "METER_REPLACED"
|
||||
occurrence.comment = "Occurrence annulée automatiquement : compteur remplacé ou inactif."
|
||||
if commit:
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def _add_months(value, months):
|
||||
index = value.year * 12 + value.month - 1 + months
|
||||
year, month = divmod(index, 12)
|
||||
|
|
@ -152,10 +165,7 @@ def generate_occurrences(*, start_date, end_date, schedule_ids=None, commit=True
|
|||
created = []
|
||||
for schedule in query.all():
|
||||
if schedule.meter.status == "replaced" or not schedule.meter.is_active:
|
||||
for old in MeterReadingOccurrence.query.filter_by(schedule_id=schedule.id, status=TODO).all():
|
||||
old.status = CANCELLED
|
||||
old.no_reading_reason = "METER_REPLACED"
|
||||
old.comment = "Occurrence annulée automatiquement : compteur remplacé ou inactif."
|
||||
cancel_open_occurrences_for_meter(schedule.meter)
|
||||
continue
|
||||
for target_date in _target_dates(schedule, start_date, end_date):
|
||||
occurrence = MeterReadingOccurrence.query.filter_by(
|
||||
|
|
|
|||
|
|
@ -176,6 +176,10 @@ def replace_meter(*, old_meter, name, user_id=None, commit=True, **kwargs):
|
|||
)
|
||||
old_meter.status = "replaced"
|
||||
old_meter.is_active = False
|
||||
# C2 : les échéances ouvertes sont clôturées dans la même transaction que
|
||||
# le remplacement ; l'historique reste consultable.
|
||||
from .meter_reading_planning import cancel_open_occurrences_for_meter
|
||||
cancel_open_occurrences_for_meter(old_meter)
|
||||
db.session.add(new_meter)
|
||||
if commit:
|
||||
db.session.commit()
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ Les décisions sont ajoutées au fil des checkpoints. Les modèles existants son
|
|||
|
||||
La date cible reste distincte de la date opérationnelle. L'anticipation réutilise le moteur horaire/calendrier existant pour les règles scolaires ; les logements sont hors calendrier scolaire par défaut. Sans horaires explicites, le système conserve la date cible plutôt que d'inventer un jour travaillé.
|
||||
|
||||
**TRAITEMENT** : une occurrence avec relevé appelle le service C1 `record_meter_reading`. Une occurrence sans relevé conserve un motif distinguant notamment inaccessible, absent, refus et relevé non connu, sans créer de mesure artificielle. Une occurrence ouverte d'un compteur remplacé est annulée avec une raison système et reste historisée.
|
||||
**TRAITEMENT** : une occurrence avec relevé appelle le service C1 `record_meter_reading`. Une occurrence sans relevé conserve un motif distinguant notamment inaccessible, absent, refus et relevé non connu, sans créer de mesure artificielle. Une occurrence ouverte d'un compteur remplacé est annulée immédiatement dans la transaction de remplacement avec une raison système et reste historisée.
|
||||
|
||||
**INTÉGRATION** : les occurrences sont une source du `DayPlanner`, avec responsable, durée et retard calculé ; elles ne créent pas d'intervention et ne simulent pas de créneau si le planificateur ne sait pas en attribuer un. Les routes de configuration sont administrateur ; le traitement d'une occurrence est limité à l'utilisateur assigné ou à un administrateur.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue