Opracowuję metodę wysyłki dla jakiejś firmy logistycznej. Ta firma ma wiele biur, w których klient może otrzymać swoje zamówienie. Mogę uzyskać listę biur według API w API, ale nie wiem, jak lepiej reprezentują ten krok?
Na razie po prostu ustawiłem nowy \Magento\Quote\Model\Quote\Address\RateResult\Method
w każdym biurze w mieście, w dużym mieście jest to liczba> 100 i myślę, że nie jest zbyt dobrze ustawić 100 linii w kasie.
Będzie to moduł publiczny dla innego projektu kasy, więc jak mogę wyświetlić w pobliżu wybranej metody wysyłki listę rozwijaną z listą biur oraz ustawić cenę i metodę po wybraniu przez użytkownika jednej.
magento-2.1
checkout
shipping-methods
Jamess Moriarty
źródło
źródło
Odpowiedzi:
Kasa Magento nie obsługuje żadnego rodzaju danych dodatkowych dotyczących sposobu wysyłki. Ale zapewnia
shippingAdditional
blok w kasie, którego można użyć do tego. Poniższe rozwiązanie będzie działać w przypadku standardowej kasy Magento.Najpierw przygotujmy nasz pojemnik, w którym możemy umieścić jakąś formę. Aby to zrobić, utwórz plik w
view/frontend/layout/checkout_index_index.xml
Teraz utwórz plik, w
Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.js
którym wyrenderuje szablon nokaut. Jego treść wygląda następującoTen plik używa szablonu nokaut, w którym należy umieścić
Vendor/Module/view/frontend/web/template/checkout/shipping/form.html
Mamy teraz pole wyboru, które będzie widoczne, gdy nasza metoda (zdefiniowana przez kod) zostanie wybrana w tabeli metod wysyłki. Czas wypełnić go kilkoma opcjami. Ponieważ wartości zależą od adresu, najlepszym sposobem jest utworzenie punktu końcowego odpoczynku, który zapewni dostępne opcje. W
Vendor/Module/etc/webapi.xml
Teraz zdefiniuj interfejs
Vendor/Module/Api/OfficeManagementInterface.php
jakoZdefiniuj interfejs dla danych biurowych w
Vendor\Module\Api\Data\OfficeInterface.php
. Interfejs ten będzie używany przez moduł webapi do filtrowania danych wyjściowych, dlatego należy zdefiniować wszystko, co należy dodać do odpowiedzi.Czas na faktyczne zajęcia. Zacznij od tworzenia preferencji dla wszystkich interfejsów w
Vendor/Module/etc/di.xml
Teraz stwórz
Vendor\Module\Model\OfficeManagement.php
klasę, która faktycznie wykona logikę pobierania danych.I wreszcie klasa dla
OfficeInterface
wVendor/Module/Model/Office.php
Powinno to pokazać pole wyboru i zaktualizować je po zmianie adresu. Ale brakuje nam jeszcze jednego elementu do manipulowania interfejsem. Musimy stworzyć funkcję, która wywoła punkt końcowy. Wywołanie do niego jest już uwzględnione
Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.js
i jest toVendor_Module/js/view/checkout/shipping/office-service
klasa, do której powinien przejśćVendor/Module/view/frontend/web/js/view/checkout/shipping/office-service.js
następujący kod:Wykorzystuje 2 kolejne pliki js.
Vendor_Module/js/view/checkout/shipping/model/resource-url-manager
tworzy adres URL do punktu końcowego i jest dość prostyVendor_Module/js/view/checkout/shipping/model/office-registry
jest sposobem na utrzymanie wyniku w lokalnej pamięci. Jego kod to:Ok, więc powinniśmy wszyscy pracować nad frontendem. Ale teraz jest inny problem do rozwiązania. Ponieważ kasa nie wie nic o tym formularzu, nie wyśle wyniku wyboru do backendu. Aby tak się stało, musimy użyć
extension_attributes
funkcji. W Magento2 jest to sposób na poinformowanie systemu, że niektóre dodatkowe dane powinny znajdować się w pozostałych wywołaniach. Bez niego magento odfiltrowałoby te dane i nigdy nie dotarłyby do kodu.Więc najpierw
Vendor/Module/etc/extension_attributes.xml
zdefiniuj:Ta wartość jest już wstawiona do żądania
form.js
zthis.selectedOffice.subscribe()
definicji. Tak więc powyższa konfiguracja przejdzie tylko przy wejściu. Aby pobrać go w kodzie, utwórz wtyczkęVendor/Module/etc/di.xml
Wewnątrz tej klasy
Oczywiście, gdzie zaoszczędzisz wartość zależy całkowicie od twoich wymagań. Powyższy kod wymagałby utworzenia dodatkowej kolumny
carrier_office
wquote_address
isales_address
tabel oraz zdarzenia (wVendor/Module/etc/events.xml
)Spowodowałoby to skopiowanie danych zapisanych w adresie oferty na adres sprzedaży.
Napisałem to dla mojego modułu dla polskiego operatora InPost, więc zmieniłem niektóre nazwy, które mogą złamać kod, ale mam nadzieję, że da ci to, czego potrzebujesz.
[EDYTOWAĆ]
Model nośnika zapytany przez @sangan
źródło
Dodaję nową odpowiedź, aby rozwinąć to, co zostało już wcześniej dostarczone, ale bez zniekształcania go.
Oto trasa, która się
QuoteAddressPlugin
zaczepiała:Ostatnią metodą było wywołanie,
Magento\Quote\Model\Quote\Address::setShippingMethod()
które było wywołaniem,Magento\Quote\Model\Quote\Address::__call()
którego użyłem. W tej chwili znalazłem lepsze miejsce na wtyczkę, to jestMagento\Quote\Model\ShippingAssignment::setShipping()
metoda. Tak więc część wtyczki można przepisać na:i sama wtyczka:
źródło
@Zefiryn, natknąłem się na problem z:
quote.shippingAddress().extensionAttributes.carrier_office = office;
Kiedy wchodzę do kasy po raz pierwszy (nowe okno prywatne) jako gość (ale to samo dzieje się z zarejestrowanym klientem), atrybut biura nie jest zapisywany w bazie danych po pierwszym „Dalej”. Chociaż w konsoli widzę prawidłowe dane wyjściowe dla:
console.log(quote.shippingAddress().extensionAttributes.carrier_office);
Gdy wrócę do pierwszej strony kasy i ponownie wybiorę biuro, zostanie ono zapisane. Co może być przyczyną takiego zachowania?
Próbowałem użyć:
address.trigger_reload = new Date().getTime(); rateRegistry.set(address.getKey(), null); rateRegistry.set(address.getCacheKey(), null); quote.shippingAddress(address);
ale bez powodzenia ...
źródło
@Zefiryn, Czy możesz wyjaśnić w kilku słowach, jak działa powyższa wtyczka? Jestem trochę zdezorientowany, ponieważ jak wiem metoda __call jest wykonywana, jeśli spróbujemy wykonać metodę, która nie istnieje dla konkretnego obiektu. Wydaje się, że to prawda, ponieważ w app / code / Magento / Quote / Model / Quote / Address.php nie widzę takiej metody - tylko komentarz:
/** * Sales Quote address model ... * @method Address setShippingMethod(string $value)
$subject->setInpostMachine
i$subject->getCarrierOffice(null);
Czy to oznacza, że powyższa metoda wtyczki zostanie wykonana ponownie, ponieważ nie ma metody setInpostMachine () i getCarrierOffice () w klasie Adress? Dla mnie wygląda to na pętlę.setShippingMethod()
? Jak zwykle stosuje się tę metodę? Nie mogę znaleźć żadnych przechwyceń similar w kodzie Magento.źródło
setShippingMethod
wywołaniaAddressInterface
obiektu, a ponieważ nie ma takiej metody, musiałem użyć około__zadzwoń, aby sprawdzić, czysetShippingMethod
został nazwany lub jakieś inne magiczne pole. W tej chwili znalazłem lepsze miejsce i opublikuję je w nowej odpowiedzi.