23. Aug. 2025·5 Min. Lesezeit

Baue eine Inventar-App mit KI‑Tools, die nie negativen Bestand hat

Baue eine Inventar‑App mit KI‑Tools und verhindere negativen Bestand mit einfachen Regeln für Empfangen, Verkaufen und Anpassen, die du vor dem Deployment testen kannst.

Baue eine Inventar-App mit KI‑Tools, die nie negativen Bestand hat

Was wir bauen und warum Bestand schiefgeht

Wenn Leute sagen, eine Inventar‑App sei "falsch", meinen sie meist eins: der Bestand wird negativ. Sobald das passiert, ist jeder Bericht fragwürdig. Du weißt nicht mehr, ob ein Artikel ausverkauft ist, ob du überverkauft hast, oder ob die Zahl einfach das Ergebnis eines schlechten Updates ist.

Das Ziel ist kein komplettes ERP. Es ist eine kleine, schlichte App für einen Laden oder einen kleinen Katalog, bei der die Bestandszahl vertrauenswürdig bleibt. Auch wenn du KI‑Tools nutzt, um Bildschirme oder Code zu generieren: die Regeln stehen zuerst.

Halte das System bei drei Aktionen:

  • Empfangen (Receive): Ware kommt rein (Lieferung, Rücksendung, Erstbestand).
  • Verkaufen (Sell): Ware geht raus (Verkauf, Versand oder sonstige Entnahme).
  • Anpassen (Adjust): Bestand ändern, weil Realität und System nicht übereinstimmen (Schaden, Verlust, Nachzählung).

„Korrekt" ist einfach zu definieren und zu testen:

  • Der Bestand fällt nie unter null für einen Artikel.
  • Jede Änderung hat einen Grund und einen Zeitstempel.
  • Gesamtsummen sind reproduzierbar: spiele die Historie ab und du erhältst dieselbe Zahl.
  • Jede Zahl lässt sich durch die Transaktionen erklären, die sie erzeugt haben.

Bestand geht aus zwei Gründen schief:

  1. Die App ändert ein Feld „aktueller Bestand“ direkt anstatt eine Transaktion zu protokollieren.

  2. Sie protokolliert Transaktionen, prüft aber beim Verkauf nicht, was gerade verfügbar ist.

Ein kurzes Beispiel: du hast 5 Tassen. Zwei Personen kaufen je 4 Tassen, Minuten auseinander. Wenn deine App den Prüf‑und‑Verringerungs‑Schritt nicht sperrt, können beide Verkäufe den „auf Lager“-Check bestehen und du landest bei -3.

Das kleinstmögliche Datenmodell, das trotzdem funktioniert

Starte mit einem Datenmodell, das schwer zu verhunzen ist. Das Hauptziel ist, es unmöglich zu machen, die "Bestandszahl" direkt zu bearbeiten. Der Bestand sollte eine Summe aus einer Historie von Änderungen sein.

Für die meisten kleinen Inventar‑Apps ist das Minimum:

  • Product: was du verfolgst (Name, SKU, active‑Flag).
  • Transaction: jede Bestandsänderung (receive, sell, adjust) mit Menge und Zeitstempel.
  • Location (optional): wo der Bestand liegt (Lager, Filiale, Pkw). Nur hinzufügen, wenn du es jetzt brauchst.
  • User (optional): wer die Transaktion erstellt hat.

Eine wichtige Regel: speichere den "stock on hand" nicht als freieditierbares Feld. Berechne ihn als Summe aller Transaktionsmengen für dieses Produkt (und Location, falls verwendet). So bleibt die Zahl erklärbar, weil jede Einheit einen Grund hat.

Einzelner Standort jetzt, mehrere später

Wenn du unsicher bist, ob du mehrere Standorte brauchst, nimm folgenden sicheren Weg:

  • Single location v1: keine Location‑Tabelle, Summen sind pro Produkt.
  • Future-ready v1: Location einschließen und location_id auf jeder Transaktion verlangen, aber mit einem Standardstandort starten.

