
ArticleOmnibus-Preisangaben ohne Panik
Wer in der EU einen Online-Shop betreibt und einen Rabatt auszeichnet, muss den niedrigsten Preis anzeigen, den das Produkt in den 30 Tagen vor der Reduzierung hatte. Das ist die Kurzfassung dessen, was die Omnibus-Richtlinie (EU 2019/2161) mit der Preisangabenrichtlinie gemacht hat. In Deutschland steht es in §11 PAngV. Der durchgestrichene Preis neben dem Aktionspreis ist keine Dekoration mehr. Er ist eine regulierte Angabe, und sowohl Behörden als auch Abmahnanwälte lesen mit.
Die meisten Shops gehen das spät und nervös an. Erst wird die Aktionslogik gebaut, dann wird die rechtliche Anforderung nachträglich angeschraubt, und plötzlich betreibt das Frontend zur Renderzeit Preisarchäologie: Historie laden, Minima berechnen, hoffen, dass der Cache warm ist. Das ist die Panik-Variante.
Die ruhige Variante behandelt den 30-Tage-Tiefstpreis als das, was er tatsächlich ist: eine Eigenschaft des Produkts, nicht eine Eigenschaft der Seite.
Eine Dateneigenschaft daraus machen
In einem aktuellen Multi-Market-Commerce-Projekt (sechs Länder, sechs Währungen, ein Katalog im sechsstelligen Bereich) haben wir die Regel in die Datenpipeline verlegt statt in die UI:
-
Die Preishistorie ist eine vollwertige Tabelle. Jede Preisänderung schreibt eine Zeile: Produkt, Markt, Preis, Zeitstempel. Langweilig, append-only, prüfbar. Diese Tabelle ist die rechtliche Wahrheit, und sie existiert unabhängig davon, ob gerade etwas im Angebot ist.
-
Der 30-Tage-Tiefstpreis wird beim Ingest berechnet, nicht beim Rendern. Bei jeder Preisänderung und im täglichen Job berechnet die Pipeline das rollierende 30-Tage-Minimum pro Produkt und Markt. Eine Window-Query über die Historientabelle.
-
Das Ergebnis liegt im Suchdokument. Wir indexieren den Tiefstpreis direkt neben dem aktuellen Preis in das Dokument der Suchmaschine. Produktlisten, Suchergebnisse und Produktseiten lesen ein Dokument und haben alles, um einen konformen Preisblock zu rendern. Keine zusätzlichen Lookups, kein N+1 auf Kategorieseiten, keine separate Compliance-API.
Die Frontend-Logik schrumpft auf eine rein darstellerische Frage: Ist der aktuelle Preis niedriger als der Referenzpreis? Wenn ja, beide anzeigen, korrekt für den Markt beschriftet. Das Frontend berechnet nie etwas rechtlich Relevantes, und genau so soll es sein. Rendering-Code ändert sich wöchentlich. Rechtliche Angaben sollten nicht davon abhängen.
Die Sonderfälle sind Policy, nicht Code
Die Umsetzung ist die einfachen 80 Prozent. Die restlichen 20 Prozent sind Fragen, die Anwalt und Vertrieb einmal beantworten müssen, und dann erzwingt die Pipeline die Antwort dauerhaft:
- Neue Produkte haben keine 30-Tage-Historie. Regel festlegen (kein Referenzpreis, bis Historie existiert) und kodieren.
- Gestaffelte Rabatte (eine Aktion, die tiefer wird) dürfen je nach Auslegung des Markts den Preis vor der ersten Reduzierung referenzieren. Das ist ein Markt-Flag, kein Rewrite.
- Jeder Markt kann abweichen. Die Regel gilt EU-weit, aber nationale Umsetzung und Durchsetzungspraxis variieren. Da der Tiefstpreis ohnehin pro Markt berechnet wird, ist marktspezifische Policy eine Verzweigung an einer Stelle.
Das Muster trägt über Omnibus hinaus. Jeder regulierte Anzeigewert, Energielabels, Grundpreise, Pfandbeträge, verhält sich als ingestierte Daten besser denn als Rendering-Logik. Dort berechnen, wo die Daten leben, das Ergebnis dort ablegen, wo das Frontend ohnehin hinschaut, und Compliance hört auf, ein Projekt zu sein. Sie wird eine Spalte.
Wenn dein Shop gerade vor einem Omnibus-Retrofit steht, ist der ehrliche erste Schritt, die UI gar nicht anzufassen. Fang mit der Preishistorien-Tabelle an. Alles Weitere folgt daraus, dass die Wahrheit an einem Ort liegt.