Przejdź do treści

Rabat klienta na markę w Magento Open Source: jak utrzymać jedną cenę od listingu do koszyka

Standardowo Magento Open Source różnicuje ceny grupami klientów. Gdy każdy klient firmowy ma własną stawkę rabatu i do tego wyjątki dla wybranych marek, potrzebna jest własna logika cenowa. Wtedy cenę liczy kilka niezależnych miejsc w sklepie, a jeśli któreś pominie wyjątek, klient widzi na karcie produktu jedną kwotę, a w koszyku inną. Opisuję zasadę, która to porządkuje, jej relację do innych cen w Magento, cztery miejsca, które muszą ją uwzględniać, pułapki, przez które ceny się rozjeżdżają, oraz testy, którymi sprawdziliśmy wdrożenie, razem z tym, czego te testy nie objęły.

W skrócie

Rabat na markę to nie jedna liczba więcej na koncie klienta. To reguła, którą muszą tak samo stosować wszystkie miejsca liczące cenę, łącznie z pamięcią podręczną. Klient zamawia na podstawie ceny z listingu, a płaci cenę z koszyka, więc każda rozbieżność między nimi jest błędem w cenie, nie kosmetyką.

Podsumowanie przypadku: konfiguracja, zasada, miejsca, które muszą znać profil, i wynik
KonfiguracjaMagento Open Source 2.4.8, wszyscy klienci firmowi w jednej grupie, rabat przypisany do konta, wyjątki dla wybranych marek osobno dla katalogu bieżącego i przedsprzedaży
Zasadawyjątek dla marki → stawka konta → brak rabatu
Miejsca, które muszą znać profilcena produktu na listingu i karcie, blok wyceny netto, koszyk i kasa, klucz pamięci stron
Wynikna sprawdzanych stronach katalogu każde konto widzi swoje ceny; koszyk zgodny z kartą przy stawce konta; rozbieżność netto/brutto w podpowiedziach wyszukiwarki poprawiona; koszyk z wyjątkiem dla marki nie był osobno testowany
01

Kiedy wystarczą grupy klientów i reguły cenowe Magento

Magento Open Source różnicuje ceny grupami klientów: ceny progowe i grupowe ustawiane na produkcie oraz reguły cenowe katalogu. Według dokumentacji Adobe o regułach cenowych katalogu reguła działa dla wybranych witryn i grup klientów, a jej warunki mogą opierać się na atrybutach produktu, o ile atrybut jest dopuszczony do warunków reguł promocyjnych. Marka jako atrybut nadaje się więc do warunku.

Przy kilku klientach to wystarcza: grupa na klienta i reguła na każdą parę „grupa × marka”. Przy kilkudziesięciu kontach z indywidualną stawką i wyjątkami dla części marek liczba grup i reguł rośnie razem z liczbą klientów, a każda zmiana warunków handlowych to edycja reguł. Adobe Commerce ma do tego katalogi współdzielone w module B2B, ale w Magento Open Source ich nie ma. Wtedy warto ocenić rozszerzenie standardowej logiki cen: gotowy moduł albo rozwiązanie przygotowane dla sklepu. W opisanym sklepie powstało to drugie: stawka konta, tabela wyjątków i jeden mechanizm, który z nich liczy cenę.

02

Zasada: wyjątek dla marki, potem stawka konta

Najprostsza reguła, która nie zmienia cen nikomu, kogo zmiana nie dotyczy, ma trzy kroki: jeśli klient ma wyjątek dla marki produktu, obowiązuje wyjątek; jeśli nie ma, obowiązuje stawka z konta; jeśli konto nie ma stawki, rabatu nie ma.

  • w tabeli wyjątków zapisuje się tylko odstępstwa (klient × marka), a nie pełną macierz stawek
  • katalog bieżący i przedsprzedaż mogą mieć osobne stawki; puste pole dla jednego obiegu znaczy „w tym obiegu stawka z konta”
  • brak wyjątku dla marki oznacza stawkę z konta, a nie ukrycie marki albo cenę bez rabatu; tę decyzję trzeba podjąć jawnie, bo wszystkie trzy warianty da się obronić

Skutek tej zasady: klient bez żadnego wyjątku liczy się dokładnie tak jak przed wdrożeniem. Zmianę można więc uruchomić bez przestawiania cen istniejącym klientom i dopisywać wyjątki pojedynczo.

Jeśli sklep ma kampanie przedsprzedażowe ze stawkami przypisanymi do klienta, kolejność wydłuża się o jeden krok: stawka imienna z kampanii, potem wyjątek dla marki kampanii, potem stawka konta. Kampania, w której jest więcej niż jedna marka, nie ma jednoznacznej marki, więc w opisanym sklepie obowiązuje w niej stawka konta.