Vermeide "optionalen Standort" auf Transaktionen. Null‑Location‑Werte führen später fast immer zu verwirrenden Summen.

IDs und Zeitstempel, auf die du dich verlassen wirst

Entscheide das früh:

  • Verwende eindeutige IDs für Product und Transaction.
  • Speichere created_at auf jeder Transaktion.
  • Behalte ein separates effective_at nur, wenn du Nachdatierungen brauchst.
  • Bearbeite Mengen nicht direkt. Füge stattdessen eine neue korrigierende Transaktion hinzu.

Beispiel: Du hast gestern 10 gezählt, aber 8 eingetragen — überschreibe 8 nicht zu 10. Füge eine Adjustment +2 mit einer Notiz hinzu.

Regeln, die Inventar vor negativen Beständen schützen

Die Regeln sind wichtiger als die UI. Die meisten negativen‑Bestand‑Bugs entstehen, weil die App die Zahl direkt ändert anstatt aufzuzeichnen, was passiert ist.

Denk an Inventar wie an ein Bankkonto: du änderst es nur über aufgezeichnete Transaktionen, und du erlaubst nie, dass der Kontostand unter null fällt.

Hier sind die Regeln, die den größten Teil der Arbeit leisten:

  • Bestand darf nach dem Anwenden einer Transaktion niemals unter null liegen.
  • Jede Änderung erzeugt einen Transaktionsdatensatz (keine stillen Edits).
  • Mengen sind positive Zahlen; der Transaktionstyp entscheidet add vs subtract.
  • Jede Anpassung braucht einen Grund und den Namen des Erstellers.
  • Schütze gegen zwei gleichzeitig ablaufende Aktionen (Concurrency).

Die "on hand"‑Zahl ist nicht die Quelle der Wahrheit. Die Transaktionshistorie ist es.

Was „kein negativer Bestand“ in der Praxis bedeutet

Bevor du eine entnehmende Transaktion speicherst, prüft die App den aktuellen On‑Hand‑Wert für den Artikel. Wenn die Entnahme ihn negativ machen würde, lehne sie ab (oder markiere sie als ausstehend, wenn du diesen Ablauf bewusst unterstützt).

Nebenläufigkeit ist der hinterhältige Faktor. Zwei Personen verkaufen zur selben Zeit die letzte Einheit. Beide Bildschirme zeigen "1 verfügbar", beide drücken Speichern, und du landest bei -1, wenn die Datenbank die Prüfung nicht durchsetzt. Das sichere Muster ist, aktuellen Bestand zu lesen und die Transaktion in einer einzigen Datenbank‑Operation zu schreiben, sodass nur eine Transaktion erfolgreich sein kann.

Wareneingang: der einfachste sichere Workflow

Der Wareneingang ist die Grundlage. Wenn du eine Lieferung falsch erfasst, sehen alle nachfolgenden Verkäufe falsch aus.

Halte das Erfassungsformular klein, damit Leute es wirklich nutzen. Ein solides Minimum ist Produkt, Menge und Zeitstempel plus eine optionale Notiz. Kosten und Lieferant können warten, bis du sicher weißt, dass du sie brauchst.

Die Validierung sollte streng und langweilig sein: Menge > 0, das Produkt muss existieren und der Zeitstempel muss gesetzt werden. Wenn eine Prüfung fehlschlägt, aktualisiere nichts.

Beim Speichern erstelle eine RECEIVE‑Transaktion. Wenn du aus Performance‑Gründen einen gecachten On‑Hand‑Wert pflegst, aktualisiere diesen im selben DB‑Transaction‑Block, damit Zahlen nicht auseinanderlaufen.

Randfall: doppelte Wareneingänge

Duplikate entstehen, wenn jemand doppelt auf Speichern klickt oder einen bereits erfassten Beleg erneut eingibt. Lösche die alte Zeile nicht. Korrigiere mit Historie.

Beispiel: Du wolltest 10 empfangen, es wurde aber zweimal eingetragen. Füge eine rückwirkende Adjustment‑Transaktion (oder einen Void, wenn unterstützt) hinzu, die 10 abzieht und in der Notiz auf den fehlerhaften Beleg verweist.

