Magento 2 เพิ่มรายการแบบเลื่อนลงเพื่อวิธีการจัดส่ง


16

ฉันพัฒนาวิธีการจัดส่งสำหรับ บริษัท ขนส่งบางแห่ง บริษัท นี้มีสำนักงานหลายแห่งที่ลูกค้าสามารถรับออเดอร์ได้ ฉันสามารถรับรายชื่อสำนักงานโดยсityในAPIแต่ตอนนี้ฉันไม่ได้เป็นตัวแทนของขั้นตอนนี้ดีขึ้นกว่าเดิมอีกแล้ว?

สำหรับตอนนี้ฉันเพิ่งตั้ง\Magento\Quote\Model\Quote\Address\RateResult\Method สำนักงานใหม่ทุกแห่งในเมืองในเมืองใหญ่มันนับ> 100และฉันคิดว่ามันไม่ดีมากที่จะกำหนด 100 บรรทัดในการชำระเงิน

มันจะเป็นโมดูลสาธารณะสำหรับการออกแบบเช็คเอาต์ที่แตกต่างกันดังนั้นฉันจะแสดงใกล้วิธีการจัดส่งของฉันที่เลือกรายการแบบเลื่อนลงที่มีรายชื่อของสำนักงานและกำหนดราคาและวิธีการหลังจากที่ผู้ใช้เลือกอย่างใดอย่างหนึ่ง


@ Zefiryn ฉันพบว่าโพสต์นี้น่าสนใจมาก แต่ฉันมีคำถามถ้าฉันต้องแสดงในการเลือกไม่ใช่สำนักงาน แต่ร้านค้าที่อยู่ในโมดูลของ Amasty ฉันจะทำอย่างไรในส่วนที่สองของโพสต์ของคุณ? ฉันหมายถึง: สถานที่ที่ฉันเรียกผู้ช่วยของ Amasty อยู่ที่ไหนเพื่อเติมองค์ประกอบ xml "seller_carrier_form" ขอบคุณ
maverickk89

หากคุณมีคำถามใหม่โปรดขอได้โดยคลิกที่ถามคำถามปุ่ม รวมลิงค์ไปยังคำถามนี้หากช่วยระบุบริบท - จากการตรวจสอบ
Jai

นี่ไม่ใช่คำถามใหม่ แต่เป็นการเปลี่ยนแปลงของวิธีที่ Zefiryn ใช้ ... เพราะฉันใช้ส่วนแรกของโพสต์ตามที่เป็นอยู่
maverickk89

คำตอบ:


17

การชำระเงินแบบคุณภาพเยี่ยมไม่สนับสนุนรูปแบบใด ๆ สำหรับวิธีการจัดส่งข้อมูลเพิ่มเติม แต่มันมีshippingAdditionalบล็อกในการชำระเงินซึ่งสามารถใช้สำหรับการนี้ วิธีแก้ปัญหาต่อไปนี้จะใช้งานได้กับการชำระเงินแบบมาตรฐานคุณภาพเยี่ยม

ก่อนอื่นมาเตรียมภาชนะของเราที่เราสามารถใส่รูปแบบ เมื่อต้องการทำสิ่งนี้ให้สร้างไฟล์ใน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กำหนดอินเตอร์เฟซสำหรับข้อมูลสำนักงานใน อินเทอร์เฟซนี้จะถูกใช้โดยโมดูล webapi เพื่อกรองข้อมูลสำหรับผลลัพธ์ดังนั้นคุณต้องกำหนดสิ่งที่คุณต้องการเพิ่มในการตอบกลับ

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);
                        }
                    );
                }
            }
        };
    }
);

มันใช้ไฟล์ js อีก 2 ไฟล์ 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 เพื่อแจ้งให้ระบบทราบว่าข้อมูลเพิ่มเติมบางอย่างคาดว่าจะอยู่ในการโทรที่เหลือ หากไม่มีวีโอไอพีจะทำการกรองข้อมูลเหล่านั้นและพวกเขาจะไม่เข้าถึงรหัส

ดังนั้นก่อนอื่นในVendor/Module/etc/extension_attributes.xmldefine:

<?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;
    }
}

