Aller au contenu principal

ENG-001.5J3 — Réconciliation Territory/SIRENE des informations municipales — Rapport d'implémentation

MissionENG-001.5J3 — Migration de la réconciliation Territory/SIRENE des informations municipales
Rattaché àENG-001.5J — Migration des infos pratiques vers Municipal Management ; ENG-001.5J1 — Rapport d'implémentation ; ENG-001.5J2 — Rapport d'implémentation
Dépôtdmv_api
Branchefeature/eng-001-5j3-municipal-infos-reconciliation
StatutImplémenté localement — aucun commit applicatif

1. Divergence initiale

  • MunicipalManagementWriter ne portait encore aucune capacité publique de réconciliation des commune_infos.
  • CommuneMairieDataRefreshService contenait encore :
    • le matching par commune_id + section + label ;
    • la décision création / mise à jour ;
    • les valeurs par défaut icon_color = blue et ordre = 0 ;
    • le calcul de infos_updated ;
    • une méthode privée upsertInfo() dédiée à commune_infos.
  • Le contrat public Municipal Management ne permettait pas encore à Territory de déléguer ce cas d’usage sans fuite SIRENE.

2. Arbitrage validé

  • L’extension du contrat MunicipalManagementWriter est validée avec :
public function reconcileInfos(
string $communeId,
MunicipalInfoReconciliationDTO $data,
): MunicipalInfoReconciliationResultDTO;
  • Municipal Management devient l’unique owner métier de la réconciliation commune_infos.
  • Territory reste limité à :
    • la lecture de la source externe ;
    • l’extraction des champs utiles ;
    • la construction de DTO neutres ;
    • l’appel du contrat ;
    • la réinjection du résultat dans MairieDataRefreshResult.

3. Signature finale du contrat

MunicipalManagementWriter::reconcileInfos(
string $communeId,
MunicipalInfoReconciliationDTO $data,
): MunicipalInfoReconciliationResultDTO

4. DTO créés

MunicipalInfoCandidateDTO

Champs exacts :

  • section
  • label
  • valeur

MunicipalInfoReconciliationDTO

Contenu exact :

  • candidates : liste typée de MunicipalInfoCandidateDTO

MunicipalInfoReconciliationResultDTO

Contenu exact :

  • infosUpdated : liste de chaînes

Compatibilité exposée :

[
'infos_updated' => [...],
]

5. Sémantique exacte de infosUpdated

  • la valeur est calculée dans Municipal Management ;
  • chaque candidat traité ajoute sa section à la liste si elle n’y est pas déjà ;
  • la liste est donc dédupliquée ;
  • une section est considérée comme impactée dès lors qu’un candidat de cette section est présent dans le payload, même si la valeur finale est identique à l’état déjà stocké ;
  • ce comportement reproduit le flux historique observé dans Territory, qui ajoutait la section dès la présence du champ source, sans distinguer création, modification effective ou identité stricte de valeur.

Conséquence d’idempotence :

  • deux appels successifs avec les mêmes candidats conservent le même état final ;
  • ils retournent encore ['identite'] si des candidats identite sont présents.

6. Logique retirée de Territory

CommuneMairieDataRefreshService ne contient plus :

  • aucune écriture directe vers commune_infos ;
  • aucune méthode upsertInfo() ;
  • aucun matching par commune_id + section + label ;
  • aucune valeur par défaut métier de création ;
  • aucun calcul local de infos_updated.

Territory conserve uniquement :

  • la construction de candidats neutres (section, label, valeur) ;
  • l’appel à MunicipalManagementWriter::reconcileInfos() ;
  • la réinjection du résultat dans MairieDataRefreshResult.

7. Logique ajoutée à Municipal Management

MunicipalManagementWriteService::reconcileInfos() porte désormais :

  • la vérification d’existence de la commune ;
  • la recherche de l’information existante par commune_id + section + label ;
  • la décision création / mise à jour ;
  • la mise à jour limitée à valeur pour les lignes existantes ;
  • la création avec valeurs historiques :
    • icon_color = blue
    • ordre = 0
    • created_at = now()
  • la déduplication de infosUpdated.

8. Comportement historique préservé

  • matching inchangé par commune_id + section + label ;
  • mise à jour inchangée limitée à valeur ;
  • création inchangée avec icon_color = blue et ordre = 0 ;
  • aucune suppression ;
  • aucune désactivation ;
  • aucune réactivation ;
  • aucun autre champ modifié sur une ligne existante ;
  • format de MairieDataRefreshResult inchangé ;
  • routes inchangées ;
  • aucun frontend modifié.

9. Idempotence

Preuve couverte par les tests :

  • premier appel : création des trois infos historiques identite ;
  • second appel identique :
    • aucun doublon ;
    • même état final en base ;
    • même liste infos_updated = ['identite'].

10. Tests et garde-fous

Tests ajoutés ou adaptés :

  • création des trois informations historiques avec défauts ;
  • mise à jour d’une information existante en ne modifiant que valeur ;
  • matching exact et isolation entre communes ;
  • idempotence sans doublon ;
  • déduplication de infos_updated ;
  • compatibilité exacte avec MairieDataRefreshResult ;
  • délégation effective Territory → contrat public ;
  • garde-fou sur l’absence d’écriture directe Territory → commune_infos ;
  • garde-fou sur l’absence de upsertInfo() dans Territory ;
  • garde-fou sur l’unicité d’implémentation métier ;
  • garde-fou sur la neutralité des DTO et l’absence de terme Sirene dans les contrats/DTO Municipal Management ;
  • garde-fou sur l’absence de route modifiée.

11. Validations

Validations à exécuter pour clôture locale :

  • php -l sur les fichiers PHP touchés ;
  • php artisan route:list ;
  • php artisan test ;
  • vendor/bin/pint --test ;
  • git diff --check ;
  • npm run build côté documentation ;
  • git diff --check côté documentation.

12. Dettes restantes

  • aucune dette supplémentaire introduite dans ce périmètre ;
  • les lectures publiques Territory restent inchangées par décision de périmètre ;
  • les autres sous-domaines municipaux ne sont pas touchés ;
  • aucune évolution sur commune_info_sections n’est nécessaire dans J3.