Verkauf: Prüfungen, die Überverkäufe verhindern

Doppelte Verkäufe verhindern
Verhinder, dass zwei Nutzer dieselbe letzte Einheit verkaufen, indem Check-und-Write atomar gemacht werden.

Verkauf ist der Punkt, an dem Inventar‑Apps meist kaputtgehen.

Für jede Verkaufszeile erfasse Produkt (oder SKU), Menge und Zeitstempel. Preis und Kunde sind optional, aber eine kurze Notiz hilft später, wenn jemand fragt: "Warum ist der Bestand gesunken?"

Zwei Prüfungen sind wichtig:

  • Menge muss größer als 0 sein.
  • Menge muss kleiner oder gleich dem verfügbaren Bestand im Moment des Verkaufs sein.

Wenn jemand 7 verkaufen will, aber nur 5 verfügbar sind, blockiere das. Zeige eine hilfreiche Meldung wie: "Nur 5 verfügbar. Menge reduzieren oder zuerst Nachschub buchen." Vermeide vage Fehlermeldungen.

Bestand aktualisieren, ohne Historie zu verlieren

Überschreibe niemals direkt ein "stock on hand"‑Feld. Lege eine Transaktionszeile für den Verkauf an (eine subtrahierende Bewegung), verknüpft mit dem Produkt und dem Verkaufsbeleg. Der On‑Hand‑Wert bleibt die Summe aller Bewegungen.

Backorders können für v1 warten. Die sicherste frühe Wahl ist, sie nicht zu erlauben. Wenn du sie unterstützen musst, behalte sie als separaten Status, der den Bestand erst bei Versand ändert.

Adjustments: Korrekturen ohne die Historie zu zerstören

Adjustments sind für die reale Welt: beschädigte Waren, Diebstahl, Nachzählung oder das Bereinigen fehlerhafter Importdaten. Ziel ist, den aktuellen On‑Hand‑Wert zu korrigieren, ohne so zu tun, als wäre die Vergangenheit nie geschehen.

Die meisten kleinen Apps brauchen nur zwei Anpassungsarten:

  • Set‑to: "Setze den Bestand auf X" (am besten nach einer physischen Zählung).
  • Delta: "Addiere oder subtrahiere N" (am besten für ein bekanntes Ereignis wie "-2 beschädigt").

Validiere Adjustments wie jede andere Bestandsbewegung:

  • Set‑to‑Wert muss 0 oder größer sein.
  • Delta kann positiv oder negativ sein, darf den On‑Hand‑Wert aber nicht unter 0 drücken.
  • Artikel und Standort (falls verwendet) müssen ausgewählt sein.
  • Die Zeit der Anpassung sollte aufgezeichnet werden.

Mach Anpassungen rechenschaftspflichtig. Fordere einen Grund und den verantwortlichen Nutzer. Halte Gründe kurz und konsistent (recount, damage, theft, data cleanup) mit einer optionalen Notiz.

Schritt‑für‑Schritt: ein AI‑Tool so anweisen, dass es sicher baut

Wenn du AI‑Tools nutzt, um die App zu bauen, sei explizit, was das Tool liefern muss: ein Datenbankschema, Serverlogik und ein paar einfache Tests. Wenn du nur nach Bildschirmen fragst, endest du oft damit, Regeln nur in der UI durchzusetzen — und genau so schleicht sich negativer Bestand ein.

Beschreibe das Datenmodell in klarem, einfachem Deutsch. Benenne die Transaktionstypen (receive, sell, adjust) und was jede speichern muss: Artikel, Menge, Zeitstempel, Notiz. Bitte um eine immutable Transaktionen‑Tabelle und eine klare Art, den aktuellen Bestand aus dem Ledger zu berechnen.

Regeln gehören auf den Server

Fordere serverseitige Validierung und mache deutlich, dass die UI nicht vertraut werden darf.

