Select Git revision
BobGo.php 34.84 KiB
<?php
declare(strict_types=1);
namespace BobGroup\BobGo\Model\Carrier;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\CatalogInventory\Api\StockRegistryInterface;
use Magento\Checkout\Api\Data\ShippingInformationInterface;
use Magento\Directory\Helper\Data;
use Magento\Directory\Model\CountryFactory;
use Magento\Directory\Model\CurrencyFactory;
use Magento\Directory\Model\RegionFactory;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\DataObject;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\HTTP\Client\CurlFactory;
use Magento\Framework\Module\Dir\Reader;
use Magento\Framework\Xml\Security;
use Magento\Quote\Model\Quote\Address\RateRequest;
use Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory;
use Magento\Quote\Model\Quote\Address\RateResult\MethodFactory;
use Magento\Sales\Model\Order\Shipment;
use Magento\Shipping\Model\Carrier\AbstractCarrier;
use Magento\Shipping\Model\Carrier\AbstractCarrierOnline;
use Magento\Shipping\Model\Rate\Result;
use Magento\Shipping\Model\Rate\ResultFactory;
use Magento\Shipping\Model\Simplexml\ElementFactory;
use Magento\Shipping\Model\Tracking\Result\StatusFactory;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
/**
* Bob Go shipping implementation
* @category Bob Go
* @package bobgo_CustomShipping
* @author Bob Go
* @website https://www.bobgo.co.za
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyFields)
*/
class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Carrier\CarrierInterface
{
/**
* Code of the carrier
* @var string
*/
public const CODE = 'bobgo';
const UNITS = 100;
/**
* Code of the carrier
*
* @var string
*/
protected $_code = self::CODE;
/**
* Rate request data
*
* @var RateRequest|null
*/
protected $_request = null;
/**
* Rate result data
*
* @var Result|null
*/
protected $_result = null;
/**
* Container types that could be customized for bobgo carrier
*
* @var string[]
*/
protected $_customizableContainerTypes = ['YOUR_PACKAGING'];
/**
* @var \Magento\Store\Model\StoreManagerInterface
*/
protected $_storeManager;
/**
* @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
*/
protected $_productCollectionFactory;
/**
* @var DataObject
*/
private $_rawTrackingRequest;
/**
* @var \Magento\Framework\HTTP\Client\Curl
*/
protected \Magento\Framework\HTTP\Client\Curl $curl;
/**
* @var ScopeConfigInterface
*/
protected $scopeConfig; // Declare the scopeConfig property
/**
* @param \Magento\Framework\Controller\Result\JsonFactory $jsonFactory
*/
protected JsonFactory $jsonFactory;
private $cartRepository;
public Company $company;
/**
* @param ScopeConfigInterface $scopeConfig
* @param ErrorFactory $rateErrorFactory
* @param LoggerInterface $logger
* @param Security $xmlSecurity
* @param ElementFactory $xmlElFactory
* @param ResultFactory $rateFactory
* @param MethodFactory $rateMethodFactory
* @param \Magento\Shipping\Model\Tracking\ResultFactory $trackFactory
* @param \Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory
* @param StatusFactory $trackStatusFactory
* @param RegionFactory $regionFactory
* @param CountryFactory $countryFactory
* @param CurrencyFactory $currencyFactory
* @param Data $directoryData
* @param StockRegistryInterface $stockRegistry
* @param StoreManagerInterface $storeManager
* @param Reader $configReader
* @param CollectionFactory $productCollectionFactory
* @param JsonFactory $jsonFactory
* @param CurlFactory $curlFactory
* @param array $data
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
Security $xmlSecurity,
\Magento\Shipping\Model\Simplexml\ElementFactory $xmlElFactory,
\Magento\Shipping\Model\Rate\ResultFactory $rateFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
\Magento\Shipping\Model\Tracking\ResultFactory $trackFactory,
\Magento\Shipping\Model\Tracking\Result\ErrorFactory $trackErrorFactory,
\Magento\Shipping\Model\Tracking\Result\StatusFactory $trackStatusFactory,
\Magento\Directory\Model\RegionFactory $regionFactory,
\Magento\Directory\Model\CountryFactory $countryFactory,
\Magento\Directory\Model\CurrencyFactory $currencyFactory,
\Magento\Directory\Helper\Data $directoryData,
\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Module\Dir\Reader $configReader,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
JsonFactory $jsonFactory,
CurlFactory $curlFactory,
array $data = []
) {
$this->_storeManager = $storeManager;
$this->_productCollectionFactory = $productCollectionFactory;
$this->scopeConfig = $scopeConfig;
parent::__construct(
$scopeConfig,
$rateErrorFactory,
$logger,
$xmlSecurity,
$xmlElFactory,
$rateFactory,
$rateMethodFactory,
$trackFactory,
$trackErrorFactory,
$trackStatusFactory,
$regionFactory,
$countryFactory,
$currencyFactory,
$directoryData,
$stockRegistry,
$data
);
$this->jsonFactory = $jsonFactory;
$this->curl = $curlFactory->create();
$this->company = new Company();
}
/*
* Gets the base url of the store by stripping the http:// or https:// and wwww. from the url
* leaving just "example.com" since Bob Go API uses this format and not the full url as the Identifier
* @var \Magento\Store\Model\StoreManagerInterface $this->_storeManager
* @return string
*/
public function getBaseUrl(): string
{
$storeBase = $this->_storeManager->getStore()->getBaseUrl();
return parse_url($storeBase, PHP_URL_HOST);
}
/**
* Make request to Bob Go API to get shipping rates for the cart
* After all the required data is collected, it makes a request to the Bob Go API to get the shipping rates
* @param $payload
* @return array
*/
public function getRates($payload): array
{
return $this->uRates($payload);
}
/**
* Processing additional validation to check if carrier applicable.
*
* @param \Magento\Framework\DataObject $request
* @return $this|bool|\Magento\Framework\DataObject
*/
public function processAdditionalValidation(\Magento\Framework\DataObject $request)
{
if (!count($this->getAllItems($request))) {
return false;
}
$maxAllowedWeight = 500; //$this->getConfigData('max_package_weight');
$errorMsg = '';
$configErrorMsg = $this->getConfigData('specificerrmsg');
$defaultErrorMsg = __('The shipping module is not available.');
$showMethod = $this->getConfigData('showmethod');
/** @var $item \Magento\Quote\Model\Quote\Item */
foreach ($this->getAllItems($request) as $item) {
$product = $item->getProduct();
if ($product && $product->getId()) {
$weight = $product->getWeight();
$stockItemData = $this->stockRegistry->getStockItem(
$product->getId(),
$item->getStore()->getWebsiteId()
);
$doValidation = true;
if ($stockItemData->getIsQtyDecimal() && $stockItemData->getIsDecimalDivided()) {
if ($stockItemData->getEnableQtyIncrements() && $stockItemData->getQtyIncrements()
) {
$weight = $weight * $stockItemData->getQtyIncrements();
} else {
$doValidation = false;
}
} elseif ($stockItemData->getIsQtyDecimal() && !$stockItemData->getIsDecimalDivided()) {
$weight = $weight * $item->getQty();
}
if ($doValidation && $weight > $maxAllowedWeight) {
$errorMsg = $configErrorMsg ? $configErrorMsg : $defaultErrorMsg;
break;
}
}
}
if (!$errorMsg && !$request->getDestPostcode() && $this->isZipCodeRequired($request->getDestCountryId())) {
$errorMsg = __('This shipping method is not available. Please specify the zip code.');
}
if ($request->getDestCountryId() == 'ZA') {
$errorMsg = '';
} else {
$errorMsg = $configErrorMsg ? $configErrorMsg : $defaultErrorMsg;
}
if ($errorMsg && $showMethod) {
$error = $this->_rateErrorFactory->create();
$error->setCarrier($this->_code);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage($errorMsg);
return $error;
} elseif ($errorMsg) {
return false;
}
return $this;
}
/**
* Collect and get rates for this shipping method based on information in $request
* This is a default function that is called by Magento to get the shipping rates for the cart
* @param RateRequest $request
* @return Result|bool|null
*/
public function collectRates(RateRequest $request)
{
/*** Make sure that Shipping method is enabled*/
if (!$this->isActive()) {
return false;
}
/**
* Gets the destination company name from Company Name field in the checkout page
* This method is used is the last resort to get the company name since the company name is not available in _rateFactory
*/
$destComp = $this->getDestComp();
$destSuburb = $this->getDestSuburb();
/** @var \Magento\Shipping\Model\Rate\Result $result */
$result = $this->_rateFactory->create();
$destination = $request->getDestPostcode();
$destCountry = $request->getDestCountryId();
$destRegion = $request->getDestRegionCode();
$destCity = $request->getDestCity();
$destStreet = $request->getDestStreet();
/** Destination Information */
[$destStreet1, $destStreet2, $destStreet3] = $this->destStreet($destStreet);
/** Origin Information */
[$originStreet, $originRegion, $originCountry, $originCity, $originStreet1, $originStreet2, $storeName, $baseIdentifier, $originSuburb,$weightUnit] = $this->storeInformation();
/** Get all items in cart */
$items = $request->getAllItems();
$itemsArray = [];
$itemsArray = $this->getStoreItems($items, $weightUnit, $itemsArray);
$payload = [
'identifier' => $baseIdentifier,
'rate' => [
'origin' => [
'company' => $storeName,
'address1' => $originStreet1,
'address2' => $originStreet2,
'city' => $originCity,
'suburb' => $originSuburb,
'province' => $originRegion,
'country_code' => $originCountry,
'postal_code' => $originStreet,
],
'destination' => [
'company' => $destComp,
'address1' => $destStreet1,
'address2' => $destStreet2,
'suburb' => $destSuburb,
'city' => $destCity,
'province' => $destRegion,
'country_code' => $destCountry,
'postal_code' => $destination,
],
'items' => $itemsArray,
]
];
$this->_getRates($payload, $result);
return $result;
}
/**
* @return array
*/
public function storeInformation(): array
{
/** Store Origin details */
$originCountry = $this->_scopeConfig->getValue(
'general/store_information/country_id',
ScopeInterface::SCOPE_STORE
);
$originRegion = $this->_scopeConfig->getValue(
'general/store_information/region_id',
ScopeInterface::SCOPE_STORE
);
$originCity = $this->_scopeConfig->getValue(
'general/store_information/city',
ScopeInterface::SCOPE_STORE
);
$originStreet = $this->_scopeConfig->getValue(
'general/store_information/postcode',
ScopeInterface::SCOPE_STORE
);
$originStreet1 = $this->_scopeConfig->getValue(
'general/store_information/street_line1',
ScopeInterface::SCOPE_STORE
);
$originStreet2 = $this->_scopeConfig->getValue(
'general/store_information/street_line2',
ScopeInterface::SCOPE_STORE
);
$storeName = $this->_scopeConfig->getValue(
'general/store_information/name',
ScopeInterface::SCOPE_STORE
);
$originSuburb = $this->_scopeConfig->getValue(
'general/store_information/suburb',
ScopeInterface::SCOPE_STORE
);
$weightUnit = $this->_scopeConfig->getValue(
'general/locale/weight_unit',
ScopeInterface::SCOPE_STORE
);
$baseIdentifier = $this->getBaseUrl();
return array($originStreet, $originRegion, $originCountry, $originCity, $originStreet1, $originStreet2, $storeName, $baseIdentifier, $originSuburb, $weightUnit);
}
/**
* Get result of request
*
* @return Result|null
*/
public function getResult()
{
if (!$this->_result) {
$this->_result = $this->_trackFactory->create();
}
return $this->_result;
}
/**
* Get final price for shipping method with handling fee per package
*
* @param float $cost
* @param string $handlingType
* @param float $handlingFee
* @return float
*/
protected function _getPerpackagePrice($cost, $handlingType, $handlingFee)
{
if ($handlingType == AbstractCarrier::HANDLING_TYPE_PERCENT) {
return $cost + $cost * $this->_numBoxes * $handlingFee / self::UNITS;
}
return $cost + $this->_numBoxes * $handlingFee;
}
/**
* Get final price for shipping method with handling fee per order
*
* @param float $cost
* @param string $handlingType
* @param float $handlingFee
* @return float
*/
protected function _getPerorderPrice($cost, $handlingType, $handlingFee)
{
if ($handlingType == self::HANDLING_TYPE_PERCENT) {
return $cost + $cost * $handlingFee / self::UNITS;
}
return $cost + $handlingFee;
}
/**
* Get configuration data of carrier
*
* @param string $type
* @param string $code
* @return array|false
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function getCode($type, $code = '')
{
$codes = [
'method' => [
'bobGo' => __('BobGo'),
],
'unit_of_measure' => [
'KGS' => __('Kilograms'),
'LBS' => __('Pounds'),
],
];
if (!isset($codes[$type])) {
return false;
} elseif ('' === $code) {
return $codes[$type];
}
if (!isset($codes[$type][$code])) {
return false;
} else {
return $codes[$type][$code];
}
}
/**
* Get tracking
*
* @param string|string[] $trackings
* @return Result|null
*/
public function getTracking($trackings)
{
$this->setTrackingReqeust();
if (!is_array($trackings)) {
$trackings = [$trackings];
}
foreach ($trackings as $tracking) {
$this->_getXMLTracking($tracking);
}
return $this->_result;
}
/**
* Set tracking request
*
* @return void
*/
protected function setTrackingReqeust()
{
$r = new \Magento\Framework\DataObject();
$account = $this->getConfigData('account');
$r->setAccount($account);
$this->_rawTrackingRequest = $r;
}
/**
* Send request for tracking
*
* @param string[] $tracking
* @return void
*/
protected function _getXMLTracking($tracking)
{
$this->_parseTrackingResponse($tracking);
}
/**
* Parse tracking response
*
* @param string $trackingValue
* @return void
*/
protected function _parseTrackingResponse($trackingValue)
{
$result = $this->getResult();
$carrierTitle = $this->getConfigData('title');
$counter = 0;
if (!is_array($trackingValue)) {
$trackingValue = [$trackingValue];
}
foreach ($trackingValue as $trackingReference) {
$tracking = $this->_trackStatusFactory->create();
$tracking->setCarrier(self::CODE);
$tracking->setCarrierTitle($carrierTitle);
//Production
/* $tracking->setUrl(sprintf(uData::TRACKING, $this->getBaseUrl(), $trackingReference));
$tracking->setTracking($trackingReference);
$tracking->addData($this->processTrackingDetails($trackingReference));
*/
//Dev
$tracking->setUrl(uData::TRACKING .$trackingReference);
$tracking->setTracking($trackingReference);
$tracking->addData($this->processTrackingDetails($trackingReference));
$result->append($tracking);
$counter ++;
}
//Tracking Details Not Available
if (!$counter) {
$this->appendTrackingError(
$trackingValue,
__('For some reason we can\'t retrieve tracking info right now.')
);
}
}
/**
* Get tracking response
*
* @return string
*/
public function getResponse()
{
$statuses = '';
if ($this->_result instanceof \Magento\Shipping\Model\Tracking\Result) {
if ($trackings = $this->_result->getAllTrackings()) {
foreach ($trackings as $tracking) {
if ($data = $tracking->getAllData()) {
if (!empty($data['status'])) {
$statuses .= __($data['status']) . "\n<br/>";
} else {
$statuses .= __('Empty response') . "\n<br/>";
}
}
}
}
}
// phpstan:ignore
if (empty($statuses)) {
$statuses = __('Empty response');
}
return $statuses;
}
/**
* Get allowed shipping methods
*
* @return array
*/
public function getAllowedMethods()
{
$allowed = explode(',', $this->getConfigData('allowed_methods'));
$arr = [];
foreach ($allowed as $k) {
$arr[$k] = $this->getCode('method', $k);
}
return $arr;
}
/**
* Do shipment request to carrier web service, obtain Print Shipping Labels and process errors in response
* Also another magic function that is required to be implemented by carrier model
* @param \Magento\Framework\DataObject $request
* @return \Magento\Framework\DataObject
*/
protected function _doShipmentRequest(\Magento\Framework\DataObject $request)
{
return null;
}
/**
* For multi package shipments. Delete requested shipments if the current shipment request is failed
*
* @param array $data
*
* @return bool
*/
public function rollBack($data)
{
return true;
}
/**
* Return container types of carrier
*
* @param \Magento\Framework\DataObject|null $params
*
* @return array|bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function getContainerTypes(\Magento\Framework\DataObject $params = null)
{
$result = [];
$allowedContainers = $this->getConfigData('containers');
if ($allowedContainers) {
$allowedContainers = explode(',', $allowedContainers);
}
if ($allowedContainers) {
foreach ($allowedContainers as $container) {
$result[$container] = $this->getCode('container_types', $container);
}
}
return $result;
}
/**
* Return delivery confirmation types of carrier
*
* @param \Magento\Framework\DataObject|null $params
*
* @return array
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function getDeliveryConfirmationTypes(\Magento\Framework\DataObject $params = null)
{
return $this->getCode('delivery_confirmation_types');
}
/**
* Recursive replace sensitive fields in debug data by the mask
*
* @param string $data
* @return string
*/
protected function filterDebugData($data)
{
foreach (array_keys($data) as $key) {
if (is_array($data[$key])) {
$data[$key] = $this->filterDebugData($data[$key]);
} elseif (in_array($key, $this->_debugReplacePrivateDataKeys)) {
$data[$key] = self::DEBUG_KEYS_MASK;
}
}
return $data;
}
/**
* Parse track details response from Bob Go
*
* @return array
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
**/
private function processTrackingDetails($trackInfo): array
{
$result = [
'shippeddate' => null,
'deliverydate' => null,
'deliverytime' => null,
'deliverylocation' => null,
'weight' => null,
'progressdetail' => [],
];
$result = $this->_requestTracking($trackInfo, $result);
return $result;
}
/**
* Append error message to rate result instance
*
* @param string $trackingValue
* @param string $errorMessage
*/
private function appendTrackingError($trackingValue, $errorMessage)
{
$error = $this->_trackErrorFactory->create();
$error->setCarrier(self::CODE);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setTracking($trackingValue);
$error->setErrorMessage($errorMessage);
$result = $this->getResult();
$result->append($error);
}
/**
* @param string $date
* @return string
*/
public function formatDate(string $date): string
{
return date('d M Y', strtotime($date));
}
/**
* @param string $time
* @return string
*/
public function formatTime(string $time): string
{
return date('H:i', strtotime($time));
}
/**
* @return string
*/
private function getApiUrl(): string
{
return uData::RATES_ENDPOINT;
}
/**
* Perfom API Request to bobgo API and return response
* @param array $payload
* @param Result $result
* @return void
*/
protected function _getRates(array $payload, Result $result): void
{
$rates = $this->uRates($payload);
$this->_formatRates($rates, $result);
}
/**
* Perform API Request for Shipment Tracking to Bob Go API and return response
* @param $trackInfo
* @param array $result
* @return array
*/
private function _requestTracking($trackInfo, array $result): array
{
$response = $this->trackbobgoShipment($trackInfo);
$result = $this->prepareActivity($response[0], $result);
return $result;
}
/**
* Format rates from Bob Go API response and append to rate result instance of carrier
* @param mixed $rates
* @param Result $result
* @return void
*/
protected function _formatRates(mixed $rates, Result $result): void
{
if (empty($rates)) {
$error = $this->_rateErrorFactory->create();
$error->setCarrierTitle($this->getConfigData('title'));
$error->setErrorMessage($this->getConfigData('specificerrmsg'));
$result->append($error);
} else {
$this->_logger->info('Rates is not empty:');
foreach ($rates['rates'] as $title) {
$method = $this->_rateMethodFactory->create();
if (isset($title)){
$method->setCarrier(self::CODE);
if ($this->getConfigData('additional_info') == 1) {
$min_delivery_date = $this->getWorkingDays(date('Y-m-d'), $title['min_delivery_date']);
$max_delivery_date = $this->getWorkingDays(date('Y-m-d'), $title['max_delivery_date']);
$this->deliveryDays($min_delivery_date, $max_delivery_date, $method);
}
}
$method->setMethod($title['service_code']);
$method->setMethodTitle($title['service_name']);
$price = $title['total_price'];
$cost = $title['total_price'];
// Log the values
$this->_logger->info('Price: ' . $price);
$this->_logger->info('Cost: ' . $cost);
// Set the values
$method->setPrice($price);
$method->setCost($cost);
$result->append($method);
}
}
}
/**
* Prepare received checkpoints and activity from Bob Go Shipment Tracking API
* @param $response
* @param array $result
* @return array
*/
private function prepareActivity($response, array $result): array
{
foreach ($response['checkpoints'] as $checkpoint) {
$result['progressdetail'][] = [
'activity' => $checkpoint['status'],
'deliverydate' => $this->formatDate($checkpoint['time']),
'deliverytime' => $this->formatTime($checkpoint['time']),
// 'deliverylocation' => 'Unavailable',//TODO: remove this line
];
}
return $result;
}
/**
* Get Working Days between time of checkout and delivery date (min and max)
* @param string $startDate
* @param string $endDate
* @return int
*/
public function getWorkingDays(string $startDate, string $endDate): int
{
$begin = strtotime($startDate);
$end = strtotime($endDate);
if ($begin > $end) {
// echo "Start Date Cannot Be In The Future! <br />";
return 0;
} else {
$no_days = 0;
$weekends = 0;
while ($begin <= $end) {
$no_days++; // no of days in the given interval
$what_day = date("N", $begin);
if ($what_day > 5) { // 6 and 7 are weekend days
$weekends++;
};
$begin += 86400; // +1 day
};
return $no_days - $weekends;
}
}
/**
* Curl request to Bob Go Shipment Tracking API
* @param $trackInfo
* @return mixed
*/
private function trackbobgoShipment($trackInfo): mixed
{
$this->curl->get(uData::TRACKING . $trackInfo);
$response = $this->curl->getBody();
return json_decode($response, true);
}
/**
* Build The Payload for Bob Go API Request and return response
* @param array $payload
* @return mixed
*/
protected function uRates(array $payload): mixed
{
$this->curl->addHeader('Content-Type', 'application/json');
$this->curl->post($this->getApiUrl(), json_encode($payload));
$rates = $this->curl->getBody();
$rates = json_decode($rates, true);
return $rates;
}
/**
* @param string $destStreet
* @return string[]
*/
protected function destStreet(string $destStreet): array
{
if (strpos($destStreet, "\n") !== false) {
$destStreet = explode("\n", $destStreet);
$destStreet1 = $destStreet[0];
$destStreet2 = $destStreet[1];
$destStreet3 = $destStreet[2] ?? '';
} else {
$destStreet1 = $destStreet;
$destStreet2 = '';
$destStreet3 = '';
}
return array($destStreet1, $destStreet2, $destStreet3);
}
/**
* @param int $min_delivery_date
* @param int $max_delivery_date
* @param $method
* @return void
*/
protected function deliveryDays(int $min_delivery_date, int $max_delivery_date, $method): void
{
if ($min_delivery_date !== $max_delivery_date) {
$method->setCarrierTitle('Delivery in '.$min_delivery_date . ' - ' . $max_delivery_date . ' days');
}else{
$method->setCarrierTitle('Delivery in ' . $min_delivery_date . ' days');
if ($min_delivery_date && $max_delivery_date == 1) {
$method->setCarrierTitle('Delivery in '.$min_delivery_date . ' day');
}
}
}
/**
* @return mixed|string
*/
public function getDestComp(): mixed
{
return $this->company->getDestComp();
}
/**
* @return mixed|string
*/
public function getDestSuburb(): mixed
{
return $this->company->getSuburb();
}
/**
* @param mixed $weightUnit
* @param mixed $item
* @return float|int
*/
public function getItemWeight(mixed $weightUnit, mixed $item): int|float
{
//1 lb = 453.59237 g exact. 1 kg = 1000 g. 1 lb = 0.45359237 kg
if ($weightUnit == 'KGS') {
$mass = $item->getWeight() ? $item->getWeight() * 1000 : 0;
} else {
$mass = $item->getWeight() ? $item->getWeight() * 0.45359237 * 1000 : 0;//Pound to Kilogram Conversion Formula
}
return $mass;
}
/**
* @param array $items
* @param mixed $weightUnit
* @param array $itemsArray
* @return array
*/
public function getStoreItems(array $items, mixed $weightUnit, array $itemsArray): array
{
foreach ($items as $item) {
$mass = $this->getItemWeight($weightUnit, $item);
$itemsArray[] = [
'sku' => $item->getSku(),
'quantity' => $item->getQty(),
'price' => $item->getPrice(),
'weight' => round($mass),
];
}
return $itemsArray;
}
/**
* Get the list of required data fields
* @return bool
*/
public function hasRequiredData(DataObject $request): bool
{
$requiredFields = [
'dest_country_id',
'dest_region_id',
];
foreach ($requiredFields as $field) {
if (!$request->getData($field)) {
return false;
}
}
return true;
}
public function triggerRatesTest()
{
// Check if the 'Show rates for checkout' setting is enabled
$isEnabled = $this->scopeConfig->getValue('carriers/bobgo/active', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
if ($isEnabled) {
// Sample test payload, replace with actual structure
$payload = [
'identifier' => $this->getBaseUrl(),
'rate' => [
'origin' => [
'company' => 'Test Store',
'address1' => '123 Test St',
'address2' => '',
'city' => 'Test City',
'suburb' => 'Test Suburb',
'province' => 'Test Province',
'country_code' => 'ZA',
'postal_code' => '2000',
],
'destination' => [
'company' => 'Test Company',
'address1' => '456 Test Ave',
'address2' => '',
'suburb' => 'Test Suburb',
'city' => 'Test City',
'province' => 'Test Province',
'country_code' => 'ZA',
'postal_code' => '3000',
],
'items' => [
[
'sku' => 'test-sku-1',
'quantity' => 1,
'price' => 100.00,
'weight' => 500, // in grams
]
],
]
];
try {
// Perform the API request
$this->curl->addHeader('Content-Type', 'application/json');
$this->curl->post($this->getApiUrl(), json_encode($payload));
$statusCode = $this->curl->getStatus();
$responseBody = $this->curl->getBody();
// Log the response for debugging purposes
$this->_logger->info('BobGo Rates API Test Response: ' . $responseBody);
// Decode the response
$response = json_decode($responseBody, true);
// Check if the response contains a 'message' (indicating an error)
if (isset($response['message'])) {
throw new \Exception('Error from BobGo: ' . $response['message']);
}
// Check if the response contains rates with a valid id field
if (isset($response['rates']) && is_array($response['rates']) && !empty($response['rates'])) {
foreach ($response['rates'] as $rate) {
if (isset($rate['id']) && $rate['id'] !== null) {
$this->_logger->info('Rates received successfully with a valid id.');
return $response; // Successful response with a valid id
}
}
throw new \Exception('Rates received but id field is empty or invalid.');
} else {
throw new \Exception('Received response but no valid rates were found.');
}
} catch (\Exception $e) {
$this->_logger->error('Error in triggerRatesTest: ' . $e->getMessage());
return false;
}
}
return false;
}
}