03

Od jakiej ceny liczy się rabat i co z innymi cenami Magento

Kolejność „wyjątek, potem stawka konta” mówi, którą stawkę wybrać, ale nie rozstrzyga, od jakiej ceny ją liczyć. Standardowe Magento ma kilka konkurujących mechanizmów: według dokumentacji Adobe o cenach specjalnych cena końcowa to najniższa z odpowiednich cen: bazowej, grupowej lub progowej, specjalnej i wyniku reguły cenowej katalogu. Własny rabat musi więc jawnie ustalić swoją relację do tych mechanizmów.

W opisanym sklepie zasady są takie:

  • rabat liczy się od ceny katalogowej produktu, przeliczonej na netto, a nie od ceny już obniżonej innym mechanizmem
  • w koszyku wynik trafia jako cena własna pozycji, więc to on decyduje o kwocie do zapłaty
  • wyprzedaż to osobna cena, jedna dla wszystkich klientów i niezależna od rabatu; rabat konta się z nią nie łączy
  • w tabeli wyjątków 0% oznacza „bez rabatu na tę markę”, a puste pole powrót do stawki konta; panel musi te dwie decyzje odróżniać

Niezależność wyprzedaży od rabatu ma skutek handlowy: klient z rabatem np. 45% przy wyprzedaży 30% zapłaciłby więcej niż swoją zwykłą cenę. Rabat wyprzedażowy musi więc przewyższać rabaty klientów, żeby miał sens. Jeśli sklep korzysta też z cen specjalnych, progowych albo reguł katalogowych, trzeba spisać, która cena wygrywa w każdej kombinacji, i sprawdzić to w koszyku. W opisanym wdrożeniu testy obejmowały rabat konta, wyjątki dla marek i cenę wyprzedażową.

04

Cztery miejsca, które muszą uwzględniać profil cenowy

W sklepie z własną logiką rabatów cena nie powstaje w jednym miejscu. Trzy z poniższych miejsc liczą albo pokazują cenę, a czwarte rozdziela warianty stron w pamięci podręcznej. Każde musi stosować tę samą zasadę:

Miejsca, które muszą uwzględniać profil cenowy, i skutek pominięcia wyjątku dla marki
MiejsceCo ustalaGdy pominie wyjątek
cena końcowa produktucena na listingu i karcie produktuklient wybiera towar po złej cenie
blok wycenywyświetlana cena nettodwie różne kwoty na jednej stronie
koszyk i kasacena, którą klient płaciw koszyku inna kwota niż na karcie
kontekst HTTPklucz pamięci stronklient dostaje stronę z cenami innego klienta

Dlatego wszystkie cztery miejsca powinny pytać o stawkę jeden wspólny mechanizm, a nie ustalać jej każde po swojemu. Rozbieżność zwykle pojawia się nie przy wdrożeniu, tylko przy kolejnej zmianie, gdy ktoś poprawi regułę w trzech miejscach z czterech. Najważniejsze z nich jest koszyk, bo tam klient płaci, więc rabat sprawdza się w koszyku, a nie tylko w modelu ceny.

05

Pułapka: marka na produkcie nadrzędnym, a nie na wariancie

W katalogu z rozmiarami i kolorami produkt to zwykle produkt konfigurowalny z wariantami. W opisanym sklepie marka była ustawiona na około 94% produktów nadrzędnych i praktycznie na żadnym wariancie. Logika, która czyta markę z wariantu, nie znajdzie jej i po cichu zastosuje stawkę konta zamiast wyjątku.

To samo dotyczy koszyka: pozycja w koszyku to produkt nadrzędny, a wariant jest jej pozycją podrzędną. Rabat trzeba więc liczyć na pozycji nadrzędnej i z jej marki, a pozycje podrzędne celowo pomijać, żeby nie policzyć rabatu dwa razy.

Nowa marka to dwie czynności: dopisanie opcji do słownika atrybutu i przypisanie jej produktom. Sama opcja w słowniku nie nadaje marki żadnemu produktowi, więc wyjątek dla nowej marki nie zadziała, dopóki produkty jej nie dostaną.
06

Pułapka: netto i brutto w różnych miejscach

W opisanym sklepie katalog trzyma ceny brutto, a klient firmowy widzi ceny netto. Rabat liczy się od netto. Wynik się zgadza, ale łatwo porównać kwoty w różnych jednostkach i uznać poprawną cenę za błąd albo odwrotnie.