Eine nützliche Prompt‑Sammlung (an dein Stack anpassen):

  • "Erzeuge DB‑Tabellen für items und inventory_transactions. Transactions sind append‑only."
  • "Erstelle eine Serverfunktion applyTransaction(type, itemId, qty, note), die validiert und in einer DB‑Transaktion schreibt."
  • "Regeln: receive addiert Bestand, sell subtrahiert Bestand darf aber stock < 0 nicht zulassen, adjust kann addieren oder subtrahieren, darf stock < 0 ebenfalls nicht zulassen."
  • "Füge API‑Endpunkte hinzu, die applyTransaction aufrufen. Die UI ist nur Client und darf Regeln nicht umgehen."
  • "Generiere 3 Seed‑Items und 8 Beispieltransaktionen, die einen geblockten Überverkauf demonstrieren."

Bitte außerdem um eine Audit‑Ansicht: eine Seite, die die Transaktionsliste (neueste zuerst) und den aktuellen Bestand neben jedem Artikel zeigt. Dieser Bildschirm ist der Ort, an dem du Unregelmäßigkeiten schnell erkennst.

Schnelle Prüfungen, bevor du den Zahlen vertraust

Sicher ausliefern
Wir schließen exponierte Secrets, schwache Authentifizierung und unsichere Eingaben, bevor deine Prototype live geht.

Bevor echte Nutzer die App verwenden, beweise mit ein paar einfachen Tests, dass die Regeln funktionieren. Inventarfehler verstecken sich, bis genau die falsche Abfolge passiert.

Schreibe 5–10 Testfälle in einfacher Sprache. Zum Beispiel:

  • Empfange 10, verkaufe 3, bestätige On‑Hand ist 7.
  • Versuche 8 zu verkaufen, wenn nur 7 verfügbar sind, bestätige, dass es blockiert und eine klare Meldung erscheint.
  • Empfange 1, verkaufe 1, dann verkaufe 1 noch einmal, bestätige, dass der zweite Verkauf blockiert wird.
  • Mach eine Nachzählung (set‑to) Adjustment, bestätige, dass Mathematik und Historie weiterhin Sinn ergeben.

Teste dann "zwei Verkäufe gleichzeitig" für denselben Artikel. Öffne den Artikel in zwei Tabs (oder auf zwei Geräten) und versuche, nahezu gleichzeitig die letzte Einheit zu verkaufen. Eine Operation sollte erfolgreich sein, die andere scheitern.

Klare Meldungen sind wichtig. "Kann nicht verkaufen: nur 2 verfügbar" hilft. "Error 500" nicht.

Zum Schluss: Entscheide deine Undo‑Policy. Triff eine Wahl und halte dich daran:

  • Soft delete (Transaktion ausblenden, aber für Audit behalten), oder
  • Reversal‑Transaktionen (gegenteilige Einträge hinzufügen), was oft sicherer ist.

Häufige Fehler, die trotzdem zu negativem Bestand führen

Die meisten negativen Bestandsprobleme sind keine Rechenfehler. Sie entstehen durch Abkürzungen, die in einer Demo harmlos aussehen, aber scheitern, sobald zwei Leute die App nutzen.

Die größte Falle ist, "stock on hand" als ein editierbares Einzelwert zu behandeln. Das wirkt einfach, nimmt dir aber später die eine Sache weg, die du brauchst: eine klare Geschichte, wie sich die Zahl verändert hat.

Wiederkehrende Fehler:

  • Bestand als editierbares Feld ohne Transaktionslog pflegen.
  • Validierung nur im Frontend durchführen.
  • Nebenläufigkeit ignorieren.
  • Temporäre negative Anpassungen erlauben.
  • Keine Audit‑Spur, wenn jemand fragt, warum ein Artikel -3 anzeigt.

Ein kleines Szenario, das das Versagen zeigt: Du hast 5 Einheiten. Zwei Mitarbeiter verkaufen gleichzeitig je 3. Wenn deine App im Browser nur "stock >= 3" prüft, sehen beide 5 und bestehen die Prüfung. Jeder schreibt sein Update und du landest bei -1. Löse das, indem du die Regel auf dem Server durchsetzt und Prüfung plus Schreiben atomar machst.

Ein weiterer leicht zu übersehender Punkt ist, Produkt‑Edits (Name, SKU, Preis) und Bestand‑Edits im selben Formular zu mischen. Das lädt zu versehentlichen Bestandsänderungen und schwer erklärbaren Summen ein.

Beispiel‑Szenario: ein Artikel von Lieferung bis Verkauf und Nachzählung

Produktionsreif werden
Mach aus einer Demo eine produktionsreife App mit sauberer Struktur und Deployment-Vorbereitung.

Stell dir einen kleinen Laden mit einem Standort und drei Artikeln vor: Coffee Beans (1 lb bag), Paper Filters und Oat Milk. Folge nur einem Artikel, Coffee Beans.

Anfang des Tages: on hand = 0.

Eine sichere Inventar‑App speichert eine Transaktionsliste und berechnet die aktuelle Zahl aus dieser Historie.

So verläuft der Tag mit laufendem Saldo:

  • Receive +10: on hand geht von 0 auf 10.
  • Sell -3: on hand geht von 10 auf 7.
  • Adjust -2 (damage): on hand geht von 7 auf 5.
  • Versuch, -6 zu verkaufen: die App blockiert, weil 5 - 6 = -1 wäre.

Wenn der Kassierer den letzten Verkauf versucht, soll die App ihn stoppen, bevor etwas gespeichert wird. Halte die Meldung einfach: "Nicht genug Bestand. Du hast 5, versuchst 6 zu verkaufen." Wichtig ist, dass die Prüfung im Moment der Transaktion passiert.

Bei der Nachzählung zählt jemand 5 Beutel, was mit dem Saldo übereinstimmt. Es muss nichts "korrigiert" werden, weil das Ledger die Zahl bereits erklärt: ein Wareneingang, ein Verkauf, eine Schadensanpassung.

Nächste Schritte: v1 ausliefern und dann härten

Sobald v1 Empfangen, Verkaufen und Anpassen kann, ohne negativen Bestand zuzulassen, liefere sie an eine kleine Gruppe aus und nutze sie für echte Bestellungen. Du lernst in einer Woche echter Nutzung mehr als bei einer weiteren Runde generierter Bildschirme.

Füge nur hinzu, was Nutzer wirklich verlangen. Übliche nächste Schritte sind mehrere Standorte, einfache Rollen, damit nicht jeder anpassen darf, CSV‑Import für Startbestände, Low‑Stock‑Warnungen und ein paar Basisberichte.

Dann mach eine kurze Härtungsrunde. Hier scheitern Prototypen oft: Authentifizierung, exponierte Secrets und inkonsistente Validierung.

Eine einfache Checkliste:

  • Authentifizierung, die wirklich Zugang blockiert (nicht nur Buttons verstecken).
  • Secrets aus dem Browser und dem Repo fernhalten.
  • Eingabevalidierung für Mengen, SKUs und IDs.
  • Klare Fehlermeldungen und Audit‑Logs für jede Bestandsbewegung.
  • Grundlegende Security‑Checks für übliche Injection‑ und Permission‑Lücken.

Wenn du bereits einen AI‑generierten Prototyp hast, der merkwürdig ist (negativer Bestand, Validierungen nur in der UI oder Geschäftslogik über viele Seiten verteilt), kann FixMyMess (fixmymess.ai) helfen, indem sie den Code auditieren und die Regeln in einen einzigen, durchsetzbaren Transaktionsfluss verlagern. Ein praktischer Startpunkt ist ihre kostenlose Codeprüfung, die die Probleme kartiert, bevor du entscheidest, was du reparierst oder neu aufbaust.

Häufige Fragen

Warum wird der Bestand negativ, obwohl die Rechnung richtig aussieht?