ขอบคุณสำหรับการตอบกลับแบบขยายฉันจะพยายามแก้ไขปัญหาของฉันโดยใช้วิธีการของคุณและจะตอบกลับพร้อมกับผลลัพธ์ในวันนี้
Siarhey Uchukhlebau

@Zefiryn ฉันได้สร้างวิธีการจัดส่งแบบกำหนดเองด้านล่างจะแสดงรายการแบบหล่นลงที่มีหมายเลขบัญชีการจัดส่งของลูกค้า (มีแอตทริบิวต์ของลูกค้าที่กำหนดเองที่สร้างขึ้น) ดังนั้นหากฉันต้องแสดงรายการแบบหล่นลงนี้ ฉันควรรับอะไรจากรหัสที่คุณให้
Shireen N

@shire ฉันจะพูดประมาณ 70% คุณต้องเปลี่ยนชิ้นส่วนที่จะดึงเครื่องเป็นหมายเลขบัญชี ดังนั้นคำจำกัดความของ api จะมีความแตกต่างกัน
เล็กน้อย

ฉันได้ลองโมดูลนี้ ... แต่มันไม่แสดงการเปลี่ยนแปลงใด ๆ ดังนั้นโปรดแบ่งปัน module.if ใด ๆ
sangan

หลังจากเพิ่มโมดูลที่ประสบความสำเร็จ .. ในการเช็คเอาต์ Ajax กำลังโหลดอย่างต่อเนื่อง .. ในคอนโซลแสดงข้อผิดพลาดดังต่อไปนี้: require.js: 166 ข้อผิดพลาดที่ไม่ได้รับ: ข้อผิดพลาดสคริปต์สำหรับ: Vendor_Module / js / view / checkout / shipping / model / office-registry requirejs.org/docs/errors.html#scripterror
sangan

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

@ Zeiryn ฉันเจอปัญหากับ: 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 คุณสามารถอธิบายได้สองสามคำว่าปลั๊กอินด้านบนทำงานอย่างไร? ฉันสับสนเล็กน้อยเพราะอย่างที่ฉันรู้ว่าวิธีการเรียกใช้ __call นั้นถูกเรียกใช้ถ้าเราลองใช้วิธีการที่ไม่มีอยู่สำหรับวัตถุนั้น ๆ ดูเหมือนว่าจะเป็นจริงเพราะใน app / รหัส / วีโอไอพี / อ้างอิง / รุ่น / ใบเสนอราคา / Address.php ฉันไม่เห็นวิธีการดังกล่าว - เพียงความเห็น:

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

  1. เหตุใดคุณจึงใช้การดักจับเมื่อไม่มีการใช้วิธีการ
  2. ต่อไปฉันเห็น$subject->setInpostMachineและ$subject->getCarrierOffice(null);หมายความว่าวิธีการข้างต้นของปลั๊กอินจะถูกดำเนินการอีกครั้งเนื่องจากไม่มีวิธี setInpostMachine () และ getCarrierOffice () ใน Adress Class หรือไม่ ดูเหมือนว่าห่วงฉัน
  3. วีโอไอพีทำงานจากที่ไหนsetShippingMethod()? วิธีนี้ใช้บ่อยแค่ไหน? ฉันไม่สามารถหาการสกัดแบบซิลลาร์ใด ๆ ในรหัสวีโอไอพี

ตกลงดังนั้นฉันจึงเตรียมคำตอบตามโมดูลที่ฉันเขียนสำหรับการทดสอบมันใช้ฟิลด์ inpost_machine ดังนั้นอันนี้เพิ่งเปลี่ยนไม่ถูกต้องเป็น carrier_office ในสถานที่นี้ ประการที่สองในขณะที่ฉันกำลังพัฒนาโมดูลนี้ฉันไม่พบสถานที่ที่ฉันสามารถรับทั้งผู้ให้บริการที่เลือกและที่อยู่พร้อมกับส่วนขยายคุณลักษณะที่ส่งยกเว้นการsetShippingMethodโทรบนAddressInterfaceวัตถุและเนื่องจากไม่มีวิธีการดังกล่าวดังนั้นฉันจึงต้องใช้setShippingMethodถูกเรียกหรือสนามเวทมนตร์อื่น ๆ ตอนนี้ฉันได้พบที่ที่ดีขึ้นแล้วและฉันจะโพสต์ไว้ในคำตอบใหม่
Zefiryn
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.