Background
We have a custom shipping method "Click & Collect", with this custom shipping method is a custom calculator on the checkout_cart_index page which will return all the nearest stockists to the given postcode.
The Problem
Most of it works fine, but the shipping carrier method and address are not being set and when the user proceeds to checkout they are required to fill this information in again.
The Code
define(
[
'ko',
'jquery',
'Magento_Ui/js/form/form',
'uiRegistry',
'Magento_Checkout/js/model/quote',
'Magento_Checkout/js/model/resource-url-manager',
'mage/storage',
'Magento_Checkout/js/action/create-shipping-address',
'Magento_Checkout/js/model/error-processor',
'Magento_Checkout/js/model/shipping-service',
'Magento_Checkout/js/model/cart/totals-processor/default',
'Magento_Checkout/js/model/shipping-rate-registry'
],
function (
ko,
$,
Component,
uiRegistry,
quote,
resourceUrlManager,
storage,
createShippingAddress,
errorProcessor,
shippingService,
totalsDefaultProvider,
rateRegistry
) {
'use strict';
var ClickAndCollectConfig = window.checkout.clickandcollect;
return Component.extend({
defaults: {
template: 'Convert_ClickAndCollect/cart/click-collect-stores'
},
formId: "#selectWarehouseForm",
parent: {},
postCode: ko.observable(''),
wareHouses: ko.observableArray(),
address: {},
isWarehouseSelected: ko.observable(""),
/**
* @override
*/
initialize: function () {
this._super();
$(document).ready(() => this.ready());
return this;
},
ready: function () {
this.parent = uiRegistry.get(this.parentName);
},
selectWarehouse: function(warehouseId) {
if ($('#s_method_freeshipping').length) {
return false;
}
if (!this.validateForm(this.formId)) {
return false;
}
if (warehouseId != null) {
let body = $('body').loader();
let uri = this.getFormAction();
let payload = JSON.stringify({
addressInformation: {
address: {
countryId: 'AU',
postcode: this.postCode(),
regionId: 0
},
shipping_carrier_code: ClickAndCollectConfig.shipping.carrier_code,
shipping_method_code: warehouseId
}
});
this.address = createShippingAddress(payload);
shippingService.isLoading(true);
storage.post(
uri, payload, true
).done(
(resp) => this.selectWarehouseSuccess(resp, this.getInputValue(warehouseId))
).fail(
(resp) => this.selectWarehouseFail(resp)
).always(
() => this.selectWarehouseAlways()
);
}
return false;
},
selectWarehouseSuccess: function(result, checked) {
if (result) {
rateRegistry.set(this.address.getCacheKey(), result);
shippingService.setShippingRates(result);
quote.setTotals(result);
}
this.isWarehouseSelected(checked);
},
selectWarehouseFail: function(response) {
console.error("There was an error saving shipping the method, no address will be used at this time");
shippingService.setShippingRates([]);
errorProcessor.process(response);
},
selectWarehouseAlways: function() {
let body = $('body').loader();
body.loader('hide');
shippingService.isLoading(false);
},
validateForm: function (form) {
return $(form).validation() && $(form).validation('isValid');
},
getInputValue(warehouseId) {
return ClickAndCollectConfig.shipping.carrier_code + "_" + warehouseId;
},
getFormAction() {
return resourceUrlManager.getUrlForTotalsEstimationForNewAddress(quote);
},
});
}
);
The main methods of concern here are:
selectWarehouse: This is the main method that gets fired on clicking the radio input. It builds the payload parameters and then performs the POST request which should garner the correct response and set the shipping method and address ready for the next page (checkout).
selectWarehouseSuccess: Where the quote and shipping totals are updated with the response of selectWarehouse.
getInputValue: This is the required format for the radio inputs which goes [Shipping Carrier Code]_[Shipping_Method_Code]
getFormAction: Returns the correct URI endpoint to POST to using the 'Magento_Checkout/js/model/resource-url-manager' which should be either '/guest-carts/:cartId/totals-information' or '/carts/mine/totals-information'.
When building the request, from the network tab of the browsers console, I can see that the correct POST has been sent with my created params and it even returns a valid 200 response. But in selectWarehouseSuccess the result is false and quote.
I am taking my inspiration from Magento_Checkout/js/model/cart/totals-processor/default.js - which does it similarly.
After a couple days of this, I believe it's time for a fresh pair of eyes. Am I doing this correctly? Is there an easier way?
Thanks for reading