Negativen Bestand bekommst du meist, wenn du ein einzelnes „aktuelles Bestands“-Feld direkt aktualisierst oder wenn du zwar Transaktionen aufzeichnest, aber beim Verkauf nicht prüfst, was gerade verfügbar ist. Die sicherste Lösung ist, Inventar wie ein Ledger zu behandeln: jede Änderung ist eine Transaktion, und jede Transaktion, die den Bestand unter null bringen würde, wird auf dem Server abgelehnt.

Was ist das kleinste Datenbankschema, das für Inventar funktioniert?

Starte mit einer products-Tabelle und einer append-only inventory_transactions-Tabelle. Jede Transaktion sollte Produkt-ID, Typ (receive, sell, adjust), Menge, Zeitstempel und ein Notiz-/Grund-Feld enthalten, damit jede Änderung später erklärbar ist.

Sollte ich ein Feld „stock_on_hand“ in der Produkt-Tabelle speichern?

Nein — nicht als Quelle der Wahrheit. Berechne den aktuellen Bestand aus der Transaktionshistorie, damit du das Ledger wieder abspielen kannst und jede Einheit auf einen Grund zurückgeführt werden kann.

Wie verhindere ich, dass zwei Personen gleichzeitig die letzte Einheit verkaufen?

Mach die Prüfung und das Schreiben in einer einzigen Datenbanktransaktion, sodass zwei Verkäufe nicht beide die Prüfung "auf Lager" bestehen können. Wenn die App im Browser prüft und später schreibt, können zwei Leute dennoch die letzte Einheit überverkaufen, selbst wenn beide Bildschirme korrekt aussehen.

Welche Validierungen sollte ich beim Wareneingang durchsetzen?

Halte das Erfassen schlicht und strikt: Menge muss größer als 0 sein, das Produkt muss existieren und ein Zeitstempel muss gesetzt werden. Beim Speichern schreibe eine RECEIVE-Transaktion und bearbeite vorherige Zeilen nicht, damit die Historie sauber bleibt.

Was mache ich, wenn jemand dieselbe Lieferung versehentlich doppelt erfasst?

Lösche den ursprünglichen Eintrag nicht und ändere ihn nicht heimlich. Füge eine korrigierende Transaktion hinzu, die den Fehler rückgängig macht, und verweise in der Notiz auf den missglückten Beleg, damit die Audit-Spur erhalten bleibt.

Sollte v1 Rückbestellungen oder Verkäufe in den negativen Bestand erlauben?

Standardmäßig blockieren. Wenn jemand mehr verkaufen will, als verfügbar ist, lehne die Transaktion ab und zeige eine klare Meldung wie „Nur 5 verfügbar“, damit der Nutzer Menge reduzieren oder zuerst Nachschub buchen kann.

Wann soll ich eine Adjustment-Transaktion statt einer Bearbeitung oder Löschung verwenden?

Verwende Anpassungen für die Realität: Schaden, Diebstahl, Nachzählung oder Bereinigung importierter Daten. Bevorzuge nach einer physischen Zählung eine „set-to“-Anpassung und für bekannte Ereignisse eine „delta“-Anpassung. Immer Grund und ausführenden Nutzer erfassen.

Wie frage ich ein AI-Tool an, damit es keine kaputte Inventar-App baut?

Fordere vom AI-Tool serverseitige Regeln und eine append-only Transaktionstabelle, nicht nur Bildschirme. Lass eine zentrale Funktion erzeugen, die Validierung und Schreiben der Inventarbewegungen übernimmt, und füge ein paar Tests hinzu, die zeigen, dass ein Überverkauf blockiert wird und das Ledger korrekt wiederholbar ist.

Woran erkenne ich, dass mein AI-generierter Inventarprototyp unsicher ist, und was kann ich tun?

Achte auf Business-Regeln, die nur in der UI durchgesetzt werden, verstreute Logik auf Seiten, editierbare Bestandsfelder, fehlende Zeitstempel und keine klare Audit‑Ansicht der Transaktionen. Wenn du so ein AI‑Prototyp geerbt hast, kann FixMyMess eine kostenlose Code‑Prüfung durchführen und die Regeln in einen einzigen, durchsetzbaren Transaktionsfluss konsolidieren.