I am working on https://www.depoto.com/.
Right now, we are having two delivery options for product availability like Product is available and Product is not available.
For this, we used https://www.magearray.com/check-delivery-availability-extension-for-magento-2.html Extension. In this extension, they provided the fields to add the pin codes. If the user entered pin code, Then available or not available message will display.
And, We provide two shipping methods like Free shipping and Flat rate shipping method
Flat rate shipping method should come to the product not available locations.
Note: Flat Rate method for Delivery available pin codes
My flatrate.php code is as follows:
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\OfflineShipping\Model\Carrier;
use Magento\OfflineShipping\Model\Carrier\Flatrate\ItemPriceCalculator;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\CarrierInterface;
use Magento\Shipping\Model\Rate\Result;
/**
* Flat rate shipping model
*
* @api
* @since 100.0.2
*/
class Flatrate extends AbstractCarrier implements CarrierInterface
{
/**
* @var string
*/
protected $_code = 'flatrate';
/**
* @var bool
*/
protected $_isFixed = true;
/**
* @var \Magento\Shipping\Model\Rate\ResultFactory
*/
protected $_rateResultFactory;
/**
* @var \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory
*/
protected $_rateMethodFactory;
/**
* @var ItemPriceCalculator
*/
private $itemPriceCalculator;
/**
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
* @param \Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory
* @param \Psr\Log\LoggerInterface $logger
* @param \Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory
* @param \Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory
* @param ItemPriceCalculator $itemPriceCalculator
* @param array $data
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
\Magento\OfflineShipping\Model\Carrier\Flatrate\ItemPriceCalculator $itemPriceCalculator,
array $data = []
) {
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
$this->itemPriceCalculator = $itemPriceCalculator;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
/**
* @param RateRequest $request
* @return Result|bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$freeBoxes = $this->getFreeBoxesCount($request);
$this->setFreeBoxes($freeBoxes);
/** @var Result $result */
$result = $this->_rateResultFactory->create();
$shippingPrice = $this->getShippingPrice($request, $freeBoxes);
if ($shippingPrice !== false) {
$method = $this->createResultMethod($shippingPrice);
$result->append($method);
}
return $result;
}
/**
* @param RateRequest $request
* @return int
*/
private function getFreeBoxesCount(RateRequest $request)
{
$freeBoxes = 0;
if ($request->getAllItems()) {
foreach ($request->getAllItems() as $item) {
if ($item->getProduct()->isVirtual() || $item->getParentItem()) {
continue;
}
if ($item->getHasChildren() && $item->isShipSeparately()) {
$freeBoxes += $this->getFreeBoxesCountFromChildren($item);
} elseif ($item->getFreeShipping()) {
$freeBoxes += $item->getQty();
}
}
}
return $freeBoxes;
}
/**
* @return array
*/
public function getAllowedMethods()
{
return ['flatrate' => $this->getConfigData('name')];
}
/**
* @param RateRequest $request
* @param int $freeBoxes
* @return bool|float
*/
private function getShippingPrice(RateRequest $request, $freeBoxes)
{
$shippingPrice = false;
$configPrice = $this->getConfigData('price');
if ($this->getConfigData('type') === 'O') {
// per order
$shippingPrice = $this->itemPriceCalculator->getShippingPricePerOrder($request, $configPrice, $freeBoxes);
} elseif ($this->getConfigData('type') === 'I') {
// per item
$shippingPrice = $this->itemPriceCalculator->getShippingPricePerItem($request, $configPrice, $freeBoxes);
}
$shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);
if ($shippingPrice !== false && $request->getPackageQty() == $freeBoxes) {
$shippingPrice = '0.00';
}
return $shippingPrice;
}
/**
* @param int|float $shippingPrice
* @return \Magento\Quote\Model\Quote\Address\RateResult\Method
*/
private function createResultMethod($shippingPrice)
{
/** @var \Magento\Quote\Model\Quote\Address\RateResult\Method $method */
$method = $this->_rateMethodFactory->create();
$method->setCarrier('flatrate');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('flatrate');
$method->setMethodTitle($this->getConfigData('name'));
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
return $method;
}
/**
* @param mixed $item
* @return mixed
*/
private function getFreeBoxesCountFromChildren($item)
{
$freeBoxes = 0;
foreach ($item->getChildren() as $child) {
if ($child->getFreeShipping() && !$child->getProduct()->isVirtual()) {
$freeBoxes += $item->getQty() * $child->getQty();
}
}
return $freeBoxes;
}
}
My check_availability.phtml file is as follows:
Path for this file: /app/code/MageArray/CheckDelivery/view/frontend/templates/product/view
<?php $product = $this->getCurrentProduct() ?>
<?php $helper=$this->helper("MageArray\CheckDelivery\Helper\Data");?>
<?php if($product && $product->getCheckDeliveryEnable() != 2 && $helper->getIsActive() == 1): ?>
<form class="form" id="check-delivery-form" method="post">
<fieldset class="fieldset">
<legend class="legend"><span><?php echo __('Check Product Availability') ?></span></legend><br>
<div class="row">
<div class="field required col-sm-6">
<label for="delivery_postcode" class="label"><span><?php echo __('Pincode') ?></span></label>
<div class="control">
<input type="text" name="postcode" id="delivery_postcode" value="" title="<?php echo __('Postcode') ?>" class="input-text" data-validate="{required:true, 'validate-digits':true}">
</div>
</div>
<div class="actions-toolbar col-sm-6">
<div class="primary">
<button type="submit" class="action submit primary action-check-delivery" title="<?php echo __('Check') ?>"><span><?php echo __('Check') ?></span></button>
</div>
</div>
</div>
<div class="break"></div>
<div class="message"></div>
</fieldset>
</form>
<script>
require([
'jquery',
'mage/mage'
], function ($) {
var dataForm = $('#check-delivery-form');
dataForm.mage('validation', {});
var dataFormMessage = $('#check-delivery-form .message');
dataFormMessage.removeClass('success').removeClass('error').hide();
$('.action-check-delivery').on('click',function () {
var formData = new FormData();
formData.append('postcode', $('#check-delivery-form input[name="postcode"]').val());
$.ajax({
url: '<?php echo $this->getUrl('checkDelivery/postcode/check',['id'=> $product->getId()]) ?>',
data: formData,
processData: false,
contentType: false,
showLoader: true,
type: 'POST',
dataType: 'json',
success: function (response) {
dataFormMessage.removeClass('success').removeClass('error').hide();
dataFormMessage.addClass(response.type).html(response.message).show();
}
});
return false;
});
});
</script>
<?php endif; ?>
Brief explanation:
We have two shipping methods, 1. Store pickup (customer will come to store and collect his items) 2. free shipping method.
We will provide the shipping items to some list of pincodes only. If any customer enter his area zip code for delivery, that entered zip code exists from our providing zipcodes, the free shipping and store pickup methods shold be same.
But if entered zipcode not available from our list, the store pickup only has to be one. For store pickup, we use flat rate method (Renamed from flat rate to Store pickup)