23 août 2025·6 min de lecture

Créer une application d'inventaire avec des outils IA qui n'affiche jamais de stock négatif

Créez une application d'inventaire avec des outils IA et empêchez le stock négatif grâce à des règles simples de réception, vente et ajustement que vous pouvez tester avant déploiement.

Créer une application d'inventaire avec des outils IA qui n'affiche jamais de stock négatif

Ce que nous construisons et pourquoi le stock déconne

Quand on dit qu'une application d'inventaire est « fausse », cela signifie généralement une chose : le stock devient négatif. Une fois arrivé là, chaque rapport devient suspect. Vous ne savez plus si vous êtes en rupture, si vous avez survendu, ou si le chiffre vient juste d'une mauvaise mise à jour.

L'objectif n'est pas un ERP complet. C'est une petite application simple que vous pouvez exploiter pour une boutique ou un petit catalogue où le compte reste digne de confiance. Même si vous utilisez des outils IA pour générer des écrans et du code, les règles passent toujours en premier.

Limitez le système à trois actions :

  • Receive : le stock entre (livraison, retours en stock, stockage initial).
  • Sell : le stock sort (vente, expédition, ou tout usage sortant).
  • Adjust : le stock change parce que la réalité et le système divergent (dégâts, perte, recomptage).

« Correct » est facile à définir et à tester :

  • Le stock ne descend jamais en dessous de zéro pour aucun article.
  • Chaque changement a une raison et un timestamp.
  • Les totaux sont reproductibles : rejouez l'historique et vous obtenez le même nombre.
  • Tout chiffre est explicable en pointant les transactions qui l'ont créé.

Le stock foire généralement pour deux raisons :

  1. L'app modifie directement un champ « stock courant » au lieu d'enregistrer une transaction.

  2. Elle enregistre des transactions, mais oublie de vérifier ce qui est disponible au moment de la vente.

Un exemple rapide : vous avez 5 mugs. Deux personnes achètent 4 mugs chacune, à quelques minutes d'intervalle. Si votre app ne verrouille pas l'étape vérifier-et-décrémenter, les deux ventes peuvent passer le contrôle « en stock » et vous vous retrouvez à -3.

Le plus petit modèle de données qui fonctionne encore

Commencez par un modèle de données difficile à saboter. L'objectif principal est de rendre impossible l'édition directe du « nombre de stock ». Le stock disponible doit être un total calculé à partir d'un historique de changements.

Pour la plupart des petites apps d'inventaire, l'ensemble minimal est :

  • Product : ce que vous suivez (nom, SKU, indicateur actif).
  • Transaction : chaque changement de stock (receive, sell, adjust), avec quantité et timestamp.
  • Location (optionnel) : où le stock vit (entrepôt, magasin, véhicule). Ajoutez-le seulement si vous en avez besoin maintenant.
  • User (optionnel) : qui a créé la transaction.

Règle clé : ne stockez pas « stock on hand » comme un champ libre éditable. Calculez-le comme la somme de toutes les quantités de transaction pour ce produit (et la location, si vous utilisez des locations). Cela garde le chiffre explicable car chaque unité a une raison.

Une seule localisation maintenant, plusieurs plus tard

Si vous n'êtes pas sûr de gérer plusieurs emplacements, choisissez une voie sûre :

  • Single location v1 : pas de table Location, les totaux sont par produit.
  • Future-ready v1 : incluez Location et exigez location_id sur chaque transaction, mais démarrez avec une localisation par défaut.

Évitez la « location optionnelle » sur les transactions. Les valeurs nulles pour la location créent presque toujours des totaux confus plus tard.

IDs et timestamps dont vous dépendrez

Décidez-en dès le départ :

  • Utilisez des IDs uniques pour Product et Transaction.
  • Stockez created_at sur chaque transaction.
  • Gardez un effective_at séparé seulement si vous avez besoin de corrections rétroactives.
  • N'éditez pas les quantités en place. Ajoutez plutôt une nouvelle transaction corrective.

