Introduction
Ce documente parcours les étapes des réflexions et conception d’un outil d’analyse de données issues d’un dépôt de tickets de caisse.
Cela fait un certain temps que j’ai commencé à m’intéresser à la nature des dépenses ménagères. Ce besoin est devenu plus présent ces dernières années pendant lesquels la fluctuation des prix me semblait loin d’être linéaire.
Certaines banques mettent à disposition de leurs clients des outils d’analyse macroscopique. La famille peut, par exemple, savoir quel est le montant annuel dépensé en énergie, en eau, dans un crédit.
Aucun de ces outils ne peut effectuer une analyse des données à l’échelle d’une gamme de produits, d’un produit un particulier, d’un point de vente. La banque recevant exclusivement le montant inhérent la transaction, les détails des articles ne font pas partie des données dont elle peut disposer. Sans compter les achats qui peuvent se faire en liquide ni ceux qui s’effectuent par d’autres moyens de payement réguliers comme les tickets restaurants.
Dans le cadre professionnel, j’ai suivi un programme de formation proposé par l’organisme Orsys reparti sur 4 sessions de septembre à décembre 2024 :
- Formation : Intelligence artificielle : enjeux et outils (2 jours)
- Machine learning, l’état de l’art (2 jours)
- Deep Learning et réseaux de neurones : les fondamentaux (3 jours)
- Big Data, état de l’art (2 jours)
Lors de la première session comme lors de la deuxième, les travaux pratiques occupaient une place importance dans le déroulé proposé par le formateur. Ces travaux pratiques étaient proposés en utilisant Python comme langage de programmation et des libraires de cet écosystème. Ayant utilisé ce langage précédemment une seule fois, cela il y a 5 ans lors d’une formation à l’Ecole des Mines, j’ai rencontré des difficultés particulières lors des TP. Le formateur, Benjamin Speziale (profil LinkedIn ici), faisait preuve d’une grande pédagogie et c’est en partie grâce à lui que j’ai pu m’en sortir malgré mes connaissances élémentaires.
Le projet objet de cet article ayant une part importante dans l’analyse des données, j’ai décidé d’en faire un terrain de jeu pour me permettre de monter en compétences avec le langage Python. Le langage utilisé ainsi que les autres choix seront des occasions pour découvrir d’autres outils, d’autres technologies que celles que j’utilise dans mon quotidien professionnel.
Je tiens à remercier tout particulièrement Monsieur Nicolas Canu, pour le temps qu’il a consacré à la révision de cet article ainsi que pour les propositions d’amélioration avancées pendant la relecture du brouillon avant publication.
Bonne lecture.
Observations et prémices d’une modélisation
Les données en entrée de l’outil sont les tickets de caisses.
Cet outil doit servir à l’analyse des achats de ma famille et je n’ai pas l’intention, pas pour le moment en tout cas, d’élargir son périmètre. Dans mon cas particulier :
- Mes habitudes d’achats m’emmènent à faire les courses presque exclusivement dans des magasins où au passage de la carte de fidélité je dispose du ticket de caisse au format électronique.
- J’effectue les courses dans un nombre très limité de magasins. Principalement deux magasins de taille moyenne appartenant à la même enseigne : Super U.
Cela me permet d’introduire quelques contraintes qui peuvent simplifier le travail à ce stade :
- Je ne m’intéresserai pas aux problématiques de reconnaissance textuelles depuis une image.
- Au regard du nombre limité de points de vente, je ne considère pas à ce stade très important de passer du temps sur la modélisation d’un annuaire de supermarchés. Un simple libellé me suffira.
A l’aide de mes archives, je récupère tous les tickets de caisse depuis janvier 2023 jusqu’à décembre 2025. Cela me permet de disposer d’une base de départ de 202 tickets de caisse répartis sur une période de 36 mois.
Avant d’avancer un brouillon d’un modèle qui pourrait décrire un ticket, j’ai voulu chercher s’il en existait déjà au moins un. A ma grande surprise je n’en ai pas trouvé un seul.
Les commerçants ont l’obligation de s’équiper d’une caisse enregistreuse conforme à la norme NF 525. Cette disposition est destinée à lutter contre la fraude à la TVA.
La norme est destinée à garantir que le ticket de caisse ne puisse pas être altéré. Le ministère de l’Economie et des Finances veut s’assurer que le commerçant lui reverse la partie de TVA le concernant. Chaque produit dispose de son propre régime de TVA. Bercy ne semble s’intéresser qu’au montant global, laissant une liberté presque dérangeante aux autres parties qui constituent le ticket. Pourtant dans une page du même ministère (accessible ici), la désignation des produits achetés, leur quantité, leur prix semblent être également des données obligatoires.
Dans mon lot des tickets j’en prends un qui me semble être significatif car il présente un format qui semble le plus courant parmi ceux que j’ai pu observer :

Je regroupe les données par leur nature :
- En rouge, un entête identifiant le commerçant
- En vert, une zone qui fournit des informations d’identification du ticket, notamment son identifiant, l’horodatage du ticket, l’opérateur à la caisse (son identifiant et les initiales de son nom et prénom), l’identifiant de la caisse
- En orange, la liste des articles achetés groupés par rayon, leur prix unitaire, le régime de TVA appliqué
- En bleu, le nombre d’articles passés en caisse, et le montant total dû.
- En violet, un détail concernant la modalité de payement et la contribution à au montant de la TVA par régime.
Au fil des différentes itérations sur un ensemble de tickets plus importants j’arrive à peaufiner le modèle ainsi que le traitement.
Cette séance de travail itératif me permet de formuler l’observations suivante :
« La plupart des fichiers contiennent les mêmes informations mais leur mise en page peut être extrêmement différente. Ces différences peuvent être importantes d’un commerçant à l’autre même s’ils appartiennent à la même franchise. Des différences, plus faibles, existent au sein des caisses du même commerçant. Autrement je pourrais déduire qu’il y a eu un changement au paramétrage sur l’ensemble de caisse entre deux de mes passages chez le même commerçant. »
Certains cas identifiés dans ces tickets méritent d’être documentés :
- Le même article plusieurs fois
Si le même article est passé plusieurs fois, il pourra se présenter de deux différentes manières selon le paramétrage de la caisse.
Le cas d’une seule ligne et une deuxième ligne avec le prix unitaire et la quantité :
![]()
Le cas d’autant de lignes qu’il y a d’articles :

- Correction de ligne
Un article semblerait avoir été retiré d’un passage en caisse. Je n’ai pas le souvenir d’avoir demandé une quelque action de ce type. J’avance une supposition : l’opérateur à la caisse pourrait avoir passé cet article sur mon compte alors qu’il appartenait à la personne juste après. Si cela est le cas je suis surpris que le ticket tienne une trace d’une telle erreur. L’origine est probablement une autre.
![]()
- Sans catégorie
Sur certains tickets, les articles ne sont pas groupés par catégories. Les catégories des produits sont dans ce cas-là absentes.

- Les produits par lots
Certains produits peuvent être achetés individuellement ou peuvent être achetés par lot. C’est parfois le cas pour les kiwis, pour les concombres. Cette expression du lot n’est pas toujours traduite de la même manière dans le ticket.
La désignation du produit décrit le kiwi unitaire. Une deuxième ligne reporte la quantité et le prix unitaire. Les deux autres lignes communiquent la réduction lorsqu’un lot de 4 est acheté. Dans ce cas-là deux kiwis étaient donc hors lot :
![]()
La désignation du produit identifie directement un lot de 5 :
![]()
- Pesée manuelle
La description des produits à la demande comporte leur poids unitaire, leur quantité ainsi que le montant du prix relatif à l’article.
Cela me semble être une situation assez classique et les informations me semblent pertinentes :
![]()
Si j’ajoute le cas ci-dessus c’est que dans certain cas ces informations détaillées étaient absentes pouvant laisser croire que le produit était conditionné alors que cela n’était pas le cas. Ci-dessous, un exemple d’absence de ces informations dans l’extrait d’un ticket :
![]()

Tous les produits ci-dessous ont fait objet d’une pesée manuelle, par un salarié du rayon pour les produits du premier groupe et par moi-même pour les produits du deuxième groupe.
- EAN
Sur un ticket il m’est arrivé de trouver son identifiant EAN :
![]()
- Les réductions
Lorsque je fourni un coupon de réduction, cette action semble se traduire dans le ticket de manière suivante :
![]()
- Les garanties
Pour les objets faisant objet d’une garantie, la durée de la garantie est indiquée dans le ticket. Par ailleurs, au regard de la dernière mise à jour de la législation concernant l’impression des tickets de caisse, cette information implique une dérogation à la règle. Le ticket doit dans ce cas-là être obligatoirement fourni.
![]()
- Les coupons
Certains produits font objet de réduction, d’une remise, directement par le fournisseur. J’imagine que cela peut être une « parade fiscale » de quelque type où il serait préférable d’afficher un prix et sa réduction par le passage d’un coupon qui est emballé avec le produit lui-même :
![]()
Ce travail itératif me permet de constituer un échantillon. Des 202 tickets constituant ma source initiale, je dispose d’un Jeux d’Essai et Vérification composé de 17 tickets de caisse qui présents les cas ayant fait objet de développement.
J’implémente une première version d’un modèle composé de deux classes : Ticket et Article, où le premier contient une propriété dont le type est une liste de la deuxième.
L’image suivante représente cette première version du diagramme :

Le diagramme ci-dessus est disponible au format graphml. Le logiciel yEd Graph Editor, gratuit, peut lire et modifier les fichiers dans ce format.
Considérations :
- La classe Ticket contient une propriété articles_nb. L’on pourrait s’en passer car la valeur devrait toujours être le nombre d’éléments contenus dans la liste list_of_articles. Finalement je décide de la laisser. Cette propriété est alimentée par la valeur présente dans le ticket toujours après le dernier article et avant le montant dû. La valeur indiquée à cet endroit-là peut différer si un même article est présent sur plusieurs lignes ou il est groupé. Pour le moment je ne maitrise pas encore suffisamment le sujet et cela me permet d’effectuer un contrôle de cohérence entre cette valeur est le nombre d’articles qui auront alimenté la propriété list_of_articles.
- Un problème concernant le choix des désignations pour les classes comme pour les propriétés se pose. J’aurais préféré trouver un modèle déjà existant, une norme pouvant au moins me guider. Pour le moment je ne suis pas satisfait des choix que j’ai fait mais je n’arrive pas à formuler des propositions qui me conviennent mieux.
- Un autre problème à résoudre, en lien avec le précédent d’ailleurs, est le choix de la langue pour les noms des classes et des propriétés. Parfois j’utilise naturellement l’anglais et d’autres fois plus naturellement le français. Je suis gêné par le français lorsqu’une appellation contient un accent. Je suis gêné par l’anglais lorsque je dois effectuer une traduction vers cette langue d’un concept que je suis en train de lire sur le ticket en français. Une chose est sûre, il faut que j’en choisisse une parmi les deux. Probablement un effort de modélisation entièrement en anglais serait plus intéressant pour l’avenir.
Conclusions
Le brouillon de cette publication a été rédigé il y a deux ans. Depuis cette première ébauche, les séances de travail se sont poursuivies et ont permis d’aboutir à une première version fonctionnelle d’une plateforme dédiée à la valorisation des données contenues dans les tickets de caisse.
Une présentation synthétique du projet est désormais disponible à l’adresse suivante : https://github.com/davideusai/Receev-public/blob/main/index.md
L’implémentation a également été l’occasion de mener une première expérimentation avec l’agent Claude Code, en octobre 2025.
La prochaine étape consistera à proposer, via un portail web, l’ensemble des analyses produites par la plateforme.
Certaines analyses existantes ont déjà été enrichies grâce au croisement avec des données publiques, notamment les indicateurs d’inflation de l’INSEE. D’autres sources mériteraient également d’être explorées : les observations des CCI, les rapports de l’Ilec, le baromètre ObsAR ou encore les travaux du Crédoc, pour n’en citer que quelques‑unes.
En lien plus direct avec mon expertise professionnelle, j’aimerais approfondir la modélisation d’un ticket de caisse dans une perspective plus universelle, afin de publier à terme une version ouverte et standardisée de ce modèle.
Si ce projet vous intéresse, si les sujets abordés résonnent avec votre quotidien professionnel, n’hésitez pas à vous manifester. L’objectif serait de constituer un groupe de réflexion capable de produire une première version publique de ce modèle et d’en organiser la mise en commentaire.