Magento 2 शिपिंग विधि में ड्रॉपडाउन सूची जोड़ें


16

मैं कुछ लॉजिस्टिक कंपनी के लिए शिपिंग विधि विकसित करता हूं। इस कंपनी के कई कार्यालय हैं जहां ग्राहक अपना ऑर्डर प्राप्त कर सकता है। मैं एपीआई में ओइटी द्वारा कार्यालयों की सूची प्राप्त कर सकता हूं लेकिन अब मैं इस कदम का बेहतर प्रतिनिधित्व नहीं करता हूं?

अभी के लिए मैं बस \Magento\Quote\Model\Quote\Address\RateResult\Method शहर के हर कार्यालय में नए सेट करता हूं , बड़े शहर में इसकी गिनती> 100 है और मुझे लगता है कि चेकआउट में 100 लाइनों को सेट करना बहुत अच्छा नहीं है।

यह अलग-अलग चेकआउट डिज़ाइन के लिए सार्वजनिक मॉड्यूल होगा, इसलिए मैं कैसे अपने शिपिंग विधि के पास रेंडर कर सकता हूं कुछ कार्यालयों की सूची के साथ ड्रॉपडाउन सूची और उपयोगकर्ता का चयन करने के बाद मूल्य और विधि निर्धारित करें।


@ ज़ेफिरिन ने इस पोस्ट को बहुत दिलचस्प पाया, लेकिन मेरा एक सवाल है, अगर मुझे चुनिंदा दफ्तरों में नहीं दिखाना है, लेकिन स्टोर जो कि एमस्टी के मॉड्यूल के अंदर हैं, तो मैं आपके पोस्ट का दूसरा भाग कैसे करूंगा? मेरा मतलब है: वह स्थान कहाँ है जहाँ मैं xml घटक "seller_carrier_form" को भरने के लिए Amasty के सहायक को बुलाता हूँ? धन्यवाद
मावेरिक्को

यदि आपके पास कोई नया प्रश्न है, तो कृपया प्रश्न पूछें बटन पर क्लिक करके पूछें । इस प्रश्न का लिंक शामिल करें यदि यह संदर्भ प्रदान करने में मदद करता है। - समीक्षा से
जय

यह एक नया सवाल नहीं है, लेकिन ज़ेफिरिन द्वारा इस्तेमाल किए जाने के तरीके की भिन्नता है ... क्योंकि मैंने इस पोस्ट के पहले भाग का उपयोग किया है
maverickk89

जवाबों:


17

Magento चेकआउट शिपिंग विधि अतिरिक्त डेटा के लिए किसी भी प्रकार के फ़ॉर्म का समर्थन नहीं करता है। लेकिन यह shippingAdditionalचेकआउट में ब्लॉक प्रदान करता है जिसका उपयोग इसके लिए किया जा सकता है। निम्न समाधान मानक Magento चेकआउट के लिए काम करेगा।

पहले अपने कंटेनर को तैयार करते हैं जहां हम कुछ फार्म डाल सकते हैं। ऐसा करने के लिए एक फ़ाइल बनाएँview/frontend/layout/checkout_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <item name="shippingAdditional" xsi:type="array">
                                                            <item name="component" xsi:type="string">uiComponent</item>
                                                            <item name="displayArea" xsi:type="string">shippingAdditional</item>
                                                            <item name="children" xsi:type="array">
                                                                <item name="vendor_carrier_form" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Vendor_Module/js/view/checkout/shipping/form</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

अब एक फाइल बनाएं Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.jsजिसमें नॉकआउट टेम्पलेट रेंडर होगा। इसकी सामग्री इस तरह दिखती है

