Skip to content
Snippets Groups Projects
Commit c6722b81 authored by Francé Wilke's avatar Francé Wilke
Browse files

Revert "Revert "Merge branch 'dev' into 'prod'""

This reverts commit 2b8c809a
parent 2b8c809a
Branches
Tags
2 merge requests!24Dev -> Prod,!23Revert "Revert "Merge branch 'dev' into 'prod'""
This commit is part of merge request !24. Comments created here will be created in the context of that merge request.
Showing
with 460 additions and 623 deletions
*.pdf
node_modules
.git
package.json
.husky
package-lock.json
.distignore
make-zip.sh
update-version.js
.gitlab-ci.yml
.gitignore
package
node_modules
*.zip
.idea
/.idea/
......@@ -4,24 +4,20 @@ variables:
GIT_SUBMODULE_STRATEGY: recursive
stages:
- tagged_release
- deploy
tagged_deploy:
stage: tagged_release
only:
- tags
deploy:
stage: deploy
before_script:
# - AWS_ACCESS_KEY_ID_KEY=$(echo "$AWS_ACCESS_KEY_ID")
# - AWS_SECRET_ACCESS_KEY_KEY=$(echo "$AWS_SECRET_ACCESS_KEY")
# - AWS_ACCESS_KEY_ID=$(eval echo -e "\$$AWS_ACCESS_KEY_ID_KEY")
# - AWS_SECRET_ACCESS_KEY=$(eval echo -e "\$$AWS_SECRET_ACCESS_KEY_KEY")
# - export AWS_ACCESS_KEY_ID
# - export AWS_SECRET_ACCESS_KEY
- AWS_ACCESS_KEY_ID_KEY=$(echo "$CI_COMMIT_BRANCH"_"AWS_ACCESS_KEY_ID")
- AWS_ACCESS_KEY_ID=$(eval echo -e "\$$AWS_ACCESS_KEY_ID_KEY")
- AWS_SECRET_ACCESS_KEY_KEY=$(echo "$CI_COMMIT_BRANCH"_"AWS_SECRET_ACCESS_KEY")
- AWS_SECRET_ACCESS_KEY=$(eval echo -e "\$$AWS_SECRET_ACCESS_KEY_KEY")
- export AWS_ACCESS_KEY_ID
- export AWS_SECRET_ACCESS_KEY
script:
# - echo $AWS_ACCESS_KEY_ID
# - echo $AWS_SECRET_ACCESS_KEY
- wget https://gitlab.bob.co.za/bob-public-utils/bobgo-magento-extension/-/archive/"$CI_COMMIT_TAG"/bobgo-magento-extension-"$CI_COMMIT_TAG".tar.gz
- ls -al
- aws s3 cp bobgo-magento-extension-"$CI_COMMIT_TAG".tar.gz s3://bobgo-s3-magento-plugin/ --region=af-south-1
allow_failure: false
when: on_success
\ No newline at end of file
- ./make-zip.sh
- aws s3 cp bobgo-magento-plugin.zip s3://bobgo-s3-magento-plugin/ --region=af-south-1
rules:
- if: '$CI_COMMIT_BRANCH == "dev" && $CI_COMMIT_TAG == null'
when: always
npm config set git-tag-version false && npm version patch && npm run update-version-files && git add package.json etc/module.xml composer.json
<?php
namespace BobGroup\BobGo\Block;
use Magento\Framework\View\Element\Html\Link\Current;
use Magento\Framework\App\Config\ScopeConfigInterface;
class TrackOrderLink extends Current
{
protected $scopeConfig;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
ScopeConfigInterface $scopeConfig,
\Magento\Framework\App\DefaultPathInterface $defaultPath,
array $data = []
) {
$this->scopeConfig = $scopeConfig;
parent::__construct($context, $defaultPath, $data);
}
protected function _toHtml()
{
// Check if the Track My Order feature is enabled
$isEnabled = $this->scopeConfig->isSetFlag(
'carriers/bobgo/enable_track_order',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
// Return an empty string if the feature is disabled
if (!$isEnabled) {
return '';
}
// Use the parent class's rendering method
return parent::_toHtml();
}
}
<?php
namespace BobGroup\BobGo\Block;
use Magento\Framework\View\Element\Template;
use Magento\Framework\Registry;
class TrackingBlock extends \Magento\Framework\View\Element\Template
{
protected $registry;
public function __construct(
Template\Context $context,
Registry $registry,
array $data = []
) {
$this->registry = $registry;
parent::__construct($context, $data);
}
public function getResponse()
{
return $this->registry->registry('shipment_data');
}
}
<?php
namespace BobGroup\BobGo\Controller\Tracking;
use Magento\Framework\App\Action\Context;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\Registry;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Controller\Result\RedirectFactory;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Store\Model\StoreManagerInterface;
use BobGroup\BobGo\Model\Carrier\UData;
class Index extends \Magento\Framework\App\Action\Action
{
protected $resultPageFactory;
protected $jsonFactory;
protected $curl;
protected $logger;
protected $scopeConfig;
protected $redirectFactory;
protected $registry;
protected StoreManagerInterface $storeManager;
public function __construct(
Context $context,
PageFactory $resultPageFactory,
JsonFactory $jsonFactory,
LoggerInterface $logger,
ScopeConfigInterface $scopeConfig,
RedirectFactory $redirectFactory,
StoreManagerInterface $storeManager,
Curl $curl,
Registry $registry
) {
$this->resultPageFactory = $resultPageFactory;
$this->jsonFactory = $jsonFactory;
$this->logger = $logger;
$this->scopeConfig = $scopeConfig;
$this->redirectFactory = $redirectFactory;
$this->storeManager = $storeManager;
$this->curl = $curl;
$this->registry = $registry;
parent::__construct($context);
}
public function execute()
{
// This is only an extra check after the TrackOrderLink block
// Check if the "Track My Order" feature is enabled
$isEnabled = $this->scopeConfig->isSetFlag(
'carriers/bobgo/enable_track_order',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
if (!$isEnabled) {
// If the feature is disabled, redirect to home page or show a 404 error
return $this->redirectFactory->create()->setPath('noroute');
}
$trackingReference = $this->getRequest()->getParam('order_reference');
$channel = $this->getStoreUrl();
if ($trackingReference) {
$trackingUrl = sprintf(UData::TRACKING, $channel, $trackingReference);
$this->curl->get($trackingUrl);
$response = $this->curl->getBody();
$decodedResponse = json_decode($response, true);
if (is_array($decodedResponse) && isset($decodedResponse[0])) {
$shipmentData = $decodedResponse[0];
// Save data to the registry
$this->registry->register('shipment_data', $shipmentData);
} else {
// Return early the response is not valid
return $this->resultPageFactory->create();
}
}
return $this->resultPageFactory->create();
}
private function getStoreUrl(): string
{
$url = $this->storeManager->getStore()->getBaseUrl();
// Remove protocol (http:// or https://)
$host = preg_replace('#^https?://#', '', $url);
// Ensure $host is a string before using it in explode
$host = $host ?? '';
// Remove everything after the host (e.g., paths, query strings)
$host = explode('/', $host)[0];
// If the host starts with 'www.', remove it
if (strpos($host, 'www.') === 0) {
$host = substr($host, 4);
}
return $host;
}
}
File added
......@@ -527,141 +527,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
}
}
/**
* Get tracking
*
* @param string|string[] $trackings
* @return \Magento\Shipping\Model\Tracking\Result|null
*/
public function getTracking($trackings)
{
$this->setTrackingRequest(); // Ensure this method is correctly defined
if (!is_array($trackings)) {
$trackings = [$trackings];
}
foreach ($trackings as $tracking) {
$this->_getXMLTracking([$tracking]); // Ensure _getXMLTracking processes tracking correctly
}
return $this->_result; // Ensure _result is a \Magento\Shipping\Model\Tracking\Result
}
/**
* Set tracking request
*
* @return void
*/
protected function setTrackingRequest()
{
$r = new \Magento\Framework\DataObject();
$account = $this->getConfigData('account');
$r->setData('account', $account); // Using setData with the key 'account'
$this->_rawTrackingRequest = $r;
}
/**
* Get tracking request
*
* @return \Magento\Framework\DataObject|null
*/
protected function getTrackingRequest(): ?\Magento\Framework\DataObject
{
return $this->_rawTrackingRequest;
}
/**
* Send request for tracking
*
* @param string[] $tracking
* @return void
*/
protected function _getXMLTracking($tracking)
{
$this->_parseTrackingResponse($tracking);
}
/**
* Parse tracking response
*
* @param string|array<int,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);
// Adjust as needed based on the environment
$tracking->setUrl(UData::TRACKING . $trackingReference);
$tracking->setTracking($trackingReference);
$tracking->addData($this->processTrackingDetails($trackingReference));
if ($result) {
$result->append($tracking);
$counter++;
}
}
// Tracking Details Not Available
if ($counter === 0) {
$this->appendTrackingError(
$trackingValue[0] ?? '',
(string)__('For some reason we can\'t retrieve tracking info right now.')
);
}
}
/**
* Get tracking response
*
* @return string
*/
public function getResponse(): string
{
$statuses = '';
// If $_result is of type \Magento\Shipping\Model\Tracking\Result, handle it
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/>";
}
}
}
}
}
// // Handle \Magento\Shipping\Model\Rate\Result if needed
// if ($this->_result instanceof \Magento\Shipping\Model\Rate\Result) {
// // Implement the logic for Rate\Result if applicable
// }
if (trim($statuses) === '') {
$statuses = (string)__('Empty response');
}
return $statuses;
}
/**
* Get allowed shipping methods
*
......@@ -670,7 +535,7 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
public function getAllowedMethods(): array
{
$allowedMethods = $this->getConfigData('allowed_methods');
if ($allowedMethods === false) {
if (empty($allowedMethods)) {
return []; // Return an empty array if no allowed methods are configured
}
......@@ -773,55 +638,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
return $data;
}
/**
* Parse track details response from Bob Go.
*
* @param string $trackInfo
* @return array<string, array<int, array<string, string>>>
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
private function processTrackingDetails(string $trackInfo): array
{
$result = [
'shippeddate' => [], // Initializing as an array of arrays
'deliverydate' => [], // Initializing as an array of arrays
'deliverytime' => [], // Initializing as an array of arrays
'deliverylocation' => [], // Initializing as an array of arrays
'weight' => [], // Initializing as an array of arrays
'progressdetail' => [], // This will be populated with an array of arrays
];
$result = $this->_requestTracking($trackInfo, $result);
return $result;
}
/**
* Append error message to rate result instance.
*
* @param string $trackingValue
* @param string $errorMessage
* @return void
*/
private function appendTrackingError(string $trackingValue, string $errorMessage): void
{
$error = $this->_trackErrorFactory->create();
$error->setCarrier(self::CODE);
$error->setCarrierTitle($this->getConfigData('title'));
$error->setTracking($trackingValue);
$error->setErrorMessage($errorMessage);
$result = $this->getResult();
if ($result !== null) {
$result->append($error);
} else {
// Handle the case where $result is null, such as logging an error
$this->_logger->error('Failed to append tracking error: Result object is null.');
}
}
/**
* Format a date to 'd M Y'.
*
......@@ -864,6 +680,11 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
return UData::RATES_ENDPOINT;
}
private function getWebhookUrl(): string
{
return UData::WEBHOOK_URL;
}
/**
* Perform API Request to Bob Go API and return response.
*
......@@ -883,26 +704,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
}
}
/**
* Perform API Request for Shipment Tracking to Bob Go API and return response.
*
* @param string $trackInfo The tracking information or tracking ID.
* @param array<string,array<int,array<string,string>>> $result The result array to be
* populated with tracking details.
* @return array<string, array<int, array<string, string>>> The updated result array with tracking details.
*/
private function _requestTracking(string $trackInfo, array $result): array
{
$response = $this->trackBobGoShipment($trackInfo);
// Validate that the response is an array and contains at least one element
if (is_array($response) && isset($response[0]) && is_array($response[0])) {
$result = $this->prepareActivity($response[0], $result);
}
return $result;
}
/**
* Format rates from Bob Go API response and append to rate result instance of carrier.
*
......@@ -976,35 +777,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
}
}
/**
* Prepare received checkpoints and activity from Bob Go Shipment Tracking API.
*
* @param array<string,mixed> $response The API response containing tracking checkpoints.
* @param array<string,array<int,array<string,string>>> $result The result array to be
* populated with activity details.
* @return array<string, array<int, array<string, string>>> The updated result array with activity details.
*/
private function prepareActivity(array $response, array $result): array
{
if (isset($response['checkpoints']) && is_array($response['checkpoints'])) {
foreach ($response['checkpoints'] as $checkpoint) {
if (is_array($checkpoint) &&
isset($checkpoint['status'], $checkpoint['time']) &&
is_string($checkpoint['status']) &&
is_string($checkpoint['time'])
) {
$result['progressdetail'][] = [
'activity' => $checkpoint['status'],
'deliverydate' => $this->formatDate($checkpoint['time']),
'deliverytime' => $this->formatTime($checkpoint['time']),
];
}
}
}
return $result;
}
/**
* Get Working Days between time of checkout and delivery date (min and max).
*
......@@ -1037,21 +809,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
return $no_days - $weekends;
}
/**
* Curl request to Bob Go Shipment Tracking API.
*
* @param string $trackInfo The tracking information or tracking ID.
* @return mixed The decoded API response.
*/
private function trackBobGoShipment(string $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 the response.
*
......@@ -1199,27 +956,6 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
return $itemsArray;
}
/**
* Checks if the required data fields are present in the request.
*
* @param \Magento\Framework\DataObject $request The data object containing the request information.
* @return bool True if all required fields are present, otherwise false.
*/
public function hasRequiredData(\Magento\Framework\DataObject $request): bool
{
$requiredFields = [
'dest_country_id',
'dest_region_id',
];
foreach ($requiredFields as $field) {
if (!$request->getData($field)) {
return false;
}
}
return true;
}
/**
* Trigger a test for rates.
*
......@@ -1310,4 +1046,72 @@ class BobGo extends AbstractCarrierOnline implements \Magento\Shipping\Model\Car
}
return false;
}
public function isWebhookEnabled(): bool
{
$enabled = $this->scopeConfig->getValue(
'carriers/bobgo/enable_webhooks',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
// Cast the value to a boolean
return filter_var($enabled, FILTER_VALIDATE_BOOLEAN);
}
public function triggerWebhookTest(): bool
{
$webhookKey = $this->scopeConfig->getValue(
'carriers/bobgo/webhook_key',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
);
// Check if the webhook key is empty and return false
if (empty($webhookKey)) {
return false;
}
// Convert the string to a boolean value
$isEnabled = $this->isWebhookEnabled();
$storeId = strval($this->_storeManager->getStore()->getId());
$payload = [
'event' => 'webhook_validation',
'channel_identifier' => $this->getBaseUrl(),
'store_id' => $storeId,
'webhooks_enabled' => $isEnabled,
];
try {
$this->encodeWebhookAndPostRequest($this->getWebhookUrl(), $payload, $storeId, $webhookKey);
$statusCode = $this->curl->getStatus();
$responseBody = $this->curl->getBody();
if ($statusCode != 200) {
throw new LocalizedException(__('Status code from BobGo: %1', $statusCode));
}
} catch (\Exception $e) {
return false;
}
return true;
}
public function encodeWebhookAndPostRequest($url, $data, $storeId, $webhookKey) {
// Generate the HMAC-SHA256 hash as raw binary data
$rawSignature = hash_hmac('sha256', $storeId, $webhookKey, true);
// Encode the binary data in Base64
$signature = base64_encode($rawSignature);
// Set headers and post the data
$this->curl->addHeader('Content-Type', 'application/json');
$this->curl->addHeader('x-m-webhook-signature', $signature);
$payloadJson = json_encode($data);
if ($payloadJson === false) {
throw new \RuntimeException('Failed to encode payload to JSON.');
}
$this->curl->addHeader('Content-Type', 'application/json');
$this->curl->post($url, $payloadJson);
}
}
......@@ -20,4 +20,11 @@ class UData
* @var string
*/
public const RATES_ENDPOINT = 'https://api.bobgo.co.za/rates-at-checkout/magento';
/**
* Order create/update webhook URL
*
* @var string
*/
public const WEBHOOK_URL = 'https://api.bobgo.co.za/webhook/channel/magento';
}
......@@ -52,6 +52,7 @@ class ConfigChangeObserver implements ObserverInterface
{
$changedPaths = $observer->getEvent()->getData('changed_paths');
// Test for rates at checkout
if (is_array($changedPaths) && in_array('carriers/bobgo/active', $changedPaths)) {
if ($this->bobGo->isActive()) {
$result = $this->bobGo->triggerRatesTest();
......@@ -70,5 +71,23 @@ class ConfigChangeObserver implements ObserverInterface
}
}
}
// Test for webhooks
if ((is_array($changedPaths) && in_array('carriers/bobgo/enable_webhooks', $changedPaths)) || (is_array($changedPaths) && in_array('carriers/bobgo/webhook_key', $changedPaths))) {
$result = $this->bobGo->triggerWebhookTest();
if ($this->bobGo->isWebhookEnabled()) {
if ($result) {
$this->messageManager->addSuccessMessage(
__('Webhook validation successful.')
);
} else {
$this->messageManager->addErrorMessage(
__('Webhook validation failed. Please check your internet connection
and use your Bob Go integration consumer secret key for webhook validation.')
);
}
}
}
}
}
<?php
namespace BobGroup\BobGo\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
use Psr\Log\LoggerInterface;
class ModifyShippingDescription implements ObserverInterface
{
public const CODE = 'bobgo';
protected $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function execute(Observer $observer)
{
// Get the order object from the event
$order = $observer->getEvent()->getOrder();
// Get the current shipping description
$shippingDescription = $order->getShippingDescription();
// Get the method title from the shipping description
$methodTitle = $this->extractMethodTitle($shippingDescription);
// Set the new shipping description based only on MethodTitle
$newDescription = $methodTitle;
// Update the shipping description in the order
$order->setShippingDescription($newDescription);
}
/**
* Helper function to extract the method title from the original shipping description
*
* @param string $shippingDescription
* @return string
*/
private function extractMethodTitle($shippingDescription)
{
// Find the position of the last dash in the string
$lastDashPosition = strrpos($shippingDescription, ' - ');
// If a dash is found, extract the part after the last dash
if ($lastDashPosition !== false) {
return trim(substr($shippingDescription, $lastDashPosition + 3)); // +3 to skip the ' - ' part
}
// If no dash is found, return the full description (fallback)
return $shippingDescription;
}
}
<?php
namespace BobGroup\BobGo\Observer;
use Magento\Framework\Event\Observer;
class OrderCreateWebhook extends OrderWebhookBase
{
public function execute(Observer $observer)
{
$order = $observer->getEvent()->getOrder();
if (!$order) {
return;
}
// Extract order data and send to the webhook URL
$this->sendWebhook($order);
}
}
<?php
namespace BobGroup\BobGo\Observer;
use BobGroup\BobGo\Model\Carrier\UData;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\HTTP\Client\Curl;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
use BobGroup\BobGo\Model\Carrier\BobGo;
abstract class OrderWebhookBase implements ObserverInterface
{
protected Curl $curl;
protected LoggerInterface $logger;
protected StoreManagerInterface $storeManager;
protected ScopeConfigInterface $scopeConfig;
protected $bobGo;
public function __construct(LoggerInterface $logger, Curl $curl, StoreManagerInterface $storeManager, ScopeConfigInterface $scopeConfig, BobGo $bobGo)
{
$this->logger = $logger;
$this->curl = $curl;
$this->storeManager = $storeManager;
$this->scopeConfig = $scopeConfig;
$this->bobGo = $bobGo;
}
protected function sendWebhook($order)
{
// Return early if not enabled
if (!$this->bobGo->isWebhookEnabled()) {
return;
}
// Webhook URL
$url = $this->getWebhookUrl();
$storeId = $this->getStoreId();
$orderId = $order->getId();
// Prepare payload
$data = [
'event' => 'order_updated',
'order_id' => $orderId,
'channel_identifier' => $this->bobGo->getBaseUrl(),
'store_id' => $storeId,
'webhooks_enabled' => true, // If we get to this point webhooks are enabled
];
// Generate the signature using the webhook key saved in config
$webhookKey = $this->scopeConfig->getValue('carriers/bobgo/webhook_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
// Check if the webhook key is empty and return false
if (empty($webhookKey)) {
return;
}
// Send the webhook
$this->bobGo->encodeWebhookAndPostRequest($url, $data, $storeId, $webhookKey);
}
private function getWebhookUrl(): string
{
return UData::WEBHOOK_URL;
}
private function getStoreId(): string
{
$storeId = $this->storeManager->getStore()->getId();
return $storeId;
}
}
<?php
namespace BobGroup\BobGo\Plugin\Block\DataProviders\Tracking;
use BobGroup\BobGo\Model\Carrier;
use Magento\Shipping\Model\Tracking\Result\Status;
use Magento\Shipping\Block\DataProviders\Tracking\DeliveryDateTitle as Subject;
/**
* Plugin to change delivery date title with bobgo customized value
*/
class ChangeTitle
{
/**
* Title modification in case if bobgo used as carrier
*
* @param Subject $subject
* @param \Magento\Framework\Phrase|string $result
* @param Status $trackingStatus
* @return \Magento\Framework\Phrase|string
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterGetTitle(Subject $subject, $result, Status $trackingStatus)
{
if ($trackingStatus->getCarrier() === \BobGroup\BobGo\Model\Carrier\BobGo::CODE) {
$result = __('Expected delivery:');
}
return $result;
}
}
<?php
namespace BobGroup\BobGo\Plugin\Block\Tracking;
use Magento\Shipping\Block\Tracking\Popup;
use Magento\Shipping\Model\Tracking\Result\Status;
/*
* Plugin to update delivery date value in case if Bob Go is a carrier used
*/
class PopupDeliveryDate
{
/**
* Bob Go carrier code
*/
private const BOB_GO_CARRIER_CODE = 'bobgo_carrier_code'; // Replace with your actual carrier code
/**
* Show only date for expected delivery in case if Bob Go is a carrier
*
* @param Popup $subject
* @param string $result
* @param string $date
* @param string $time
* @return string
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterFormatDeliveryDateTime(Popup $subject, $result, $date, $time)
{
if ($this->getCarrier($subject) === self::BOB_GO_CARRIER_CODE) {
$result = $subject->formatDeliveryDate($date);
}
return $result;
}
/**
* Retrieve carrier name from tracking info
*
* @param Popup $subject
* @return string
*/
private function getCarrier(Popup $subject): string
{
foreach ($subject->getTrackingInfo() as $trackingData) {
foreach ($trackingData as $trackingInfo) {
if ($trackingInfo instanceof Status) {
return $trackingInfo->getCarrier() ?? '';
}
}
}
return '';
}
}
# Magento 2 Bob Go Shipping Extension
# Bob Go shipping extension for Magento 2
## Introduction
A complete guide to install Magento Bob Go Shipping extension in Magento 2.
## Features
>This extension allows you to get real-time shipping rates from Bob Go shipping services and display them to your customers during checkout.
>This extension also allows you to track shipments and get delivery status updates from Bob Go shipping services.
## How to install Magento 2 Bob Go Shipping Extension
### Option 1 (recommended): Install via composer
Run the following command in Magento 2 root folder:</br>
>_Note: You must have composer installed on your server for this option_
#### 1. Execute the following command to install the module:
```
composer require bobgo/bobgo-magento-extension
```
#### 2. Enter following commands to enable the module:
```
bin/magento module:enable BobGroup_BobGo
bin/magento cache:clean
bin/magento cache:flush
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy
```
### Option 2: Install via zip file
1. Download the extension zip file from the link below: </br>
<a href="https://gitlab.bob.co.za/bob-public-utils/bobgo-magento-extension/-/archive/prod/bobgo-magento-extension-prod.zip"> Download Magento 2 Bob Go Shipping Extension </a>
2. Unzip the file and copy contents
3. Create `BobGroup/BobGo` <em>Directory</em>
**It should look like this:** </br>
>{Magento root}/app/code/BobGroup/BobGo/
>**{Magento root}**`/app/code/BobGroup/BobGo/`**{Paste here}**
4. Go to Magento root folder and run all commands below to install `BobGroup_BobGo`: </br>
```
bin/magento cache:clean
bin/magento cache:flush
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento setup:static-content:deploy
```
_____________________________________________________________________________________________________________________
# After installation
## How to configure Magento 2 Bob Go Shipping Extension
### ✓ Step 1: Create an account on Bob Go
You need to create an account on Bob Go to get your store identified by the API.
Please visit [Bob Go](https://bobgo.co.za) to create an account.
### ✓ Step 2: Integrate Magento and Bob Go
1. In the Magento admin portal click on `System > Integrations` and click on `Add New Integration`
2. Under `Basic Settings > Integration Info` fill in the name of the integration eg. Bob Go
3. Under `Basic Settings > API` select `All` for Resource access
4. Click `Save` and enter your Magento admin portal password
5. The `Integration Details` will be displayed on the page
6. On [Bob Go](https://bobgo.co.za) go to `Sales channels > Add channel > Magento` and enter the Magento integration details from step 5 and click `Grant access`
7. On Bob Go go to `Rates at checkout > Settings > Installed channels` and enable your channel for rates at checkout
8. Make sure you have service levels configured and enabled on Bob Go `Rates at checkout > Service levels`
### ✓ Step 3: Login to Magento Admin
1. In the Magento admin portal click on `Stores > Configuration > Sales > Delivery Methods`
2. Go to the Bob Go delivery method and enable Bob Go rates at checkout
3. Click `Save Config`
4. A message at the top of the screen will confirm that rates at checkout is enabled correctly: `Bob Go rates at checkout connected.`
#### Admin Configurations: Update Store Information*
When the extension is **installed** and **enabled**, a new field will be created in `Store Information` : `Suburb`. Enter the necessary details:
1. `Stores`> `Configuration`> `General`>`General`
2. `Store Information`>`Suburb`
3. Update the store information and click `Save config`
See the installation guide for information: [Installation Guide](./Installation guide - Bob Go shipping extension for Magento 2.pdf)
\ No newline at end of file
<?php
namespace BobGroup\BobGo\Test\Unit\Plugin\Block\DataProviders\Tracking;
use BobGroup\BobGo\Plugin\Block\DataProviders\Tracking\ChangeTitle;
use BobGroup\BobGo\Model\Carrier\BobGo;
use Magento\Shipping\Model\Tracking\Result\Status;
use Magento\Shipping\Block\DataProviders\Tracking\DeliveryDateTitle as Subject;
use PHPUnit\Framework\TestCase;
class ChangeTitleTest extends TestCase
{
/**
* @var ChangeTitle
*/
private $plugin;
protected function setUp(): void
{
// Instantiate the ChangeTitle plugin
$this->plugin = new ChangeTitle();
}
public function testAfterGetTitleWithBobGoCarrier(): void
{
// Create a custom Status object with BobGo carrier
$status = $this->getMockBuilder(Status::class)
->setMethods(['getCarrier'])
->getMock();
$status->method('getCarrier')->willReturn(BobGo::CODE);
// Mock the Subject class
$subjectMock = $this->createMock(Subject::class);
// Call the plugin method afterGetTitle
$result = $this->plugin->afterGetTitle($subjectMock, 'Original Title', $status);
// Assert that the title was changed for BobGo carrier
$this->assertEquals('Expected delivery:', $result);
}
public function testAfterGetTitleWithOtherCarrier(): void
{
// Create a custom Status object with a different carrier
$status = $this->getMockBuilder(Status::class)
->setMethods(['getCarrier'])
->getMock();
$status->method('getCarrier')->willReturn('other_carrier_code');
// Mock the Subject class
$subjectMock = $this->createMock(Subject::class);
// Call the plugin method afterGetTitle
$originalTitle = 'Original Title';
$result = $this->plugin->afterGetTitle($subjectMock, $originalTitle, $status);
// Assert that the title was not changed for other carriers
$this->assertEquals($originalTitle, $result);
}
}
<?php
namespace BobGroup\BobGo\Test\Unit\Plugin\Block\Tracking;
use BobGroup\BobGo\Plugin\Block\Tracking\PopupDeliveryDate;
use Magento\Shipping\Block\Tracking\Popup;
use Magento\Shipping\Model\Tracking\Result\Status;
use PHPUnit\Framework\TestCase;
class PopupDeliveryDateTest extends TestCase
{
/**
* @var PopupDeliveryDate
*/
private $plugin;
protected function setUp(): void
{
// Instantiate the PopupDeliveryDate plugin
$this->plugin = new PopupDeliveryDate();
}
public function testAfterFormatDeliveryDateTimeWithBobGoCarrier(): void
{
// Create an instance of the Status class
$status = new Status();
$status->setCarrier('bobgo_carrier_code');
// Mock the Popup class
$popupMock = $this->createMock(Popup::class);
$popupMock->method('getTrackingInfo')->willReturn([
['tracking_info' => $status],
]);
// Mock the formatDeliveryDate method
$popupMock->method('formatDeliveryDate')
->with('2024-08-19')
->willReturn('Aug 19, 2024');
// Call the plugin method afterFormatDeliveryDateTime
$result = $this->plugin->afterFormatDeliveryDateTime(
$popupMock,
'Aug 19, 2024 10:00 AM',
'2024-08-19',
'10:00 AM'
);
// Assert that the time was stripped for BobGo carrier
$this->assertEquals('Aug 19, 2024', $result);
}
public function testAfterFormatDeliveryDateTimeWithOtherCarrier(): void
{
// Create an instance of the Status class
$status = new Status();
$status->setCarrier('other_carrier_code');
// Mock the Popup class
$popupMock = $this->createMock(Popup::class);
$popupMock->method('getTrackingInfo')->willReturn([
['tracking_info' => $status],
]);
// Call the plugin method afterFormatDeliveryDateTime
$result = $this->plugin->afterFormatDeliveryDateTime(
$popupMock,
'Aug 19, 2024 10:00 AM',
'2024-08-19',
'10:00 AM'
);
// Assert that the time remains unchanged for other carriers
$this->assertEquals('Aug 19, 2024 10:00 AM', $result);
}
public function testGetCarrierWithNoTrackingInfo(): void
{
// Mock the Popup class with no tracking info
$popupMock = $this->createMock(Popup::class);
$popupMock->method('getTrackingInfo')->willReturn([]);
// Call the getCarrier method directly
$reflection = new \ReflectionClass($this->plugin);
$method = $reflection->getMethod('getCarrier');
$method->setAccessible(true);
$result = $method->invokeArgs($this->plugin, [$popupMock]);
// Assert that an empty string is returned when no tracking info is available
$this->assertEquals('', $result);
}
}
......@@ -2,7 +2,7 @@
"name": "bobgo/bobgo-magento-extension",
"description": "Smart shipping and order management solution in South Africa",
"type": "magento2-module",
"version": "1.0.33",
"version": "1.0.41",
"authors": [
{
"name": "Bob Go",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment