B2B Preislogik in Shopware 6: Kundenpreise, Staffelpreise & ERP-Integration
Händler A bekommt 12 % Rabatt auf alles. Händler B hat individuelle Listenpreise aus dem ERP, die täglich aktualisiert werden. Händler C kauft in Staffeln — ab 50 Stück greift ein anderer Preis. Und der Außendienst-Mitarbeiter soll für seinen Key Account noch manuell übersteuern können. Willkommen in der Realität des B2B-Vertriebs. Wie du das in Shopware 6 sauber abbildest, ohne dass das System nach drei Monaten zur unlösbaren Blackbox wird.
1. Was Shopware 6 von Haus aus mitbringt
Shopware 6 hat im Kern ein solides Preissystem, das für viele B2B-Setups bereits ausreicht: Kundengruppen mit prozentualen Rabatten, artikelspezifische Preise pro Kundengruppe und Staffelpreise (Quantity-based Pricing) direkt im Produkt. Das klingt banal, ist aber bereits ein gewaltiger Fortschritt gegenüber Shopware 5, wo dieses System deutlich starrer war.
Das Preismodell in Shopware 6 arbeitet mit einer klaren Hierarchie: Spezifischerer Preis gewinnt immer. Ein direkt am Produkt hinterlegter Kundengruppen-Preis schlägt den allgemeinen Gruppenrabatt. Ein Staffelpreis schlägt den Einzelpreis. Das Regelwerk ist in der Datenbank in der Tabelle product_price abgebildet — und genau da setzt auch die ERP-Integration an.
2. Wo das Bordmittel an seine Grenzen stößt
Das Problem beginnt, wenn Preise nicht statisch, sondern dynamisch sind. Im echten B2B-Betrieb hängen Preise oft von Parametern ab, die Shopware gar nicht kennt: der aktuelle Einkaufspreis, die verhandelte Marge für einen spezifischen Kunden oder der Lagerbestand. All das lebt im ERP — SAP, Microsoft Dynamics, Sage, oder ein selbst gebastelte Middleware.
Ein weiterer Fallstrick: individuelle Kundenpreise auf Artikel-Ebene für Hunderte Kunden. Sobald du anfängst, jeden Kunden als eigene Kundengruppe zu behandeln, explodiert die Zahl der Einträge in der Preistabelle, und das System wird träge. Ich habe Shops gesehen, die nach einem unkontrollierten ERP-Sync 50 Millionen Zeilen in product_price hatten — und sich gewundert, warum der Checkout 8 Sekunden lädt.
3. Die drei Architektur-Muster für komplexe Preislogik
In der Praxis haben sich drei Ansätze bewährt, je nach Anforderungsprofil:
- Muster 1: Synchronisierter ERP-Preis via APIDas ERP schreibt Preise regelmäßig (z.B. nächtlich oder bei Änderung) über die Shopware Admin-API direkt in die
product_price-Tabelle. Shopware löst selbst auf. Vorteil: keine Echtzeit-Abhängigkeit vom ERP im Checkout. Nachteil: Preise sind maximal so aktuell wie der letzte Sync. - Muster 2: Echtzeit-Preisabfrage via PluginEin Custom-Plugin subscribed auf den
SalesChannelProductPriceCalculatedEventund überschreibt den berechneten Preis mit einem Live-Call ins ERP. Vorteil: immer aktuelle Preise. Nachteil: Checkout-Stabilität hängt direkt an der ERP-Verfügbarkeit, und Latenz ist ein echtes Problem. - Muster 3: Hybrid mit Cache-LayerKombination aus beidem: Ein dedizierter Preis-Cache (Redis oder eine eigene Tabelle) wird kontinuierlich vom ERP befüllt. Shopware fragt bei der Preisberechnung zuerst den Cache ab. Fallback ist der native Shopware-Preis. Dieses Muster ist aufwendiger, aber für den produktiven Einsatz mit hohem Traffic das robusteste.
4. Kundenindividuelle Preise: Kunden-ID statt Kundengruppe
Shopware 6 kennt standardmäßig nur Preise auf Kundengruppen-Ebene, nicht auf Kunden-Ebene. Für echte Individualpreise gibt es zwei saubere Wege: Entweder du legst tatsächlich eine eigene Kundengruppe pro Kunde an (nur sinnvoll bei sehr wenigen Kunden), oder du implementierst ein Custom-Plugin, das einen eigenen Preis-Resolver mitbringt.
Der technisch sauberere Weg ist das AbstractCartProcessor-Pattern: Du erweiterst die Cart-Berechnung und injizierst dort kundenbezogene Preise aus deiner eigenen Preistabelle. Das Shopware-eigene Preissystem bleibt unangetastet, und du hast die volle Kontrolle darüber, welcher Preis für welchen Kunden greift — inkl. der Möglichkeit, Staffeln und Aktionspreise zu kombinieren.
5. Staffelpreise: Richtig gemacht, nicht nur eingetragen
Staffelpreise funktionieren in Shopware 6 gut — solange sie statisch sind. Der Admin-UI lässt dich Mengen-Schwellen definieren und daneben den jeweiligen Preis hinterlegen. Das reicht für viele Setups.
Problematisch wird es, wenn Staffeln dynamisch aus dem ERP kommen und sich je nach Kunden-Vertrag unterscheiden: Kunde A bekommt ab 10 Stück einen anderen Preis als Kunde B, obwohl beide dieselbe Kundengruppe haben. Hier hilft das Hybrid-Muster aus Abschnitt 3: Staffeln werden pro Kunde in einer Custom-Tabelle persistiert, und der eigene Preis-Resolver zieht sich die passende Staffel zur Laufzeit. Das ist mehr Aufwand, aber deutlich wartbarer als 50.000 generierte Kundengruppen.
6. Performance: Der unterschätzte Faktor
Preisberechnungen laufen bei jedem Seitenaufruf, bei jeder Warenkorbaktualisierung und bei jedem API-Call der Store-API. Wenn deine Preislogik schlecht implementiert ist, spürst du das sofort in der Ladezeit.
Die wichtigsten Faustregeln aus der Praxis: Kein N+1-Problem in der Preisberechnung (keinen ERP-Call pro Artikel im Warenkorb, sondern einen Batch-Call für alle Artikel). Preisergebnisse aggressiv cachen — mindestens für die Dauer einer Session. Und die Custom-Preistabellen richtig indexieren: ein fehlender Index auf (customer_id, product_id) kann bei 100.000 Einträgen bereits spürbar werden.
7. Fazit: Sauber modelliert schlägt clever gebaut
Komplexe B2B-Preislogik in Shopware 6 ist lösbar — aber sie verlangt, dass du dich früh für ein klares Architektur-Muster entscheidest. Die häufigste Fehlerquelle ist nicht fehlende Funktionalität in Shopware, sondern fehlende Modellierung: Preisregeln werden ad hoc eingebaut, ohne eine klare Antwort darauf zu haben, welche Quelle für welchen Preis zuständig ist.
Wer das vorher durchdenkt — und insbesondere die ERP-Integration sauber über eine Middleware abstrahiert statt direkt ins Shopware-Datenmodell zu schreiben — hat langfristig einen Shop, der sich auch bei wachsenden Anforderungen noch sauber warten lässt.
Du stehst vor einer komplexen B2B-Preislogik oder ERP-Integration?
In 30 Minuten schauen wir gemeinsam, welches Architektur-Muster für deinen spezifischen Use-Case passt — und wo die Fallstricke liegen, bevor du anfängst zu bauen.