Przykład umowny: produkt kosztuje 123,00 zł brutto, czyli 100,00 zł netto przy VAT 23%. Rabat 40% daje 60,00 zł netto, czyli 73,80 zł brutto. Karta pokazuje 60,00 zł netto, a podpowiedzi wyszukiwarki 73,80 zł. To ta sama cena, ale klient widzi dwie różne kwoty. W opisanym sklepie dokładnie tak rozjechały się podpowiedzi wyszukiwarki i karta produktu. Podpowiedzi poprawiliśmy tak, żeby pokazywały netto, jak karta.

Przy testach zapisuj więc przy każdej kwocie, czy to netto, czy brutto, i porównuj kwoty w tej samej jednostce. Skąd w Magento bierze się VAT doliczany do ceny brutto i dlaczego jeden klient może widzieć brutto jako netto, opisuje kolejny wpis z serii: Magento dolicza VAT do ceny brutto.

07

Pułapka: klucz pamięci bez wyjątków

Jeśli do kontekstu pamięci stron trafia tylko stawka z konta, dwóch klientów z tą samą stawką ogólną, ale innymi wyjątkami dla marek, dostaje ten sam klucz i dzieli te same strony z cenami. Do kontekstu musi trafiać cały profil: stawka konta i lista wyjątków, zapisane w stałej kolejności. Bez stałej kolejności ten sam profil daje różne klucze i pamięć mnoży kopie stron.

Dlaczego do kontekstu nie wkłada się identyfikatora konta, wyjaśnia dokumentacja Adobe o kontekście pamięci stron: zmienna kontekstu per użytkownik oznacza osobną kopię strony dla każdego użytkownika. Profil pozwala kontom o identycznych warunkach dzielić wpisy. Ten sam warunek dotyczy pamięci bloków z ceną i widżetów produktów, które w kluczu rozróżniają tylko grupę klienta. Mechanizm i testy opisuje poprzedni wpis z tej serii: Magento 2.4.8: problem z full page cache po zalogowaniu.

08

Pułapka: stara kopia profilu po zapisie wyjątku

Mechanizm liczący stawkę zwykle buduje profil klienta raz i trzyma go w pamięci, żeby nie czytać tabeli wyjątków przy każdym produkcie na listingu. Po zapisie nowego wyjątku taki profil jest nieaktualny i do czasu odświeżenia pokazuje starą stawkę.

W opisanym wdrożeniu zapamiętany profil ma w kluczu numer wersji tabeli wyjątków. Każdy zapis podnosi wersję, więc kolejne odczyty budują profil od nowa. Ten błąd wyszedł w teście przed wdrożeniem: zapis wyjątku i odczyt ceny w tym samym żądaniu pokazywały starą stawkę.

Numer wersji odświeża profil po stronie serwera. Nie odświeża sam z siebie danych prywatnych w przeglądarce klienta, np. paska z rabatem. Według dokumentacji Adobe o treściach prywatnych Magento trzyma takie sekcje w pamięci przeglądarki i odświeża je według reguł unieważniania. Opisany test nie potwierdza więc ani nowej ceny w kolejnych żądaniach trwającej sesji, ani odświeżenia paska w otwartej przeglądarce. To osobne testy, opisane w sekcji o testach odbioru.

09

Jak pokazać klientowi, jaki ma rabat

Gdy rabat zależy od marki, jedna liczba „Twój rabat: 40%” przestaje być prawdziwa. W opisanym sklepie wszystkie miejsca, które opisują rabat, korzystają z jednego wspólnego podsumowania:

  • klient bez wyjątków widzi jedną liczbę, tak jak wcześniej
  • klient z wyjątkami widzi zakres od najniższej do najwyższej stawki, np. „40–45%”, także wtedy, gdy wyjątek jest niższy od stawki konta
  • na koncie klienta jest dodatkowo lista marek z wyjątkiem i ich stawek
  • ten sam opis trafia do pasku konta, na stronę konta, do maila o zamówieniu i do eksportu klientów w panelu

Pasek z rabatem jest częścią prywatnych danych klienta, ładowanych osobnym zapytaniem, więc nie trafia do pamięci stron i nie musi być uwzględniany w jej kluczu.

10

Testy odbioru rabatów marek

W opisanym sklepie ceny na stronach katalogu sprawdziliśmy dwoma kontami z różnymi stawkami, w obu kolejnościach, od pustej pamięci. Koszyk sprawdziliśmy przy samej stawce konta i przy cenie wyprzedażowej:

Testy odbioru rabatów marek
TestWynik
strona główna, kategoria marki (str. 1 i 2), podkategoria, szybkie zamawianie, dwa wyszukiwania, karta produktukażde konto widzi swoje ceny
podpowiedzi wyszukiwarkibez przecieku cen; rozbieżność netto/brutto znaleziona i poprawiona
koszyk z 2 szt. przy stawce konta: netto, VAT i sumazgodny z kartą co do grosza
cena wyprzedażowa na karcie i w koszykuzgodna; rabat konta się z nią nie łączy
zapis wyjątku i odczyt ceny w tym samym żądaniunowa stawka po dodaniu wersji do klucza profilu

Tych testów w opisanym przeglądzie nie było: koszyk i kasa z wyjątkiem dla marki, zmiana ilości w koszyku, dwa konta z tą samą stawką ogólną i różnymi wyjątkami (najlepszy test pułapki klucza pamięci), nowa cena w kolejnych żądaniach trwającej sesji po zapisie wyjątku i odświeżenie paska rabatu w otwartej przeglądarce. Przy podobnym wdrożeniu to pierwsze testy do wykonania.

Test w modelu albo w konsoli sprawdza samo obliczenie. Nie pokazuje tego, co klient zobaczy w sesji, po wyrenderowaniu strony i z pamięcią podręczną, dlatego testy odbioru robi się przez żądania HTTP z prawdziwymi sesjami klientów.

11

Kiedy zrobisz to regułami, a kiedy rozszerzeniem logiki cen

Regułami Magento

Kilku klientów firmowych, stawki zmieniane rzadko, wyjątki dla nielicznych marek. Grupa na klienta i reguły cenowe katalogu z warunkiem na markę dadzą ten sam efekt bez własnego kodu. Zostaje kontrola, czy reguły są przeliczone i czy marka jest atrybutem dopuszczonym do warunków.

Rozszerzeniem logiki cen

Dziesiątki kont z indywidualną stawką, wyjątki per marka, osobne stawki dla przedsprzedaży i katalog dostępny po zalogowaniu. Gotowy moduł albo rozwiązanie przygotowane dla sklepu musi objąć wszystkie cztery miejsca z tabeli, klucze pamięci i każde miejsce, które opisuje rabat klientowi.

Gdy zlecasz nam taki przegląd albo wdrożenie, dostajesz opis obowiązującej zasady liczenia ceny, listę miejsc, które ją stosują, porównanie cen na kontach testowych na listingu, karcie, w wyszukiwarce, w koszyku i w kasie oraz raport z testów odbioru w układzie z sekcji 10. Więcej o pracy przy indywidualnych rabatach i cennikach B2B i przy sklepach na Magento.

FAQ: rabat klienta na markę w Magento

Przy kilku klientach wystarczy grupa klientów na klienta i reguła cenowa katalogu z warunkiem na atrybut marki, dopuszczony do warunków reguł promocyjnych. Przy wielu kontach z indywidualnymi stawkami warto ocenić rozszerzenie standardowej logiki cen, gotowym modułem albo rozwiązaniem przygotowanym dla sklepu: stawka konta, tabela wyjątków klient × marka i jeden mechanizm, z którego korzystają wszystkie miejsca liczące lub pokazujące cenę.
Najczęściej dlatego, że cenę na karcie i w koszyku liczą dwa różne miejsca i jedno z nich nie stosuje wyjątku dla marki, albo czyta markę z wariantu, a jest ona ustawiona na produkcie nadrzędnym. Warto też sprawdzić, czy obie kwoty są w tej samej jednostce, netto albo brutto.
Wyjątek dla marki, potem stawka z konta, potem brak rabatu. W tabeli zapisuje się tylko odstępstwa, więc klient bez wyjątków liczy się tak jak przed zmianą, a wyjątki można dodawać pojedynczo.
Tak, jeśli ceny są w stronach trzymanych w pamięci. Kontekst pamięci stron musi zawierać cały profil cenowy, czyli stawkę konta i listę wyjątków w stałej kolejności. Inaczej dwóch klientów z tą samą stawką ogólną, ale innymi wyjątkami, dostanie te same strony z cenami.
Jako zakres od najniższej do najwyższej obowiązującej stawki, np. 40–45%, i listę marek z wyjątkiem na koncie klienta. Klient bez wyjątków nadal widzi jedną liczbę. Ten sam opis powinien trafiać wszędzie, gdzie rabat jest pokazywany: na pasek konta, stronę konta, do maila o zamówieniu i do eksportu w panelu.
W standardowym Magento cena końcowa to najniższa z ceny bazowej, grupowej lub progowej, specjalnej i wyniku reguły katalogowej. Własny rabat musi jawnie ustalić relację do tych cen. W opisanym sklepie rabat liczy się od ceny katalogowej przeliczonej na netto, w koszyku trafia jako cena własna pozycji, a cena wyprzedażowa jest osobna i niezależna od rabatu.