ম্যাজেন্টো চেকআউট অতিরিক্ত ডেটা শিপিংয়ের জন্য কোনও ধরণের ফর্ম সমর্থন করে না। তবে এটি 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
। এই ইন্টারফেসটি আউটপুটটির জন্য ডেটা ফিল্টার করার জন্য ওয়েবপি মডিউল ব্যবহার করবে যাতে আপনাকে প্রতিক্রিয়াতে যা যোগ করতে হবে তা নির্ধারণ করতে হবে।
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 টি জেএস ফাইল ব্যবহার করা হয়। Vendor_Module/js/view/checkout/shipping/model/resource-url-manager
শেষ পয়েন্টে একটি ইউআরএল তৈরি করে এবং বেশ সহজ
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
বৈশিষ্ট্যটি ব্যবহার করতে হবে । সিস্টেমটিকে অবহিত করার জন্য এটি ম্যাজেন্টো 2-তে একটি উপায় যা কিছু অতিরিক্ত ডেটা বাকী কলগুলিতে প্রত্যাশিত। এটি ছাড়া ম্যাজেন্টো সেই ডেটাগুলি ফিল্টার করে দেয় এবং তারা কখনই কোডে পৌঁছাতে পারে না।
সুতরাং 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;
}
}
অবশ্যই আপনি মানটি কোথায় সংরক্ষণ করবেন তা আপনার প্রয়োজনীয়তার উপর নির্ভর করে on উপরের কোড অতিরিক্ত কলাম তৈরি করতে হবে 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>
এটি বিক্রয় ঠিকানাতে উদ্ধৃতি ঠিকানায় সংরক্ষিত ডেটা অনুলিপি করবে।
আমি পোলিশ ক্যারিয়ার ইনপোস্টের জন্য আমার মডিউলটির জন্য এটি লিখেছিলাম তাই আমি কিছু নাম পরিবর্তন করেছি যা কোড ভঙ্গ করতে পারে তবে আমি আশা করি এটি আপনাকে যা দেবে তা আপনাকে দেবে।
[Edit]
ক্যারিয়ারের মডেল @ সাঙ্গান জিজ্ঞাসা করেছেন
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;
}
}