Certification cosmétique, international
Automatiser un reporting multi sources non standardisées
Mission de deux mois en binôme. Supprimer un traitement manuel mensuel sans perdre la fiabilité du chiffre, alors que chaque source arrive avec ses propres conventions.
Contexte
Le client édite un standard international de certification pour les cosmétiques biologiques et naturels. Le suivi des produits certifiés repose sur des fichiers Excel transmis chaque mois par une douzaine d'organismes certificateurs répartis dans plusieurs pays, chacun avec son propre formatage.
Ces données étaient consolidées à la main, puis publiées sous forme de rapport mensuel. Deux limites : un temps de traitement récurrent important, et un reporting Power BI difficile à faire évoluer.
Trois besoins distincts
- Fiabiliser l'ingestion de sources hétérogènes et non standardisées.
- Remplacer les tableaux de bord Power BI par une solution intégrée à l'écosystème cloud existant.
- Supprimer les étapes manuelles de publication du reporting mensuel.
Le vrai blocage n'était pas technique
Un même organisme certificateur apparaissait sous plusieurs libellés selon le fichier source, par exemple une entité présente tantôt sous sa raison sociale complète, tantôt sous une marque commerciale, tantôt sous une abréviation. Toute agrégation par organisme était donc fausse, sans jamais lever la moindre erreur.
J'ai traité le problème à deux niveaux, parce qu'un seul n'aurait pas suffi : correction rétroactive de l'historique en base, et normalisation au moment du cast dans le pipeline Python, pour que le problème ne réapparaisse pas au prochain fichier reçu.
Un principe que je réapplique depuis
La normalisation des référentiels est un prérequis, pas une finition. Sans elle, toute agrégation est fausse et le reste silencieusement.
Une contrainte d'outil devenue règle d'architecture
À l'usage, une limite s'est imposée : dans l'outil de restitution retenu, croiser plusieurs sources ou empiler des vues sur des vues casse le filtrage croisé entre graphiques.
Plutôt que de contourner au cas par cas, j'en ai fait une règle : une vue unique et autoportante par page de tableau de bord. Chaque vue encapsule sa propre logique métier, ce qui rend l'affichage purement déclaratif et la couche analytique indépendante de l'outil de visualisation.
Restitution et automatisation
Tableau de bord de cinq pages : vue d'ensemble, catalogue produits, ingrédients et conformité, pipeline de validation des matières premières, matrice de présence des entreprises par organisme.
Côté publication, développement d'un module de dépôt automatique du rapport mensuel : rafraîchissement du jeton par OAuth via un gestionnaire de secrets, gestion des erreurs avec relance et temporisation croissante, envoi des fichiers en deux étapes. L'appel est volontairement non bloquant, un échec de publication n'interrompt pas le pipeline de données.
Un bug représentatif
L'indicateur du nombre d'entreprises actives renvoyait un résultat aberrant. La cause : la vue filtrait sur le dernier mois disponible, puis calculait la date de première apparition de chaque entreprise avec une fonction de fenêtrage. Comme le filtre s'applique avant la fenêtre, cette date valait toujours le mois courant, et toutes les entreprises étaient classées comme nouvelles.
C'est le type de bug le plus dangereux : aucune erreur levée, juste un chiffre plausible et faux. Nous l'avons corrigé en simplifiant la logique, et nous avons assumé de reporter la distinction entre nouveau et actif tant que l'historique disponible ne couvrait qu'un seul mois, plutôt que d'afficher une segmentation sans fondement.
Résultats
- Reporting mensuel multi organismes automatisé de bout en bout, de l'ingestion des fichiers sources jusqu'à la publication.
- Couche analytique réutilisable, indépendante de l'outil de visualisation.
- Migration du reporting existant vers la nouvelle solution effectuée.
Ce que j'en retiens
Une contrainte d'outil bien identifiée devient une règle d'architecture, et vaut mieux qu'une série de contournements. Et surtout, mieux vaut ne pas afficher une métrique que d'en afficher une non fondée. C'est le même arbitrage que je retrouve sur chaque mission.
- BigQuery
- Python
- Looker Studio
- Google Cloud Platform
- API REST
- OAuth