define([
    'jquery',
    'ko',
    'uiComponent',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/model/shipping-service',
    'Vendor_Module/js/view/checkout/shipping/office-service',
    'mage/translate',
], function ($, ko, Component, quote, shippingService, officeService, t) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Vendor_Module/checkout/shipping/form'
        },

        initialize: function (config) {
            this.offices = ko.observableArray();
            this.selectedOffice = ko.observable();
            this._super();
        },

        initObservable: function () {
            this._super();

            this.showOfficeSelection = ko.computed(function() {
                return this.ofices().length != 0
            }, this);

            this.selectedMethod = ko.computed(function() {
                var method = quote.shippingMethod();
                var selectedMethod = method != null ? method.carrier_code + '_' + method.method_code : null;
                return selectedMethod;
            }, this);

            quote.shippingMethod.subscribe(function(method) {
                var selectedMethod = method != null ? method.carrier_code + '_' + method.method_code : null;
                if (selectedMethod == 'carrier_method') {
                    this.reloadOffices();
                }
            }, this);

            this.selectedOffice.subscribe(function(office) {
                if (quote.shippingAddress().extensionAttributes == undefined) {
                    quote.shippingAddress().extensionAttributes = {};
                }
                quote.shippingAddress().extensionAttributes.carrier_office = office;
            });


            return this;
        },

        setOfficeList: function(list) {
            this.offices(list);
        },

        reloadOffices: function() {
            officeService.getOfficeList(quote.shippingAddress(), this);
            var defaultOffice = this.offices()[0];
            if (defaultOffice) {
                this.selectedOffice(defaultOffice);
            }
        },

        getOffice: function() {
            var office;
            if (this.selectedOffice()) {
                for (var i in this.offices()) {
                    var m = this.offices()[i];
                    if (m.name == this.selectedOffice()) {
                        office = m;
                    }
                }
            }
            else {
                office = this.offices()[0];
            }

            return office;
        },

        initSelector: function() {
            var startOffice = this.getOffice();
        }
    });
});

यह फ़ाइल नॉकआउट टेम्पलेट का उपयोग करती है जिसे अंदर रखा जाना चाहिए Vendor/Module/view/frontend/web/template/checkout/shipping/form.html

<div id="carrier-office-list-wrapper" data-bind="visible: selectedMethod() == 'carrier_method'">
    <p data-bind="visible: !showOfficeSelection(), i18n: 'Please provide postcode to see nearest offices'"></p>
    <div data-bind="visible: showOfficeSelection()">
        <p>
            <span data-bind="i18n: 'Select pickup office.'"></span>
        </p>
        <select id="carrier-office-list" data-bind="options: offices(),
                                            value: selectedOffice,
                                            optionsValue: 'name',
                                            optionsText: function(item){return item.location + ' (' + item.name +')';}">
        </select>
    </div>
</div>

अब हमारे पास एक चुनिंदा फ़ील्ड है जो तब दिखाई देगा जब हमारा तरीका (इसके कोड द्वारा परिभाषित) शिपिंग विधियों तालिका में चुना जाएगा। कुछ विकल्पों के साथ इसे भरने का समय। चूंकि मान पते पर निर्भर हैं, इसलिए सबसे अच्छा तरीका बाकी समापन बिंदु बनाना है जो उपलब्ध विकल्प प्रदान करेगा। मेंVendor/Module/etc/webapi.xml

<?xml version="1.0"?>

<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">

    <!-- Managing Office List on Checkout page -->
    <route url="/V1/module/get-office-list/:postcode/:city" method="GET">
        <service class="Vendor\Module\Api\OfficeManagementInterface" method="fetchOffices"/>
        <resources>
            <resource ref="anonymous" />
        </resources>
    </route>
</routes>

अब इंटरफ़ेस को इस Vendor/Module/Api/OfficeManagementInterface.phpरूप में परिभाषित करें

namespace Vendor\Module\Api;

interface OfficeManagementInterface
{

    /**
     * Find offices for the customer
     *
     * @param string $postcode
     * @param string $city
     * @return \Vendor\Module\Api\Data\OfficeInterface[]
     */
    public function fetchOffices($postcode, $city);
}

में कार्यालय डेटा के लिए इंटरफ़ेस को परिभाषित करें Vendor\Module\Api\Data\OfficeInterface.php। इस इंटरफ़ेस का उपयोग वेबैपी मॉड्यूल द्वारा आउटपुट के लिए डेटा को फ़िल्टर करने के लिए किया जाएगा ताकि आपको प्रतिक्रिया में जोड़ने के लिए जो भी आवश्यक हो उसे परिभाषित करना पड़े।

namespace Vendor\Module\Api\Data;

/**
 * Office Interface
 */
interface OfficeInterface
{
    /**
     * @return string
     */
    public function getName();

    /**
     * @return string
     */
    public function getLocation();
}

वास्तविक कक्षाओं के लिए समय। में सभी इंटरफेस के लिए प्राथमिकताएँ बनाने के साथ शुरू करेंVendor/Module/etc/di.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Vendor\Module\Api\OfficeManagementInterface" type="Vendor\Module\Model\OfficeManagement" />
    <preference for="Vendor\Module\Api\Data\OfficeInterface" type="Vendor\Module\Model\Office" />
</config>

अब Vendor\Module\Model\OfficeManagement.phpवह वर्ग बनाएं जो वास्तव में डेटा लाने का तर्क देगा।

namespace Vednor\Module\Model;

use Vednor\Module\Api\OfficeManagementInterface;
use Vednor\Module\Api\Data\OfficeInterfaceFactory;

class OfficeManagement implements OfficeManagementInterface
{
    protected $officeFactory;

    /**
     * OfficeManagement constructor.
     * @param OfficeInterfaceFactory $officeInterfaceFactory
     */
    public function __construct(OfficeInterfaceFactory $officeInterfaceFactory)
    {
        $this->officeFactory = $officeInterfaceFactory;
    }

    /**
     * Get offices for the given postcode and city
     *
     * @param string $postcode
     * @param string $limit
     * @return \Vendor\Module\Api\Data\OfficeInterface[]
     */
    public function fetchOffices($postcode, $city)
    {
        $result = [];
        for($i = 0, $i < 4;$i++) {
            $office = $this->officeFactory->create();
            $office->setName("Office {$i}");
            $office->setLocation("Address {$i}");
            $result[] = $office;
        }

        return $result;
    }
}

और अंत में के लिए वर्ग OfficeInterfaceमेंVendor/Module/Model/Office.php

namespace Vendor\Module\Model;

use Magento\Framework\DataObject;
use Vendor\Module\Api\Data\OfficeInterface;

class Office extends DataObject implements OfficeInterface
{
    /**
     * @return string
     */
    public function getName()
    {
        return (string)$this->_getData('name');
    }

    /**
     * @return string
     */
    public function getLocation()
    {
        return (string)$this->_getData('location');
    }
}

यह चुनिंदा फ़ील्ड दिखाना चाहिए और पता बदलने पर इसे अपडेट करना चाहिए। लेकिन हम दृश्यपटल हेरफेर के लिए एक और तत्व को याद कर रहे हैं। हमें फ़ंक्शन बनाने की आवश्यकता है जो समापन बिंदु को कॉल करेगा। इसमें कॉल पहले से ही शामिल है Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.jsऔर यह Vendor_Module/js/view/checkout/shipping/office-serviceवर्ग है जिसे Vendor/Module/view/frontend/web/js/view/checkout/shipping/office-service.jsनिम्नलिखित कोड के साथ जाना चाहिए :

define(
    [
        'Vendor_Module/js/view/checkout/shipping/model/resource-url-manager',
        'Magento_Checkout/js/model/quote',
        'Magento_Customer/js/model/customer',
        'mage/storage',
        'Magento_Checkout/js/model/shipping-service',
        'Vendor_Module/js/view/checkout/shipping/model/office-registry',
        'Magento_Checkout/js/model/error-processor'
    ],
    function (resourceUrlManager, quote, customer, storage, shippingService, officeRegistry, errorProcessor) {
        'use strict';

        return {
            /**
             * Get nearest machine list for specified address
             * @param {Object} address
             */
            getOfficeList: function (address, form) {
                shippingService.isLoading(true);
                var cacheKey = address.getCacheKey(),
                    cache = officeRegistry.get(cacheKey),
                    serviceUrl = resourceUrlManager.getUrlForOfficeList(quote);

                if (cache) {
                    form.setOfficeList(cache);
                    shippingService.isLoading(false);
                } else {
                    storage.get(
                        serviceUrl, false
                    ).done(
                        function (result) {
                            officeRegistry.set(cacheKey, result);
                            form.setOfficeList(result);
                        }
                    ).fail(
                        function (response) {
                            errorProcessor.process(response);
                        }
                    ).always(
                        function () {
                            shippingService.isLoading(false);
                        }
                    );
                }
            }
        };
    }
);

यह 2 और js फ़ाइलों का उपयोग करता है। Vendor_Module/js/view/checkout/shipping/model/resource-url-managerसमापन बिंदु के लिए एक url बनाता है और बहुत सरल है

define(
    [
        'Magento_Customer/js/model/customer',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/model/url-builder',
        'mageUtils'
    ],
    function(customer, quote, urlBuilder, utils) {
        "use strict";
        return {
            getUrlForOfficeList: function(quote, limit) {
                var params = {postcode: quote.shippingAddress().postcode, city: quote.shippingAddress().city};
                var urls = {
                    'default': '/module/get-office-list/:postcode/:city'
                };
                return this.getUrl(urls, params);
            },

            /** Get url for service */
            getUrl: function(urls, urlParams) {
                var url;

                if (utils.isEmpty(urls)) {
                    return 'Provided service call does not exist.';
                }

                if (!utils.isEmpty(urls['default'])) {
                    url = urls['default'];
                } else {
                    url = urls[this.getCheckoutMethod()];
                }
                return urlBuilder.createUrl(url, urlParams);
            },

            getCheckoutMethod: function() {
                return customer.isLoggedIn() ? 'customer' : 'guest';
            }
        };
    }
);

Vendor_Module/js/view/checkout/shipping/model/office-registryस्थानीय भंडारण में परिणाम रखने का एक तरीका है। इसका कोड है:

define(
    [],
    function() {
        "use strict";
        var cache = [];
        return {
            get: function(addressKey) {
                if (cache[addressKey]) {
                    return cache[addressKey];
                }
                return false;
            },
            set: function(addressKey, data) {
                cache[addressKey] = data;
            }
        };
    }
);

ठीक है, इसलिए हम सभी को फ्रंटेंड पर काम करना चाहिए। लेकिन अब इसके समाधान के लिए एक और समस्या है। चूंकि चेकआउट को इस फॉर्म के बारे में कुछ भी पता नहीं है, इसलिए यह चयन परिणाम को बैकएंड पर नहीं भेजेगा। ऐसा करने के लिए हमें उपयोग करने की आवश्यकता हैextension_attributes सुविधा । यह सिस्टम को सूचित करने के लिए magento2 में एक तरीका है कि बाकी कॉल में कुछ अतिरिक्त डेटा होने की उम्मीद है। इसके बिना Magento उन डेटा को फ़िल्टर कर देगा और वे कभी भी कोड तक नहीं पहुंचेंगे।

तो पहले Vendor/Module/etc/extension_attributes.xmlपरिभाषित करें:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="Magento\Quote\Api\Data\AddressInterface">
        <attribute code="carrier_office" type="string"/>
    </extension_attributes>
</config>

यह मान पहले से ही में अनुरोध में डाला जाता है form.jsद्वारा this.selectedOffice.subscribe()परिभाषा। तो उपरोक्त कॉन्फ़िगरेशन केवल प्रवेश द्वार पर इसे पारित करेगा। कोड में लाने के लिए एक प्लगइन बनाएंVendor/Module/etc/di.xml

<type name="Magento\Quote\Model\Quote\Address">
    <plugin name="inpost-address" type="Vendor\Module\Quote\AddressPlugin" sortOrder="1" disabled="false"/>
</type>

उस वर्ग के अंदर

namespace Vendor\Module\Plugin\Quote;

use Magento\Quote\Model\Quote\Address;
use Vendor\Module\Model\Carrier;

class AddressPlugin
{
    /**
     * Hook into setShippingMethod.
     * As this is magic function processed by __call method we need to hook around __call
     * to get the name of the called method. after__call does not provide this information.
     *
     * @param Address $subject
     * @param callable $proceed
     * @param string $method
     * @param mixed $vars
     * @return Address
     */
    public function around__call($subject, $proceed, $method, $vars)
    {
        $result = $proceed($method, $vars);
        if ($method == 'setShippingMethod'
            && $vars[0] == Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
            && $subject->getExtensionAttributes()
            && $subject->getExtensionAttributes()->getCarrierOffice()
        ) {
            $subject->setCarrierOffice($subject->getExtensionAttributes()->getCarrierOffice());
        }
        elseif (
            $method == 'setShippingMethod'
            && $vars[0] != Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
        ) {
            //reset office when changing shipping method
            $subject->getCarrierOffice(null);
        }
        return $result;
    }
}

बेशक जहां आप मूल्य बचाएंगे, यह पूरी तरह से आपकी आवश्यकताओं पर निर्भर करता है। उपरोक्त कोड अतिरिक्त स्तंभ बनाने की आवश्यकता होगी carrier_officeमें quote_addressऔर sales_addressटेबल और एक घटना (में Vendor/Module/etc/events.xml)

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_model_service_quote_submit_before">
        <observer name="copy_carrier_office" instance="Vendor\Module\Observer\Model\Order" />
    </event>
</config>

वह उद्धरण पते में सहेजे गए डेटा को बिक्री पते पर कॉपी करेगा।

मैंने पॉलिश कैरियर InPost के लिए अपने मॉड्यूल के लिए यह लिखा था इसलिए मैंने कुछ नाम बदले जो कोड को तोड़ सकते हैं लेकिन मुझे आशा है कि यह आपको वह देगा जो आपको चाहिए।

[संपादित करें]

कैरियर मॉडल @sangan द्वारा पूछा गया

namespace Vendor\Module\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Phrase;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Simplexml\ElementFactory;

class Carrier extends AbstractCarrier implements CarrierInterface
{
    const CARRIER_CODE = 'mycarier';

    const METHOD_CODE = 'mymethod';

    /** @var string */
    protected $_code = self::CARRIER_CODE;

    /** @var bool */
    protected $_isFixed = true;

    /**
     * Prepare stores to show on frontend
     *
     * @param RateRequest $request
     * @return \Magento\Framework\DataObject|bool|null
     */
    public function collectRates(RateRequest $request)
    {
        if (!$this->getConfigData('active')) {
            return false;
        }

        /** @var \Magento\Shipping\Model\Rate\Result $result */
        $result = $this->_rateFactory->create();

        /** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
        $method = $this->_rateMethodFactory->create();
        $method->setCarrier($this->_code);
        $method->setCarrierTitle($this->getConfigData('title'));

        $price = $this->getFinalPriceWithHandlingFee(0);
        $method->setMethod(self::METHOD_CODE);
        $method->setMethodTitle(new Phrase('MyMethod'));
        $method->setPrice($price);
        $method->setCost($price);
        $result->append($method);;

        return $result;
    }


    /**
     * @return array
     */
    public function getAllowedMethods()
    {
        $methods = [
            'mymethod' => new Phrase('MyMethod')
        ];
        return $methods;
    }
}

आपके विस्तारित उत्तर के लिए धन्यवाद, मैं आपके तरीके का उपयोग करके मेरी समस्या को हल करने का प्रयास करूंगा और इन दिनों परिणाम के साथ उत्तर दूंगा।
सियारि उचुकलेबौ

@Zefiryn मैंने एक कस्टम शिपिंग विधि बनाई है, इसके नीचे एक ड्रॉपडाउन होगा जिसमें ग्राहक के शिपिंग अकाउंट नंबर हैं (वहाँ कस्टम कस्टमर एट्रीब्यूट बनाया गया है) इसलिए अगर मुझे यह ड्रॉपडाउन दिखाना है तो आपका कितना प्रतिशत कोड मददगार होगा? आपके द्वारा प्रदान किए गए कोड से मुझे क्या चुनना चाहिए?
शिरीन एन

@ शायरन मैं लगभग 70% कहूँगा। आपको उस हिस्से को बदलने की आवश्यकता है जहां यह संख्याओं को साझा करने के लिए मशीनों को लाता है। तो एपीआई परिभाषा अलग-अलग होगी और जेएस इसका हिस्सा होगा
ज़ीफिरिन

मैंने इस मॉड्यूल को आज़माया है ... लेकिन इसका कोई परिवर्तन नहीं दिखा रहा है, इसलिए कृपया कार्यशील मॉड्यूल को साझा करें। यदि कोई भी
sangan

सफल मॉड्यूल को जोड़ने के बाद .. इन चेकआउट ajax लोडिंग को लगातार .. नीचे की तरह कंसोल एरर में दिखाया गया है: आवश्यकता:। js: 166 अनकवर्ड एरर: स्क्रिप्ट त्रुटि के लिए: Vendor_Module / js / view / checkout / शिपिंग / मॉडल / ऑफिस-रजिस्ट्री। आवश्यकता
js.org/docs/errors.html#scripterror

2

मैं पहले से ही प्रदान किए गए लेकिन इसे विकृत किए बिना विस्तार करने के लिए नए उत्तर जोड़ रहा हूं।

यह वह मार्ग है जो निम्नलिखित QuoteAddressPluginमें शामिल था:

1. Magento\Checkout\Api\ShippingInformationManagementInterface::saveAddressInformation()
2. Magento\Quote\Model\QuoteRepository::save() 
3. Magento\Quote\Model\QuoteRepository\SaveHandler::save() 
4. Magento\Quote\Model\QuoteRepository\SaveHandler::processShippingAssignment() 
5. Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentPersister::save()
6. Magento\Quote\Model\Quote\ShippingAssignment\ShippingAssignmentProcessor::save()
7. Magento\Quote\Model\Quote\ShippingAssignment\ShippingProcessor::save()
8. Magento\Quote\Model\ShippingMethodManagement::apply() 

अंतिम विधि कॉलिंग थी Magento\Quote\Model\Quote\Address::setShippingMethod()जो वास्तव में कॉल थी Magento\Quote\Model\Quote\Address::__call()जिसके लिए मैंने उपयोग किया था। अभी मुझे प्लगइन के लिए एक बेहतर जगह मिली, यह Magento\Quote\Model\ShippingAssignment::setShipping()विधि है। तो प्लगइन भाग को फिर से लिखा जा सकता है:

<type name="Magento\Quote\Model\ShippingAssignment">
    <plugin name="carrier-office-plugin" type="Vendor\Module\Plugin\Quote\ShippingAssignmentPlugin" sortOrder="1" disabled="false"/>
</type>

और खुद प्लगइन:

namespace Vednor\Module\Plugin\Quote;

use Magento\Quote\Api\Data\AddressInterface;
use Magento\Quote\Api\Data\ShippingInterface;
use Magento\Quote\Model\ShippingAssignment;
use Vendor\Module\Model\Carrier;

/**
 * ShippingAssignmentPlugin
 */
class ShippingAssignmentPlugin
{
    /**
     * Hook into setShipping.
     *
     * @param ShippingAssignment $subject
     * @param ShippingInterface $value
     * @return Address
     */
    public function beforeSetShipping($subject, ShippingInterface $value)
    {
        $method = $value->getMethod();
        /** @var AddressInterface $address */
        $address = $value->getAddress();
        if ($method === Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE
            && $address->getExtensionAttributes()
            && $address->getExtensionAttributes()->getCarrierOffice()
        ) {
            $address->setCarrierOffice($address->getExtensionAttributes()->getCarrierOffice());
        }
        elseif ($method !== Carrier::CARRIER_CODE.'_'.Carrier::METHOD_CODE) {
            //reset inpost machine when changing shipping method
            $address->setCarrierOffice(null);
        }
        return [$value];
    }
}

1

@ ज़ेफिरिन, मुझे इस समस्या का सामना करना पड़ा: quote.shippingAddress().extensionAttributes.carrier_office = office;

जब मैं पहली बार (नई निजी विंडो) चेकआउट में एक अतिथि के रूप में (लेकिन पंजीकृत ग्राहक के साथ ऐसा ही होता है) विशेषता कार्यालय पहले "अगला" के बाद डेटाबेस में सहेजा नहीं गया है। हालांकि कंसोल में मुझे सही आउटपुट दिखाई देता है:console.log(quote.shippingAddress().extensionAttributes.carrier_office);

जब मैं पहले चेकआउट पृष्ठ पर वापस जाता हूं और फिर से कार्यालय का चयन करता हूं तब इसे बचाया जाता है। इस व्यवहार का कारण क्या हो सकता है?

मैंने उपयोग करने की कोशिश की: address.trigger_reload = new Date().getTime(); rateRegistry.set(address.getKey(), null); rateRegistry.set(address.getCacheKey(), null); quote.shippingAddress(address);

लेकिन सफलता के बिना ...


0

@Zefiryn, क्या आप कुछ शब्दों में समझा सकते हैं कि आपका उपरोक्त प्लगइन कैसे काम करता है? Im थोड़ा उलझन में है क्योंकि जैसा कि मुझे पता है कि __call पद्धति को निष्पादित किया जाता है यदि हम किसी विशेष वस्तु के लिए मौजूद पद्धति को निष्पादित करने का प्रयास करते हैं। यह सच प्रतीत होता है क्योंकि ऐप / कोड / मैगनेटो / उद्धरण / मॉडल / उद्धरण / पता.php में मुझे ऐसी कोई विधि नहीं दिखती है - केवल इस प्रकार है:

/** * Sales Quote address model ... * @method Address setShippingMethod(string $value)

  1. जब कोई विधि लागू नहीं होती है तो आप अवरोधन के चारों ओर क्यों इस्तेमाल करते हैं?
  2. आगे मैं देख रहा हूं $subject->setInpostMachineऔर $subject->getCarrierOffice(null);क्या इसका मतलब है कि उपरोक्त विधि को फिर से निष्पादित किया जाएगा क्योंकि कोई सेट नहीं है। InInostMachine () और getCarrierOffice () विधि Adress Class में है? यह मुझे पाश की तरह लगता है।
  3. जहां से Magento निष्पादित करते हैं setShippingMethod()? आमतौर पर इस विधि का उपयोग कैसे किया जाता है? मैं Magento कोड में किसी भी simillar अवरोधन नहीं मिल सकता।

ठीक है, इसलिए मैंने एक मॉड्यूल के आधार पर उत्तर तैयार किया जिसे मैंने परीक्षण के लिए लिखा था, इसमें inpost_machine फ़ील्ड का उपयोग किया गया था, इसलिए यह सिर्फ इस जगह वाहक_ऑफ़िस में सही रूप से परिवर्तित नहीं हुआ। दूसरा, उस समय जब मैं इस मॉड्यूल को विकसित कर रहा था, मुझे ऐसी जगह नहीं मिली, जहां मुझे चयनित वाहक और पते दोनों मिल सकते हैं, setShippingMethodजिसे AddressInterfaceऑब्जेक्ट पर कॉल के अलावा भेजे गए एक्सटेंशन विशेषताओं के साथ भेजा गया है और चूंकि ऐसी कोई विधि नहीं है, तो मुझे यह देखने के लिए लगभग _call का उपयोग करना होगा कि क्या setShippingMethodबुलाया गया था या कुछ अन्य जादू क्षेत्र। अभी मुझे एक बेहतर जगह मिली है और मैं इसे नए उत्तर में पोस्ट करूंगा।
ज़ेफिरिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.