Exemple : si vous avez compté 10 unités hier mais que vous avez entré 8, n'écrasez pas 8 par 10. Ajoutez un ajustement de +2 avec une note.

Règles qui empêchent le stock d'aller en négatif

Les règles comptent plus que l'UI. La plupart des bugs de stock négatif arrivent parce que l'app « édite le nombre » au lieu d'enregistrer ce qui s'est passé.

Pensez l'inventaire comme un compte bancaire : vous ne le changez que par des transactions enregistrées, et vous n'autorisez jamais le solde à passer sous zéro.

Voici les règles qui portent l'essentiel du poids :

  • Le stock ne doit jamais être inférieur à zéro après application d'une transaction.
  • Chaque changement crée un enregistrement de transaction (pas d'éditions silencieuses).
  • Les quantités sont des nombres positifs ; le type de transaction décide ajout vs soustraction.
  • Tout ajustement nécessite une raison et l'identité de qui l'a fait.
  • Protégez contre deux actions simultanées.

Le nombre « on hand » n'est pas la source de vérité. L'historique des transactions l'est.

Ce que « pas de stock négatif » signifie en pratique

Avant d'enregistrer une transaction qui enlève des articles, l'app vérifie la quantité disponible pour cet article. Si la soustraction la ferait tomber en négatif, refusez-la (ou marquez-la en attente si vous supportez volontairement ce flux).

La concurrence est la sournoise. Deux personnes vendent la dernière unité en même temps. Les deux écrans affichent « 1 disponible », les deux cliquent sur Enregistrer, et vous vous retrouvez à -1 à moins que la base de données n'impose la vérification. Le pattern sûr est de lire le stock courant et d'écrire la transaction dans une même opération de base de données, ainsi une seule peut réussir.

Réception de stock : le flux le plus simple et sûr

La réception est là où vos chiffres commencent. Si vous enregistrez mal une livraison, chaque vente après cela semblera erronée.

Gardez le formulaire de réception petit pour que les gens l'utilisent réellement. Un minimum solide : produit, quantité et timestamp, plus une note optionnelle. Le coût et le fournisseur peuvent attendre sauf si vous savez en avoir besoin.

La validation doit être stricte et ennuyeuse : la quantité doit être supérieure à 0, le produit doit exister et le timestamp doit être enregistré. Si un contrôle échoue, ne mettez rien à jour.

À l'enregistrement, créez une transaction RECEIVE. Si vous maintenez aussi une valeur en cache pour le on-hand pour des raisons de performance, mettez-la à jour dans la même transaction de base de données pour éviter des chiffres désynchronisés.

Cas limite : réception en double

Les doublons surviennent quand quelqu'un double-clique sur Enregistrer ou réentère un reçu déjà saisi. Ne supprimez pas la vieille ligne. Corrigez avec de l'historique.

Exemple : vous vouliez recevoir 10 unités, mais cela a été entré deux fois. Ajoutez un ajustement inverse (ou une annulation si vous le supportez) qui soustrait 10 et référence le reçu erroné dans la note.

Vente de stock : contrôles qui empêchent la sur-vente

Prevent Double-Sell Errors
Stop two users selling the last unit by making the check-and-write step atomic.

La vente est l'endroit où les applis d'inventaire cassent généralement.

Pour chaque ligne de vente, capturez le produit (ou SKU), la quantité et le timestamp. Le prix et le client sont optionnels, mais une courte note peut aider plus tard quand quelqu'un demande « Pourquoi le stock a-t-il baissé ? »

Deux contrôles importent :

  • La quantité doit être supérieure à 0.
  • La quantité doit être inférieure ou égale au stock disponible au moment de la vente.

Si quelqu'un essaie de vendre 7 quand seulement 5 sont disponibles, bloquez-le. Affichez un message qui aide à agir, par exemple : « Only 5 available. Reduce quantity or receive stock first. » Évitez les erreurs vagues.

Mettre à jour le stock sans perdre l'historique

N'écrasez pas un champ « stock on hand » directement. Enregistrez une ligne de transaction pour la vente (un mouvement soustractif) lié au produit et à l'enregistrement de vente. Le stock on hand reste la somme de tous les mouvements.

Les précommandes peuvent attendre pour v1. Le choix le plus sûr au début est de ne pas les autoriser. Si vous devez les prendre en charge, gardez-les comme un statut séparé qui ne change pas le stock tant que les articles n'ont pas été expédiés.

Ajustements : corrections sans casser l'historique

Les ajustements servent la vie réelle : marchandises endommagées, vol, recomptage ou nettoyage de données après une importation. L'objectif est de corriger le nombre on-hand d'aujourd'hui sans prétendre que le passé n'a jamais existé.

La plupart des petites apps n'ont besoin que de deux styles d'ajustement :

  • Set-to : « Rendre le on-hand égal à X » (idéal après un comptage physique).
  • Delta : « Ajouter ou retirer N » (idéal pour un événement connu comme « -2 endommagés »).

Validez les ajustements comme tout autre mouvement de stock :

  • La valeur set-to doit être 0 ou plus.
  • Le delta peut être positif ou négatif, mais il ne doit pas faire passer le on-hand sous 0.
  • L'article et la location (si vous suivez des locations) doivent être sélectionnés.
  • L'heure de l'ajustement doit être enregistrée.

Rendez les ajustements traçables. Exigez une raison et l'utilisateur qui a fait le changement. Gardez les raisons courtes et cohérentes (recount, damage, theft, data cleanup), avec une note optionnelle.

Étape par étape : demander à un outil IA de le construire en sécurité

Si vous utilisez des outils IA pour construire l'app, soyez explicite sur ce que l'outil doit produire : un schéma de base de données, la logique serveur et quelques tests de base. Si vous ne demandez que des écrans, vous finirez souvent par appliquer les règles dans l'UI, ce qui est exactement la manière dont le stock négatif s'insinue.

Décrivez le modèle de données en anglais simple. Nommez les types de transaction (receive, sell, adjust) et ce que chacun doit stocker : article, quantité, timestamp, note. Demandez une table de transactions immuable et un moyen clair de calculer le stock courant à partir du grand livre.

Les règles doivent vivre sur le serveur

Demandez une validation côté serveur et précisez que l'UI n'est pas fiable.

Un ensemble de prompts utile (à adapter selon votre stack) :

  • "Generate DB tables for items and inventory_transactions. Transactions are append-only."
  • "Create one server function applyTransaction(type, itemId, qty, note) that validates and writes in a DB transaction."
  • "Rules: receive adds stock, sell subtracts stock but must not allow stock < 0, adjust can add or subtract but also must not allow stock < 0."
  • "Add API endpoints that call applyTransaction. UI is just a client and cannot bypass rules."
  • "Generate 3 seed items and 8 sample transactions that demonstrate a blocked oversell."

Demandez aussi une vue d'audit : une page qui montre la liste des transactions (les plus récentes en premier) et le stock courant à côté de chaque article. Cet écran est celui où vous repérez les anomalies rapidement.

Vérifications rapides avant de faire confiance aux chiffres

Put Rules Where They Belong
We move your inventory rules to the server so oversells get blocked every time.

Avant que de vrais utilisateurs ne l'utilisent, prouvez que les règles fonctionnent avec quelques tests simples. Les bugs d'inventaire se cachent jusqu'à la séquence exacte qui déclenche le problème.

Écrivez 5 à 10 cas de test en langage courant. Par exemple :

  • Receive 10, sell 3, confirmer que le on-hand est 7.
  • Tenter de vendre 8 quand seuls 7 sont disponibles, confirmer que c'est bloqué avec un message clair.
  • Receive 1, sell 1, puis sell 1 à nouveau, confirmer que la deuxième vente est bloquée.
  • Faire un recount (set-to) adjustment, confirmer que les calculs et l'historique restent cohérents.

Puis testez « deux ventes en même temps » pour le même article. Ouvrez l'article dans deux onglets (ou deux appareils) et tentez de vendre la dernière unité presque simultanément. Vous devriez voir une vente réussir et l'autre échouer.

Les messages clairs comptent. « Cannot sell: only 2 available » est utile. « Error 500 » ne l'est pas.

Enfin, décidez de votre politique d'annulation. Choisissez-en une et tenez-vous-y :

  • Soft delete (masquer une transaction, la garder pour l'audit), ou
  • Transactions de reversal (ajouter une entrée opposée pour annuler), souvent plus sûr.

Erreurs courantes qui causent quand même du stock négatif

La plupart des problèmes de stock négatif ne sont pas des erreurs de calcul. Ils viennent de raccourcis qui ont l'air corrects dans une démo, puis s'effondrent dès que deux personnes utilisent l'app.

Le piège le plus grand est de traiter « stock on hand » comme un seul nombre éditable. C'est simple en apparence, mais cela supprime la chose dont vous aurez besoin plus tard : une histoire claire de la façon dont le nombre a changé.

Les récidivistes :

  • Garder le stock comme champ éditable sans journal de transactions.
  • Valider uniquement dans le frontend.
  • Ignorer la concurrence.
  • Permettre des ajustements négatifs « temporaires ».
  • Pas de trace d'audit quand quelqu'un demande pourquoi un article affiche -3.

Un petit scénario montrant l'échec : vous avez 5 unités. Deux employés vendent chacun 3 en même temps. Si votre app vérifie « stock >= 3 » dans le navigateur, les deux écrans voient 5 et passent. Chacun écrit sa mise à jour et vous finissez à -1. Corrigez cela en faisant appliquer la règle côté serveur et en rendant la vérification et l'écriture atomiques.

Un autre problème facile à manquer est de mélanger les éditions produit (nom, SKU, prix) et les éditions de stock sur le même formulaire. Cela incite aux modifications accidentelles du stock et à des totaux difficiles à expliquer.

Scénario d'exemple : un article de la livraison à la vente puis au recomptage

Make the Ledger Trustworthy
FixMyMess cleans up spaghetti logic so inventory math stays explainable and testable.

Imaginez une petite boutique avec une localisation et trois articles : Coffee Beans (sac 1 lb), Paper Filters et Oat Milk. Suivez un seul article, Coffee Beans.

Début de journée : on hand = 0.

Une app d'inventaire sûre stocke une liste de transactions et calcule le nombre courant à partir de cet historique.

Voici la journée avec un solde courant :

  • Receive +10 : on hand passe de 0 à 10.
  • Sell -3 : on hand passe de 10 à 7.
  • Adjust -2 (damage) : on hand passe de 7 à 5.
  • Tentative de vente -6 : l'app la bloque parce que 5 - 6 ferait -1.

Quand la caissière tente cette dernière vente, l'app doit l'arrêter avant d'enregistrer quoi que ce soit. Gardez le message simple : "Not enough stock. You have 5, trying to sell 6." L'important est que la vérification ait lieu au moment de la transaction.

Puis le recomptage : quelqu'un compte 5 sacs, ce qui correspond au solde. Rien n'a besoin d'être « corrigé » parce que le grand livre explique déjà le chiffre : un reçu, une vente, un ajustement pour dommage.

Étapes suivantes : livrer le v1, puis le durcir pour production

Une fois que v1 peut recevoir, vendre et ajuster sans laisser le stock devenir négatif, déployez-le à un petit groupe et utilisez-le pour de vraies commandes. Vous apprendrez plus en une semaine d'usage réel qu'avec une autre série d'écrans générés.

N'ajoutez que ce que les utilisateurs demandent réellement. Les étapes courantes sont : multi-locations, rôles simples pour que tout le monde ne puisse pas ajuster le stock, import CSV pour l'inventaire de départ, alertes de faible stock et quelques rapports de base.

Puis faites un passage de durcissement court. C'est là que les prototypes échouent souvent : authentification, secrets exposés et validation incohérente.

Une checklist simple :

  • Authentification qui bloque vraiment l'accès (pas seulement des boutons cachés).
  • Secrets hors du navigateur et du dépôt.
  • Validation des entrées sur quantités, SKUs et IDs.
  • Messages d'erreur clairs et journaux d'audit pour chaque mouvement de stock.
  • Vérifications de sécurité basiques contre les injections courantes et les failles de permission.

Si vous avez déjà un prototype généré par IA qui se comporte mal (stock négatif, validations uniquement dans l'UI, logique métier éparpillée), FixMyMess (fixmymess.ai) peut aider en audité le code et en déplaçant les règles dans un flux de transaction unique et exécutable. Un point de départ pratique est leur audit de code gratuit, qui cartographie les problèmes avant que vous décidiez quoi réparer ou reconstruire.

Questions Fréquentes

Why does stock go negative even when my math seems right?

Le stock négatif arrive généralement quand on met à jour un seul champ “stock courant” directement, ou quand on enregistre des transactions mais qu'on n'applique pas de contrôle « disponible maintenant » au moment de la vente. La solution la plus sûre est de traiter l'inventaire comme un grand livre : chaque changement est une transaction, et toute transaction qui ferait tomber le stock sous zéro est rejetée côté serveur.

What’s the smallest database schema that still works for inventory?

Commencez avec une table products et une table append-only inventory_transactions. Chaque transaction doit inclure l'ID du produit, le type (receive, sell, adjust), la quantité, le timestamp et un champ note/raison pour que chaque modification soit explicable plus tard.

Should I store a “stock_on_hand” field on the product?

Non, pas comme source de vérité. Calculez le “on hand” à partir de l'historique des transactions pour pouvoir rejouer le grand livre et toujours obtenir la même réponse, et pour que chaque unité soit traçable à une raison.

How do I prevent two people from selling the last item at the same time?

Faites la lecture et l'écriture dans une seule transaction de base de données afin que deux ventes ne puissent pas toutes deux réussir la vérification “en stock”. Si vous vérifiez dans le navigateur puis écrivez plus tard, deux personnes peuvent sur-vendre la dernière unité même si les deux écrans affichaient correctement la disponibilité.

What validations should I enforce when receiving stock?

Rendez la réception ennuyeuse et stricte : quantité supérieure à zéro, le produit doit exister et le timestamp doit être enregistré. À l'enregistrement, écrivez une transaction RECEIVE et n'éditez pas les lignes précédentes afin que l'historique reste propre.

What should I do if someone accidentally receives the same shipment twice?

Ne supprimez pas l'entrée d'origine ni ne l'éditez discrètement. Ajoutez une transaction corrective qui inverse l'erreur et référence ce qui s'est passé dans la note afin que vous puissiez comprendre la trace d'audit plus tard.

Should v1 allow backorders or selling into negative stock?

Par défaut, bloquez-la. Quand quelqu'un essaie de vendre plus que ce qui est disponible, rejetez la transaction et affichez un message clair comme « Only 5 available » pour que l'utilisateur réduise la quantité ou enregistre la réception d'abord.

When should I use an adjustment instead of editing or deleting a transaction?

Utilisez les ajustements pour la réalité : dommages, pertes, recomptes ou nettoyage de données importées. Privilégiez un ajustement “set-to” après un comptage physique et un ajustement “delta” pour des événements connus, et exigez toujours une raison et l'utilisateur qui l'a effectué.

How do I prompt an AI tool so it doesn’t build an inventory app that breaks?

Demandez au modèle IA des règles côté serveur et une table de transactions append-only, pas seulement des écrans. Faites-lui générer une fonction centrale qui valide et écrit les mouvements d'inventaire, et ajoutez quelques tests prouvant qu'une sur-vente est bloquée et que le grand livre se rejoue correctement.

How do I know my AI-generated inventory prototype is unsafe, and what can I do?

Recherchez des règles métier appliquées uniquement dans l'UI, une logique dispersée sur plusieurs pages, des champs de stock éditables, des timestamps manquants et pas de vue d'audit claire. Si vous avez hérité d'un prototype généré par IA avec ces problèmes, FixMyMess peut réaliser un audit de code gratuit et consolider les règles en un flux de transaction unique et exécutable pour que les chiffres tiennent en production.