TailorFitWMS — Warehouse-Management-System

Ein maßgeschneidertes Lagersystem für Cookinglife: von Auftragsannahme und Kommissionierung bis zu Bestandsführung, Versandlabels und NetSuite-ERP-Synchronisation — seit fast zwei Jahren durchgehend im Produktivbetrieb und in der Wartung.

Lagerverwaltung
PHP-→-Laravel-Migration
NetSuite ERP
Multi-Carrier-Versand

Rolle & Umfang

Cookinglife (ein Webshop für Küchenartikel mit angeschlossenen Ladengeschäften) wickelt den gesamten Lagerprozess über ein System ab, das ich gebaut habe und seitdem weiterentwickle: Auftragsannahme, Kommissionierung (einzeln, Batch, Trolley und mehrstufig), Bestands- und Lagerplatzverwaltung, Packen, Versandlabels und Synchronisation mit NetSuite als ERP. Neben der laufenden Wartung wird das bestehende PHP-Platform Modul für Modul nach Laravel migriert, ohne Ausfallzeit.

  • Von der Auftragsannahme bis zum Versand: ein System für den gesamten Fulfilment-Prozess, angebunden an NetSuite als Source of Truth für Aufträge und Bestand.
  • Mehrere Kommissioniermethoden (einzeln, Batch, Trolley, mehrstufig) und Barcode-Scanning auf der Fläche über OnScan.js.
  • Multi-Carrier-Versandlabels über Sendcloud, mit einem eigenen Sweep-Job, der Labels abholt, sobald NetSuite sie nach dem Status "packed" erzeugt hat.
  • Anbindungen an Shopify und Magento sowie Adress- und Telefonnummern-Normalisierung über Alumio.
  • Zero-Downtime-Migration nach Laravel: Modul für Modul (Aufträge, Kommissionierung, Bestand, Versand, NetSuite, Admin) über nginx-Routing, mit sofortigem Rollback je Modul.
Live-Plattform ansehen

Wirkung

  • Ein System für den kompletten Fulfilment-Prozess statt einzelner Werkzeuge für Kommissionierung, Bestand und Versand.
  • Ein struktureller NetSuite-Fehler bei Kit-Aufträgen (Produkte aus mehreren Komponenten) wurde behoben, indem Bestand automatisch über mehrere Lagerplätze alloziert wird, statt alles auf einem einzigen Platz zu verlangen.
  • Eine Race Condition zwischen dem Erzeugen und dem Abholen von Versandlabels wurde mit einem wiederkehrenden Sync-Job beseitigt, sodass Labels nicht mehr gelegentlich verloren gingen.
  • Ein Backup-Versandweg für Ausfälle des WMS außerhalb der Geschäftszeiten, mit Abgleich, damit Aufträge nicht doppelt in der Pick-Queue landen.
  • Seit fast zwei Jahren durchgehend produktiv (848 Commits seit August 2024) — kein Greenfield-Projekt, sondern ein System, das mit dem Unternehmen mitwächst.

Architektur

Drei Schichten: ein gemeinsamer Core, das TailorFitWMS-Modul selbst und kundenspezifische Overwrites — damit firmenspezifische Anpassungen nicht im Kern landen. Funktionalität ist als Plugin-Module aufgebaut, die pro Unternehmen ein- oder ausgeschaltet werden können, mit event-getriebenen Erweiterungspunkten. Daten liegen in MySQL (transaktionale Daten), MongoDB (Dokumente) und Redis (Caching und Sessions); Hintergrundarbeit (Label-Sync, NetSuite-Tasks) läuft über Laravel Horizon, mit 100 bis 500 Jobs pro Stunde. Die laufende Migration des bestehenden PHP-Platforms nach Laravel erfolgt Modul für Modul über nginx-Location-Blöcke, sodass jeder Teil separat ausgerollt und zurückgerollt werden kann, ohne den Rest zu berühren.

Modellwahl

Keine KI/LLM im Kern dieser Plattform — Fulfilment-Logik (Bestand, Kommissionierung, Versand, ERP-Synchronisation) verlangt Vorhersagbarkeit und Nachvollziehbarkeit, nicht die Flexibilität eines Sprachmodells. Die wichtigste "Modellwahl" ist hier architektonisch, nicht KI-bezogen: der Wechsel vom bestehenden eigenen PHP-Framework zu Laravel für ein größeres Tooling-Ökosystem und bessere Wartbarkeit, aber schrittweise und Modul für Modul statt als Big-Bang-Rewrite, um das Risiko für ein System zu begrenzen, das rund um die Uhr ein Lager steuert.

Kosten & Latenz

  • Die Produktivumgebung läuft auf 5 Docker-Services mit je 8 CPU / 8 GB — eine Dimensionierung, die zu einem System passt, das laufend Auftrags- und NetSuite-Verkehr verarbeitet, nicht nur zu Spitzenlast.
  • Versandlabels sind bewusst asynchron: NetSuite erzeugt das Label erst nach dem Status "packed", das System muss also nicht warten — ein Sweep-Job holt Labels alle 3 Minuten ab, statt pro Auftrag zu pollen.
  • Die NetSuite-Integration (OAuth1 TBA, SOAP + RESTlet + REST) ist das langsamere Glied in der Kette; lokale Lageraktionen wie Scannen und Kommissionieren laufen davon unabhängig weiter.

Lessons learned

Kit-Aufträge (Produkte aus mehreren Komponenten) scheiterten immer wieder an NetSuites Fehler VALID_LINE_ITEM_REQD, weil der Bestand der Komponenten über mehrere Lagerplätze verteilt war, NetSuite aber einen Platz pro Zeile erwartete. Gelöst durch ein Rewrite der RESTlet-Integration, sodass Bestand automatisch über mehrere Plätze alloziert wird. Versandlabels gingen gelegentlich verloren — durch eine Race Condition zwischen dem Moment, in dem NetSuite ein Label erzeugt, und dem Moment, in dem das System es abholt; ein wiederkehrender Sweep-Job alle 3 Minuten hat das strukturell gelöst statt als einmaliger Patch. Und für Abende und Wochenenden, an denen das WMS selbst ausfällt, gibt es einen externen Notfallweg, damit weiter versendet werden kann — mit Abgleichlogik, die verhindert, dass dieselben Aufträge doppelt in der Pick-Queue auftauchen, sobald das System wieder online ist.