Cenniki kontraktowe per kontrahent w sklepie B2B
Cenniki kontraktowe to nie feature - to warunek istnienia poważnego sklepu B2B. Każdy klient korporacyjny rozmawia z handlowcem o kontrakcie, podpisuje rabat 12%, dostaje progi ilościowe albo specjalne ceny na konkretne kategorie. To wszystko musi być widoczne w sklepie automatycznie, bez ręcznego stosowania kuponów albo dodawania notatek. Implementacja brzmi prosto - jest trudna.
Spis treści (9)
W skrócie
- 1. ERP jest źródłem cenników, sklep konsumuje przez API
- 2. Modele cenników: indywidualny, grupowy, progi ilościowe, czasowe - najczęściej miks
- 3. Cache Redis obowiązkowy (TTL 5-15 min), bez cache ERP umiera w peak'u
- 4. Walidacja synchronizna przy checkoutcie (cena z koszyka mogła się zmienić)
- 5. Antywzorzec: sklep utrzymujący własną logikę cen kontraktowych - zawsze rozjazd z fakturami
Modele cenników w polskim B2B
Z pięciu wdrożeń, te modele występują najczęściej:
Model A: Procent rabatu od cennika. Klient ACME ma -12% na wszystko. Cennik bazowy × 0.88.
Najprostszy, ale ma sufity (klient nie może mieć innej ceny na grupy / produkty).
Model B: Cenniki indywidualne per SKU. Klient ACME na SKU ABC = 12 zł. Na SKU DEF = 15 zł. Na SKU GHI = cena bazowa.
Pełna elastyczność, ale trzymanie tego w ERP wymaga dyscypliny.
Model C: Cenniki grupowe. Klienci „platynowi" (top 20 obrotem) widzą cennik X, „złoci" cennik Y, „srebrni" cennik bazowy.
Średnia elastyczność, łatwiejsze utrzymanie.
Model D: Progi ilościowe. Od 1 szt. 12 zł, od 100 szt. 11 zł, od 1000 szt. 10 zł.
Klasyka hurtu. Wymaga obliczania per ilość w koszyku.
Model E: Cenniki czasowe. Promocja od X do Y. Po przekroczeniu daty wraca cennik standardowy.
Marketing-driven, dodatek do innych modeli.
Model F: Mix. Klient ACME ma 5% rabatu na wszystko + indywidualną cenę na SKU ABC + próg ilościowy od 500 szt. + promocję czasową.
Realny model dla większych klientów.
Skąd cenniki przychodzą
Cenniki żyją w ERP. Każdy poważny ERP ma rozbudowany silnik cen:
Comarch ERP XL:
- Cenniki bazowe, indywidualne, grupowe, progi ilościowe, promocje
- Wywołanie API:
PriceCalculation(REST/SOAP) - Sklep pyta: „daj cenę dla klienta X, SKU Y, ilość Z"
SAP S/4HANA:
- Condition records (najmocniejszy silnik na rynku)
- Pricing procedure: złożona hierarchia warunków
- API: OData lub BAPI
Subiekt GT:
- Cenniki indywidualne, grupowe, rabaty
- Sfera API
- Mniej elastyczne niż XL czy SAP
enova365:
- Cenniki indywidualne, grupowe, progi, promocje
- REST API
- Solidny model
Zasada: sklep nigdy nie liczy cen sam. Zawsze pyta ERP.
Integracje z ERP - pełen pillar.
Architektura - sklep + cache + ERP
[Klient w sklepie]
|
| wyświetlenie produktu
v
[Sklep]
|
| "daj cenę dla K001, SKU ABC, qty 5"
v
[Cache Redis]
|
+-- HIT (cache świeży, < 10 min): zwróć cenę
|
+-- MISS: zapytaj ERP
|
v
[ERP]
|
| zwróć cenę
v
[Cache Redis] (zapis z TTL 600s)
|
v
[Sklep] (zwróć cenę klientowi)
TTL: 5-15 minut. Krócej = ERP zasypywany. Dłużej = klient widzi nieaktualne ceny.
Hit ratio target: >85%. Poniżej - TTL za krótkie lub niewłaściwa strategia.
Cache batch - dla PLP
Na liście produktów (PLP) 50 produktów. 50 wywołań cache = 50 cache lookups. Lepiej: batch.
GET prices for customer K001, SKUs [ABC, DEF, GHI, ..., XYZ50]
-> Redis MGET keys ["price:K001:ABC", "price:K001:DEF", ...]
-> 50 keys, część hit, część miss
-> Dla miss: 1 batch call do ERP "daj ceny dla K001 na te SKUs"
-> ERP zwraca mapę
-> Zapis brakujących do Redis
-> Return mapa cen
ERP call 1× zamiast 50×. Redis call 1× (MGET) zamiast 50× (GET). Znacząca różnica na PLP.
Walidacja przy checkoutcie
Cena w koszyku może się zestarzeć. Klient dodaje produkt w poniedziałek, kupuje w środę - w międzyczasie cennik się zmienił.
Strategia:
1. Soft check w koszyku. Cena z cache 10 min. Klient widzi orientacyjne wartości.
2. Hard check przy „Złóż zamówienie". Sklep pyta ERP o aktualne ceny (sync, bez cache). Porównuje z cenami w koszyku.
3. Jeśli ceny się zmieniły:
- Mała różnica (do 1%): akceptujemy bez zatwierdzania (drobne korekty)
- Większa różnica: pokazujemy klientowi nowe ceny, klient potwierdza
4. Po akceptacji: Zamówienie wchodzi z aktualnymi cenami. ERP wystawia fakturę zgodną z tymi cenami.
Cenniki w Magento Adobe Commerce - Shared Catalogs
Adobe Commerce ma natywny mechanizm - Shared Catalogs.
Jak działa:
- Definiujesz „Katalog A" z 1200 produktami i ich cenami specjalnymi
- Przypisujesz „Katalog A" do 30 firm (Companies)
- Te 30 firm widzi tylko produkty z katalogu A + ich ceny
Plusy:
- Wbudowane, nie trzeba dorabiać
- UI w panelu administracyjnym
- Action workflow do tworzenia
Minusy:
- Sztywne (ceny statyczne, nie real-time z ERP)
- Synchronizacja z ERP - własna implementacja
- Trudne dla bardzo wielu wariantów cenowych (każdy unique = osobny katalog)
W praktyce dla polskiego B2B: Shared Catalogs jako fasada UI + integracja z ERP która synchronizuje ceny do Magento jako cenniki katalogowe. Hybryda.
Cenniki w Shopware Enterprise B2B Suite
Shopware B2B Suite ma „Customer Specific Prices" - bardziej elastyczne niż Magento Shared Catalogs.
- CSV import cen per klient
- API endpoint do bulk update
- Wsparcie dla progów ilościowych
Też wymaga integracji z ERP - wbudowane modele zapełniasz danymi z zewnątrz.
Magento Open Source bez Shared Catalogs
Magento OS nie ma Shared Catalogs. Dorabiasz:
Opcja 1: Customer groups + tier pricing. Magento OS ma tier pricing per customer group. Klient w grupie X widzi cenę dla grupy X. Ograniczone (nie da się indywidualnych cen per SKU per kontrahent), ale dla podstawowych modeli wystarcza.
Opcja 2: Modułe komercyjne.
- Aheadworks B2B Suite - Customer-specific Pricing, Shared Catalogs (kopia Adobe Commerce)
- Amasty B2B - podobne
- Webkul - alternatywa
Opcja 3: Custom. Własne implementacje. Bardziej elastyczne, droższe w utrzymaniu. Pisze się dla nietypowych modeli.
Najczęstsze problemy
1. Trzymanie cenników w sklepie i w ERP równolegle. Klient zmienia cennik w ERP, sklep dalej pokazuje stary. Albo sklep ma cennik nie istniejący w ERP. Faktury się rozjeżdżają.
Rozwiązanie: sklep nigdy nie jest source of truth. Tylko cache.
2. Brak cache → ERP umiera. 50 wywołań ERP / sec w peak'u = ERP timeout, sklep też pada.
Rozwiązanie: Redis cache z TTL 5-15 min + batch fetching.
3. Cache za długi → klient widzi stare ceny. TTL 1h → klient w godzinie widzi cenę wcześniejszą.
Rozwiązanie: TTL 5-15 min + webhook z ERP przy zmianie cennika (event-based invalidation).
4. Cenniki na PLP wolne. 50 wywołań ERP per render = LCP 10s.
Rozwiązanie: batch fetching + cache. Optymalizacja PLP.
5. Brak walidacji przy checkout. Cena z koszyka != cena w fakturze. Reklamacja, dramat.
Rozwiązanie: hard validation sync z ERP przy „Złóż zamówienie".
6. Kanibalizacja kanałów. Klient B2B widzi cennik kontraktowy w sklepie B2B. Allegro widzi cennik detaliczny. Ale jeśli klient B2B znajdzie na Allegro tańsze... problem.
Rozwiązanie: separacja kanałów. Marketplace'y z cenami detalicznymi, sklep B2B z kontraktowymi (i często wyższymi przy uwzględnieniu wartości dodanej).
7. Cenniki dla NIP-osób fizycznych prowadzących DG. „Klient" = firma czy osoba fizyczna? Jednoosobowa działalność z VAT to formalnie firma.
Rozwiązanie: identyfikacja po NIP + decyzja w ERP („JDG z NIP-em otrzymuje cennik klasy X").
FAQ
Czy mogę mieć cennik kontraktowy bez zalogowania? Nie. Cennik kontraktowy = klient zidentyfikowany. Klient musi się zalogować, sklep wie kim jest, pyta ERP o jego cenę.
Co jeśli klient widzi cennik niezalogowany, a inną cenę po zalogowaniu? Klasyczny pattern: niezalogowany widzi „cena katalogowa" (sugerowana), po zaloguj - kontraktowa. Klient ma świadomość, że loguje się dla swojej ceny.
Co jeśli klient nie ma jeszcze kontraktu (nowy klient B2B)? Standardowy cennik katalogowy. Negocjacje kontraktu offline, po podpisaniu w ERP - automatycznie zaczyna widzieć swoje ceny.
Czy mogę pokazywać marżę handlowcowi w panelu? Tak - w panelu „Sales Representative". Handlowiec widzi marżę dla zamówienia, może świadomie udzielać rabatów. Klient nie widzi.
Czy cennik kontraktowy działa z BNPL (Mondu)? Tak. Cennik kontraktowy daje cenę zamówienia. BNPL przejmuje fakturę, klient płaci BNPL, dostawca dostaje pieniądze od BNPL.
Co dalej
- Pillar procesów B2B: Procesy zakupowe B2B
- Multi-account (kto kupuje): Multi-account dla organizacji
- Integracja z ERP: Comarch XL
- Cache cen - architektura: Cache warstwy
O autorze
Jakub Owsianka
Architekt rozwiązania w WiseB2B - silniku platform B2B. Zaczynał po stronie biznesu (własne sklepy), potem deweloper, dziś projektuje wdrożenia dla sklepów z katalogami w dziesiątkach tysięcy SKU. W ostatnich latach wdrożył AI-development w zespole i funkcjonalności oparte o AI bezpośrednio w silniku sklepu.
Czytaj dalej w temacie wydajności
Wszystkie wpisyMasz pytanie do tego artykułu?
Dodatkowy kontekst, problem z własnym wdrożeniem, druga opinia - napisz wprost. Odpowiadam osobiście w 1-2 dni robocze.