Le CRM d'audit, en production
Faire évoluer le CRM repris pendant le stage : de la demande du client à la recette en production, sur deux systèmes qui doivent rester d'accord.
Deux demandes, deux lectures possibles
Le client a envoyé deux demandes par message. La première : pouvoir envoyer un dossier en audit sans visite préalable. La seconde : mettre en place « la facturation des inspecteurs ». Aucune des deux n'était aussi simple qu'elle en avait l'air.
- Un sens inversé. La demande parlait d'un envoi dans un sens qui n'existait pas. En lisant le code des deux CRM et l'historique des décisions, j'ai compris qu'il s'agissait du sens inverse — et qu'un mode « audit direct » existait déjà, mais seulement à la création manuelle. J'ai fait confirmer l'interprétation plutôt que de la supposer.
- Un mot qui désigne deux choses. « Facturation des inspecteurs » pouvait vouloir dire les payer, ou facturer leur passage aux installateurs. Les données de l'ancien outil tranchaient : les numéros de facture étaient propres à chaque installateur et partagés entre plusieurs inspecteurs. J'ai posé la question fermée au client — c'était bien leur paie.
Aucune ligne de code n'a été écrite avant les réponses : les deux lectures menaient à deux modules différents.
La paie des inspecteurs
Une prévisite devient due quand son rapport est transmis. Son prix dépend du type de bien, selon une grille commune ou un tarif propre à l'inspecteur. Les paiements sont enregistrés par lots, avec un numéro et une date de facture, et le montant est figé dans le lot : changer un tarif ne réécrit jamais ce qui a été payé.
- Le calcul vit à un seul endroit. En base. Deux écrans de facturation affichaient déjà des montants différents parce que la même règle existait en SQL et en TypeScript ; je n'allais pas recréer le problème.
- Payer la bonne personne. La personne qui transmet le rapport n'est pas toujours l'inspecteur. Les données montraient que l'inspecteur assigné au dossier est, lui, toujours celui du rendez-vous : c'est lui qui est payé.
- Valider sur les vraies données. J'ai reproduit le calcul de la migration sur la production, en lecture seule, avant de livrer : 274 prévisites depuis avril, dont 18 sans bien saisi et 3 sans inspecteur — des cas qu'il fallait afficher « à compléter » plutôt que d'ignorer.
- Une liste qui aurait été tronquée en un an. L'API de la base renvoie au plus mille lignes. À soixante-dix prévisites par mois, la liste aurait été coupée sans prévenir. La lecture est paginée avec un tri stable.
Livrer sans ordre imposé
L'audit direct touche les deux CRM. Pour qu'aucun des deux ne casse pendant la transition, l'évolution est additive : le CRM d'audit accepte d'abord un champ optionnel, sans effet tant qu'on ne l'envoie pas ; puis le CRM partenaire l'envoie. Et le partenaire ne marque un dossier « audit direct » que si le CRM d'audit le confirme dans sa réponse : un déploiement dans le mauvais ordre dégrade proprement, au lieu de créer une incohérence.
La recette, sur la production, sans toucher une donnée réelle
Après la mise en production, j'ai écrit des scripts qui pilotent les deux CRM par leurs API, sur des clients et des dossiers créés pour l'occasion et tracés dans un manifeste. Chaque script s'arrête avant d'écrire s'il trouve des données réelles dans son périmètre, et nettoie tout à la fin. 99 contrôles, 98 conformes. Le seul écart était un comportement ancien : quatre changements de statut dans la même seconde partaient avec la même clé d'idempotence. Je l'ai documenté et signalé, pas corrigé en douce.
Un statut différent d'un CRM à l'autre
Un dossier n'affichait pas le même statut dans les deux CRM, et ses notes n'apparaissaient pas chez le partenaire. Plutôt que de corriger ce seul dossier, j'ai comparé les 826 dossiers liés entre les deux bases, par un script de rapprochement.
- Une panne datée au jour près. L'envoi des statuts se fait sans reprise. En croisant chaque changement de statut de juin avec ce qui avait été reçu en face, j'ai daté une panne du récepteur partenaire : cinq jours, quatorze statuts perdus.
- Des notes jamais reprises. La synchronisation des notes n'existait que depuis mi-juin, et l'historique n'avait pas été repris. 232 dossiers étaient concernés.
- Un écart voulu. 53 dossiers différaient parce qu'on avait décidé, à l'origine, de ne plus synchroniser le statut après le rapport d'audit. Rien à corriger.
Le rattrapage a suivi un ordre strict : simulation, validation, sauvegarde de l'état avant écriture, exécution — 14 statuts et 872 notes —, puis nouvelle simulation pour prouver qu'il ne restait aucun écart. Les notes venues du partenaire ont été exclues pour ne créer aucun doublon.
Une alerte de sécurité prise au mot
L'hébergeur de la base signalait une table accessible publiquement. Avant de corriger, j'ai vérifié le risque réel de l'extérieur, avec la seule clé publique de l'application : des tables de biens immobiliers — plus de cinq mille lignes, adresses comprises — étaient lisibles et modifiables sans connexion. Et l'audit a trouvé ce que l'alerte ne disait pas : une vue de diagnostic, exécutée avec les droits de son propriétaire, exposait plus de vingt et un mille lignes avec leurs coordonnées GPS.
Le correctif a été découpé en deux temps. D'abord fermer l'accès public sans changer le comportement de l'application — l'onglet qui lit ces tables aurait cassé sinon. Ensuite seulement cloisonner chaque bien par dossier, après avoir mesuré ce que cela coûterait à la liste des dossiers. Après application : accès anonyme refusé sur les cinq objets, et des utilisateurs qui continuaient de créer des biens sans erreur.